mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2025-01-10 15:14:09 +00:00
lib/promscrape/discovery/kubernetes/: unify apiConfig creation
This commit is contained in:
parent
54414fefef
commit
c50fd219dc
7 changed files with 101 additions and 95 deletions
|
@ -301,12 +301,7 @@ type scrapeWorkConfig struct {
|
|||
}
|
||||
|
||||
func appendKubernetesScrapeWork(dst []ScrapeWork, sdc *kubernetes.SDConfig, baseDir string, swc *scrapeWorkConfig) []ScrapeWork {
|
||||
ac, err := promauth.NewConfig(baseDir, sdc.BasicAuth, sdc.BearerToken, sdc.BearerTokenFile, sdc.TLSConfig)
|
||||
if err != nil {
|
||||
logger.Errorf("cannot parse auth config for `kubernetes_sd_config` for `job_name` %q: %s; skipping it", swc.jobName, err)
|
||||
return dst
|
||||
}
|
||||
targetLabels, err := kubernetes.GetLabels(ac, sdc)
|
||||
targetLabels, err := kubernetes.GetLabels(sdc, baseDir)
|
||||
if err != nil {
|
||||
logger.Errorf("error when discovering kubernetes nodes for `job_name` %q: %s; skipping it", swc.jobName, err)
|
||||
return dst
|
||||
|
|
|
@ -16,34 +16,101 @@ import (
|
|||
|
||||
// apiConfig contains config for API server
|
||||
type apiConfig struct {
|
||||
Server string
|
||||
AuthConfig *promauth.Config
|
||||
Namespaces []string
|
||||
Selectors []Selector
|
||||
client *fasthttp.HostClient
|
||||
server string
|
||||
hostPort string
|
||||
authConfig *promauth.Config
|
||||
namespaces []string
|
||||
selectors []Selector
|
||||
}
|
||||
|
||||
func getAPIResponse(cfg *apiConfig, role, path string) ([]byte, error) {
|
||||
hcv, err := getHostClient(cfg.Server, cfg.AuthConfig)
|
||||
func getAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
|
||||
apiConfigMapLock.Lock()
|
||||
defer apiConfigMapLock.Unlock()
|
||||
|
||||
if !hasAPIConfigMapCleaner {
|
||||
hasAPIConfigMapCleaner = true
|
||||
go apiConfigMapCleaner()
|
||||
}
|
||||
|
||||
e := apiConfigMap[sdc]
|
||||
if e != nil {
|
||||
e.lastAccessTime = time.Now()
|
||||
return e.cfg, nil
|
||||
}
|
||||
cfg, err := newAPIConfig(sdc, baseDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
query := joinSelectors(role, cfg.Namespaces, cfg.Selectors)
|
||||
apiConfigMap[sdc] = &apiConfigMapEntry{
|
||||
cfg: cfg,
|
||||
lastAccessTime: time.Now(),
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func apiConfigMapCleaner() {
|
||||
tc := time.NewTicker(15 * time.Minute)
|
||||
for currentTime := range tc.C {
|
||||
apiConfigMapLock.Lock()
|
||||
for k, e := range apiConfigMap {
|
||||
if currentTime.Sub(e.lastAccessTime) > 10*time.Minute {
|
||||
delete(apiConfigMap, k)
|
||||
}
|
||||
}
|
||||
apiConfigMapLock.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
type apiConfigMapEntry struct {
|
||||
cfg *apiConfig
|
||||
lastAccessTime time.Time
|
||||
}
|
||||
|
||||
var (
|
||||
apiConfigMap = make(map[*SDConfig]*apiConfigMapEntry)
|
||||
apiConfigMapLock sync.Mutex
|
||||
hasAPIConfigMapCleaner bool
|
||||
)
|
||||
|
||||
func newAPIConfig(sdc *SDConfig, baseDir string) (*apiConfig, error) {
|
||||
ac, err := promauth.NewConfig(baseDir, sdc.BasicAuth, sdc.BearerToken, sdc.BearerTokenFile, sdc.TLSConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse auth config: %s", err)
|
||||
}
|
||||
hcv, err := newHostClient(sdc.APIServer, ac)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create HTTP client for %q: %s", sdc.APIServer, err)
|
||||
}
|
||||
cfg := &apiConfig{
|
||||
client: hcv.hc,
|
||||
server: hcv.apiServer,
|
||||
hostPort: hcv.hostPort,
|
||||
authConfig: hcv.ac,
|
||||
namespaces: sdc.Namespaces.Names,
|
||||
selectors: sdc.Selectors,
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func getAPIResponse(cfg *apiConfig, role, path string) ([]byte, error) {
|
||||
query := joinSelectors(role, cfg.namespaces, cfg.selectors)
|
||||
if len(query) > 0 {
|
||||
path += "?" + query
|
||||
}
|
||||
requestURL := hcv.apiServer + path
|
||||
requestURL := cfg.server + path
|
||||
var u fasthttp.URI
|
||||
u.Update(requestURL)
|
||||
var req fasthttp.Request
|
||||
req.SetRequestURIBytes(u.RequestURI())
|
||||
req.SetHost(hcv.hostPort)
|
||||
req.SetHost(cfg.hostPort)
|
||||
req.Header.Set("Accept-Encoding", "gzip")
|
||||
if hcv.ac != nil && hcv.ac.Authorization != "" {
|
||||
req.Header.Set("Authorization", hcv.ac.Authorization)
|
||||
if cfg.authConfig != nil && cfg.authConfig.Authorization != "" {
|
||||
req.Header.Set("Authorization", cfg.authConfig.Authorization)
|
||||
}
|
||||
var resp fasthttp.Response
|
||||
// There is no need in calling DoTimeout, since the timeout is already set in hc.ReadTimeout above.
|
||||
if err := hcv.hc.Do(&req, &resp); err != nil {
|
||||
if err := cfg.client.Do(&req, &resp); err != nil {
|
||||
return nil, fmt.Errorf("cannot fetch %q: %s", requestURL, err)
|
||||
}
|
||||
var data []byte
|
||||
|
@ -64,67 +131,13 @@ func getAPIResponse(cfg *apiConfig, role, path string) ([]byte, error) {
|
|||
return data, nil
|
||||
}
|
||||
|
||||
func getHostClient(apiServer string, ac *promauth.Config) (*hcValue, error) {
|
||||
if len(apiServer) == 0 {
|
||||
// ac is ignored when apiServer should be auto-discovered when running inside k8s pod.
|
||||
ac = nil
|
||||
}
|
||||
k := hcKey{
|
||||
apiServer: apiServer,
|
||||
ac: ac,
|
||||
}
|
||||
hcMapLock.Lock()
|
||||
defer hcMapLock.Unlock()
|
||||
|
||||
if !hasHCMapCleaner {
|
||||
go hcMapCleaner()
|
||||
hasHCMapCleaner = true
|
||||
}
|
||||
hcv := hcMap[k]
|
||||
if hcv == nil {
|
||||
hcvNew, err := newHostClient(apiServer, ac)
|
||||
if err != nil {
|
||||
return hcv, fmt.Errorf("cannot create new HTTP client for %q: %s", apiServer, err)
|
||||
}
|
||||
hcMap[k] = hcvNew
|
||||
hcv = hcvNew
|
||||
}
|
||||
hcv.lastAccessTime = time.Now()
|
||||
return hcv, nil
|
||||
}
|
||||
|
||||
func hcMapCleaner() {
|
||||
tc := time.NewTicker(15 * time.Minute)
|
||||
for currentTime := range tc.C {
|
||||
hcMapLock.Lock()
|
||||
for k, v := range hcMap {
|
||||
if currentTime.Sub(v.lastAccessTime) > 10*time.Minute {
|
||||
delete(hcMap, k)
|
||||
}
|
||||
}
|
||||
hcMapLock.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
type hcKey struct {
|
||||
apiServer string
|
||||
ac *promauth.Config
|
||||
}
|
||||
|
||||
type hcValue struct {
|
||||
hc *fasthttp.HostClient
|
||||
ac *promauth.Config
|
||||
apiServer string
|
||||
hostPort string
|
||||
lastAccessTime time.Time
|
||||
hc *fasthttp.HostClient
|
||||
ac *promauth.Config
|
||||
apiServer string
|
||||
hostPort string
|
||||
}
|
||||
|
||||
var (
|
||||
hasHCMapCleaner bool
|
||||
hcMap = make(map[hcKey]*hcValue)
|
||||
hcMapLock sync.Mutex
|
||||
)
|
||||
|
||||
func newHostClient(apiServer string, ac *promauth.Config) (*hcValue, error) {
|
||||
if len(apiServer) == 0 {
|
||||
// Assume we run at k8s pod.
|
||||
|
|
|
@ -29,14 +29,14 @@ func getEndpointsLabels(cfg *apiConfig) ([]map[string]string, error) {
|
|||
}
|
||||
|
||||
func getEndpoints(cfg *apiConfig) ([]Endpoints, error) {
|
||||
if len(cfg.Namespaces) == 0 {
|
||||
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
|
||||
namespaces := cfgCopy.namespaces
|
||||
cfgCopy.namespaces = nil
|
||||
cfg = &cfgCopy
|
||||
var result []Endpoints
|
||||
for _, ns := range namespaces {
|
||||
|
|
|
@ -19,14 +19,14 @@ func getIngressesLabels(cfg *apiConfig) ([]map[string]string, error) {
|
|||
}
|
||||
|
||||
func getIngresses(cfg *apiConfig) ([]Ingress, error) {
|
||||
if len(cfg.Namespaces) == 0 {
|
||||
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
|
||||
namespaces := cfgCopy.namespaces
|
||||
cfgCopy.namespaces = nil
|
||||
cfg = &cfgCopy
|
||||
var result []Ingress
|
||||
for _, ns := range namespaces {
|
||||
|
|
|
@ -35,13 +35,11 @@ type Selector struct {
|
|||
Field string `yaml:"field"`
|
||||
}
|
||||
|
||||
// GetLabels returns labels for the given k8s role and the given ac and sdc.
|
||||
func GetLabels(ac *promauth.Config, sdc *SDConfig) ([]map[string]string, error) {
|
||||
cfg := &apiConfig{
|
||||
Server: sdc.APIServer,
|
||||
AuthConfig: ac,
|
||||
Namespaces: sdc.Namespaces.Names,
|
||||
Selectors: sdc.Selectors,
|
||||
// GetLabels returns labels for the given sdc and baseDir.
|
||||
func GetLabels(sdc *SDConfig, baseDir string) ([]map[string]string, error) {
|
||||
cfg, err := getAPIConfig(sdc, baseDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create API config: %s", err)
|
||||
}
|
||||
switch sdc.Role {
|
||||
case "node":
|
||||
|
|
|
@ -23,14 +23,14 @@ func getPodsLabels(cfg *apiConfig) ([]map[string]string, error) {
|
|||
}
|
||||
|
||||
func getPods(cfg *apiConfig) ([]Pod, error) {
|
||||
if len(cfg.Namespaces) == 0 {
|
||||
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
|
||||
namespaces := cfgCopy.namespaces
|
||||
cfgCopy.namespaces = nil
|
||||
cfg = &cfgCopy
|
||||
var result []Pod
|
||||
for _, ns := range namespaces {
|
||||
|
|
|
@ -21,14 +21,14 @@ func getServicesLabels(cfg *apiConfig) ([]map[string]string, error) {
|
|||
}
|
||||
|
||||
func getServices(cfg *apiConfig) ([]Service, error) {
|
||||
if len(cfg.Namespaces) == 0 {
|
||||
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
|
||||
namespaces := cfgCopy.namespaces
|
||||
cfgCopy.namespaces = nil
|
||||
cfg = &cfgCopy
|
||||
var result []Service
|
||||
for _, ns := range namespaces {
|
||||
|
|
Loading…
Reference in a new issue