diff --git a/helm/tansu/.gitignore b/helm/tansu/.gitignore new file mode 100644 index 00000000..2cb5f760 --- /dev/null +++ b/helm/tansu/.gitignore @@ -0,0 +1,3 @@ +# Helm +Chart.lock +*.tgz diff --git a/helm/tansu/Chart.yaml b/helm/tansu/Chart.yaml new file mode 100644 index 00000000..1c1cab36 --- /dev/null +++ b/helm/tansu/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +name: tansu +description: Tansu - Apache Kafka-compatible broker with pluggable storage backends +type: application +version: 0.1.0 +appVersion: "1" +keywords: + - kafka + - message-broker + - event-streaming +maintainers: [] +home: https://github.com/tansu-io/tansu +sources: [] +license: Apache-2.0 diff --git a/helm/tansu/README.md b/helm/tansu/README.md new file mode 100644 index 00000000..f63d8900 --- /dev/null +++ b/helm/tansu/README.md @@ -0,0 +1,173 @@ +# Tansu Helm Chart + +[Tansu](https://github.com/tansu-io/tansu) is an Apache Kafka-compatible broker with pluggable storage backends. This chart runs the Tansu broker as a Deployment with configurable replicas, autoscaling, and storage engine. + +## Prerequisites + +- Kubernetes 1.23+ +- Helm 3+ + +## Install + +```bash +helm repo add tansu https://tansu-io.github.io/tansu +helm install tansu ./helm/tansu +``` + +## Configuration + +### Replicas and autoscaling + +- **Replicas**: Set `replicaCount` (used when autoscaling is disabled). +- **Autoscaling**: Enable HPA with `autoscaling.enabled: true`, then set: + - `autoscaling.minReplicas` / `autoscaling.maxReplicas` + - `autoscaling.targetCPUUtilizationPercentage` (and optionally `targetMemoryUtilizationPercentage`) + +Example: + +```yaml +replicaCount: 2 + +autoscaling: + enabled: true + minReplicas: 2 + maxReplicas: 10 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: 80 +``` + +### Storage engine + +Set `storageEngine.type` to one of: **memory**, **s3**, **postgres**, **sqlite**. + +| Type | Use case | Required config | +|-----------|------------------|-----------------| +| `memory` | Dev / tests | `storageEngine.memory.prefix` (default `tansu`) | +| `s3` | Production (S3) | `storageEngine.s3.bucket`, and credentials via `storageEngine.s3.existingSecret` (keys `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`). Optional: `endpoint`, `region`, `allowHttp` | +| `postgres`| Production | `storageEngine.postgres.host`, `user`, `database`. Set `storageEngine.postgres.password` or use `storageEngine.postgres.existingSecret` (key `password`) for the DB password | +| `sqlite` | Single-node / dev | `storageEngine.sqlite.path` (default `/data/tansu.db`). Uses `emptyDir` by default; for persistence use `extraVolumes` / `extraVolumeMounts` with a PVC | + +Example – S3 with existing secret: + +```yaml +storageEngine: + type: s3 + s3: + bucket: tansu + region: eu-west-2 + endpoint: "" # omit for default AWS + allowHttp: "true" + existingSecret: tansu-s3-credentials +``` + +Example – Postgres with password from secret: + +```yaml +storageEngine: + type: postgres + postgres: + host: postgres + port: 5432 + database: postgres + user: postgres + existingSecret: tansu-postgres-password + existingSecretPasswordKey: password +``` + +For a fully custom storage URL (e.g. postgres URL with special characters), use a Secret and reference it: + +```yaml +storageUrlFromSecret: + name: tansu-storage-url + key: STORAGE_ENGINE +``` + +Create the secret with the exact URL, e.g.: + +```bash +kubectl create secret generic tansu-storage-url --from-literal=STORAGE_ENGINE='postgres://user:pass@host:5432/db' +``` + +### Image + +Default image: `ghcr.io/tansu-io/tansu`. Override with: + +```yaml +image: + repository: ghcr.io/tansu-io/tansu + tag: "v1.0.0" + pullPolicy: IfNotPresent +``` + +### Advertised listener + +Clients use the advertised listener to connect. In-cluster default is `tansu:9092`. For a specific namespace or release name: + +```yaml +advertisedListener: "tansu.my-namespace.svc.cluster.local:9092" +``` + +### Kafka LoadBalancer + +To expose Kafka (TCP 9092) externally via a cloud LoadBalancer, enable the dedicated Kafka LoadBalancer service. The main service stays ClusterIP for in-cluster traffic. + +```yaml +kafkaLoadBalancer: + enabled: true + port: 9092 + # annotations: # optional, e.g. for AWS NLB + # service.beta.kubernetes.io/aws-load-balancer-type: "nlb" + # service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing" +``` + +Set `advertisedListener` to the external host and port clients will use (e.g. the LoadBalancer hostname or IP and `9092`), so broker metadata points clients to the right address. + +### Ingress + +Standard Ingress is HTTP/HTTPS only. The chart defaults the Ingress backend to the **metrics** port (9100). For Kafka (TCP 9092), use the Kafka LoadBalancer above or NodePort. + +Enable and configure Ingress: + +```yaml +ingress: + enabled: true + className: nginx + hosts: + - host: tansu.example.com + paths: + - path: / + pathType: Prefix + port: metrics + tls: + - secretName: tansu-tls + hosts: + - tansu.example.com +``` + +## Values reference + +| Key | Default | Description | +|-----|---------|-------------| +| `replicaCount` | `1` | Number of replicas when autoscaling is disabled | +| `autoscaling.enabled` | `false` | Enable HorizontalPodAutoscaler | +| `autoscaling.minReplicas` | `1` | Minimum replicas under HPA | +| `autoscaling.maxReplicas` | `10` | Maximum replicas under HPA | +| `autoscaling.targetCPUUtilizationPercentage` | `70` | Target CPU % for HPA | +| `storageEngine.type` | `memory` | One of: `memory`, `s3`, `postgres`, `sqlite` | +| `image.repository` | `ghcr.io/tansu-io/tansu` | Container image | +| `image.tag` | (chart appVersion) | Image tag | +| `clusterId` | `tansu` | Kafka cluster ID | +| `advertisedListener` | `tansu:9092` | Advertised listener URL host:port | +| `service.kafkaPort` | `9092` | Kafka port | +| `service.metricsPort` | `9100` | Metrics port | +| `kafkaLoadBalancer.enabled` | `false` | Create a LoadBalancer/NodePort service for Kafka TCP | +| `kafkaLoadBalancer.serviceType` | `LoadBalancer` | `LoadBalancer` (cloud) or `NodePort` (local k8s) | +| `kafkaLoadBalancer.nodePort` | `null` | For NodePort: fixed port (e.g. 30092); omit for auto | +| `kafkaLoadBalancer.port` | `9092` | Service port | +| `kafkaLoadBalancer.annotations` | `{}` | Annotations (e.g. AWS NLB type) | +| `ingress.enabled` | `false` | Enable Ingress (HTTP; for metrics) | +| `ingress.className` | `""` | IngressClass name (e.g. nginx) | +| `ingress.hosts` | see values | Hosts and paths (default: metrics port) | +| `ingress.tls` | `[]` | TLS secret and hosts | + +See [values.yaml](values.yaml) for all options. diff --git a/helm/tansu/templates/NOTES.txt b/helm/tansu/templates/NOTES.txt new file mode 100644 index 00000000..176c6fbc --- /dev/null +++ b/helm/tansu/templates/NOTES.txt @@ -0,0 +1,7 @@ +1. Kafka bootstrap (in-cluster): + {{ include "tansu.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local:{{ .Values.service.kafkaPort }} + +2. Connect to the broker (in-cluster): + kafka-bootstrap-servers: {{ include "tansu.fullname" . }}.{{ .Release.Namespace }}.svc:{{ .Values.service.kafkaPort }} + +3. Storage engine: {{ .Values.storageEngine.type }} diff --git a/helm/tansu/templates/_helpers.tpl b/helm/tansu/templates/_helpers.tpl new file mode 100644 index 00000000..465d71da --- /dev/null +++ b/helm/tansu/templates/_helpers.tpl @@ -0,0 +1,86 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "tansu.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "tansu.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "tansu.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "tansu.labels" -}} +helm.sh/chart: {{ include "tansu.chart" . }} +{{ include "tansu.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "tansu.selectorLabels" -}} +app.kubernetes.io/name: {{ include "tansu.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Storage engine URL from values (when not using storageUrlFromSecret). +For postgres with password from secret, use storageUrlFromSecret with a secret containing the full URL. +*/}} +{{- define "tansu.storageEngineUrl" -}} +{{- $type := .Values.storageEngine.type -}} +{{- if eq $type "memory" -}} +memory://{{ .Values.storageEngine.memory.prefix }}/ +{{- else if eq $type "s3" -}} +s3://{{ .Values.storageEngine.s3.bucket }}/{{ .Values.storageEngine.s3.path | trimSuffix "/" }}{{- if .Values.storageEngine.s3.path }}/{{ end }} +{{- else if eq $type "postgres" -}} +postgres://{{ .Values.storageEngine.postgres.user }}:{{ .Values.storageEngine.postgres.password | default "" }}@{{ .Values.storageEngine.postgres.host }}:{{ .Values.storageEngine.postgres.port }}/{{ .Values.storageEngine.postgres.database }} +{{- else if eq $type "sqlite" -}} +sqlite://{{ .Values.storageEngine.sqlite.path }} +{{- else -}} +memory://tansu/ +{{- end -}} +{{- end }} + +{{/* +Whether storage URL comes from a secret (key STORAGE_ENGINE). +*/}} +{{- define "tansu.storageUrlFromSecret" -}} +{{- if and .Values.storageUrlFromSecret .Values.storageUrlFromSecret.name .Values.storageUrlFromSecret.key }}true{{ end }} +{{- end }} + +{{/* +ServiceAccount name. +*/}} +{{- define "tansu.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "tansu.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/tansu/templates/deployment.yaml b/helm/tansu/templates/deployment.yaml new file mode 100644 index 00000000..a0a3fb8f --- /dev/null +++ b/helm/tansu/templates/deployment.yaml @@ -0,0 +1,166 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "tansu.fullname" . }} + labels: + {{- include "tansu.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "tansu.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "tansu.labels" . | nindent 8 }} + spec: + {{- with .Values.serviceAccount }} + serviceAccountName: {{ include "tansu.serviceAccountName" $ }} + {{- end }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: tansu + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + {{- if and (not (eq (include "tansu.storageUrlFromSecret" .) "true")) (not (and (eq .Values.storageEngine.type "postgres") .Values.storageEngine.postgres.existingSecret)) }} + args: + - broker + - --kafka-cluster-id + - {{ .Values.clusterId | quote }} + - --kafka-listener-url + - "tcp://0.0.0.0:{{ .Values.service.kafkaPort }}/" + - --kafka-advertised-listener-url + - "tcp://{{ .Values.advertisedListener }}" + - --storage-engine + - {{ include "tansu.storageEngineUrl" . | quote }} + {{- if .Values.schemaRegistry }} + - --schema-registry + - {{ .Values.schemaRegistry | quote }} + {{- end }} + {{- end }} + env: + - name: RUST_LOG + value: {{ .Values.rustLog | quote }} + - name: RUST_BACKTRACE + value: {{ .Values.rustBacktrace | quote }} + {{- if eq .Values.storageEngine.type "s3" }} + - name: AWS_DEFAULT_REGION + value: {{ .Values.storageEngine.s3.region | quote }} + {{- if .Values.storageEngine.s3.endpoint }} + - name: AWS_ENDPOINT + value: {{ .Values.storageEngine.s3.endpoint | quote }} + {{- end }} + - name: AWS_ALLOW_HTTP + value: {{ .Values.storageEngine.s3.allowHttp | quote }} + {{- if .Values.storageEngine.s3.existingSecret }} + - name: AWS_ACCESS_KEY_ID + valueFrom: + secretKeyRef: + name: {{ .Values.storageEngine.s3.existingSecret }} + key: {{ .Values.storageEngine.s3.existingSecretAccessKeyIdKey }} + - name: AWS_SECRET_ACCESS_KEY + valueFrom: + secretKeyRef: + name: {{ .Values.storageEngine.s3.existingSecret }} + key: {{ .Values.storageEngine.s3.existingSecretAccessKeyKey }} + {{- end }} + {{- end }} + {{- if and (eq .Values.storageEngine.type "postgres") .Values.storageEngine.postgres.existingSecret }} + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: {{ .Values.storageEngine.postgres.existingSecret }} + key: {{ .Values.storageEngine.postgres.existingSecretPasswordKey }} + {{- end }} + {{- range $key, $val := .Values.extraEnv }} + - name: {{ $key }} + value: {{ $val | quote }} + {{- end }} + {{- if or (eq (include "tansu.storageUrlFromSecret" .) "true") (and (eq .Values.storageEngine.type "postgres") .Values.storageEngine.postgres.existingSecret) }} + command: + - /bin/sh + - -c + - | + {{- if eq (include "tansu.storageUrlFromSecret" .) "true" }} + export STORAGE_ENGINE=$(cat /etc/tansu-storage/STORAGE_ENGINE) + {{- else }} + export STORAGE_ENGINE="postgres://{{ .Values.storageEngine.postgres.user }}:${POSTGRES_PASSWORD}@{{ .Values.storageEngine.postgres.host }}:{{ .Values.storageEngine.postgres.port }}/{{ .Values.storageEngine.postgres.database }}" + {{- end }} + exec tansu broker \ + --kafka-cluster-id {{ .Values.clusterId | quote }} \ + --kafka-listener-url "tcp://0.0.0.0:{{ .Values.service.kafkaPort }}/" \ + --kafka-advertised-listener-url "tcp://{{ .Values.advertisedListener }}" \ + --storage-engine "$STORAGE_ENGINE" \ + {{- if .Values.schemaRegistry }} + --schema-registry {{ .Values.schemaRegistry | quote }} + {{- end }} + {{- end }} + ports: + - name: kafka + containerPort: {{ .Values.service.kafkaPort }} + protocol: TCP + - name: metrics + containerPort: {{ .Values.service.metricsPort }} + protocol: TCP + livenessProbe: + tcpSocket: + port: kafka + initialDelaySeconds: 10 + periodSeconds: 10 + readinessProbe: + tcpSocket: + port: kafka + initialDelaySeconds: 5 + periodSeconds: 5 + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + {{- if eq (include "tansu.storageUrlFromSecret" .) "true" }} + - name: storage-url + mountPath: /etc/tansu-storage + readOnly: true + {{- end }} + {{- if eq .Values.storageEngine.type "sqlite" }} + - name: data + mountPath: {{ .Values.storageEngine.sqlite.path | dir }} + {{- end }} + {{- with .Values.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if or (eq (include "tansu.storageUrlFromSecret" .) "true") (eq .Values.storageEngine.type "sqlite") .Values.extraVolumes }} + volumes: + {{- if eq (include "tansu.storageUrlFromSecret" .) "true" }} + - name: storage-url + secret: + secretName: {{ .Values.storageUrlFromSecret.name }} + items: + - key: {{ .Values.storageUrlFromSecret.key }} + path: STORAGE_ENGINE + {{- end }} + {{- if eq .Values.storageEngine.type "sqlite" }} + - name: data + emptyDir: {} + {{- end }} + {{- with .Values.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- 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 }} diff --git a/helm/tansu/templates/hpa.yaml b/helm/tansu/templates/hpa.yaml new file mode 100644 index 00000000..11c59788 --- /dev/null +++ b/helm/tansu/templates/hpa.yaml @@ -0,0 +1,30 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "tansu.fullname" . }} + labels: + {{- include "tansu.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "tansu.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/tansu/templates/ingress.yaml b/helm/tansu/templates/ingress.yaml new file mode 100644 index 00000000..bebea192 --- /dev/null +++ b/helm/tansu/templates/ingress.yaml @@ -0,0 +1,45 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "tansu.fullname" . }} + labels: + {{- include "tansu.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.className }} + 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 }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "tansu.fullname" $ }} + port: + {{- if kindIs "string" .port }} + name: {{ .port }} + {{- else }} + number: {{ .port }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/tansu/templates/service-kafka-lb.yaml b/helm/tansu/templates/service-kafka-lb.yaml new file mode 100644 index 00000000..9a3c5e27 --- /dev/null +++ b/helm/tansu/templates/service-kafka-lb.yaml @@ -0,0 +1,25 @@ +{{- if .Values.kafkaLoadBalancer.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "tansu.fullname" . }}-kafka + labels: + {{- include "tansu.labels" . | nindent 4 }} + app.kubernetes.io/component: kafka-lb + {{- with .Values.kafkaLoadBalancer.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.kafkaLoadBalancer.serviceType }} + ports: + - port: {{ .Values.kafkaLoadBalancer.port }} + targetPort: kafka + protocol: TCP + name: kafka + {{- if and (eq .Values.kafkaLoadBalancer.serviceType "NodePort") .Values.kafkaLoadBalancer.nodePort }} + nodePort: {{ .Values.kafkaLoadBalancer.nodePort }} + {{- end }} + selector: + {{- include "tansu.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/helm/tansu/templates/service.yaml b/helm/tansu/templates/service.yaml new file mode 100644 index 00000000..bab18880 --- /dev/null +++ b/helm/tansu/templates/service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "tansu.fullname" . }} + labels: + {{- include "tansu.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.kafkaPort }} + targetPort: kafka + protocol: TCP + name: kafka + - port: {{ .Values.service.metricsPort }} + targetPort: metrics + protocol: TCP + name: metrics + selector: + {{- include "tansu.selectorLabels" . | nindent 4 }} diff --git a/helm/tansu/templates/serviceaccount.yaml b/helm/tansu/templates/serviceaccount.yaml new file mode 100644 index 00000000..1c04e253 --- /dev/null +++ b/helm/tansu/templates/serviceaccount.yaml @@ -0,0 +1,8 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "tansu.serviceAccountName" . }} + labels: + {{- include "tansu.labels" . | nindent 4 }} +{{- end }} diff --git a/helm/tansu/values.yaml b/helm/tansu/values.yaml new file mode 100644 index 00000000..9f667e91 --- /dev/null +++ b/helm/tansu/values.yaml @@ -0,0 +1,149 @@ +# Default values for tansu. +# This is a YAML-formatted file. Declare variables to be passed into your templates. + +nameOverride: "" +fullnameOverride: "" + +# Number of replicas (used when autoscaling is disabled, or as minimum when enabled) +replicaCount: 1 + +image: + repository: ghcr.io/tansu-io/tansu + tag: "main" + pullPolicy: IfNotPresent + +# Kafka cluster identity +clusterId: tansu + +# Advertised listener for clients (use service DNS in-cluster, or ingress host when exposed) +# In-cluster example: "tansu.{{ .Release.Namespace }}.svc.cluster.local:9092" +advertisedListener: "tansu:9092" + +# Schema registry (optional). Leave empty to omit --schema-registry. +# Example: "file:///schema" +schemaRegistry: "" + +# --- Autoscaling (HorizontalPodAutoscaler) --- +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 10 + targetCPUUtilizationPercentage: 70 + targetMemoryUtilizationPercentage: null # optional, e.g. 80 for memory-based scaling + +# --- Storage engine: memory | s3 | postgres | sqlite --- +storageEngine: + # One of: memory, s3, postgres, sqlite + type: memory + + # For type=memory: prefix for in-memory storage (e.g. "tansu" -> memory://tansu/) + memory: + prefix: tansu + + # For type=s3: bucket/path and AWS settings (credentials via existingSecret) + s3: + bucket: tansu + path: "" # optional path prefix, e.g. "data" + region: eu-west-2 + endpoint: "" # optional custom S3 endpoint + allowHttp: "false" + # Name of existing secret containing AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY + existingSecret: "" # e.g. "tansu-s3-credentials" + existingSecretAccessKeyKey: AWS_SECRET_ACCESS_KEY + existingSecretAccessKeyIdKey: AWS_ACCESS_KEY_ID + + # For type=postgres: connection URL (password from existingSecret recommended) + postgres: + host: postgres + port: 5432 + database: postgres + user: postgres + # Plain password (prefer existingSecret in production) + password: "" + # Name of existing secret; if set, password is read from secretKey + existingSecret: "" + existingSecretPasswordKey: password + + # For type=sqlite: path (use PVC or emptyDir) + sqlite: + path: /data/tansu.db + +# Optional: use a Secret for storage URL (overrides storageEngine.*) +# If set, storageEngine type/params are ignored and this URL is used as-is. +# storageUrlFromSecret: +# name: tansu-storage-url +# key: STORAGE_ENGINE + +serviceAccount: + create: true + name: "" + +service: + type: ClusterIP + kafkaPort: 9092 + metricsPort: 9100 + +# --- Kafka TCP LoadBalancer (expose Kafka externally) --- +kafkaLoadBalancer: + enabled: false + # LoadBalancer (cloud) or NodePort (local k8s, e.g. Docker Desktop on Mac) + serviceType: LoadBalancer + # For NodePort: optional fixed port (e.g. 30092); omit for auto-assigned + nodePort: null + # Optional annotations (e.g. AWS NLB, GCP backend config) + annotations: {} + # annotations: + # service.beta.kubernetes.io/aws-load-balancer-type: "nlb" + # service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing" + port: 9092 # external port (must match advertisedListener when clients connect) + +# --- Ingress (HTTP/HTTPS) --- +ingress: + enabled: false + className: "" # e.g. nginx, traefik + annotations: {} + # annotations: + # cert-manager.io/cluster-issuer: letsencrypt-prod + # nginx.ingress.kubernetes.io/proxy-body-size: "0" + hosts: + - host: tansu.local + paths: + - path: / + pathType: Prefix + port: metrics # metrics port (9100) + tls: [] + # tls: + # - secretName: tansu-tls + # hosts: + # - tansu.local + +resources: + limits: + cpu: 1000m + memory: 512Mi + requests: + cpu: 100m + memory: 256Mi + +# Logging +# Rust log level (env_logger): error, warn, info, debug, trace. Default warning. +rustLog: "warn" +rustBacktrace: "0" + +# Extra env vars (key-value) +extraEnv: {} +# extraEnv: +# AWS_DEFAULT_REGION: eu-west-2 + +# Extra volumes and volumeMounts (e.g. for schema files) +extraVolumes: [] +extraVolumeMounts: [] + +# Pod security context +podSecurityContext: {} +securityContext: {} + +# Node selector / tolerations / affinity +nodeSelector: {} +tolerations: [] +affinity: {}