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
This commit is contained in:
Aliaksandr Valialkin 2020-04-24 14:33:16 +03:00
parent 00e897119f
commit 24461153bf
4 changed files with 119 additions and 15 deletions

View file

@ -9,13 +9,9 @@ import (
// getEndpointsLabels returns labels for k8s endpoints obtained from the given cfg. // getEndpointsLabels returns labels for k8s endpoints obtained from the given cfg.
func getEndpointsLabels(cfg *apiConfig) ([]map[string]string, error) { func getEndpointsLabels(cfg *apiConfig) ([]map[string]string, error) {
data, err := getAPIResponse(cfg, "endpoints", "/api/v1/endpoints") eps, err := getEndpoints(cfg)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot obtain endpoints data from API server: %s", err) return nil, err
}
epl, err := parseEndpointsList(data)
if err != nil {
return nil, fmt.Errorf("cannot parse endpoints response from API server: %s", err)
} }
pods, err := getPods(cfg) pods, err := getPods(cfg)
if err != nil { if err != nil {
@ -26,12 +22,46 @@ func getEndpointsLabels(cfg *apiConfig) ([]map[string]string, error) {
return nil, err return nil, err
} }
var ms []map[string]string var ms []map[string]string
for _, ep := range epl.Items { for _, ep := range eps {
ms = ep.appendTargetLabels(ms, pods, svcs) ms = ep.appendTargetLabels(ms, pods, svcs)
} }
return ms, nil 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. // EndpointsList implements k8s endpoints list.
// //
// See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#endpointslist-v1-core // See https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#endpointslist-v1-core

View file

@ -7,7 +7,41 @@ import (
// getIngressesLabels returns labels for k8s ingresses obtained from the given cfg. // getIngressesLabels returns labels for k8s ingresses obtained from the given cfg.
func getIngressesLabels(cfg *apiConfig) ([]map[string]string, error) { 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 { if err != nil {
return nil, fmt.Errorf("cannot obtain ingresses data from API server: %s", err) 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 { if err != nil {
return nil, fmt.Errorf("cannot parse ingresses response from API server: %s", err) return nil, fmt.Errorf("cannot parse ingresses response from API server: %s", err)
} }
var ms []map[string]string return igl.Items, nil
for _, ig := range igl.Items {
ms = ig.appendTargetLabels(ms)
}
return ms, nil
} }
// IngressList represents ingress list in k8s. // IngressList represents ingress list in k8s.

View file

@ -23,7 +23,29 @@ func getPodsLabels(cfg *apiConfig) ([]map[string]string, error) {
} }
func getPods(cfg *apiConfig) ([]Pod, 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 { if err != nil {
return nil, fmt.Errorf("cannot obtain pods data from API server: %s", err) return nil, fmt.Errorf("cannot obtain pods data from API server: %s", err)
} }

View file

@ -21,7 +21,29 @@ func getServicesLabels(cfg *apiConfig) ([]map[string]string, error) {
} }
func getServices(cfg *apiConfig) ([]Service, 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 { if err != nil {
return nil, fmt.Errorf("cannot obtain services data from API server: %s", err) return nil, fmt.Errorf("cannot obtain services data from API server: %s", err)
} }