The kube-prometheus-stack bundles Prometheus, Grafana, and AlertManager for monitoring a Kubernetes cluster.
By default, the Ingress of these services is disabled. In this article I will show you how to expose these services with NGINX Ingress either via subdomain (e.g. prometheus.my.domain) or web context (e.g. my.domain/prometheus).
You would not want to expose these monitoring applications on the same Ingress as your public end-user traffic, but if you had a secondary NGINX ingress tied to a private internal-only network, then exposing these applications could be appropriate.
Prerequisites
Kubernetes cluster with NGINX Ingress
You will need a Kubernetes cluster with NGINX Ingress installed in order to go through this article.
You can use my article on installing a K3s with MetalLB and NGINX Ingress available here.
Certificates available for TLS
Depending on whether we will be exposing these services at subdomains, for example:
- alertmanager.k3s.local
- grafana.k3s.local
- prometheus.local
OR at a web context path, for example:
- k3s.local/alertmanager
- k3s.local/grafana
- k3s.local/prometheus
Certificates can be created using OpenSSL for the required name(s). It can be as simple as a self-signed SAN, or custom CA with SAN, or you can get them from a commercial certificate provider.
Ultimately, the TLS key+certificate for the domain name(s) must be loaded as a secret into the cluster.
secret_name="tls-credential" # create Kubernetes secret from local file named my.key and my.crt kubectl create secret tls $secret_name \ --key=my.key \ --cert=my.crt \ -n default
Option #1: Exposing monitoring applications at subdomain
Exposing Prometheus, AlertManager, and Grafana with their own subdomain requires an override of the Helm chart defaults by creating your own custom values file.
This section assumes we are exposing the applications at the subdomains below and the ‘tls-credential’ secret has all these subdomain names in its SAN certificate:
- alertmanager.k3s.local
- grafana.k3s.local
- prometheus.local
AlertManager ingress enabled
Here is the proper syntax for enabling AlertManager ingress at a subdomain (https://alertmanager.k3s.local)
alertmanager: ingress: enabled: true annotations: kubernetes.io/ingress.class: nginx hosts: ['alertmanager.k3s.local'] paths: ['/'] tls: - secretName: tls-credential hosts: - alertmanager.k3s.local ... alertmanagerSpec: externalUrl: https://alertmanager.k3s.local/ routePrefix: /
Grafana ingress enabled
Here is the proper syntax for enabling Grafana ingress at a subdomain (https://grafana.k3s.local)
grafana: # username is 'admin' adminPassword: prom-operator ingress: enabled: true annotations: kubernetes.io/ingress.class: nginx hosts: ['grafana.k3s.local'] path: "/" tls: - secretName: tls-credential hosts: - grafana.k3s.local
Prometheus ingress enabled
Here is the syntax for enabling the Prometheus Ingress at a subdomain (https://prometheus.k3s.local)
prometheus: ingress: enabled: true annotations: kubernetes.io/ingress.class: nginx hosts: ['prometheus.k3s.local'] paths: ['/'] tls: - secretName: tls-credential hosts: - prometheus.k3s.local ... prometheusSpec: externalUrl: "https://prometheus.k3s.local/" routePrefix: /
Option #2: Exposing monitoring applications at web context
Exposing Prometheus, AlertManager, and Grafana at the same domain (but different web context) requires an override of the Helm chart defaults by creating your own custom values file.
This section assumes we are exposing the applications at the ‘k3s.local’ domain and the ‘tls-credential’ secret has this domain name as is common name or SAN.
- k3s.local/alertmanager
- k3s.local/grafana
- k3s.local/prometheus
AlertManager ingress enabled
Here is the proper syntax for enabling AlertManager ingress at a web context path (https://k3s.local/alertmanager)
alertmanager: ingress: enabled: true annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: /$2 hosts: ['k3s.local'] paths: ['/alertmanager(/|$)(.*)'] tls: - secretName: tls-credential hosts: - k3s.local ... alertmanagerSpec: externalUrl: https://k3s.local/alertmanager routePrefix: "/" # does not need alertmanager suffix
Grafana ingress enabled
Here is the proper syntax for enabling Grafana ingress at a web context path (https://k3s.local/grafana). Notice we had to add a couple of environment variables to get Grafana to properly process requests at a context path.
grafana: env: GF_SERVER_ROOT_URL: https://k3s.local/grafana GF_SERVER_SERVE_FROM_SUB_PATH: 'true' # username is 'admin' adminPassword: prom-operator ingress: enabled: true annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: /$2 hosts: ['k3s.local'] path: "/grafana(/|$)(.*)" tls: - secretName: tls-credential hosts: - k3s.local
Prometheus ingress enabled
Here is the syntax for enabling the Prometheus Ingress at a web context path (https://k3s.local/prometheus)
prometheus: ingress: enabled: true annotations: kubernetes.io/ingress.class: nginx hosts: ['k3s.local'] paths: ['/prometheus'] # does not need regex capture like others tls: - secretName: tls-credential hosts: - k3s.local ... prometheusSpec: externalUrl: "https://k3s.local/prometheus" routePrefix: /prometheus
Full custom values file
I have a full example values file for a K3s cluster that exposes these monitoring services by subdomain at prom-sparse.expanded.yaml.
Run Helm installation
Helm can either install or upgrade the kube-prometheus-stack using custom override values described in this article.
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts # create the namespace kubectl create ns prom # install|upgrade helm install \ --namespace prom \ -f prom-sparse.yaml \ prom-stack prometheus-community/kube-prometheus-stack
REFERENCES
kube-prometheus-stack, values.yaml containing all values