From 522b9d33ad74254e711dc27b6dce349e25019fc1 Mon Sep 17 00:00:00 2001 From: Chen Wang Date: Tue, 16 May 2023 09:37:10 -0700 Subject: [PATCH] resolve issue #56 (#62) * resolve issue #56 * quick fix of CA x509 issue * fix the error loading CA file --------- Co-authored-by: root --- README.md | 2 +- manifests/load-watcher-deployment.yaml | 46 ++++++++++++++++ .../internal/metricsprovider/prometheus.go | 54 +++++++------------ 3 files changed, 67 insertions(+), 35 deletions(-) create mode 100644 manifests/load-watcher-deployment.yaml diff --git a/README.md b/README.md index 9a9d7bb..30d15a4 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ This will return metrics for all nodes. A query parameter to filter by host can - To use the SignalFx client, please configure environment variables `METRICS_PROVIDER_NAME`, `METRICS_PROVIDER_ADDRESS` and `METRICS_PROVIDER_TOKEN` to `SignalFx`, SignalFx address and auth token respectively. Default value of address set is `https://api.signalfx.com` for SignalFx client. ## Deploy `load-watcher` as a service -To deploy `load-watcher` as a monitoring service in your Kubernetes cluster, you can run the following. +To deploy `load-watcher` as a monitoring service in your Kubernetes cluster, you should replace the values in the `[]` with your own cluster monitoring stack and then you can run the following. ```bash > kubectl create -f manifests/load-watcher-deployment.yaml ``` diff --git a/manifests/load-watcher-deployment.yaml b/manifests/load-watcher-deployment.yaml new file mode 100644 index 0000000..5c0063d --- /dev/null +++ b/manifests/load-watcher-deployment.yaml @@ -0,0 +1,46 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: load-watcher-deployment + namespace: loadwatcher + labels: + app: load-watcher +spec: + replicas: 1 + selector: + matchLabels: + app: load-watcher + template: + metadata: + labels: + app: load-watcher + spec: + containers: + - name: load-watcher + image: [load-watcher image] + env: + - name: METRICS_PROVIDER_NAME + value: [Prometheus/SignalFx] + - name: METRICS_PROVIDER_ADDRESS + value: [metrics_provider_endpoint] + - name: METRICS_PROVIDER_TOKEN + value: [token] + ports: + - containerPort: 2020 +--- +apiVersion: v1 +kind: Service +metadata: + namespace: loadwatcher + name: load-watcher + labels: + app: load-watcher +spec: + type: ClusterIP + ports: + - name: http + port: 2020 + targetPort: 2020 + protocol: TCP + selector: + app: load-watcher diff --git a/pkg/watcher/internal/metricsprovider/prometheus.go b/pkg/watcher/internal/metricsprovider/prometheus.go index 87800cc..a2b7406 100644 --- a/pkg/watcher/internal/metricsprovider/prometheus.go +++ b/pkg/watcher/internal/metricsprovider/prometheus.go @@ -21,10 +21,7 @@ import ( "crypto/tls" "crypto/x509" "fmt" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" + "io/ioutil" "k8s.io/client-go/transport" "net" "net/http" @@ -44,6 +41,7 @@ import ( const ( EnableOpenShiftAuth = "ENABLE_OPENSHIFT_AUTH" + K8sPodCAFilePath = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" DefaultPromAddress = "http://prometheus-k8s:9090" promStd = "stddev_over_time" promAvg = "avg_over_time" @@ -56,13 +54,26 @@ const ( promDiskIOMetric = "instance_device:node_disk_io_time_seconds:rate5m" allHosts = "all" hostMetricKey = "instance" - defaultKubeConfig = "~/.kube/config" ) type promClient struct { client api.Client } +func loadCAFile(filepath string) (*x509.CertPool, error) { + caCert, err := ioutil.ReadFile(filepath) + if err != nil { + return nil, err + } + + caCertPool := x509.NewCertPool() + if ok := caCertPool.AppendCertsFromPEM(caCert); !ok { + return nil, fmt.Errorf("failed to append CA certificate to the pool") + } + + return caCertPool, nil +} + func NewPromClient(opts watcher.MetricsProviderOpts) (watcher.MetricsProviderClient, error) { if opts.Name != watcher.PromClientName { return nil, fmt.Errorf("metric provider name should be %v, found %v", watcher.PromClientName, opts.Name) @@ -84,37 +95,12 @@ func NewPromClient(opts watcher.MetricsProviderOpts) (watcher.MetricsProviderCli // Check if EnableOpenShiftAuth is set. _, enableOpenShiftAuth := os.LookupEnv(EnableOpenShiftAuth) if enableOpenShiftAuth { - // Create the config for kubernetes client - clusterConfig, err := rest.InClusterConfig() - if err != nil { - // Get the kubeconfig path - kubeConfigPath, ok := os.LookupEnv(kubeConfig) - if !ok { - kubeConfigPath = defaultKubeConfig - } - clusterConfig, err = clientcmd.BuildConfigFromFlags("", kubeConfigPath) - if err != nil { - return nil, fmt.Errorf("failed to get kubernetes config: %v", err) - } - } - - // Create the client for kubernetes - kclient, err := kubernetes.NewForConfig(clusterConfig) + // Retrieve Pod CA cert + caCertPool, err := loadCAFile(K8sPodCAFilePath) if err != nil { - return nil, fmt.Errorf("failed to create kubernetes client: %v", err) + return nil, fmt.Errorf("Error loading CA file: %v", err) } - // Retrieve router CA cert - routerCAConfigMap, err := kclient.CoreV1().ConfigMaps("openshift-config-managed").Get(context.TODO(), "default-ingress-cert", metav1.GetOptions{}) - if err != nil { - return nil, err - } - bundlePEM := []byte(routerCAConfigMap.Data["ca-bundle.crt"]) - - // make a client connection configured with the provided bundle. - roots := x509.NewCertPool() - roots.AppendCertsFromPEM(bundlePEM) - // Get Prometheus Host u, _ := url.Parse(opts.Address) roundTripper = transport.NewBearerAuthRoundTripper( @@ -127,7 +113,7 @@ func NewPromClient(opts watcher.MetricsProviderOpts) (watcher.MetricsProviderCli }).DialContext, TLSHandshakeTimeout: 10 * time.Second, TLSClientConfig: &tls.Config{ - RootCAs: roots, + RootCAs: caCertPool, ServerName: u.Host, }, },