From b684624f67389100dc14549a8bf8130cdb654804 Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Mon, 13 Sep 2021 13:30:13 +0300 Subject: [PATCH] lib/promscrape/discovery/docker: support host networking mode See https://github.com/prometheus/prometheus/issues/9116 --- docs/CHANGELOG.md | 1 + lib/promscrape/discovery/docker/api.go | 14 ++- lib/promscrape/discovery/docker/container.go | 10 +- .../discovery/docker/container_test.go | 114 +++++++++++++++++- lib/promscrape/discovery/docker/docker.go | 7 +- 5 files changed, 135 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 59cdb9e770..d60871f64d 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -21,6 +21,7 @@ sort: 15 * BUGFIX: vmselect: reset connection timeouts after each request to `vmstorage`. This should prevent from `cannot read data in 0.000 seconds: unexpected EOF` warning in logs. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1562). Thanks to @mxlxm . * BUGFIX: keep metric name for time series returned from [rollup_candlestick](https://docs.victoriametrics.com/MetricsQL.html#rollup_candlestick) function, since the returned series don't change the meaning of the original series. See [this issue](https://github.com/VictoriaMetrics/VictoriaMetrics/issues/1600). * BUGFIX: vmagent: properly use `https` scheme for wildcard TLS certificates for `role: ingress` targets in Kubernetes service discovery. See [this issue](https://github.com/prometheus/prometheus/issues/8902). +* BUGFIX: vmagent: support host networking mode for `docker_sd_config`. See [this issue](https://github.com/prometheus/prometheus/issues/9116). ## [v1.65.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.65.0) diff --git a/lib/promscrape/discovery/docker/api.go b/lib/promscrape/discovery/docker/api.go index f2c76be3b9..e09d063ab9 100644 --- a/lib/promscrape/discovery/docker/api.go +++ b/lib/promscrape/discovery/docker/api.go @@ -13,8 +13,9 @@ import ( var configMap = discoveryutils.NewConfigMap() type apiConfig struct { - client *discoveryutils.Client - port int + client *discoveryutils.Client + port int + hostNetworkingHost string // filtersQueryArg contains escaped `filters` query arg to add to each request to Docker Swarm API. filtersQueryArg string @@ -29,9 +30,14 @@ func getAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) { } func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) { + hostNetworkingHost := sdc.HostNetworkingHost + if hostNetworkingHost == "" { + hostNetworkingHost = "localhost" + } cfg := &apiConfig{ - port: sdc.Port, - filtersQueryArg: getFiltersQueryArg(sdc.Filters), + port: sdc.Port, + hostNetworkingHost: hostNetworkingHost, + filtersQueryArg: getFiltersQueryArg(sdc.Filters), } if cfg.port == 0 { cfg.port = 80 diff --git a/lib/promscrape/discovery/docker/container.go b/lib/promscrape/discovery/docker/container.go index fd727f2594..a8ff92f8ba 100644 --- a/lib/promscrape/discovery/docker/container.go +++ b/lib/promscrape/discovery/docker/container.go @@ -39,7 +39,7 @@ func getContainersLabels(cfg *apiConfig) ([]map[string]string, error) { if err != nil { return nil, err } - return addContainersLabels(containers, networkLabels, cfg.port), nil + return addContainersLabels(containers, networkLabels, cfg.port, cfg.hostNetworkingHost), nil } func getContainers(cfg *apiConfig) ([]container, error) { @@ -58,7 +58,7 @@ func parseContainers(data []byte) ([]container, error) { return containers, nil } -func addContainersLabels(containers []container, networkLabels map[string]map[string]string, defaultPort int) []map[string]string { +func addContainersLabels(containers []container, networkLabels map[string]map[string]string, defaultPort int, hostNetworkingHost string) []map[string]string { var ms []map[string]string for i := range containers { c := &containers[i] @@ -86,8 +86,12 @@ func addContainersLabels(containers []container, networkLabels map[string]map[st } if !added { // Use fallback port when no exposed ports are available or if all are non-TCP + addr := hostNetworkingHost + if c.HostConfig.NetworkMode != "host" { + addr = discoveryutils.JoinHostPort(n.IPAddress, defaultPort) + } m := map[string]string{ - "__address__": discoveryutils.JoinHostPort(n.IPAddress, defaultPort), + "__address__": addr, "__meta_docker_network_ip": n.IPAddress, } addCommonLabels(m, c, networkLabels[n.NetworkID]) diff --git a/lib/promscrape/discovery/docker/container_test.go b/lib/promscrape/discovery/docker/container_test.go index 62fe342d91..95785a8415 100644 --- a/lib/promscrape/discovery/docker/container_test.go +++ b/lib/promscrape/discovery/docker/container_test.go @@ -317,6 +317,118 @@ func Test_addContainerLabels(t *testing.T) { want []map[string]string wantErr bool }{ + { + name: "NetworkMode!=host", + c: container{ + ID: "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700", + Names: []string{"/crow-server"}, + Labels: map[string]string{ + "com.docker.compose.config-hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec", + "com.docker.compose.container-number": "1", + "com.docker.compose.oneoff": "False", + "com.docker.compose.project": "crowserver", + "com.docker.compose.service": "crow-server", + "com.docker.compose.version": "1.11.2", + }, + HostConfig: struct { + NetworkMode string + }{ + NetworkMode: "bridge", + }, + NetworkSettings: struct { + Networks map[string]struct { + IPAddress string + NetworkID string + } + }{ + Networks: map[string]struct { + IPAddress string + NetworkID string + }{ + "host": { + IPAddress: "172.17.0.2", + NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634", + }, + }, + }, + }, + want: []map[string]string{ + { + "__address__": "172.17.0.2:8012", + "__meta_docker_container_id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700", + "__meta_docker_container_label_com_docker_compose_config_hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec", + "__meta_docker_container_label_com_docker_compose_container_number": "1", + "__meta_docker_container_label_com_docker_compose_oneoff": "False", + "__meta_docker_container_label_com_docker_compose_project": "crowserver", + "__meta_docker_container_label_com_docker_compose_service": "crow-server", + "__meta_docker_container_label_com_docker_compose_version": "1.11.2", + "__meta_docker_container_name": "/crow-server", + "__meta_docker_container_network_mode": "bridge", + "__meta_docker_network_id": "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634", + "__meta_docker_network_ingress": "false", + "__meta_docker_network_internal": "false", + "__meta_docker_network_ip": "172.17.0.2", + "__meta_docker_network_name": "bridge", + "__meta_docker_network_scope": "local", + }, + }, + }, + { + name: "NetworkMode=host", + c: container{ + ID: "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700", + Names: []string{"/crow-server"}, + Labels: map[string]string{ + "com.docker.compose.config-hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec", + "com.docker.compose.container-number": "1", + "com.docker.compose.oneoff": "False", + "com.docker.compose.project": "crowserver", + "com.docker.compose.service": "crow-server", + "com.docker.compose.version": "1.11.2", + }, + HostConfig: struct { + NetworkMode string + }{ + NetworkMode: "host", + }, + NetworkSettings: struct { + Networks map[string]struct { + IPAddress string + NetworkID string + } + }{ + Networks: map[string]struct { + IPAddress string + NetworkID string + }{ + "host": { + IPAddress: "172.17.0.2", + NetworkID: "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634", + }, + }, + }, + }, + want: []map[string]string{ + { + "__address__": "foobar", + "__meta_docker_container_id": "90bc3b31aa13da5c0b11af2e228d54b38428a84e25d4e249ae9e9c95e51a0700", + "__meta_docker_container_label_com_docker_compose_config_hash": "c9f0bd5bb31921f94cff367d819a30a0cc08d4399080897a6c5cd74b983156ec", + "__meta_docker_container_label_com_docker_compose_container_number": "1", + "__meta_docker_container_label_com_docker_compose_oneoff": "False", + "__meta_docker_container_label_com_docker_compose_project": "crowserver", + "__meta_docker_container_label_com_docker_compose_service": "crow-server", + "__meta_docker_container_label_com_docker_compose_version": "1.11.2", + "__meta_docker_container_name": "/crow-server", + "__meta_docker_container_network_mode": "host", + "__meta_docker_network_id": "1dd8d1a8bef59943345c7231d7ce8268333ff5a8c5b3c94881e6b4742b447634", + "__meta_docker_network_ingress": "false", + "__meta_docker_network_internal": "false", + "__meta_docker_network_ip": "172.17.0.2", + "__meta_docker_network_name": "bridge", + "__meta_docker_network_scope": "local", + }, + }, + }, { name: "get labels from a container", c: container{ @@ -391,7 +503,7 @@ func Test_addContainerLabels(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - labelsMap := addContainersLabels([]container{tt.c}, networkLabels, 80) + labelsMap := addContainersLabels([]container{tt.c}, networkLabels, 8012, "foobar") if (err != nil) != tt.wantErr { t.Errorf("addContainersLabels() error = %v, wantErr %v", err, tt.wantErr) return diff --git a/lib/promscrape/discovery/docker/docker.go b/lib/promscrape/discovery/docker/docker.go index e0589abb39..70fe913be7 100644 --- a/lib/promscrape/discovery/docker/docker.go +++ b/lib/promscrape/discovery/docker/docker.go @@ -18,9 +18,10 @@ var SDCheckInterval = flag.Duration("promscrape.dockerSDCheckInterval", 30*time. // // See https://prometheus.io/docs/prometheus/latest/configuration/configuration/#docker_sd_config type SDConfig struct { - Host string `yaml:"host"` - Port int `yaml:"port,omitempty"` - Filters []Filter `yaml:"filters,omitempty"` + Host string `yaml:"host"` + Port int `yaml:"port,omitempty"` + Filters []Filter `yaml:"filters,omitempty"` + HostNetworkingHost string `yaml:"host_networking_host,omitempty"` HTTPClientConfig promauth.HTTPClientConfig `yaml:",inline"` ProxyURL proxy.URL `yaml:"proxy_url,omitempty"`