Skip to content

Commit

Permalink
Support listen on vsock
Browse files Browse the repository at this point in the history
With this patch, node_exporter can run with `--web.listen-address=vsock:
//:9100` to listen on vsock in qemu guest. Then host can get the
metrics.

Signed-off-by: Jeffrey Zhang <zhang.lei.fly@gmail.com>
  • Loading branch information
jeffrey4l authored and Leonid99 committed Aug 2, 2024
1 parent 3c3217e commit e772fca
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 7 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/alecthomas/kingpin/v2 v2.4.0
github.com/coreos/go-systemd/v22 v22.5.0
github.com/go-kit/log v0.2.1
github.com/mdlayher/vsock v1.2.1
github.com/prometheus/common v0.55.0
golang.org/x/crypto v0.25.0
golang.org/x/sync v0.7.0
Expand All @@ -19,6 +20,7 @@ require (
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/mdlayher/socket v0.4.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/mdlayher/vsock v1.2.1 h1:pC1mTJTvjo1r9n9fbm7S1j04rCgCzhCOS5DY0zqHlnQ=
github.com/mdlayher/vsock v1.2.1/go.mod h1:NRfCibel++DgeMD8z/hP+PPTjlNJsdPOmxcnENvE+SE=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
Expand Down
2 changes: 1 addition & 1 deletion web/kingpinflag/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func AddFlags(a *kingpin.Application, defaultAddress string) *web.FlagConfig {
flags := web.FlagConfig{
WebListenAddresses: a.Flag(
"web.listen-address",
"Addresses on which to expose metrics and web interface. Repeatable for multiple addresses.",
"Addresses on which to expose metrics and web interface. Repeatable for multiple addresses. Examples: `:9100` or `127.0.0.1:9100` for http, `vsock://:9100` for vsock",
).Default(defaultAddress).HintOptions(defaultAddress).Strings(),
WebSystemdSocket: systemdSocket,
WebConfigFile: a.Flag(
Expand Down
47 changes: 41 additions & 6 deletions web/tls_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ import (
"fmt"
"net"
"net/http"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"

"github.com/coreos/go-systemd/v22/activation"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/mdlayher/vsock"
config_util "github.com/prometheus/common/config"
"golang.org/x/sync/errgroup"
"gopkg.in/yaml.v2"
Expand Down Expand Up @@ -275,9 +279,11 @@ func ServeMultiple(listeners []net.Listener, server *http.Server, flags *FlagCon
}

// ListenAndServe starts the server on addresses given in WebListenAddresses in
// the FlagConfig or instead uses systemd socket activated listeners if
// WebSystemdSocket in the FlagConfig is true. The FlagConfig is also passed on
// to ServeMultiple.
// the FlagConfig. When address starts looks like vsock://:{port}, it listens on
// vsock. More info check https://wiki.qemu.org/Features/VirtioVsock .
// Or instead uses systemd socket activated listeners if WebSystemdSocket in the
// FlagConfig is true.
// The FlagConfig is also passed on to ServeMultiple.
func ListenAndServe(server *http.Server, flags *FlagConfig, logger log.Logger) error {
if flags.WebSystemdSocket == nil && (flags.WebListenAddresses == nil || len(*flags.WebListenAddresses) == 0) {
return ErrNoListeners
Expand All @@ -297,16 +303,45 @@ func ListenAndServe(server *http.Server, flags *FlagConfig, logger log.Logger) e

listeners := make([]net.Listener, 0, len(*flags.WebListenAddresses))
for _, address := range *flags.WebListenAddresses {
listener, err := net.Listen("tcp", address)
if err != nil {
return err
var err error
var listener net.Listener
if strings.HasPrefix(address, "vsock://") {
port, err := parseVsockPort(address)
if err != nil {
return err
}
listener, err = vsock.Listen(port, nil)
if err != nil {
return err
}
} else {
listener, err = net.Listen("tcp", address)
if err != nil {
return nil
}
}
defer listener.Close()
listeners = append(listeners, listener)
}
return ServeMultiple(listeners, server, flags, logger)
}

func parseVsockPort(address string) (uint32, error) {
uri, err := url.Parse(address)
if err != nil {
return 0, err
}
_, portStr, err := net.SplitHostPort(uri.Host)
if err != nil {
return 0, err
}
port, err := strconv.ParseUint(portStr, 10, 32)
if err != nil {
return 0, err
}
return uint32(port), nil
}

// Server starts the server on the given listener. Based on the file path
// WebConfigFile in the FlagConfig, TLS or basic auth could be enabled.
func Serve(l net.Listener, server *http.Server, flags *FlagConfig, logger log.Logger) error {
Expand Down

0 comments on commit e772fca

Please sign in to comment.