From 1e92ecbd19eec76c4d9e7bf32ad7f4cabae8298e Mon Sep 17 00:00:00 2001 From: Finn Rades Date: Tue, 31 Mar 2026 09:31:50 +0200 Subject: [PATCH 1/2] ClickHouse: Implement first clickhouse impl --- charts/clickhouse/.helmignore | 2 + charts/clickhouse/CHANGELOG.md | 21 ++ charts/clickhouse/Chart.lock | 6 + charts/clickhouse/Chart.yaml | 49 +++ charts/clickhouse/artifacthub-repo.yml | 1 + charts/clickhouse/templates/_helpers.tpl | 125 +++++++ charts/clickhouse/templates/configmap.yaml | 71 ++++ charts/clickhouse/templates/extraobjects.yaml | 4 + charts/clickhouse/templates/httproute.yaml | 69 ++++ charts/clickhouse/templates/ingress.yaml | 52 +++ .../templates/init-scripts-configmap.yaml | 18 + charts/clickhouse/templates/secret.yaml | 33 ++ .../clickhouse/templates/service-metrics.yaml | 27 ++ charts/clickhouse/templates/service.yaml | 61 +++ .../clickhouse/templates/serviceaccount.yaml | 14 + .../clickhouse/templates/servicemonitor.yaml | 52 +++ charts/clickhouse/templates/statefulset.yaml | 260 +++++++++++++ .../tests/common-parameters_test.yaml | 131 +++++++ charts/clickhouse/tests/secret_test.yaml | 43 +++ charts/clickhouse/tests/service_test.yaml | 77 ++++ .../clickhouse/tests/volume-claim_test.yaml | 64 ++++ charts/clickhouse/values.yaml | 351 ++++++++++++++++++ 22 files changed, 1531 insertions(+) create mode 100644 charts/clickhouse/.helmignore create mode 100644 charts/clickhouse/CHANGELOG.md create mode 100644 charts/clickhouse/Chart.lock create mode 100644 charts/clickhouse/Chart.yaml create mode 100644 charts/clickhouse/artifacthub-repo.yml create mode 100644 charts/clickhouse/templates/_helpers.tpl create mode 100644 charts/clickhouse/templates/configmap.yaml create mode 100644 charts/clickhouse/templates/extraobjects.yaml create mode 100644 charts/clickhouse/templates/httproute.yaml create mode 100644 charts/clickhouse/templates/ingress.yaml create mode 100644 charts/clickhouse/templates/init-scripts-configmap.yaml create mode 100644 charts/clickhouse/templates/secret.yaml create mode 100644 charts/clickhouse/templates/service-metrics.yaml create mode 100644 charts/clickhouse/templates/service.yaml create mode 100644 charts/clickhouse/templates/serviceaccount.yaml create mode 100644 charts/clickhouse/templates/servicemonitor.yaml create mode 100644 charts/clickhouse/templates/statefulset.yaml create mode 100644 charts/clickhouse/tests/common-parameters_test.yaml create mode 100644 charts/clickhouse/tests/secret_test.yaml create mode 100644 charts/clickhouse/tests/service_test.yaml create mode 100644 charts/clickhouse/tests/volume-claim_test.yaml create mode 100644 charts/clickhouse/values.yaml diff --git a/charts/clickhouse/.helmignore b/charts/clickhouse/.helmignore new file mode 100644 index 000000000..bc120b4b8 --- /dev/null +++ b/charts/clickhouse/.helmignore @@ -0,0 +1,2 @@ +artifacthub-repo.yaml +tests/ diff --git a/charts/clickhouse/CHANGELOG.md b/charts/clickhouse/CHANGELOG.md new file mode 100644 index 000000000..bee3e08ee --- /dev/null +++ b/charts/clickhouse/CHANGELOG.md @@ -0,0 +1,21 @@ +# Changelog + +## [0.1.0] + +### Added + +- Initial release of the standalone ClickHouse Helm chart +- StatefulSet deployment using official `clickhouse/clickhouse-server` image +- Configurable `config.xml` and `users.xml` via ConfigMaps +- Persistent storage via PVC with configurable size and storage class +- HTTP (8123) and TCP/native (9000) service ports +- Headless service for StatefulSet DNS +- Optional Prometheus metrics sidecar with ServiceMonitor support +- Optional Ingress and Gateway API HTTPRoute resources +- Optional ServiceAccount creation +- Liveness, readiness, and startup probes via ClickHouse `/ping` endpoint +- Support for init SQL scripts via ConfigMap +- `extraObjects`, `extraEnvVars`, `extraVolumes`, `extraVolumeMounts` escape hatches +- Auto-generated credentials secret with connection URI +- Pod and container security context defaults +- `persistentVolumeClaimRetentionPolicy` support diff --git a/charts/clickhouse/Chart.lock b/charts/clickhouse/Chart.lock new file mode 100644 index 000000000..a48d5ffa9 --- /dev/null +++ b/charts/clickhouse/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: common + repository: oci://registry-1.docker.io/cloudpirates + version: 2.2.0 +digest: sha256:a2168dfa04b6fbeb8ab278d891670dd5d27c51366c36853e156f07479720cefe +generated: "2026-03-30T07:55:43.090874+02:00" diff --git a/charts/clickhouse/Chart.yaml b/charts/clickhouse/Chart.yaml new file mode 100644 index 000000000..3912227b7 --- /dev/null +++ b/charts/clickhouse/Chart.yaml @@ -0,0 +1,49 @@ +apiVersion: v2 +name: clickhouse +description: The Open-Source, High Performance Columnar OLAP Database Management System +type: application +version: 0.1.0 +appVersion: "25.3.14.14" +keywords: + - clickhouse + - database + - olap + - analytics + - columnar +home: https://clickhouse.com +sources: + - https://github.com/CloudPirates-io/helm-charts/tree/main/charts/clickhouse + - https://github.com/ClickHouse/ClickHouse +maintainers: + - name: CloudPirates GmbH & Co. KG + email: hello@cloudpirates.io + url: https://www.cloudpirates.io +dependencies: + - name: common + version: "2.2.x" + repository: oci://registry-1.docker.io/cloudpirates +icon: https://a.storyblok.com/f/143071/512x512/7be3e97a51/clickhouse-logo.svg +annotations: + license: Apache-2.0 + artifacthub.io/category: database + artifacthub.io/containsSecurityUpdates: "false" + artifacthub.io/signKey: | + fingerprint: 6917f1a88c122cbb1de5aa55457752135bdcf95a + url: https://raw.githubusercontent.com/CloudPirates-io/helm-charts/refs/heads/main/cosign.pub + artifacthub.io/links: | + - name: ClickHouse + url: https://clickhouse.com + - name: Helm Chart + url: https://github.com/CloudPirates-io/helm-charts/tree/main/charts/clickhouse + - name: Application + url: https://github.com/ClickHouse/ClickHouse + - name: Docker Image + url: https://hub.docker.com/r/clickhouse/clickhouse-server + - name: Maintainer CloudPirates + url: https://www.cloudpirates.io + artifacthub.io/changes: |- + - kind: added + description: "Initial release of the ClickHouse chart" + links: + - name: "Changelog" + url: "https://github.com/CloudPirates-io/helm-charts/blob/main/charts/clickhouse/CHANGELOG.md" diff --git a/charts/clickhouse/artifacthub-repo.yml b/charts/clickhouse/artifacthub-repo.yml new file mode 100644 index 000000000..66e588618 --- /dev/null +++ b/charts/clickhouse/artifacthub-repo.yml @@ -0,0 +1 @@ +repositoryID: XXXXXXXX diff --git a/charts/clickhouse/templates/_helpers.tpl b/charts/clickhouse/templates/_helpers.tpl new file mode 100644 index 000000000..d12dbe2dc --- /dev/null +++ b/charts/clickhouse/templates/_helpers.tpl @@ -0,0 +1,125 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "clickhouse.name" -}} +{{- include "cloudpirates.name" . -}} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "clickhouse.fullname" -}} +{{- include "cloudpirates.fullname" . -}} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "clickhouse.chart" -}} +{{- include "cloudpirates.chart" . -}} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "clickhouse.labels" -}} +{{- include "cloudpirates.labels" . -}} +{{- end }} + +{{/* +Common annotations +*/}} +{{- define "clickhouse.annotations" -}} +{{- with .Values.commonAnnotations }} +{{- toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "clickhouse.selectorLabels" -}} +{{- include "cloudpirates.selectorLabels" . -}} +{{- end }} + +{{/* +Return the proper ClickHouse image name +*/}} +{{- define "clickhouse.image" -}} +{{- include "cloudpirates.image" (dict "image" .Values.image "global" .Values.global) -}} +{{- end }} + +{{/* +Return ClickHouse credentials secret name +*/}} +{{- define "clickhouse.secretName" -}} +{{- if .Values.auth.existingSecret -}} + {{- include "cloudpirates.tplvalues.render" (dict "value" .Values.auth.existingSecret "context" .) -}} +{{- else -}} + {{- include "clickhouse.fullname" . -}} +{{- end -}} +{{- end }} + +{{/* +Return ClickHouse admin password key +*/}} +{{- define "clickhouse.passwordKey" -}} +{{- if .Values.auth.existingSecret -}} + {{- include "cloudpirates.tplvalues.render" (dict "value" .Values.auth.secretKeys.passwordKey "context" .) | default "clickhouse-password" -}} +{{- else -}} +clickhouse-password +{{- end -}} +{{- end }} + +{{/* +Return ClickHouse configuration ConfigMap name +*/}} +{{- define "clickhouse.configmapName" -}} +{{- if .Values.config.existingConfigmap -}} + {{- .Values.config.existingConfigmap -}} +{{- else -}} + {{- printf "%s-config" (include "clickhouse.fullname" .) -}} +{{- end -}} +{{- end }} + +{{/* +Return ClickHouse users configuration ConfigMap name +*/}} +{{- define "clickhouse.usersConfigmapName" -}} +{{- if .Values.config.existingUsersConfigmap -}} + {{- .Values.config.existingUsersConfigmap -}} +{{- else -}} + {{- printf "%s-users" (include "clickhouse.fullname" .) -}} +{{- end -}} +{{- end }} + +{{/* +Return ClickHouse init scripts ConfigMap name +*/}} +{{- define "clickhouse.initdb.scriptsCM" -}} +{{- if .Values.initdb.scriptsConfigMap -}} + {{- printf "%s" (tpl .Values.initdb.scriptsConfigMap $) -}} +{{- else -}} + {{- printf "%s-init-scripts" (include "clickhouse.fullname" .) -}} +{{- end -}} +{{- end -}} + +{{/* +Return the proper Docker Image Registry Secret Names +*/}} +{{- define "clickhouse.imagePullSecrets" -}} +{{ include "cloudpirates.images.renderPullSecrets" (dict "images" (list .Values.image) "context" .) }} +{{- end -}} + +{{/* +Create the name of the service account to use +*/}} +{{- define "clickhouse.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "clickhouse.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/charts/clickhouse/templates/configmap.yaml b/charts/clickhouse/templates/configmap.yaml new file mode 100644 index 000000000..7880d422f --- /dev/null +++ b/charts/clickhouse/templates/configmap.yaml @@ -0,0 +1,71 @@ +{{- if not .Values.config.existingConfigmap }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "clickhouse.configmapName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: + {{- include "clickhouse.annotations" . | nindent 4 }} + {{- end }} +data: + kubernetes.xml: | + + + {{ .Values.config.listenHost }} + {{ .Values.service.httpPort }} + {{ .Values.service.tcpPort }} + {{ .Values.config.maxConnections }} + {{ .Values.config.maxConcurrentQueries }} + {{ .Values.config.timezone }} + + {{ .Values.config.logLevel }} + 1 + + {{- if .Values.config.extraConfig }} + {{ .Values.config.extraConfig | nindent 6 }} + {{- end }} + +{{- end }} +--- +{{- if not .Values.config.existingUsersConfigmap }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "clickhouse.usersConfigmapName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: + {{- include "clickhouse.annotations" . | nindent 4 }} + {{- end }} +data: + kubernetes.xml: | + + + + <{{ .Values.auth.username }}> + + + ::/0 + + default + default + 1 + + + {{- if gt (.Values.config.maxMemoryUsage | int) 0 }} + + + {{ .Values.config.maxMemoryUsage }} + + + {{- end }} + {{- if .Values.config.extraUsersConfig }} + {{ .Values.config.extraUsersConfig | nindent 6 }} + {{- end }} + +{{- end }} diff --git a/charts/clickhouse/templates/extraobjects.yaml b/charts/clickhouse/templates/extraobjects.yaml new file mode 100644 index 000000000..d12e6cc6e --- /dev/null +++ b/charts/clickhouse/templates/extraobjects.yaml @@ -0,0 +1,4 @@ +{{- range .Values.extraObjects }} +--- +{{- include "cloudpirates.tplvalues.render" (dict "value" . "context" $) }} +{{- end }} diff --git a/charts/clickhouse/templates/httproute.yaml b/charts/clickhouse/templates/httproute.yaml new file mode 100644 index 000000000..39761801e --- /dev/null +++ b/charts/clickhouse/templates/httproute.yaml @@ -0,0 +1,69 @@ +{{- if .Values.gatewayAPI.httpRoute.enabled -}} +{{- $fullName := include "clickhouse.fullname" . -}} +{{- $svcPort := .Values.service.httpPort -}} +{{- $httpRoute := .Values.gatewayAPI.httpRoute -}} +{{- $hostnames := $httpRoute.hostnames -}} +{{- if not $hostnames }} +{{- $hostnames = list -}} +{{- range .Values.ingress.hosts -}} +{{- $hostnames = append $hostnames .host -}} +{{- end -}} +{{- end -}} +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: {{ $fullName }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + {{- $annotations := merge $httpRoute.annotations .Values.commonAnnotations }} + {{- with $annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + parentRefs: + {{- range $httpRoute.parentRefs }} + - name: {{ .name }} + {{- if .namespace }} + namespace: {{ .namespace }} + {{- end }} + {{- if .sectionName }} + sectionName: {{ .sectionName }} + {{- end }} + {{- end }} + {{- if $hostnames }} + hostnames: + {{- range $hostnames }} + - {{ . | quote }} + {{- end }} + {{- end }} + rules: + {{- if $httpRoute.rules }} + {{- range $httpRoute.rules }} + - {{- if .matches }} + matches: + {{- range .matches }} + - path: + type: {{ .path.type }} + value: {{ .path.value }} + {{- end }} + {{- end }} + backendRefs: + - name: {{ $fullName }} + port: {{ $svcPort }} + {{- end }} + {{- else }} + {{- range .Values.ingress.hosts }} + {{- range .paths }} + - matches: + - path: + type: {{ if eq .pathType "Exact" }}Exact{{ else }}PathPrefix{{ end }} + value: {{ .path }} + backendRefs: + - name: {{ $fullName }} + port: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/clickhouse/templates/ingress.yaml b/charts/clickhouse/templates/ingress.yaml new file mode 100644 index 000000000..c45ad6e35 --- /dev/null +++ b/charts/clickhouse/templates/ingress.yaml @@ -0,0 +1,52 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "clickhouse.fullname" . -}} +{{- $svcPort := .Values.service.httpPort -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $fullName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + {{- $annotations := merge .Values.ingress.annotations .Values.commonAnnotations }} + {{- with $annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/clickhouse/templates/init-scripts-configmap.yaml b/charts/clickhouse/templates/init-scripts-configmap.yaml new file mode 100644 index 000000000..265df1857 --- /dev/null +++ b/charts/clickhouse/templates/init-scripts-configmap.yaml @@ -0,0 +1,18 @@ +{{- if and .Values.initdb.scripts (not .Values.initdb.scriptsConfigMap) }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "clickhouse.initdb.scriptsCM" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: + {{- include "clickhouse.annotations" . | nindent 4 }} + {{- end }} +data: + {{- range $key, $value := .Values.initdb.scripts }} + {{ $key }}: | + {{- $value | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/clickhouse/templates/secret.yaml b/charts/clickhouse/templates/secret.yaml new file mode 100644 index 000000000..e57ebd46b --- /dev/null +++ b/charts/clickhouse/templates/secret.yaml @@ -0,0 +1,33 @@ +{{- if not .Values.auth.existingSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "clickhouse.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: + {{- include "clickhouse.annotations" . | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- $existingSecret := (lookup "v1" "Secret" .Release.Namespace (include "clickhouse.fullname" .)) }} + {{- $existingPassword := "" }} + {{- if and $existingSecret $existingSecret.data }} + {{- $existingPassword = index $existingSecret.data "clickhouse-password" }} + {{- end }} + {{- $password := $existingPassword | default (.Values.auth.password | default (randAlphaNum 32) | b64enc) }} + {{- $host := printf "%s.%s.svc" (include "clickhouse.fullname" .) .Release.Namespace }} + {{- $tcpPort := .Values.service.tcpPort | toString }} + {{- $httpPort := .Values.service.httpPort | toString }} + {{- $username := .Values.auth.username }} + {{- $database := .Values.auth.database }} + clickhouse-password: {{ $password | quote }} + host: {{ $host | b64enc | quote }} + tcp-port: {{ $tcpPort | b64enc | quote }} + http-port: {{ $httpPort | b64enc | quote }} + username: {{ $username | b64enc | quote }} + database: {{ $database | b64enc | quote }} + uri: {{ printf "clickhouse://%s:%s@%s:%s/%s" $username ($password | b64dec) $host $tcpPort $database | b64enc | quote }} +{{- end }} diff --git a/charts/clickhouse/templates/service-metrics.yaml b/charts/clickhouse/templates/service-metrics.yaml new file mode 100644 index 000000000..4c09929fe --- /dev/null +++ b/charts/clickhouse/templates/service-metrics.yaml @@ -0,0 +1,27 @@ +{{- if .Values.metrics.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "clickhouse.fullname" . }}-metrics + namespace: {{ .Release.Namespace }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + app.kubernetes.io/component: metrics + {{- with .Values.metrics.service.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- $annotations := merge .Values.metrics.service.annotations .Values.commonAnnotations }} + {{- with $annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + ports: + - name: metrics + port: {{ .Values.metrics.service.port }} + protocol: TCP + targetPort: metrics + selector: + {{- include "clickhouse.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/charts/clickhouse/templates/service.yaml b/charts/clickhouse/templates/service.yaml new file mode 100644 index 000000000..1e52e8a33 --- /dev/null +++ b/charts/clickhouse/templates/service.yaml @@ -0,0 +1,61 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "clickhouse.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + {{- $annotations := merge .Values.service.annotations .Values.commonAnnotations }} + {{- with $annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + {{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + {{- if and (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) (not (empty .Values.service.externalTrafficPolicy)) }} + externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }} + {{- end }} + ports: + - port: {{ .Values.service.httpPort }} + targetPort: http + protocol: TCP + name: http + - port: {{ .Values.service.tcpPort }} + targetPort: tcp + {{- if and (or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort")) .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + protocol: TCP + name: tcp + selector: + {{- include "clickhouse.selectorLabels" . | nindent 4 }} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "clickhouse.fullname" . }}-headless + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + {{- $annotations := merge .Values.service.annotations .Values.commonAnnotations }} + {{- with $annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: ClusterIP + clusterIP: None + ports: + - port: {{ .Values.service.httpPort }} + targetPort: http + protocol: TCP + name: http + - port: {{ .Values.service.tcpPort }} + targetPort: tcp + protocol: TCP + name: tcp + selector: + {{- include "clickhouse.selectorLabels" . | nindent 4 }} diff --git a/charts/clickhouse/templates/serviceaccount.yaml b/charts/clickhouse/templates/serviceaccount.yaml new file mode 100644 index 000000000..886225523 --- /dev/null +++ b/charts/clickhouse/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "clickhouse.serviceAccountName" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + {{- $annotations := merge .Values.serviceAccount.annotations .Values.commonAnnotations }} + {{- with $annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/clickhouse/templates/servicemonitor.yaml b/charts/clickhouse/templates/servicemonitor.yaml new file mode 100644 index 000000000..6bc7dd02d --- /dev/null +++ b/charts/clickhouse/templates/servicemonitor.yaml @@ -0,0 +1,52 @@ +{{- if and .Values.metrics.enabled .Values.metrics.serviceMonitor.enabled }} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ include "clickhouse.fullname" . }}-metrics + {{- if .Values.metrics.serviceMonitor.namespace }} + namespace: {{ .Values.metrics.serviceMonitor.namespace }} + {{- else }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + app.kubernetes.io/component: metrics + {{- with .Values.metrics.serviceMonitor.selector }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- $annotations := merge .Values.metrics.serviceMonitor.annotations .Values.commonAnnotations }} + {{- with $annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + jobLabel: {{ include "clickhouse.fullname" . }} + selector: + matchLabels: + {{- include "clickhouse.selectorLabels" . | nindent 6 }} + app.kubernetes.io/component: metrics + endpoints: + - port: metrics + {{- with .Values.metrics.serviceMonitor.interval }} + interval: {{ . }} + {{- end }} + {{- with .Values.metrics.serviceMonitor.scrapeTimeout }} + scrapeTimeout: {{ . }} + {{- end }} + path: /metrics + {{- with .Values.metrics.serviceMonitor.honorLabels }} + honorLabels: {{ . }} + {{- end }} + {{- with .Values.metrics.serviceMonitor.relabelings }} + relabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.metrics.serviceMonitor.metricRelabelings }} + metricRelabelings: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.metrics.serviceMonitor.namespaceSelector }} + namespaceSelector: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/clickhouse/templates/statefulset.yaml b/charts/clickhouse/templates/statefulset.yaml new file mode 100644 index 000000000..9bc2d54ab --- /dev/null +++ b/charts/clickhouse/templates/statefulset.yaml @@ -0,0 +1,260 @@ +{{- $hasInitScripts := or .Values.initdb.scripts .Values.initdb.scriptsConfigMap -}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "clickhouse.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "clickhouse.labels" . | nindent 4 }} + {{- if .Values.commonAnnotations }} + annotations: + {{- include "clickhouse.annotations" . | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.replicaCount }} + serviceName: {{ include "clickhouse.fullname" . }}-headless + updateStrategy: + type: RollingUpdate + selector: + matchLabels: + {{- include "clickhouse.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- $annotations := merge .Values.podAnnotations .Values.commonAnnotations }} + {{- with $annotations }} + annotations: {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "clickhouse.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + serviceAccountName: {{ include "clickhouse.serviceAccountName" . }} + {{- if .Values.priorityClassName }} + priorityClassName: {{ .Values.priorityClassName }} + {{- end }} + automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }} +{{- with (include "clickhouse.imagePullSecrets" .) }} +{{- . | nindent 6 }} +{{- end }} + securityContext: {{ include "cloudpirates.renderPodSecurityContext" . | nindent 8 }} + {{- if .Values.initContainers }} + initContainers: + {{- toYaml .Values.initContainers | nindent 8 }} + {{- end }} + terminationGracePeriodSeconds: {{ .Values.terminationGracePeriodSeconds }} + enableServiceLinks: {{ .Values.global.enableServiceLinks }} + containers: + - name: {{ .Chart.Name }} + securityContext: {{ include "cloudpirates.renderContainerSecurityContext" . | nindent 12 }} + image: {{ include "clickhouse.image" . }} + imagePullPolicy: {{ .Values.image.imagePullPolicy }} + {{- if .Values.command }} + command: {{- toYaml .Values.command | nindent 12 }} + {{- end }} + {{- if .Values.args }} + args: {{- toYaml .Values.args | nindent 12 }} + {{- end }} + env: + - name: CLICKHOUSE_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "clickhouse.secretName" . }} + key: {{ include "clickhouse.passwordKey" . }} + - name: CLICKHOUSE_DB + value: {{ .Values.auth.database | quote }} + - name: CLICKHOUSE_USER + value: {{ .Values.auth.username | quote }} + - name: CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT + value: "1" + {{- with .Values.extraEnvVars }} +{{ toYaml . | indent 12 }} + {{- end }} + {{- if .Values.extraEnvVarsSecret }} + envFrom: + - secretRef: + name: {{ .Values.extraEnvVarsSecret }} + {{- end }} + ports: + - name: http + containerPort: {{ .Values.service.httpPort }} + protocol: TCP + - name: tcp + containerPort: {{ .Values.service.tcpPort }} + protocol: TCP + {{- if .Values.livenessProbe.enabled }} + livenessProbe: + httpGet: + path: /ping + port: http + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + successThreshold: {{ .Values.livenessProbe.successThreshold }} + failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + {{- end }} + {{- if .Values.readinessProbe.enabled }} + readinessProbe: + httpGet: + path: /ping + port: http + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + successThreshold: {{ .Values.readinessProbe.successThreshold }} + failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + {{- end }} + {{- if .Values.startupProbe.enabled }} + startupProbe: + httpGet: + path: /ping + port: http + initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.startupProbe.periodSeconds }} + timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} + successThreshold: {{ .Values.startupProbe.successThreshold }} + failureThreshold: {{ .Values.startupProbe.failureThreshold }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeMounts: + - name: {{ .Values.persistence.volumeName }} + mountPath: /var/lib/clickhouse + {{- if .Values.persistence.subPath }} + subPath: {{ .Values.persistence.subPath }} + {{- end }} + - name: config + mountPath: /etc/clickhouse-server/config.d/kubernetes.xml + subPath: kubernetes.xml + - name: users-config + mountPath: /etc/clickhouse-server/users.d/kubernetes.xml + subPath: kubernetes.xml + - name: tmp + mountPath: /tmp + {{- if $hasInitScripts }} + - name: init-scripts + mountPath: /docker-entrypoint-initdb.d + {{- end }} + {{- if .Values.extraVolumeMounts }} + {{- toYaml .Values.extraVolumeMounts | nindent 12 }} + {{- end }} + {{- if .Values.metrics.enabled }} + - name: metrics + image: "{{ .Values.metrics.image.registry }}/{{ .Values.metrics.image.repository }}:{{ .Values.metrics.image.tag }}" + imagePullPolicy: {{ .Values.metrics.image.pullPolicy }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65534 + runAsGroup: 65534 + env: + - name: CLICKHOUSE_USER + value: {{ .Values.auth.username | quote }} + - name: CLICKHOUSE_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "clickhouse.secretName" . }} + key: {{ include "clickhouse.passwordKey" . }} + - name: CLICKHOUSE_URL + value: "http://localhost:{{ .Values.service.httpPort }}/" + ports: + - name: metrics + containerPort: {{ .Values.metrics.service.port }} + protocol: TCP + startupProbe: + httpGet: + path: /metrics + port: metrics + readinessProbe: + httpGet: + path: /metrics + port: metrics + livenessProbe: + httpGet: + path: /metrics + port: metrics + {{- with .Values.metrics.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + volumes: + {{- if not .Values.persistence.enabled }} + - name: {{ .Values.persistence.volumeName }} + emptyDir: {} + {{- end }} + {{- if .Values.persistence.existingClaim }} + - name: {{ .Values.persistence.volumeName }} + persistentVolumeClaim: + claimName: {{ .Values.persistence.existingClaim }} + {{- end }} + - name: config + configMap: + name: {{ include "clickhouse.configmapName" . }} + - name: users-config + configMap: + name: {{ include "clickhouse.usersConfigmapName" . }} + - name: tmp + emptyDir: {} + {{- if $hasInitScripts }} + - name: init-scripts + configMap: + name: {{ include "clickhouse.initdb.scriptsCM" . }} + defaultMode: 0755 + {{- end }} + {{- if .Values.extraVolumes }} + {{- toYaml .Values.extraVolumes | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.persistence.enabled }} + {{- if .Values.persistentVolumeClaimRetentionPolicy.enabled }} + persistentVolumeClaimRetentionPolicy: + whenDeleted: {{ .Values.persistentVolumeClaimRetentionPolicy.whenDeleted }} + whenScaled: {{ .Values.persistentVolumeClaimRetentionPolicy.whenScaled }} + {{- end }} + {{- if not .Values.persistence.existingClaim }} + volumeClaimTemplates: + - metadata: + name: {{ .Values.persistence.volumeName }} + {{- with $labels := merge (include "clickhouse.selectorLabels" . | fromYaml) .Values.persistence.labels .Values.podLabels }} + labels: + {{- toYaml $labels | nindent 8 }} + {{- end }} + {{- with .Values.persistence.annotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + accessModes: + {{- range .Values.persistence.accessModes }} + - {{ . | quote }} + {{- end }} + resources: + requests: + storage: {{ .Values.persistence.size | quote }} + {{- if .Values.persistence.storageClass }} + {{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.persistence.storageClass | quote }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} diff --git a/charts/clickhouse/tests/common-parameters_test.yaml b/charts/clickhouse/tests/common-parameters_test.yaml new file mode 100644 index 000000000..7fa66a830 --- /dev/null +++ b/charts/clickhouse/tests/common-parameters_test.yaml @@ -0,0 +1,131 @@ +suite: test clickhouse common parameters +templates: + - statefulset.yaml +tests: + - it: should use default values when nothing is overridden + asserts: + - equal: + path: metadata.name + value: RELEASE-NAME-clickhouse + - equal: + path: metadata.labels["app.kubernetes.io/name"] + value: clickhouse + - equal: + path: metadata.labels["app.kubernetes.io/instance"] + value: RELEASE-NAME + - equal: + path: spec.template.spec.containers[0].imagePullPolicy + value: Always + + - it: should respect global.imageRegistry override + set: + global: + imageRegistry: "my-registry.com" + asserts: + - matchRegex: + path: spec.template.spec.containers[0].image + pattern: "^my-registry.com/clickhouse/clickhouse-server:.*" + + - it: should respect global.imagePullSecrets + set: + global: + imagePullSecrets: + - name: my-secret-1 + - name: my-secret-2 + asserts: + - equal: + path: spec.template.spec.imagePullSecrets[0].name + value: my-secret-1 + - equal: + path: spec.template.spec.imagePullSecrets[1].name + value: my-secret-2 + + - it: should respect nameOverride + set: + nameOverride: "custom-name" + asserts: + - equal: + path: metadata.name + value: RELEASE-NAME-custom-name + - equal: + path: metadata.labels["app.kubernetes.io/name"] + value: custom-name + + - it: should respect fullnameOverride + set: + fullnameOverride: "completely-custom-name" + asserts: + - equal: + path: metadata.name + value: completely-custom-name + + - it: should add commonLabels to all resources + set: + commonLabels: + environment: "test" + team: "platform" + asserts: + - equal: + path: metadata.labels.environment + value: test + - equal: + path: metadata.labels.team + value: platform + + - it: should add commonAnnotations to all resources + set: + commonAnnotations: + deployment.kubernetes.io/revision: "1" + prometheus.io/scrape: "true" + asserts: + - equal: + path: metadata.annotations["deployment.kubernetes.io/revision"] + value: "1" + - equal: + path: metadata.annotations["prometheus.io/scrape"] + value: "true" + + - it: should respect image.imagePullPolicy override + set: + image: + imagePullPolicy: "IfNotPresent" + asserts: + - equal: + path: spec.template.spec.containers[0].imagePullPolicy + value: IfNotPresent + + - it: should set CLICKHOUSE_USER env var from values + set: + auth: + username: "myadmin" + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: CLICKHOUSE_USER + value: "myadmin" + + - it: should set CLICKHOUSE_DB env var from values + set: + auth: + database: "mydb" + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: CLICKHOUSE_DB + value: "mydb" + + - it: should set replicaCount + set: + replicaCount: 3 + asserts: + - equal: + path: spec.replicas + value: 3 + + - it: should set the headless service name + asserts: + - equal: + path: spec.serviceName + value: RELEASE-NAME-clickhouse-headless diff --git a/charts/clickhouse/tests/secret_test.yaml b/charts/clickhouse/tests/secret_test.yaml new file mode 100644 index 000000000..a15f4ca8f --- /dev/null +++ b/charts/clickhouse/tests/secret_test.yaml @@ -0,0 +1,43 @@ +suite: test clickhouse secret +templates: + - secret.yaml +tests: + - it: should create secret by default + asserts: + - isKind: + of: Secret + - equal: + path: metadata.name + value: RELEASE-NAME-clickhouse + + - it: should not create secret when existingSecret is set + set: + auth: + existingSecret: "my-existing-secret" + asserts: + - hasDocuments: + count: 0 + + - it: should use provided password when set + set: + auth: + password: "mysecretpassword" + asserts: + - equal: + path: data["clickhouse-password"] + value: bXlzZWNyZXRwYXNzd29yZA== + + - it: should include host and port keys + asserts: + - isNotEmpty: + path: data.host + - isNotEmpty: + path: data["tcp-port"] + - isNotEmpty: + path: data["http-port"] + - isNotEmpty: + path: data.username + - isNotEmpty: + path: data.database + - isNotEmpty: + path: data.uri diff --git a/charts/clickhouse/tests/service_test.yaml b/charts/clickhouse/tests/service_test.yaml new file mode 100644 index 000000000..54e11101d --- /dev/null +++ b/charts/clickhouse/tests/service_test.yaml @@ -0,0 +1,77 @@ +suite: test clickhouse service +templates: + - service.yaml +tests: + - it: should create ClusterIP service by default + documentIndex: 0 + asserts: + - equal: + path: spec.type + value: ClusterIP + - equal: + path: metadata.name + value: RELEASE-NAME-clickhouse + + - it: should expose HTTP port 8123 + documentIndex: 0 + asserts: + - contains: + path: spec.ports + content: + port: 8123 + targetPort: http + protocol: TCP + name: http + + - it: should expose TCP port 9000 + documentIndex: 0 + asserts: + - contains: + path: spec.ports + content: + port: 9000 + targetPort: tcp + protocol: TCP + name: tcp + + - it: should create headless service + documentIndex: 1 + asserts: + - equal: + path: metadata.name + value: RELEASE-NAME-clickhouse-headless + - equal: + path: spec.clusterIP + value: None + + - it: should support custom service ports + set: + service: + httpPort: 8124 + tcpPort: 9001 + documentIndex: 0 + asserts: + - contains: + path: spec.ports + content: + port: 8124 + targetPort: http + protocol: TCP + name: http + - contains: + path: spec.ports + content: + port: 9001 + targetPort: tcp + protocol: TCP + name: tcp + + - it: should support LoadBalancer service type + set: + service: + type: LoadBalancer + documentIndex: 0 + asserts: + - equal: + path: spec.type + value: LoadBalancer diff --git a/charts/clickhouse/tests/volume-claim_test.yaml b/charts/clickhouse/tests/volume-claim_test.yaml new file mode 100644 index 000000000..0eb592a1b --- /dev/null +++ b/charts/clickhouse/tests/volume-claim_test.yaml @@ -0,0 +1,64 @@ +suite: test clickhouse persistence +templates: + - statefulset.yaml +tests: + - it: should create volumeClaimTemplate when persistence is enabled + asserts: + - isNotEmpty: + path: spec.volumeClaimTemplates + - equal: + path: spec.volumeClaimTemplates[0].metadata.name + value: data + - equal: + path: spec.volumeClaimTemplates[0].spec.resources.requests.storage + value: 10Gi + + - it: should use emptyDir when persistence is disabled + set: + persistence: + enabled: false + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: data + emptyDir: {} + + - it: should use existingClaim when set + set: + persistence: + existingClaim: "my-existing-pvc" + asserts: + - contains: + path: spec.template.spec.volumes + content: + name: data + persistentVolumeClaim: + claimName: my-existing-pvc + + - it: should use custom storageClass + set: + persistence: + storageClass: "fast-ssd" + asserts: + - equal: + path: spec.volumeClaimTemplates[0].spec.storageClassName + value: fast-ssd + + - it: should set empty storageClass when set to dash + set: + persistence: + storageClass: "-" + asserts: + - equal: + path: spec.volumeClaimTemplates[0].spec.storageClassName + value: "" + + - it: should use custom persistence size + set: + persistence: + size: 50Gi + asserts: + - equal: + path: spec.volumeClaimTemplates[0].spec.resources.requests.storage + value: 50Gi diff --git a/charts/clickhouse/values.yaml b/charts/clickhouse/values.yaml new file mode 100644 index 000000000..270ce3f16 --- /dev/null +++ b/charts/clickhouse/values.yaml @@ -0,0 +1,351 @@ +## @section Global parameters +global: + ## @param global.imageRegistry Global Docker Image registry + imageRegistry: "" + ## @param global.imagePullSecrets Global Docker registry secret names as an array + imagePullSecrets: [] + enableServiceLinks: true + +## @section Common parameters +## @param nameOverride String to partially override clickhouse.fullname +nameOverride: "" +## @param fullnameOverride String to fully override clickhouse.fullname +fullnameOverride: "" +## @param commonLabels Labels to add to all deployed objects +commonLabels: {} +## @param commonAnnotations Annotations to add to all deployed objects +commonAnnotations: {} +## @param priorityClassName Priority class name to be used for the pods +priorityClassName: "" + +## @param terminationGracePeriodSeconds Time for Kubernetes to wait for the pod to gracefully terminate +terminationGracePeriodSeconds: 30 + +## @section ClickHouse image configuration +image: + ## @param image.registry ClickHouse image registry + registry: docker.io + ## @param image.repository ClickHouse image repository + repository: clickhouse/clickhouse-server + ## @param image.tag ClickHouse image tag (immutable tags are recommended) + tag: "25.3@sha256:b627d7a9bc0e0c1bac26cdbe9d2fc6316faa29c5d8a174f28f5abd57d0fa6ba2" + ## @param image.imagePullPolicy ClickHouse image pull policy + imagePullPolicy: Always + +## @section Deployment configuration +## @param replicaCount Number of ClickHouse replicas to deploy +replicaCount: 1 + +## @section Pod annotations and labels +## @param podAnnotations Map of annotations to add to the pods +podAnnotations: {} +## @param podLabels Map of labels to add to the pods +podLabels: {} + +## @section Security Context +podSecurityContext: + ## @param podSecurityContext.fsGroup Group ID for the volumes of the pod + fsGroup: 101 + +containerSecurityContext: + ## @param containerSecurityContext.allowPrivilegeEscalation Enable container privilege escalation + allowPrivilegeEscalation: false + ## @param containerSecurityContext.runAsNonRoot Configure the container to run as a non-root user + runAsNonRoot: true + ## @param containerSecurityContext.runAsUser User ID for the ClickHouse container + runAsUser: 101 + ## @param containerSecurityContext.runAsGroup Group ID for the ClickHouse container + runAsGroup: 101 + ## @param containerSecurityContext.readOnlyRootFilesystem Mount container root filesystem as read-only + readOnlyRootFilesystem: false + ## @param containerSecurityContext.capabilities.drop Linux capabilities to be dropped + capabilities: + drop: + - ALL + +## @section ClickHouse Authentication +auth: + ## @param auth.username ClickHouse admin username + username: "default" + ## @param auth.password Password for the ClickHouse admin user (auto-generated if empty) + password: "" + ## @param auth.database Default database to create at initialisation + database: "default" + ## @param auth.existingSecret Name of existing secret to use for ClickHouse credentials + existingSecret: "" + secretKeys: + ## @param auth.secretKeys.passwordKey Name of key in existing secret for ClickHouse admin password + passwordKey: "clickhouse-password" + +## @section ClickHouse Configuration +config: + ## @param config.existingConfigmap Name of existing ConfigMap with ClickHouse configuration (config.xml) + existingConfigmap: "" + ## @param config.existingUsersConfigmap Name of existing ConfigMap with ClickHouse users configuration (users.xml) + existingUsersConfigmap: "" + ## @param config.listenHost Listen host for ClickHouse (default: listen on all interfaces) + listenHost: "0.0.0.0" + ## @param config.maxConnections Maximum number of simultaneous client connections + maxConnections: 4096 + ## @param config.maxConcurrentQueries Maximum number of simultaneously processed queries + maxConcurrentQueries: 100 + ## @param config.maxMemoryUsage Maximum memory usage for a single query in bytes (0 = unlimited) + maxMemoryUsage: 0 + ## @param config.timezone Default timezone + timezone: "UTC" + ## @param config.logLevel Log level (trace, debug, information, warning, error, fatal) + logLevel: "information" + ## @param config.extraConfig Additional ClickHouse XML configuration snippets merged into config.xml + extraConfig: "" + ## @param config.extraUsersConfig Additional ClickHouse XML configuration snippets merged into users.xml + extraUsersConfig: "" + +## @section ClickHouse Initialization scripts +initdb: + ## @param initdb.scripts Dictionary of SQL scripts to run at first boot (key: filename, value: SQL content) + scripts: {} + ## @param initdb.scriptsConfigMap ConfigMap with SQL scripts to be run at first boot + scriptsConfigMap: "" + +## @section Service configuration +service: + ## @param service.type ClickHouse service type + type: ClusterIP + ## @param service.httpPort ClickHouse HTTP interface port + httpPort: 8123 + ## @param service.tcpPort ClickHouse TCP (native) interface port + tcpPort: 9000 + ## @param service.nodePort NodePort for TCP service (only used when type=NodePort) + nodePort: 30900 + ## @param service.annotations Service annotations + annotations: {} + ## @param service.loadBalancerIP LoadBalancer IP if service type is `LoadBalancer` + loadBalancerIP: "" + ## @param service.externalTrafficPolicy External traffic policy for the service + externalTrafficPolicy: "" + +## @section Ingress configuration +ingress: + ## @param ingress.enabled Enable ingress record generation for ClickHouse HTTP interface + enabled: false + ## @param ingress.className IngressClass that will be used to implement the Ingress + className: "" + ## @param ingress.annotations Additional annotations for the Ingress resource + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + ## @param ingress.hosts[0].host Hostname for ClickHouse ingress + ## @param ingress.hosts[0].paths[0].path Path for ClickHouse ingress + ## @param ingress.hosts[0].paths[0].pathType Path type for ClickHouse ingress + hosts: + - host: clickhouse.local + paths: + - path: / + pathType: Prefix + ## @param ingress.tls TLS configuration for ClickHouse ingress + tls: [] + # - secretName: clickhouse-tls + # hosts: + # - clickhouse.local + +## @section Gateway API parameters +gatewayAPI: + httpRoute: + ## @param gatewayAPI.httpRoute.enabled Enable Gateway API HTTPRoute generation for ClickHouse + enabled: false + ## @param gatewayAPI.httpRoute.annotations Additional annotations for the HTTPRoute resource + annotations: {} + ## @param gatewayAPI.httpRoute.parentRefs References to the parent Gateways + parentRefs: + - name: gateway + namespace: "" + sectionName: "" + ## @param gatewayAPI.httpRoute.hostnames List of hostnames to match + hostnames: + - clickhouse.local + ## @param gatewayAPI.httpRoute.rules HTTPRoute rules + rules: + - matches: + - path: + type: PathPrefix + value: / + +## @section Resources +resources: {} + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: "2" + # memory: 4Gi + # requests: + # cpu: 500m + # memory: 1Gi + +## @section Persistence +persistence: + ## @param persistence.enabled Enable persistence using Persistent Volume Claims + enabled: true + ## @param persistence.storageClass Persistent Volume storage class + storageClass: "" + ## @param persistence.annotations Persistent Volume Claim annotations + annotations: {} + ## @param persistence.size Persistent Volume size + size: 10Gi + ## @param persistence.accessModes Persistent Volume access modes + accessModes: + - ReadWriteOnce + ## @param persistence.existingClaim The name of an existing PVC to use for persistence + existingClaim: "" + ## @param persistence.subPath The subdirectory of the volume to mount to + subPath: "" + ## @param persistence.labels Labels for persistent volume claims + labels: {} + ## @param persistence.volumeName Container volume name and volume claim prefix + volumeName: "data" + +## @section Persistent Volume Claim Retention Policy +persistentVolumeClaimRetentionPolicy: + ## @param persistentVolumeClaimRetentionPolicy.enabled Enable Persistent volume retention policy for the Statefulset + enabled: false + ## @param persistentVolumeClaimRetentionPolicy.whenScaled Volume retention behavior when the replica count of the StatefulSet is reduced + whenScaled: Retain + ## @param persistentVolumeClaimRetentionPolicy.whenDeleted Volume retention behavior that applies when the StatefulSet is deleted + whenDeleted: Retain + +## @section Liveness and readiness probes +livenessProbe: + ## @param livenessProbe.enabled Enable livenessProbe on ClickHouse containers + enabled: true + ## @param livenessProbe.initialDelaySeconds Initial delay seconds for livenessProbe + initialDelaySeconds: 30 + ## @param livenessProbe.periodSeconds Period seconds for livenessProbe + periodSeconds: 10 + ## @param livenessProbe.timeoutSeconds Timeout seconds for livenessProbe + timeoutSeconds: 5 + ## @param livenessProbe.failureThreshold Failure threshold for livenessProbe + failureThreshold: 3 + ## @param livenessProbe.successThreshold Success threshold for livenessProbe + successThreshold: 1 + +readinessProbe: + ## @param readinessProbe.enabled Enable readinessProbe on ClickHouse containers + enabled: true + ## @param readinessProbe.initialDelaySeconds Initial delay seconds for readinessProbe + initialDelaySeconds: 10 + ## @param readinessProbe.periodSeconds Period seconds for readinessProbe + periodSeconds: 5 + ## @param readinessProbe.timeoutSeconds Timeout seconds for readinessProbe + timeoutSeconds: 5 + ## @param readinessProbe.failureThreshold Failure threshold for readinessProbe + failureThreshold: 3 + ## @param readinessProbe.successThreshold Success threshold for readinessProbe + successThreshold: 1 + +startupProbe: + ## @param startupProbe.enabled Enable startupProbe on ClickHouse containers + enabled: true + ## @param startupProbe.initialDelaySeconds Initial delay seconds for startupProbe + initialDelaySeconds: 30 + ## @param startupProbe.periodSeconds Period seconds for startupProbe + periodSeconds: 10 + ## @param startupProbe.timeoutSeconds Timeout seconds for startupProbe + timeoutSeconds: 5 + ## @param startupProbe.failureThreshold Failure threshold for startupProbe + failureThreshold: 30 + ## @param startupProbe.successThreshold Success threshold for startupProbe + successThreshold: 1 + +## @section Node Selection +## @param nodeSelector Node labels for pod assignment +nodeSelector: {} + +## @param tolerations Toleration labels for pod assignment +tolerations: [] + +## @param affinity Affinity settings for pod assignment +affinity: {} + +## @section Service Account +serviceAccount: + ## @param serviceAccount.create Specifies whether a service account should be created + create: false + ## @param serviceAccount.annotations Annotations to add to the service account + annotations: {} + ## @param serviceAccount.name The name of the service account to use. If not set and create is true, a name is generated using the `fullname` template. + name: "" + ## @param serviceAccount.automountServiceAccountToken whether to automount the SA token inside the pod + automountServiceAccountToken: false + +## @param extraEnvVars Additional environment variables to set +extraEnvVars: [] + # - name: CUSTOM_VAR + # value: "custom-value" + +## @param extraEnvVarsSecret Name of a secret containing additional environment variables +extraEnvVarsSecret: "" + +## @param extraVolumes Additional volumes to add to the pod +extraVolumes: [] + +## @param extraVolumeMounts Additional volume mounts to add to the ClickHouse container +extraVolumeMounts: [] + +## @param initContainers Init containers to add to the ClickHouse pods +initContainers: [] + +## @param command Override default container command +command: [] + +## @param args Override default container args +args: [] + +## @param extraObjects Array of extra objects to deploy with the release +extraObjects: [] + +## @section Metrics configuration +metrics: + ## @param metrics.enabled Start a sidecar prometheus exporter to expose ClickHouse metrics + enabled: false + image: + ## @param metrics.image.registry ClickHouse exporter image registry + registry: docker.io + ## @param metrics.image.repository ClickHouse exporter image repository + repository: altinity/clickhouse-exporter + ## @param metrics.image.tag ClickHouse exporter image tag + tag: "0.0.2@sha256:d19bb9e5e42c3eedbb14e1da7e43b59de86cf87b0012f9acb6c7d74e69cefb58" + ## @param metrics.image.pullPolicy ClickHouse exporter image pull policy + pullPolicy: Always + ## @param metrics.resources Resource limits and requests for metrics container + resources: {} + ## Metrics service configuration + service: + ## @param metrics.service.annotations Additional custom annotations for Metrics service + annotations: {} + ## @param metrics.service.labels Additional custom labels for Metrics service + labels: {} + ## @param metrics.service.port Metrics service port + port: 9116 + ## Prometheus Operator ServiceMonitor configuration + serviceMonitor: + ## @param metrics.serviceMonitor.enabled Create ServiceMonitor resource(s) for scraping metrics using PrometheusOperator + enabled: false + ## @param metrics.serviceMonitor.namespace The namespace in which the ServiceMonitor will be created + namespace: "" + ## @param metrics.serviceMonitor.interval The interval at which metrics should be scraped + interval: 30s + ## @param metrics.serviceMonitor.scrapeTimeout The timeout after which the scrape is ended + scrapeTimeout: 10s + ## @param metrics.serviceMonitor.selector Additional labels for ServiceMonitor resource + selector: {} + ## @param metrics.serviceMonitor.annotations ServiceMonitor annotations + annotations: {} + ## @param metrics.serviceMonitor.honorLabels honorLabels chooses the metric's labels on collisions with target labels + honorLabels: false + ## @param metrics.serviceMonitor.relabelings ServiceMonitor relabel configs to apply to samples before scraping + relabelings: [] + ## @param metrics.serviceMonitor.metricRelabelings ServiceMonitor metricRelabelings configs to apply to samples before ingestion + metricRelabelings: [] + ## @param metrics.serviceMonitor.namespaceSelector ServiceMonitor namespace selector + namespaceSelector: {} From 60661c3c7f3713983ab5c2a795fa31d3adace161 Mon Sep 17 00:00:00 2001 From: cloudpirates-bot Date: Tue, 31 Mar 2026 07:33:09 +0000 Subject: [PATCH 2/2] chore: auto-generate values.schema.json Signed-off-by: cloudpirates-bot --- charts/clickhouse/values.schema.json | 556 +++++++++++++++++++++++++++ 1 file changed, 556 insertions(+) create mode 100644 charts/clickhouse/values.schema.json diff --git a/charts/clickhouse/values.schema.json b/charts/clickhouse/values.schema.json new file mode 100644 index 000000000..66cc34cbc --- /dev/null +++ b/charts/clickhouse/values.schema.json @@ -0,0 +1,556 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "affinity": { + "type": "object" + }, + "args": { + "type": "array" + }, + "auth": { + "type": "object", + "properties": { + "database": { + "type": "string" + }, + "existingSecret": { + "type": "string" + }, + "password": { + "type": "string" + }, + "secretKeys": { + "type": "object", + "properties": { + "passwordKey": { + "type": "string" + } + } + }, + "username": { + "type": "string" + } + } + }, + "command": { + "type": "array" + }, + "commonAnnotations": { + "type": "object" + }, + "commonLabels": { + "type": "object" + }, + "config": { + "type": "object", + "properties": { + "existingConfigmap": { + "type": "string" + }, + "existingUsersConfigmap": { + "type": "string" + }, + "extraConfig": { + "type": "string" + }, + "extraUsersConfig": { + "type": "string" + }, + "listenHost": { + "type": "string" + }, + "logLevel": { + "type": "string" + }, + "maxConcurrentQueries": { + "type": "integer" + }, + "maxConnections": { + "type": "integer" + }, + "maxMemoryUsage": { + "type": "integer" + }, + "timezone": { + "type": "string" + } + } + }, + "containerSecurityContext": { + "type": "object", + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "capabilities": { + "type": "object", + "properties": { + "drop": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsGroup": { + "type": "integer" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + } + } + }, + "extraEnvVars": { + "type": "array" + }, + "extraEnvVarsSecret": { + "type": "string" + }, + "extraObjects": { + "type": "array" + }, + "extraVolumeMounts": { + "type": "array" + }, + "extraVolumes": { + "type": "array" + }, + "fullnameOverride": { + "type": "string" + }, + "gatewayAPI": { + "type": "object", + "properties": { + "httpRoute": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "hostnames": { + "type": "array", + "items": { + "type": "string" + } + }, + "parentRefs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "namespace": { + "type": "string" + }, + "sectionName": { + "type": "string" + } + } + } + }, + "rules": { + "type": "array", + "items": { + "type": "object", + "properties": { + "matches": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + } + } + } + } + } + } + } + } + }, + "global": { + "type": "object", + "properties": { + "enableServiceLinks": { + "type": "boolean" + }, + "imagePullSecrets": { + "type": "array" + }, + "imageRegistry": { + "type": "string" + } + } + }, + "image": { + "type": "object", + "properties": { + "imagePullPolicy": { + "type": "string" + }, + "registry": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "ingress": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "className": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "hosts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "paths": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "pathType": { + "type": "string" + } + } + } + } + } + } + }, + "tls": { + "type": "array" + } + } + }, + "initContainers": { + "type": "array" + }, + "initdb": { + "type": "object", + "properties": { + "scripts": { + "type": "object" + }, + "scriptsConfigMap": { + "type": "string" + } + } + }, + "livenessProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + } + }, + "metrics": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "image": { + "type": "object", + "properties": { + "pullPolicy": { + "type": "string" + }, + "registry": { + "type": "string" + }, + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "resources": { + "type": "object" + }, + "service": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "labels": { + "type": "object" + }, + "port": { + "type": "integer" + } + } + }, + "serviceMonitor": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "honorLabels": { + "type": "boolean" + }, + "interval": { + "type": "string" + }, + "metricRelabelings": { + "type": "array" + }, + "namespace": { + "type": "string" + }, + "namespaceSelector": { + "type": "object" + }, + "relabelings": { + "type": "array" + }, + "scrapeTimeout": { + "type": "string" + }, + "selector": { + "type": "object" + } + } + } + } + }, + "nameOverride": { + "type": "string" + }, + "nodeSelector": { + "type": "object" + }, + "persistence": { + "type": "object", + "properties": { + "accessModes": { + "type": "array", + "items": { + "type": "string" + } + }, + "annotations": { + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "existingClaim": { + "type": "string" + }, + "labels": { + "type": "object" + }, + "size": { + "type": "string" + }, + "storageClass": { + "type": "string" + }, + "subPath": { + "type": "string" + }, + "volumeName": { + "type": "string" + } + } + }, + "persistentVolumeClaimRetentionPolicy": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "whenDeleted": { + "type": "string" + }, + "whenScaled": { + "type": "string" + } + } + }, + "podAnnotations": { + "type": "object" + }, + "podLabels": { + "type": "object" + }, + "podSecurityContext": { + "type": "object", + "properties": { + "fsGroup": { + "type": "integer" + } + } + }, + "priorityClassName": { + "type": "string" + }, + "readinessProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + } + }, + "replicaCount": { + "type": "integer" + }, + "resources": { + "type": "object" + }, + "service": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "externalTrafficPolicy": { + "type": "string" + }, + "httpPort": { + "type": "integer" + }, + "loadBalancerIP": { + "type": "string" + }, + "nodePort": { + "type": "integer" + }, + "tcpPort": { + "type": "integer" + }, + "type": { + "type": "string" + } + } + }, + "serviceAccount": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + }, + "automountServiceAccountToken": { + "type": "boolean" + }, + "create": { + "type": "boolean" + }, + "name": { + "type": "string" + } + } + }, + "startupProbe": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + }, + "successThreshold": { + "type": "integer" + }, + "timeoutSeconds": { + "type": "integer" + } + } + }, + "terminationGracePeriodSeconds": { + "type": "integer" + }, + "tolerations": { + "type": "array" + } + } +}