diff --git a/charts/node-readiness-controller/README.md b/charts/node-readiness-controller/README.md index 60eddbfe..2b8b6aef 100644 --- a/charts/node-readiness-controller/README.md +++ b/charts/node-readiness-controller/README.md @@ -11,6 +11,8 @@ helm install my-release --namespace nrr-system --create-namespace ./charts/node- ``` > Published chart releases via `registry.k8s.io` OCI are WIP. +> +> **Note on Secure Metrics and ServiceMonitors:** If you enable secure metrics (`metrics.secure: true`), the Prometheus Operator requires RBAC permissions to scrape the `/metrics` endpoint. This Helm chart does *not* automatically create a `ClusterRoleBinding` for Prometheus. The cluster administrator must manually bind the `metrics-reader` ClusterRole (or equivalent) to the Prometheus ServiceAccount in their monitoring namespace. ## Introduction @@ -93,6 +95,14 @@ The following table lists the configurable parameters of the _node-readiness-con | `metrics.service.targetPort` | The target port for the metrics service | `8443` | | `metrics.certDir` | Directory for metrics server certificates | `/tmp/k8s-metrics-server/metrics-certs` | | `metrics.certSecretName` | Name of the secret containing metrics server certificates | `metrics-server-cert` | +| `metrics.serviceMonitor.enabled` | Deploy a Prometheus Operator ServiceMonitor to scrape metrics (requires `monitoring.coreos.com/v1` CRD installed) | `false` | +| `metrics.serviceMonitor.labels` | Additional labels for the ServiceMonitor | `{}` | +| `metrics.serviceMonitor.interval` | Scrape interval | `30s` | +| `metrics.serviceMonitor.scrapeTimeout` | Scrape timeout | `10s` | +| `metrics.serviceMonitor.bearerTokenFile` | Bearer token file for authenticating with secure metrics endpoints | `""` (defaults to Prometheus token) | +| `metrics.serviceMonitor.tlsConfig` | TLS configuration for scraping secure metrics (e.g. providing a `caFile`) | `{"insecureSkipVerify": true}` | +| `metrics.serviceMonitor.metricRelabelings`| Metric relabeling configs | `[]` | +| `metrics.serviceMonitor.relabelings` | Relabeling configs | `[]` | | `webhook.enabled` | Enable the webhook server | `false` | | `webhook.port` | The port for the webhook server | `9443` | | `webhook.service.port` | The port exposed by the webhook service | `443` | diff --git a/charts/node-readiness-controller/templates/NOTES.txt b/charts/node-readiness-controller/templates/NOTES.txt new file mode 100644 index 00000000..029aeec7 --- /dev/null +++ b/charts/node-readiness-controller/templates/NOTES.txt @@ -0,0 +1,24 @@ +Thanks for installing the {{ template "node-readiness-controller.fullname" . }} chart! + +To verify that the controller pods are running, execute: + kubectl get pods -n {{ .Release.Namespace }} -l app.kubernetes.io/name={{ include "node-readiness-controller.name" . }} + +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +{{- if not (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1") }} + +=================================================================================== +WARNING: Prometheus ServiceMonitor requested but CRD is missing! +=================================================================================== +You have enabled `metrics.serviceMonitor.enabled: true`, but the Kubernetes +API server does not report the `monitoring.coreos.com/v1` API as available. + +The ServiceMonitor resource was NOT created. + +If you are using offline rendering (e.g., `helm template`), this warning is +expected because Helm cannot detect cluster capabilities offline. You can +bypass this warning and force rendering by passing: + --api-versions "monitoring.coreos.com/v1" +=================================================================================== + +{{- end }} +{{- end }} diff --git a/charts/node-readiness-controller/templates/servicemonitor.yaml b/charts/node-readiness-controller/templates/servicemonitor.yaml new file mode 100644 index 00000000..ca7e0b32 --- /dev/null +++ b/charts/node-readiness-controller/templates/servicemonitor.yaml @@ -0,0 +1,45 @@ +{{- if .Values.metrics.serviceMonitor.enabled }} +{{- if not .Values.metrics.enabled }} +{{- fail "You enabled metrics.serviceMonitor.enabled, but metrics.enabled is false. Please enable metrics to use the ServiceMonitor." }} +{{- end }} +{{- if .Capabilities.APIVersions.Has "monitoring.coreos.com/v1" }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "node-readiness-controller.fullname" . }} + namespace: {{ include "node-readiness-controller.namespace" . }} + labels: + {{- include "node-readiness-controller.labels" . | nindent 4 }} + {{- with .Values.metrics.serviceMonitor.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + {{- include "node-readiness-controller.selectorLabels" . | nindent 6 }} + endpoints: + - port: {{ ternary "https" "http" .Values.metrics.secure }} + interval: {{ .Values.metrics.serviceMonitor.interval }} + scrapeTimeout: {{ .Values.metrics.serviceMonitor.scrapeTimeout }} + {{- if .Values.metrics.secure }} + scheme: https + {{- if .Values.metrics.serviceMonitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.metrics.serviceMonitor.bearerTokenFile }} + {{- else }} + bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + {{- end }} + {{- with .Values.metrics.serviceMonitor.tlsConfig }} + tlsConfig: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- with .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.metrics.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} +{{- end }} diff --git a/charts/node-readiness-controller/tests/servicemonitor_test.yaml b/charts/node-readiness-controller/tests/servicemonitor_test.yaml new file mode 100644 index 00000000..cd9772dd --- /dev/null +++ b/charts/node-readiness-controller/tests/servicemonitor_test.yaml @@ -0,0 +1,121 @@ +suite: Test ServiceMonitor Template +templates: + - servicemonitor.yaml + +tests: + - it: does not render when metrics.enabled is false + set: + metrics: + enabled: false + serviceMonitor: + enabled: true + asserts: + - failedTemplate: + errorMessage: You enabled metrics.serviceMonitor.enabled, but metrics.enabled is false. Please enable metrics to use the ServiceMonitor. + + - it: does not render when metrics.serviceMonitor.enabled is false + set: + metrics: + enabled: true + serviceMonitor: + enabled: false + asserts: + - hasDocuments: + count: 0 + + - it: does not render when monitoring.coreos.com/v1 capability is missing + set: + metrics: + enabled: true + serviceMonitor: + enabled: true + asserts: + - hasDocuments: + count: 0 + + - it: renders correctly when both flags are true (assumes monitoring.coreos.com/v1 exists) + capabilities: + apiVersions: + - monitoring.coreos.com/v1 + set: + metrics: + enabled: true + serviceMonitor: + enabled: true + asserts: + - isKind: + of: ServiceMonitor + - equal: + path: apiVersion + value: monitoring.coreos.com/v1 + - equal: + path: spec.endpoints[0].port + value: http + - equal: + path: spec.endpoints[0].interval + value: 30s + - equal: + path: spec.endpoints[0].scrapeTimeout + value: 10s + + - it: uses https scheme, bearer token, and injects custom tlsConfig when secure is true + capabilities: + apiVersions: + - monitoring.coreos.com/v1 + set: + metrics: + enabled: true + secure: true + serviceMonitor: + enabled: true + bearerTokenFile: /custom/path/to/token + tlsConfig: + insecureSkipVerify: true + asserts: + - equal: + path: spec.endpoints[0].port + value: https + - equal: + path: spec.endpoints[0].scheme + value: https + - equal: + path: spec.endpoints[0].bearerTokenFile + value: /custom/path/to/token + - equal: + path: spec.endpoints[0].tlsConfig.insecureSkipVerify + value: true + + - it: merges custom labels + capabilities: + apiVersions: + - monitoring.coreos.com/v1 + set: + metrics: + enabled: true + serviceMonitor: + enabled: true + labels: + release: prometheus + asserts: + - equal: + path: metadata.labels.release + value: prometheus + + - it: applies custom interval and timeout + capabilities: + apiVersions: + - monitoring.coreos.com/v1 + set: + metrics: + enabled: true + serviceMonitor: + enabled: true + interval: 1m + scrapeTimeout: 30s + asserts: + - equal: + path: spec.endpoints[0].interval + value: 1m + - equal: + path: spec.endpoints[0].scrapeTimeout + value: 30s diff --git a/charts/node-readiness-controller/values.yaml b/charts/node-readiness-controller/values.yaml index 4a348e0c..638f229f 100644 --- a/charts/node-readiness-controller/values.yaml +++ b/charts/node-readiness-controller/values.yaml @@ -124,6 +124,28 @@ metrics: targetPort: 8443 certDir: /tmp/k8s-metrics-server/metrics-certs certSecretName: metrics-server-cert + # -- Prometheus Operator ServiceMonitor. + # Requires metrics.enabled=true and the Prometheus Operator CRD + # (monitoring.coreos.com/v1) to be installed in the cluster. + serviceMonitor: + enabled: false + # -- Additional labels for the ServiceMonitor (e.g. release: prometheus) + labels: {} + # -- Scrape interval + interval: 30s + # -- Scrape timeout + scrapeTimeout: 10s + # -- Bearer token for scraping secure metrics + # Defaults to Prometheus's default token path if metrics.secure is true + bearerTokenFile: "" + # -- TLS configuration for scraping secure metrics + # e.g. providing a caFile, or setting insecureSkipVerify: false + tlsConfig: + insecureSkipVerify: true + # -- Metric relabeling configs + metricRelabelings: [] + # -- Relabeling configs + relabelings: [] # Webhook server configuration webhook: