From b6d9b710878065ef07b336db0e4d3532f9a699f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Burzy=C5=84ski?= Date: Tue, 14 Oct 2025 13:44:20 +0200 Subject: [PATCH 1/4] Deprecate exposeOptions in ScyllaDBMonitoring --- pkg/api/scylla/v1alpha1/types_monitoring.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkg/api/scylla/v1alpha1/types_monitoring.go b/pkg/api/scylla/v1alpha1/types_monitoring.go index 5ab2e55a8be..b21ae6f3e0d 100644 --- a/pkg/api/scylla/v1alpha1/types_monitoring.go +++ b/pkg/api/scylla/v1alpha1/types_monitoring.go @@ -118,6 +118,10 @@ type PrometheusSpec struct { Resources corev1.ResourceRequirements `json:"resources"` // exposeOptions specifies options for exposing Prometheus UI. + // + // Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future + // versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Prometheus if needed. + // // +optional ExposeOptions *PrometheusExposeOptions `json:"exposeOptions,omitempty"` @@ -143,6 +147,10 @@ type GrafanaSpec struct { Resources corev1.ResourceRequirements `json:"resources"` // exposeOptions specifies options for exposing Grafana UI. + // + // Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future + // versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Grafana if needed. + // // +optional ExposeOptions *GrafanaExposeOptions `json:"exposeOptions,omitempty"` From b4021746d0cfb730ae1d6c29cf56b0cfbfccf64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Burzy=C5=84ski?= Date: Wed, 22 Oct 2025 20:06:32 +0200 Subject: [PATCH 2/4] Adjust 'Exposing Grafana' guide to use external Ingress --- .../management/monitoring/exposing-grafana.md | 89 ++++++++++--------- .../v1alpha1/grafana-haproxy.ingress.yaml | 24 +++++ 2 files changed, 72 insertions(+), 41 deletions(-) create mode 100644 examples/monitoring/v1alpha1/grafana-haproxy.ingress.yaml diff --git a/docs/source/management/monitoring/exposing-grafana.md b/docs/source/management/monitoring/exposing-grafana.md index 0dd4d3a9998..1f1cdea4999 100644 --- a/docs/source/management/monitoring/exposing-grafana.md +++ b/docs/source/management/monitoring/exposing-grafana.md @@ -1,17 +1,18 @@ # Exposing Grafana -This guide shows how to expose Grafana deployed by `ScyllaDBMonitoring` using an Ingress resource. +This guide shows how to expose Grafana deployed by `ScyllaDBMonitoring` using an `Ingress` resource. -For accessing Grafana service from outside the Kubernetes cluster we recommend using an Ingress, although there are many other ways to do so. -When using Ingress, what matters is to direct your packets to the ingress controller Service/Pods and have the correct TLS SNI field set by the caller when reaching out to the service, so it is routed properly, and your client can successfully validate the grafana serving certificate. -This is easier when you are using a real DNS domain that resolves to your Ingress controller's IP address but most clients and tools allow setting the SNI field manually. +:::{note} +For accessing the Grafana service from outside the Kubernetes cluster we document using an `Ingress`, although there are other options like an `HTTPRoute` from the Gateway API. +Use whatever method fits your use case best. +::: ## Prerequisites -This assumes you have already deployed `ScyllaDBMonitoring` in your cluster. If you haven't done so, please follow the [ScyllaDB Monitoring setup](setup.md) guide first. +This assumes that you have already deployed a `ScyllaDBMonitoring` in your cluster. If you haven't done so, please follow the [ScyllaDB Monitoring setup](setup.md) guide first. -In the example below we're using HAProxy Ingress Controller. You can deploy it in your Kubernetes cluster using the provided -third-party example. If you already have it (or other Ingress Controller) deployed in your cluster, you can skip the below steps. +In the example below we're using the HAProxy Ingress Controller. You can deploy it in your Kubernetes cluster using the provided +third-party example. If you already have it (or another Ingress Controller) deployed in your cluster, you can skip the below steps. ### Install HAProxy Ingress @@ -26,65 +27,71 @@ Wait for HAProxy Ingress to roll out: kubectl -n haproxy-ingress rollout status --timeout=5m deployments.apps/haproxy-ingress ``` -## Get Grafana credentials +## Expose Grafana using Ingress -To access Grafana, you first need to collect the serving CA and the credentials. +{{productName}} creates a `ClusterIP` Service named `-grafana` for each `ScyllaDBMonitoring`. +Grafana serves TLS using a self-signed certificate that's signed by a CA stored in a Secret named `-grafana-serving-ca` by default. -```console -$ GRAFANA_SERVING_CERT="$( kubectl -n scylla get secret/example-grafana-serving-ca --template '{{ index .data "tls.crt" }}' | base64 -d )" -$ GRAFANA_USER="$( kubectl -n scylla get secret/example-grafana-admin-credentials --template '{{ index .data "username" }}' | base64 -d )" -$ GRAFANA_PASSWORD="$( kubectl -n scylla get secret/example-grafana-admin-credentials --template '{{ index .data "password" }}' | base64 -d )" -``` +:::{note} +You can use your own serving certificate by setting `ScyllaDBMonitoring`'s `spec.components.grafana.servingCertSecretName` field. +::: + +Create the following Ingress resource that will route requests with `test-grafana.test.svc.cluster.local` SNI to the Grafana: -## Connect through Ingress using a resolvable domain +:::{literalinclude} ../../../../examples/monitoring/v1alpha1/grafana-haproxy.ingress.yaml +:language: yaml +:linenos: +::: -In production clusters, the Ingress controller and appropriate DNS records should be set up already. Often there is already a generic wildcard record like `*.app.mydomain` pointing to the Ingress controller's external IP. For custom service domains, it is usually a CNAME pointing to the Ingress controller's A record. +You can apply the above manifest using `kubectl`: -:::{note} -The ScyllaDBMonitoring example creates an Ingress object with `test-grafana.test.svc.cluster.local` DNS domain that you should adjust to your domain. Below examples use `example-grafana.apps.mydomain`. +:::{code-block} shell +:substitutions: +kubectl apply -n scylla --server-side -f=https://raw.githubusercontent.com/{{repository}}/{{revision}}/examples/monitoring/v1alpha1/grafana-haproxy.ingress.yaml ::: :::{note} -To test a resolvable domain from your machine without creating DNS records, you can adjust `/etc/hosts` or similar. +In production, you should make sure that the Ingress controller properly terminates TLS using certificates issued by a trusted CA, +e.g. using [cert-manager](https://cert-manager.io/docs/) to automatically issue and renew certificates from Let's Encrypt. ::: -```console -$ curl --fail -s -o /dev/null -w '%{http_code}' -L --cacert <( echo "${GRAFANA_SERVING_CERT}" ) "https://example-grafana.apps.mydomain" --user "${GRAFANA_USER}:${GRAFANA_PASSWORD}" -200 -``` - -## Connect through Ingress using an unresolvable domain +## Verify connection -To connect to an Ingress without a resolvable domain you first need to find out your Ingress controller's IP that can be resolved externally. Again, there are many ways to do so beyond the below examples. +### Get Grafana credentials -Unless stated otherwise, we assume your Ingress is running on port 443. +To access Grafana, you need to collect the credentials. ```console -$ INGRESS_PORT=443 +GRAFANA_USER="$( kubectl -n scylla get secret/example-grafana-admin-credentials --template '{{ index .data "username" }}' | base64 -d )" +GRAFANA_PASSWORD="$( kubectl -n scylla get secret/example-grafana-admin-credentials --template '{{ index .data "password" }}' | base64 -d )" ``` -### Variants +### Get Ingress IP and Port -#### Ingress ExternalIP - -When you are running in a real cluster there is usually a cloud LoadBalancer or a bare metal alternative providing you with an externally reachable IP address. +If your cluster supports `LoadBalancer` services, your Ingress should be assigned an external IP address. You can get it by running: ```console -$ INGRESS_IP="$( kubectl -n=haproxy-ingress get service/haproxy-ingress --template='{{ ( index .status.loadBalancer.ingress 0 ).ip }}' )" +INGRESS_IP="$( kubectl -n haproxy-ingress get svc haproxy-ingress --template '{{ index .status.loadBalancer.ingress 0 "ip" }}' )" +INGRESS_PORT="443" ``` -#### Ingress NodePort - -NodePort is slightly less convenient, but it's available in development clusters as well. +Otherwise, if you're running this locally (e.g. using `minikube` or `kind`), you can port-forward the Ingress controller service to your local machine: ```console -$ INGRESS_IP="$( kubectl get nodes --template='{{ $internal_ip := "" }}{{ $external_ip := "" }}{{ range ( index .items 0 ).status.addresses }}{{ if eq .type "InternalIP" }}{{ $internal_ip = .address }}{{ else if eq .type "ExternalIP" }}{{ $external_ip = .address }}{{ end }}{{ end }}{{ if $external_ip }}{{ $external_ip }}{{ else }}{{ $internal_ip }}{{ end }}' )" -$ INGRESS_PORT="$( kubectl -n=haproxy-ingress get services/haproxy-ingress --template='{{ range .spec.ports }}{{ if eq .port 443 }}{{ .nodePort }}{{ end }}{{ end }}' )" +kubectl -n haproxy-ingress port-forward svc/haproxy-ingress 8443:443 & +INGRESS_IP="127.0.0.1" +INGRESS_PORT="8443" ``` -#### Connection +### Test connection + +Now, you can verify the connection to the Grafana through the Ingress. ```console -$ curl --fail -s -o /dev/null -w '%{http_code}' -L --cacert <( echo "${GRAFANA_SERVING_CERT}" ) "https://test-grafana.test.svc.cluster.local:${INGRESS_PORT}" --resolve "test-grafana.test.svc.cluster.local:${INGRESS_PORT}:${INGRESS_IP}" --user "${GRAFANA_USER}:${GRAFANA_PASSWORD}" -200 +curl --fail -s -o /dev/null -w '%{http_code}' -k \ + --resolve "test-grafana.test.svc.cluster.local:${INGRESS_PORT}:${INGRESS_IP}" \ + --user "${GRAFANA_USER}:${GRAFANA_PASSWORD}" \ + "https://test-grafana.test.svc.cluster.local:${INGRESS_PORT}/" ``` + +You should see `200` as the output, indicating a successful connection. diff --git a/examples/monitoring/v1alpha1/grafana-haproxy.ingress.yaml b/examples/monitoring/v1alpha1/grafana-haproxy.ingress.yaml new file mode 100644 index 00000000000..6ee3b618eff --- /dev/null +++ b/examples/monitoring/v1alpha1/grafana-haproxy.ingress.yaml @@ -0,0 +1,24 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: "example-grafana" + namespace: "scylla" + annotations: + haproxy.org/server-ssl: "true" # HA Proxy should use TLS when connecting to the backend. + haproxy.org/server-ca: "default/example-grafana-serving-ca" # HA Proxy should trust the Grafana serving certificate signed by this CA. +spec: + ingressClassName: haproxy + tls: + - hosts: + - "test-grafana.test.svc.cluster.local" + rules: + - host: "test-grafana.test.svc.cluster.local" + http: + paths: + - backend: + service: + name: "example-grafana" + port: + number: 3000 + path: / + pathType: Prefix From 30293ae82f4a238da24fd97351cdec56c8b88dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Burzy=C5=84ski?= Date: Wed, 22 Oct 2025 20:20:01 +0200 Subject: [PATCH 3/4] Remove exposeOptions from ScyllaDBMonitoring example --- examples/monitoring/v1alpha1/scylladbmonitoring.yaml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/examples/monitoring/v1alpha1/scylladbmonitoring.yaml b/examples/monitoring/v1alpha1/scylladbmonitoring.yaml index 709b24f97cb..1199a853d42 100644 --- a/examples/monitoring/v1alpha1/scylladbmonitoring.yaml +++ b/examples/monitoring/v1alpha1/scylladbmonitoring.yaml @@ -32,12 +32,3 @@ spec: key: scylla-operator.scylladb.com/dedicated operator: Equal value: scyllaclusters - grafana: - exposeOptions: - webInterface: - ingress: - ingressClassName: haproxy - dnsDomains: - - example-grafana.test.svc.cluster.local - annotations: - haproxy-ingress.github.io/ssl-passthrough: "true" From 88cc9de16e5e60dbb34c7dc9688f9f0d86a9f771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20Burzy=C5=84ski?= Date: Wed, 22 Oct 2025 20:19:46 +0200 Subject: [PATCH 4/4] Update generated --- .../scylla.scylladb.com_scylladbmonitorings.yaml | 14 ++++++++++---- deploy/operator.yaml | 12 ++++++++++-- .../scylla.scylladb.com/scylladbmonitorings.rst | 8 ++++---- .../scylla.scylladb.com_scylladbmonitorings.yaml | 12 ++++++++++-- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/bundle/manifests/scylla.scylladb.com_scylladbmonitorings.yaml b/bundle/manifests/scylla.scylladb.com_scylladbmonitorings.yaml index ae672ff531c..3ca84486c32 100644 --- a/bundle/manifests/scylla.scylladb.com_scylladbmonitorings.yaml +++ b/bundle/manifests/scylla.scylladb.com_scylladbmonitorings.yaml @@ -171,8 +171,11 @@ spec: maxItems: 1 type: array exposeOptions: - description: exposeOptions specifies options for exposing - Grafana UI. + description: |- + exposeOptions specifies options for exposing Grafana UI. + + Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future + versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Grafana if needed. properties: webInterface: description: webInterface specifies expose options for @@ -1239,8 +1242,11 @@ spec: instance, if any. properties: exposeOptions: - description: exposeOptions specifies options for exposing - Prometheus UI. + description: |- + exposeOptions specifies options for exposing Prometheus UI. + + Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future + versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Prometheus if needed. properties: webInterface: description: webInterface specifies expose options for diff --git a/deploy/operator.yaml b/deploy/operator.yaml index 56f7fc9b8d9..bd8c4c5f095 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -45951,7 +45951,11 @@ spec: maxItems: 1 type: array exposeOptions: - description: exposeOptions specifies options for exposing Grafana UI. + description: |- + exposeOptions specifies options for exposing Grafana UI. + + Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future + versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Grafana if needed. properties: webInterface: description: webInterface specifies expose options for the user web interface. @@ -46962,7 +46966,11 @@ spec: description: prometheus holds configuration for the prometheus instance, if any. properties: exposeOptions: - description: exposeOptions specifies options for exposing Prometheus UI. + description: |- + exposeOptions specifies options for exposing Prometheus UI. + + Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future + versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Prometheus if needed. properties: webInterface: description: webInterface specifies expose options for the user web interface. diff --git a/docs/source/api-reference/groups/scylla.scylladb.com/scylladbmonitorings.rst b/docs/source/api-reference/groups/scylla.scylladb.com/scylladbmonitorings.rst index 242944c1f7e..e58da0f5bc9 100755 --- a/docs/source/api-reference/groups/scylla.scylladb.com/scylladbmonitorings.rst +++ b/docs/source/api-reference/groups/scylla.scylladb.com/scylladbmonitorings.rst @@ -142,7 +142,7 @@ object - datasources is a list of Grafana datasources to configure. It's expected to be set when using Prometheus component in `External` mode. At most one datasource is allowed for now (only Prometheus is supported). * - :ref:`exposeOptions` - object - - exposeOptions specifies options for exposing Grafana UI. + - exposeOptions specifies options for exposing Grafana UI. Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Grafana if needed. * - :ref:`placement` - object - placement describes restrictions for the nodes Grafana is scheduled on. @@ -412,7 +412,7 @@ object Description """"""""""" -exposeOptions specifies options for exposing Grafana UI. +exposeOptions specifies options for exposing Grafana UI. Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Grafana if needed. Type """" @@ -1801,7 +1801,7 @@ object - Description * - :ref:`exposeOptions` - object - - exposeOptions specifies options for exposing Prometheus UI. + - exposeOptions specifies options for exposing Prometheus UI. Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Prometheus if needed. * - mode - string - mode defines the mode of the Prometheus instance. @@ -1822,7 +1822,7 @@ object Description """"""""""" -exposeOptions specifies options for exposing Prometheus UI. +exposeOptions specifies options for exposing Prometheus UI. Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Prometheus if needed. Type """" diff --git a/pkg/api/scylla/v1alpha1/scylla.scylladb.com_scylladbmonitorings.yaml b/pkg/api/scylla/v1alpha1/scylla.scylladb.com_scylladbmonitorings.yaml index 595713895ff..2ec83ad83e5 100644 --- a/pkg/api/scylla/v1alpha1/scylla.scylladb.com_scylladbmonitorings.yaml +++ b/pkg/api/scylla/v1alpha1/scylla.scylladb.com_scylladbmonitorings.yaml @@ -156,7 +156,11 @@ spec: maxItems: 1 type: array exposeOptions: - description: exposeOptions specifies options for exposing Grafana UI. + description: |- + exposeOptions specifies options for exposing Grafana UI. + + Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future + versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Grafana if needed. properties: webInterface: description: webInterface specifies expose options for the user web interface. @@ -1167,7 +1171,11 @@ spec: description: prometheus holds configuration for the prometheus instance, if any. properties: exposeOptions: - description: exposeOptions specifies options for exposing Prometheus UI. + description: |- + exposeOptions specifies options for exposing Prometheus UI. + + Deprecated: This field will be removed in the next version of the API. Support for it will be removed in the future + versions of the operator. We recommend managing your own Ingress or HTTPRoute resources to expose Prometheus if needed. properties: webInterface: description: webInterface specifies expose options for the user web interface.