Skip to content

Commit

Permalink
resolve issue #56 (#62)
Browse files Browse the repository at this point in the history
* resolve issue #56

* quick fix of CA x509 issue

* fix the error loading CA file

---------

Co-authored-by: root <[email protected]>
  • Loading branch information
wangchen615 and root authored May 16, 2023
1 parent 82e4048 commit 522b9d3
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 35 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
Expand Down
46 changes: 46 additions & 0 deletions manifests/load-watcher-deployment.yaml
Original file line number Diff line number Diff line change
@@ -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
54 changes: 20 additions & 34 deletions pkg/watcher/internal/metricsprovider/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand All @@ -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)
Expand All @@ -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(
Expand All @@ -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,
},
},
Expand Down

0 comments on commit 522b9d3

Please sign in to comment.