From 24461153bffb133676f92693cf5ae8645e1719ad Mon Sep 17 00:00:00 2001 From: Aliaksandr Valialkin Date: Fri, 24 Apr 2020 14:33:16 +0300 Subject: [PATCH] lib/promscrape: query `/api/v1/namespaces/*` for the configured namespaces in `kubernetes_sd_config` This should fix authroization issues described at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/432 --- .../discovery/kubernetes/endpoints.go | 44 ++++++++++++++++--- .../discovery/kubernetes/ingress.go | 42 +++++++++++++++--- lib/promscrape/discovery/kubernetes/pod.go | 24 +++++++++- .../discovery/kubernetes/service.go | 24 +++++++++- 4 files changed, 119 insertions(+), 15 deletions(-) diff --git a/lib/promscrape/discovery/kubernetes/endpoints.go b/lib/promscrape/discovery/kubernetes/endpoints.go index 7a7e0d6b7..9d48b7e09 100644 --- a/lib/promscrape/discovery/kubernetes/endpoints.go +++ b/lib/promscrape/discovery/kubernetes/endpoints.go @@ -9,13 +9,9 @@ import ( // getEndpointsLabels returns labels for k8s endpoints obtained from the given cfg. func getEndpointsLabels(cfg *apiConfig) ([]map[string]string, error) { - data, err := getAPIResponse(cfg, "endpoints", "/api/v1/endpoints") + eps, err := getEndpoints(cfg) if err != nil { - return nil, fmt.Errorf("cannot obtain endpoints data from API server: %s", err) - } - epl, err := parseEndpointsList(data) - if err != nil { - return nil, fmt.Errorf("cannot parse endpoints response from API server: %s", err) + return nil, err } pods, err := getPods(cfg) if err != nil { @@ -26,12 +22,46 @@ func getEndpointsLabels(cfg *apiConfig) ([]map[string]string, error) { return nil, err } var ms []map[string]string - for _, ep := range epl.Items { + for _, ep := range eps { ms = ep.appendTargetLabels(ms, pods, svcs) } return ms, nil } +func getEndpoints(cfg *apiConfig) ([]Endpoints, error) { + if len(cfg.Namespaces) == 0 { + return getEndpointsByPath(cfg, "/api/v1/endpoints") + } + // Query /api/v1/namespaces/* for each namespace. + // This fixes authorization issue at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/432 + cfgCopy := *cfg + namespaces := cfgCopy.Namespaces + cfgCopy.Namespaces = nil + cfg = &cfgCopy + var result []Endpoints + for _, ns := range namespaces { + path := fmt.Sprintf("/api/v1/namespaces/%s/endpoints", ns) + eps, err := getEndpointsByPath(cfg, path) + if err != nil { + return nil, err + } + result = append(result, eps...) + } + return result, nil +} + +func getEndpointsByPath(cfg *apiConfig, path string) ([]Endpoints, error) { + data, err := getAPIResponse(cfg, "endpoints", path) + if err != nil { + return nil, fmt.Errorf("cannot obtain endpoints data from API server: %s", err) + } + epl, err := parseEndpointsList(data) + if err != nil { + return nil, fmt.Errorf("cannot parse endpoints response from API server: %s", err) + } + return epl.Items, nil +} + // EndpointsList implements k8s endpoints list. // // See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#endpointslist-v1-core diff --git a/lib/promscrape/discovery/kubernetes/ingress.go b/lib/promscrape/discovery/kubernetes/ingress.go index 322e19e90..c90035913 100644 --- a/lib/promscrape/discovery/kubernetes/ingress.go +++ b/lib/promscrape/discovery/kubernetes/ingress.go @@ -7,7 +7,41 @@ import ( // getIngressesLabels returns labels for k8s ingresses obtained from the given cfg. func getIngressesLabels(cfg *apiConfig) ([]map[string]string, error) { - data, err := getAPIResponse(cfg, "ingress", "/apis/extensions/v1beta1/ingresses") + igs, err := getIngresses(cfg) + if err != nil { + return nil, err + } + var ms []map[string]string + for _, ig := range igs { + ms = ig.appendTargetLabels(ms) + } + return ms, nil +} + +func getIngresses(cfg *apiConfig) ([]Ingress, error) { + if len(cfg.Namespaces) == 0 { + return getIngressesByPath(cfg, "/apis/extensions/v1beta1/ingresses") + } + // Query /api/v1/namespaces/* for each namespace. + // This fixes authorization issue at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/432 + cfgCopy := *cfg + namespaces := cfgCopy.Namespaces + cfgCopy.Namespaces = nil + cfg = &cfgCopy + var result []Ingress + for _, ns := range namespaces { + path := fmt.Sprintf("/apis/extensions/v1beta1/namespaces/%s/ingresses", ns) + igs, err := getIngressesByPath(cfg, path) + if err != nil { + return nil, err + } + result = append(result, igs...) + } + return result, nil +} + +func getIngressesByPath(cfg *apiConfig, path string) ([]Ingress, error) { + data, err := getAPIResponse(cfg, "ingress", path) if err != nil { return nil, fmt.Errorf("cannot obtain ingresses data from API server: %s", err) } @@ -15,11 +49,7 @@ func getIngressesLabels(cfg *apiConfig) ([]map[string]string, error) { if err != nil { return nil, fmt.Errorf("cannot parse ingresses response from API server: %s", err) } - var ms []map[string]string - for _, ig := range igl.Items { - ms = ig.appendTargetLabels(ms) - } - return ms, nil + return igl.Items, nil } // IngressList represents ingress list in k8s. diff --git a/lib/promscrape/discovery/kubernetes/pod.go b/lib/promscrape/discovery/kubernetes/pod.go index 3602ff154..3220faab3 100644 --- a/lib/promscrape/discovery/kubernetes/pod.go +++ b/lib/promscrape/discovery/kubernetes/pod.go @@ -23,7 +23,29 @@ func getPodsLabels(cfg *apiConfig) ([]map[string]string, error) { } func getPods(cfg *apiConfig) ([]Pod, error) { - data, err := getAPIResponse(cfg, "pod", "/api/v1/pods") + if len(cfg.Namespaces) == 0 { + return getPodsByPath(cfg, "/api/v1/pods") + } + // Query /api/v1/namespaces/* for each namespace. + // This fixes authorization issue at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/432 + cfgCopy := *cfg + namespaces := cfgCopy.Namespaces + cfgCopy.Namespaces = nil + cfg = &cfgCopy + var result []Pod + for _, ns := range namespaces { + path := fmt.Sprintf("/api/v1/namespaces/%s/pods", ns) + pods, err := getPodsByPath(cfg, path) + if err != nil { + return nil, err + } + result = append(result, pods...) + } + return result, nil +} + +func getPodsByPath(cfg *apiConfig, path string) ([]Pod, error) { + data, err := getAPIResponse(cfg, "pod", path) if err != nil { return nil, fmt.Errorf("cannot obtain pods data from API server: %s", err) } diff --git a/lib/promscrape/discovery/kubernetes/service.go b/lib/promscrape/discovery/kubernetes/service.go index ec4f02064..53c69172b 100644 --- a/lib/promscrape/discovery/kubernetes/service.go +++ b/lib/promscrape/discovery/kubernetes/service.go @@ -21,7 +21,29 @@ func getServicesLabels(cfg *apiConfig) ([]map[string]string, error) { } func getServices(cfg *apiConfig) ([]Service, error) { - data, err := getAPIResponse(cfg, "service", "/api/v1/services") + if len(cfg.Namespaces) == 0 { + return getServicesByPath(cfg, "/api/v1/services") + } + // Query /api/v1/namespaces/* for each namespace. + // This fixes authorization issue at https://github.com/VictoriaMetrics/VictoriaMetrics/issues/432 + cfgCopy := *cfg + namespaces := cfgCopy.Namespaces + cfgCopy.Namespaces = nil + cfg = &cfgCopy + var result []Service + for _, ns := range namespaces { + path := fmt.Sprintf("/api/v1/namespaces/%s/services", ns) + svcs, err := getServicesByPath(cfg, path) + if err != nil { + return nil, err + } + result = append(result, svcs...) + } + return result, nil +} + +func getServicesByPath(cfg *apiConfig, path string) ([]Service, error) { + data, err := getAPIResponse(cfg, "service", path) if err != nil { return nil, fmt.Errorf("cannot obtain services data from API server: %s", err) }