1# -- Global configuration
3 # -- Override the image registry for all images in the chart
4 # Useful for air-gapped clusters that mirror images to an internal registry
6 # -- Override image pull secrets globally
8 # -- Kubernetes cluster DNS domain
9 clusterDomain: "cluster.local"
10# -- Enable production guard rails: template rendering fails if insecure
11# chart defaults (e.g. the default database password) would reach the
12# cluster. Enabled in values-prod.yaml; leave false for dev/kind.
14# -- Number of Kates API pods. Must be 1; values.schema.json refuses more.
15# The Kates API keeps each run's workers, the concurrent-run limit, the
16# disruption lease and the live event streams in its own memory, and a pod
17# that starts marks every RUNNING run in the database FAILED. A second pod
18# fails the runs the first is executing, and the two can each run a
19# disruption plan against the same cluster.
21# -- Container image configuration
24 repository: cgr.dev/chainguard-private/kates
25 # -- Image tag. Must be the release that carries the non-blocking health
26 # endpoints the probe defaults below depend on (>= 1.22.0).
27 tag: 1.29.0-r0@sha256:44c3abc1bfb61a74bd39b84c737974611c2c4bc10fc87181eac4fec860d65802
28 # -- Image pull policy
29 pullPolicy: IfNotPresent
30# -- Secrets for pulling images from private registries
32# -- Override the chart name
34# -- Override the full release name
36# -- DNS policy for pods (ClusterFirst, Default, None, ClusterFirstWithHostNet)
38# -- Custom DNS configuration (nameservers, searches, options)
40# -- Service account configuration
42 # -- Create a ServiceAccount
44 # -- ServiceAccount name (auto-generated if empty)
46 # -- Extra annotations for the ServiceAccount
48 # -- Automount the service account token
50# -- RBAC configuration
52 # -- Create ClusterRole and ClusterRoleBinding
54 # -- Grant the writes the direct Kubernetes chaos backend makes itself
55 # (KATES_CHAOS_PROVIDER=kubernetes, or hybrid without Litmus): NetworkPolicies,
56 # StatefulSet scaling, and pod ephemeral containers. Litmus runs its
57 # experiments as litmus-admin and needs none of this.
59 # -- Namespaces where the INTEGRATION_CDC test may read its database's
60 # password: a Role in each grants get on the Secret `postgresql` (key
61 # postgres-password), the only Secret the Kates API reads. The test uses the
62 # PostgreSQL behind the first Service labelled
63 # app.kubernetes.io/name=postgresql in any namespace, or in `database` when
64 # there is none. `kates deploy --with-kafka-connect` installs it there and
65 # sets this to that namespace. Each one must exist before the install.
66 # Empty grants nothing, and an INTEGRATION_CDC run then fails at DB_SETUP.
67 cdcSecretNamespaces: []
68 # -- Extra RBAC rules (e.g. for Litmus Chaos integration)
70# -- Extra annotations to add to pods
72# -- Extra labels to add to pods
74# -- Kubernetes Service configuration
78 # -- HTTP service port
80 # -- NodePort value (only when type=NodePort)
82 # -- Application protocol hint for service mesh
84 # -- Extra annotations for the Service
86# -- gRPC port configuration
88 # -- gRPC container/service port
90 # -- gRPC NodePort value (only when type=NodePort)
92# -- Ingress configuration
96 # -- Ingress class name (e.g. nginx)
98 # -- Extra Ingress annotations
100 # -- cert-manager integration
102 # -- Enable cert-manager annotations
104 # -- Issuer or ClusterIssuer name
106 # -- Issuer kind (ClusterIssuer or Issuer)
107 issuerKind: ClusterIssuer
114 # -- TLS configuration
116 # -- gRPC Ingress (separate Ingress resource for gRPC traffic)
118 # -- Enable gRPC Ingress
120 # -- gRPC Ingress hostname
121 host: grpc.kates.local
122 # -- Extra gRPC Ingress annotations
124 # -- gRPC TLS configuration
126# -- Resource requests and limits for the KATES container
134# -- Flyway schema migration behaviour
136 # -- Repair the schema history on startup before migrating.
138 # DEVELOPMENT ONLY. It fixes "Migration checksum mismatch", which happens when
139 # an unreleased migration is edited after a local database already applied it.
140 # On a real database that mismatch means the file and the schema genuinely
141 # disagree, and silently rewriting the history hides it — so this stays off by
142 # default and is enabled in the local overlays.
144# -- Container args, replacing the image's CMD. Empty means "use the image's
145# own default". The native image sets its heap percentage through CMD, since a
146# native binary ignores JAVA_TOOL_OPTIONS; override it here rather than
147# rebuilding the image.
149# -- JVM configuration
151# JVM IMAGE ONLY. A GraalVM native image does not read JAVA_TOOL_OPTIONS, so
152# everything here is silently ignored when running a `-native` tag — see
153# values-native.yaml, which empties it for that reason.
155 # -- JVM options passed via JAVA_TOOL_OPTIONS (ignored by the native image)
156 options: "-Xms512m -Xmx2560m -XX:+UseZGC -XX:+ZGenerational"
157# -- Pod-level security context (PSS restricted compliant)
158# NOTE: runAsUser and fsGroup are intentionally unset so that platforms
159# like OpenShift can assign random UIDs via their Security Context Constraints.
160# Set them explicitly in your environment values file if needed.
167# -- Container-level security context (PSS restricted compliant)
168containerSecurityContext:
169 allowPrivilegeEscalation: false
170 readOnlyRootFilesystem: true
175# -- Grace period for pod termination (seconds)
176terminationGracePeriodSeconds: 60
177# -- Deployment update strategy. Must be Recreate; values.schema.json refuses
178# RollingUpdate, which starts the new pod while the old one still runs (see
179# replicaCount). Recreate stops the old pod first, so every upgrade has a gap:
180# the API is unreachable until the new pod is Ready, a minute or two on the
181# JVM image, and a run still going when the old pod stops ends FAILED, as on
182# any restart. Upgrade between runs.
185# -- Horizontal Pod Autoscaler configuration. enabled must stay false;
186# values.schema.json refuses true. Kates runs one replica (see replicaCount),
187# and the CPU a native benchmark burns is what would make an autoscaler add a
188# second pod in the middle of a run.
190 # -- Enable HPA (must be false)
192 # -- Minimum replicas
194 # -- Maximum replicas
196 # -- Target CPU utilization percentage
197 targetCPUUtilizationPercentage: 80
198 # -- Target memory utilization percentage (empty to disable)
199 targetMemoryUtilizationPercentage: ""
200 # -- Custom metrics for HPA
202 # -- Scale behavior policies
205 stabilizationWindowSeconds: 300
211 stabilizationWindowSeconds: 30
216# -- Pod Disruption Budget configuration. With one pod, a budget either allows
217# its eviction or blocks every node drain: set maxUnavailable, and leave
222 # -- Minimum available pods. Must stay empty; values.schema.json refuses a
223 # value: any minimum leaves the one pod unevictable, and a drain never ends
225 # -- Maximum unavailable pods
227 # -- Unhealthy pod eviction policy
228 unhealthyPodEvictionPolicy: IfHealthy
229# -- Priority class name for pod scheduling
231# -- Topology spread constraints for pod scheduling
232topologySpreadConstraints: []
233# -- Node selector for pod scheduling
235# -- Tolerations for pod scheduling
237# -- Affinity rules (includes default pod anti-affinity for HA)
240 preferredDuringSchedulingIgnoredDuringExecution:
245 - key: app.kubernetes.io/name
249 topologyKey: kubernetes.io/hostname
250# -- Extra environment variables for the KATES container
252# -- Extra init containers (e.g. for Vault secret fetching, schema migration)
253extraInitContainers: []
256# -- Extra volume mounts
258# -- API key authentication
260 # -- Enable API key authentication
262 # -- API key value (auto-generated 32-char key if empty)
264 # -- Use an existing Secret instead of creating one
266 # -- Key in the existing Secret
268# -- Health probe configuration
270# Every probe points at a MicroProfile health endpoint, never at a business
271# endpoint. `/api/health` looks like the obvious readiness URL but calls
272# ClusterHealthService.isReachable() — an uncached AdminClient round-trip with a
273# 5s blocking get — on every request. Since a probe's timeoutSeconds defaults to
274# 1s, a cluster whose Kafka is still coming up fails EVERY readiness probe and
275# the pod never goes Ready, even though the app is fine. `/q/health/ready` reads
276# the periodically-refreshed KafkaReachabilityCache instead and never blocks on a
279 # -- Startup probe (gates readiness/liveness probes)
281 path: /q/health/started
282 # 60 x 2s = 120s of JVM boot budget. 30 (60s) is not enough on a
283 # CPU-constrained node: the kubelet kills the container mid-boot and the
284 # restart loop reads as "kates takes forever to start".
290 path: /q/health/ready
291 initialDelaySeconds: 5
298 initialDelaySeconds: 15
302# -- Container lifecycle hooks
304 # -- Seconds to sleep in preStop hook (allows LB drain)
305 preStopSleepSeconds: 5
306# -- Init container configuration
308 # -- Busybox image for wait-for-postgres init container
310 image: cgr.dev/chainguard-private/netcat:1.239-r0@sha256:6133b957a7ca4ca6603c2da7757cf37c5aa72fb53b4dd001d9610afb5dc5dbb8
311 pullPolicy: IfNotPresent
312# -- Kafka connection configuration
314 # -- Kafka bootstrap servers
315 bootstrapServers: "krafter-kafka-bootstrap.kafka.svc:9092"
316 # -- Namespace where CDC integration test KafkaTopic CRs are managed (empty = auto-detect)
318 # -- Client rack ID for rack-aware consumption
320 # -- Security protocol
322 protocol: SASL_PLAINTEXT
323 # -- SASL authentication
328 mechanism: SCRAM-SHA-512
330 username: kates-backend
331 # -- K8s Secret name containing the SASL password
332 secretName: kates-backend
333 # -- Key in the Secret containing the SASL password
335 # -- OAuthBearer configuration (when mechanism=OAUTHBEARER)
340 clientSecretKey: client-secret
341 # -- SSL/TLS configuration
345 # -- Truststore configuration
350 # -- Keystore configuration
355# -- Trogdor coordinator configuration
357 # -- Trogdor coordinator URL
358 coordinatorUrl: "http://trogdor-coordinator.kafka.svc:8889"
359 # -- Trogdor agents that run tasks (KATES_TROGDOR_AGENT_NODES): node names
360 # from the coordinator's platform config, comma-separated; a run's tasks take
361 # them in turn. node0 is the name in the trogdor.conf Kafka ships. A name the
362 # coordinator does not know fails the task with "Unknown node names".
364# -- Prometheus the backend queries for a disruption's Kafka metrics
366 # -- Prometheus base URL (KATES_PROMETHEUS_URL). The default is the Service
367 # kube-prometheus-stack creates for charts/monitoring installed as release
368 # `monitoring` in namespace `monitoring`, which is what `kates deploy` does
369 # (it sets this for the namespace it uses). `make monitoring` installs that
370 # release in namespace `kafka`: set
371 # http://monitoring-kube-prometheus-prometheus.kafka.svc:9090 there, and
372 # networkPolicy.prometheus.namespace to kafka. Unreachable, a disruption's
373 # Prometheus metrics are missing and its SLA verdict lists them unevaluated.
374 url: "http://monitoring-kube-prometheus-prometheus.monitoring.svc:9090"
375# -- Benchmark engine configuration
377 # -- Default benchmark backend (native or trogdor)
378 defaultBackend: "native"
379 # -- Maximum planned duration accepted for one run (ms)
380 maxDurationMs: "7200000"
381 # -- Grace after a RUNNING/STOPPING run's planned duration before it is failed (ms)
382 reaperGraceMs: "300000"
383 # -- Maximum time a run may stay PENDING before submission is considered stranded (ms)
384 submissionTimeoutMs: "120000"
385# -- Fault tolerance timeout configuration (ms)
388 # -- Timeout for all TopicService operations
390 clusterHealthService:
391 # -- Default timeout for cluster health operations
392 defaultTimeoutMs: "35000"
393 # -- Timeout for reachability check
394 reachableTimeoutMs: "10000"
395 # -- Timeout for full health check
396 healthCheckTimeoutMs: "60000"
397 consumerGroupService:
398 # -- Timeout for consumer group operations
400# -- NetworkPolicy configuration
402 # -- Enable NetworkPolicy
407 - namespaceSelector: {}
412 - namespaceSelector: {}
416 # -- Kafka egress configuration
420 # -- Prometheus egress configuration: the namespace prometheus.url points
421 # into. The policy used to allow `monitoring` whatever this said.
423 namespace: monitoring
425 # -- CDC integration test database egress. `kates deploy
426 # --with-kafka-connect` sets namespace from --db-ns so the backend can
427 # create/read the test tables in the demo PostgreSQL database.
432 app.kubernetes.io/name: postgresql
434 # -- Extra egress rules
436# -- Observability and monitoring
438 # -- Prometheus ServiceMonitor
440 # -- Enable ServiceMonitor
442 # -- Target namespace for the ServiceMonitor
448 # -- Extra labels for ServiceMonitor
450 # -- Metric relabeling rules
451 metricRelabelings: []
452 # -- Relabeling rules
454 # -- PrometheusRule for alerting
456 # -- Enable PrometheusRule
458 # -- Target namespace for the PrometheusRule
465 expr: up{job="{{ include \"kates.fullname\" . }}"} == 0
470 summary: "KATES instance is down"
471 description: "KATES pod {{ $labels.pod }} has been down for more than 5 minutes."
472 - alert: KatesHighErrorRate
473 expr: rate(http_server_requests_seconds_count{job="{{ include \"kates.fullname\" . }}", status=~"5.."}[5m]) > 0.1
478 summary: "KATES high error rate"
479 description: "KATES is returning more than 10% 5xx responses."
480 # -- GONE in 0.9.0: the "KATES — Overview" board (dashboards/kates-overview/)
481 # is delivered by charts/monitoring with every other board in dashboards/
482 # (its `dashboards.enabled`), scoped to a release by its `$job` template
483 # variable. A release that still sets any `metrics.grafanaDashboard.*` key
484 # is REFUSED with the new location named (this chart has no values schema,
485 # so without the refusal the key would be accepted and silently ignored).
486# -- Bundled PostgreSQL configuration.
487# A self-contained single-instance StatefulSet on the official `postgres`
488# image (no Bitnami). For production HA, set enabled=false and point
489# externalDatabase at a managed cluster (CloudNativePG recommended).
491 # -- Deploy bundled PostgreSQL
493 # -- PostgreSQL image (official library image; Alpine variants also work)
495 repository: cgr.dev/chainguard-private/postgres
496 tag: 16.15-r5@sha256:74cf7262337ca121ffd0e057daafe750062581e74b3d8c4e63bc32d8298d1b02
497 # -- Database authentication
501 # -- Database username
503 # -- Database password (ignored if existingSecret is set)
505 # -- Use an existing Secret for DB credentials
507 # -- Key in the existing Secret
508 passwordKey: "password"
509 # -- Node selector for the embedded PostgreSQL pod (dev/test only)
511 # -- Tolerations for the embedded PostgreSQL pod
513 # -- Affinity rules for the embedded PostgreSQL pod
515 # -- PVC storage configuration
519 # -- Storage class (empty for default)
521 # -- PostgreSQL resource requests and limits
529 # -- PostgreSQL pod security context
534 # -- PostgreSQL container security context
535 containerSecurityContext:
536 allowPrivilegeEscalation: false
540 # -- JDBC connection pool settings
542 # -- Maximum pool size
544 # -- Minimum pool size
546# -- External database configuration (when postgresql.enabled=false).
547# Recommended for production HA: run a CloudNativePG `Cluster` (official
548# postgres images, streaming replication, backups) and point host/port at its
549# `-rw` service, e.g. host: kates-db-rw.database.svc — no Bitnami involved.
551 # -- Enable external database
559 # -- Database username
561 # -- Database password (ignored if existingSecret is set)
563 # -- Use an existing Secret for DB credentials
565 # -- Key in the existing Secret
566 passwordKey: "password"
567# -- Default benchmark parameters (fallback for all test types)
569 replicationFactor: "3"
571 minInsyncReplicas: "2"
575 compressionType: "lz4"
577 numRecords: "1000000"
582# -- Per-test-type parameter overrides
584 # -- LOAD: baseline throughput test
589 numRecords: "1000000"
592 # -- STRESS: high-concurrency, large batches
597 numRecords: "5000000"
600 # -- SPIKE: burst traffic, low-latency
605 compressionType: "none"
606 numRecords: "2000000"
608 # -- ENDURANCE: long-running, rate-limited
610 numRecords: "10000000"
612 durationMs: "3600000"
613 # -- VOLUME: large records, high batch size
619 numRecords: "2000000"
620 # -- CAPACITY: max parallelism
625 numRecords: "10000000"
626 durationMs: "1200000"
628 # -- ROUNDTRIP: latency-focused
632 compressionType: "none"
635# -- PostgreSQL backup CronJob
637 # -- Enable backup CronJob
639 # -- Cron schedule expression
640 schedule: "0 2 * * *"
641 # -- PostgreSQL image for pg_dump
642 image: cgr.dev/chainguard-private/postgres:16.15-r5@sha256:74cf7262337ca121ffd0e057daafe750062581e74b3d8c4e63bc32d8298d1b02
643 # -- Days to retain backups
645 # -- Backup persistence
651 # -- Backup job resources
659# -- Pre-upgrade Flyway migration Job
661 # -- Enable migration Job (runs as pre-upgrade Helm hook)
663 # -- Override image (defaults to KATES app image)
664 image: cgr.dev/chainguard-private/kates:1.29.0-r0@sha256:44c3abc1bfb61a74bd39b84c737974611c2c4bc10fc87181eac4fec860d65802
665 # -- Custom command (overrides default Flyway migration)
667 # -- Maximum retry attempts
669 # -- Maximum Job duration (seconds)
670 activeDeadlineSeconds: 600
671 # -- Migration job resources
679# -- Stale test run cleanup CronJob. It deletes finished runs through the
680# API's DELETE /api/tests, sending the key from apiKey's Secret. That
681# endpoint takes an image newer than 1.25.0: on 1.25.0 every job fails with
682# HTTP 405 and deletes nothing.
684 # -- Enable cleanup CronJob
686 # -- Cron schedule expression
687 schedule: "0 4 * * 0"
688 # -- Delete finished test runs created more than N days ago
690 # -- Which finished runs to delete: DONE, FAILED or both. A cancelled run
691 # is stored FAILED. A run still PENDING, RUNNING or STOPPING is never
692 # deleted, however old it is.
696 # -- Curl image for API calls
697 image: cgr.dev/chainguard-private/min-toolkit-debug:latest@sha256:c38f30c67937b88d461d1caec40f118d582339df0bcd7cc6a8e26b0ac8c1b759
698# -- Kyverno pod security policies (requires Kyverno controller in cluster)
700 # -- Enable Kyverno ClusterPolicy for the kates namespace
702 # -- Policy action: Audit (observe only) or Enforce (block non-compliant)
704 # -- Enable mutation rules to auto-inject security contexts
706 # -- Enable image registry restriction
707 restrictRegistries: false
708 # -- Allowed image registries (when restrictRegistries is true)
715 # -- GONE in 0.9.0: the Kyverno board (dashboards/kyverno-security/) is
716 # delivered by charts/monitoring with every other board in dashboards/ (its
717 # `dashboards.enabled`) — one Kyverno per cluster, one board, and it belongs
718 # where the rest of the cluster's boards live. `grafanaDashboard` (both the
719 # bool and the map shape) and `grafanaDashboardNamespace` are REFUSED if
720 # set, with the new location named.
721 # -- Cosign image signature verification
723 # -- Enable image signature verification via Cosign
725 # -- Image patterns requiring valid signatures
727 - "ghcr.io/bmscomp/*"
728 # -- Cosign public key (PEM format) — set via --set-file or Secrets
730 # -- Auto-generate default-deny NetworkPolicies for new namespaces
731 networkPolicyGeneration:
733 # -- Namespaces to exclude from default-deny generation
745 # -- PolicyExceptions for dev/test namespaces
747 # -- Enable PolicyException resources
749 # -- Dev namespaces where policies are relaxed
753 # -- Policies to create exceptions for
755 - kates-pod-security-standards
756 # -- Rules to exempt in dev namespaces
758 - validate-readonly-rootfs
759 - require-resource-limits
760 - disallow-latest-tag
761# -- Monitoring integration
763 # -- Enable telemetry export (Jaeger)