Search code examples
keycloakmonitoringmetricsprometheus-operator

Auto-scrape realm metrics from Keycloak with Prometheus-Operator


I installed Keycloak using the bitnami/keycloak Helm chart (https://bitnami.com/stack/keycloak/helm).

As I'm also using Prometheus-Operator for monitoring I enabled the metrics endpoint and the service monitor:

keycloak:
  ...
  metrics:
    enabled: true
    serviceMonitor:
      enabled: true
      namespace: monitoring
      additionalLabels:
        release: my-prom-operator-release

As I'm way more interested in actual realm metrics I installed the keycloak-metrics-spi provider (https://github.com/aerogear/keycloak-metrics-spi) by setting up an init container that downloads it to a shared volume.

keycloak:
  ...
  extraVolumeMounts:
    - name: providers
      mountPath: /opt/bitnami/keycloak/providers

  extraVolumes:
    - name: providers
      emptyDir: {}
  ...
  initContainers:
    - name: metrics-spi-provider
      image: SOME_IMAGE_WITH_WGET_INSTALLED
      imagePullPolicy: Always
      command:
        - sh
      args:
        - -c
        - |
          KEYCLOAK_METRICS_SPI_VERSION=2.5.2
          wget --no-check-certificate -O /providers/keycloak-metrics-spi-${KEYCLOAK_METRICS_SPI_VERSION}.jar \
            https://github.com/aerogear/keycloak-metrics-spi/releases/download/${KEYCLOAK_METRICS_SPI_VERSION}/keycloak-metrics-spi-${KEYCLOAK_METRICS_SPI_VERSION}.jar
          chmod +x /providers/keycloak-metrics-spi-${KEYCLOAK_METRICS_SPI_VERSION}.jar
          touch /providers/keycloak-metrics-spi-${KEYCLOAK_METRICS_SPI_VERSION}.jar.dodeploy
      volumeMounts:
        - name: providers
          mountPath: /providers

The provider enables metrics endpoints on the regular public-facing http port instead of the http-management port, which is not great for me. But I can block external access to them in my reverse proxy.

What I'm missing is some kind of auto-scraping of those endpoints. Right now I created an additional template, that creates a new service monitor for each element of a predefined list in my chart:

values.yaml

keycloak:
  ...
  metrics:
    extraServiceMonitors:
      - realmName: master
      - realmName: my-realm

servicemonitor-metrics-spi.yaml

{{- range $serviceMonitor := .Values.keycloak.metrics.extraServiceMonitors }}
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: {{ $.Release.Name }}-spi-{{ $serviceMonitor.realmName }}
...
spec:
  endpoints:
    - port: http
      path: /auth/realms/{{ $serviceMonitor.realmName }}/metrics
...
{{- end }}

Is there a better way of doing this? So that Prometheus can auto-detect all my realms and scrape their endpoints?

Thanks in advance!


Solution

  • As commented by @jan-garaj there is no need to query all the endpoints. All return the accumulated data of all realms. So it is enough to just scrape the endpoint of one realm (e.g. the master realm).

    Thanks a lot!