Kubernetes
Run the chmonitor dashboard on Kubernetes with either the in-repo
Helm chart or the raw kustomize manifests. Both ship the same container image
(ghcr.io/duyet/chmonitor), expose port 3000, run as the non-root
app user (uid/gid 1001), and wire the same health probes and CLICKHOUSE_*
environment.
- Helm — templating, an optional HorizontalPodAutoscaler, and an Ingress.
- kustomize — plain YAML you can read, diff, and patch with overlays.
Install with Helm
The chart is vendored in the repo at
deploy/helm/chmonitor
so it tracks the app it ships.
helm install my-chm ./deploy/helm/chmonitor \
--set clickhouse.host="https://clickhouse.example.com:8443" \
--set clickhouse.user="default" \
--set clickhouse.password="<password>"
Or with a values file:
cat <<EOF > values.yaml
clickhouse:
host: "https://clickhouse.example.com:8443"
user: "default"
password: "<password>"
maxExecutionTime: "60"
extraEnv:
- name: CLICKHOUSE_TZ
value: "UTC"
EOF
helm install my-chm ./deploy/helm/chmonitor -f values.yaml
Upgrade and uninstall:
helm upgrade my-chm ./deploy/helm/chmonitor -f values.yaml
helm uninstall my-chm
Install with kustomize (no Helm)
The raw manifests live at
deploy/kubernetes/base.
Edit base/configmap.yaml (host/user) and set the password, then:
# Review the rendered output first
kubectl kustomize deploy/kubernetes/base
# Apply
kubectl apply -k deploy/kubernetes/base
Reach the dashboard locally:
kubectl port-forward svc/chmonitor 3000:3000
# open http://localhost:3000
Overlays
Keep environment differences (namespace, replicas, image tag) in an overlay that references the base:
# deploy/kubernetes/overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: monitoring
resources:
- ../../base
images:
- name: ghcr.io/duyet/chmonitor
newTag: v1.2.3
replicas:
- name: chmonitor
count: 2
kubectl apply -k deploy/kubernetes/overlays/prod
Health probes
Both install paths configure the same probes:
- Liveness —
GET /healthz(static, always200while the process runs). - Readiness —
GET /api/healthz(returns503when no configured ClickHouse host is reachable, so traffic is only routed once a host is up).
Secrets
The ClickHouse password is stored in a Kubernetes Secret, never in a
ConfigMap. The chart renders one for you (or reuses an existing one via
clickhouse.existingSecret); the kustomize secret.yaml ships an empty
placeholder you must override. Never commit a real password to Git — create
the Secret out of band or use a secrets operator:
kubectl create secret generic chmonitor \
--from-literal=CLICKHOUSE_PASSWORD='change-me'
For GitOps, prefer External Secrets, SOPS, or Sealed Secrets.
Autoscaling (HPA)
The Helm chart can manage a HorizontalPodAutoscaler. Enable it and the chart
drops the static replicaCount in favor of the HPA:
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
With kustomize, add the HPA as an extra resource in your overlay. The dashboard is stateless, so scaling out is safe; the readiness probe keeps traffic off pods until ClickHouse is reachable.
Validation
Manifests and the chart are linted in CI by
.github/workflows/k8s-lint.yml
using helm lint and kubeconform.
Validate locally:
helm lint ./deploy/helm/chmonitor
helm template release ./deploy/helm/chmonitor | kubeconform -strict -summary
kubectl kustomize deploy/kubernetes/base | kubeconform -strict -summary