Skip to main content

Helm Reference

Conncentric is deployed through a single Helm chart. This page documents every configurable value. Values marked REQUIRED must be set for your environment. The production values.yaml provided by Connamara contains these values with inline comments; this page serves as the complete reference.

Pin image tags in production

The orchestrator, adapter, portal, and installer image.tag values default to latest for convenience. Production deployments must pin each to a released version (for example 1.5.0); running latest in production is not supported. See the Deployment Runbook and Platform Images.

Installation

The chart is published as an OCI artifact alongside the images. Install it directly from your registry:

helm install conncentric oci://<your-registry>/conncentric/charts/conncentric \
--version <release-tag> \
-n conncentric \
--create-namespace \
-f values.production.yaml

<your-registry> is the same host you set for global.imageRegistry. For the minimal values.production.yaml to start from, use the values skeleton in the Deployment Runbook; this page documents each field in full.

Global

KeyDefaultDescription
global.imageRegistry""REQUIRED. URL of your own registry that the cluster pulls from, populated by an eager mirror. See Platform Images.
global.imagePullPolicyIfNotPresentImage pull policy for every component. Use IfNotPresent with immutable, pinned release tags. Use Always only when you deploy mutable tags (for example nightly builds) that are overwritten in place.
global.imagePullSecrets[]Pre-existing Kubernetes Secret names (a list of strings, not { name: ... } objects) for private-registry authentication.
global.logging.formatjsonLog output format: json (structured, for production) or text (human-readable, for debugging).
global.logging.level"" (INFO)Root log level for the Orchestrator and adapters: INFO, DEBUG, WARN, ERROR, or TRACE. Unset uses INFO. Applying a change restarts the pods. For a single package, append -Dlogging.level.<package>=<LEVEL> to javaToolOptions instead.

Security

KeyDefaultDescription
security.internalApiKey""REQUIRED unless security.internalApiKeyExistingSecret is set. Shared key for internal communication between Adapter pods and the Orchestrator. When set inline, the chart synthesizes a Secret from it (fine for dev/demo). Generate with openssl rand -hex 32.
security.internalApiKeyExistingSecret""Name of a pre-existing Secret holding the internal key under data key internal-api-key. Recommended for production: when set, the chart references it instead of synthesizing a Secret from security.internalApiKey, so the key never lives in your values file.
security.provider""REQUIRED. OIDC provider identifier: cognito, okta, auth0, entra, or your provider. Must match portal.auth.provider.
security.jwt.issuerUri""REQUIRED. OIDC issuer URI for backend JWT validation. Must be reachable from inside the cluster, since the backend fetches signing keys from it to validate tokens. It must additionally be reachable from the browser only when it is also the Portal authority. Plan egress and firewall rules for cluster reachability first.
security.jwt.audience""JWT audience claim validation. Leave empty to skip (e.g., Cognito access tokens have no audience claim).
security.corsAllowedOrigins""Comma-separated CORS allowed-origin patterns for the browser/Portal (for example https://portal.example.com,https://admin.example.com). Empty uses the orchestrator default of * (all origins); set this only to restrict the API to specific origins.

Database

Both the Orchestrator and Adapter read from the same database.* keys.

KeyDefaultDescription
database.host""REQUIRED. PostgreSQL hostname.
database.port5432PostgreSQL port.
database.nameconncentricDatabase name.
database.sslMode""JDBC sslmode. Empty uses the driver default (prefer, which allows a silent plaintext fallback). Set require to force TLS; verify-ca/verify-full also verify the certificate (the CA must be available to the pods).
database.auth.username""REQUIRED. Database username.
database.auth.existingSecret""Name of a Kubernetes Secret containing username and password keys. Recommended for production.
database.auth.password""Database password. Use existingSecret instead for production.
durabilityProfiledurability-firstTop-level key. Durability vs. write-acknowledgement posture. durability-first: a write survives the loss of an entire availability zone before it is acknowledged. latency-first: a write is acknowledged after durable storage within its primary zone, with a full-zone disaster recovered from a replicated second region (a recovery-point window applies, and the database must be co-located with the adapters in one zone). See Disaster Recovery for the full trade-off and when to choose each.

Orchestrator

KeyDefaultDescription
orchestrator.replicaCount2Number of Orchestrator instances.
orchestrator.staleness.thresholdSeconds75Seconds a missed adapter heartbeat is tolerated before the Orchestrator reclaims the lease so a standby can claim it. Keep adapter.leasePartitionFenceMs comfortably above this plus your rollout budget. Raise it to widen the rollout budget; lower it for faster failover.
orchestrator.rollingUpdate.maxSurge0Rolling-update surge. With the default 0/1 pairing, one replica is evicted before its replacement is scheduled, so a rollout completes on the two-schedulable-node control-plane minimum (and on a single node for a scaled-down evaluation). Set maxSurge: 1/maxUnavailable: 0 if you run a spare control-plane node (N+1) and want rollouts that never reduce capacity.
orchestrator.rollingUpdate.maxUnavailable1Rolling-update unavailability budget. See maxSurge above.
orchestrator.image.taglatestImage version.
orchestrator.nodeSelector{}Node labels for scheduling. For control-plane isolation, set to conncentric.io/node-pool: control-plane.
orchestrator.tolerations[]Taints the Orchestrator tolerates.
orchestrator.javaToolOptions-XX:MaxRAMPercentage=75.0Runtime options for the component. To raise log verbosity, see Logging.
orchestrator.resources.requests.cpu1500mCPU request. Sized for 10k msg/sec sustained across a 4-adapter fleet.
orchestrator.resources.requests.memory2.5GiMemory request.
orchestrator.resources.limits.cpu3000mCPU limit.
orchestrator.resources.limits.memory4GiMemory limit.

The chart renders a PodDisruptionBudget with minAvailable: 1 whenever replicaCount > 1. Hard pod anti-affinity ensures two replicas cannot share a node.

Adapter

KeyDefaultDescription
adapter.replicaCount4Number of adapter pods. This is a topology decision, not an elasticity lever: the platform does not autoscale adapters, so set the count for your chosen topology.
adapter.image.taglatestImage version.
adapter.extraEnvFromSecrets[]Names of Kubernetes Secrets surfaced to adapter pods as environment variables, for ${env:VAR_NAME} references in component configurations. See Security.
adapter.nodeSelector{}Node labels for scheduling. For data-plane isolation, set to conncentric.io/node-pool: data-plane.
adapter.tolerations[]Taints the adapter tolerates.
adapter.javaToolOptions-XX:MaxRAMPercentage=75.0 -XX:+UseZGC -XX:+ZGenerationalRuntime options for the component, tuned by default for latency-sensitive workloads.
adapter.heartbeatInterval5000Lease heartbeat interval in milliseconds.
adapter.configRetryDelay5000Delay in milliseconds before an adapter retries fetching its configuration from the Orchestrator.
adapter.leasePartitionFenceMs90000Top-level under adapter (flat key, not adapter.lease.*). Asymmetric-partition self-fence window in milliseconds, armed by default. The pod self-fences after this many milliseconds of continuous check-in failure, closing the split-brain window when a standby may have taken the lease. Keep it comfortably above orchestrator.staleness.thresholdSeconds (75s app default) plus your rollout budget. Set to 0 to disable (not recommended in production). See Deployment Topologies.
adapter.terminationGracePeriodSeconds60Graceful-shutdown budget in seconds. Must exceed the pipeline drain timeout (30s default) plus the preStop sleep (10s) plus headroom for connector close and final sequence-state flush. Raise it if you raise the drain timeout.
adapter.managementPort8081Fixed port for health checks and Prometheus scraping.
adapter.resources.requests.cpu500mCPU request. Intentionally lower than the Orchestrator so the scheduler prioritizes the control plane.
adapter.resources.requests.memory512MiMemory request.
adapter.resources.limits.cpu2000mHard CPU limit per adapter pod.
adapter.resources.limits.memory2GiMemory limit.
adapter.service.typeLoadBalancerKubernetes Service type. Use ClusterIP if all adapters are initiator-only.
adapter.service.annotations{}Provider Service annotations on the acceptor LoadBalancer, used for production setup (balancer type, a stable address). See Networking & Ingress.
adapter.service.externalTrafficPolicy""Traffic policy for the acceptor Service. Set to Local to preserve the counterparty source IP; empty uses the cluster default. See Networking & Ingress.
adapter.service.loadBalancerSourceRanges[]Restrict inbound at the load balancer to known counterparty CIDRs. Empty allows all. See Networking & Ingress.
adapter.service.loadBalancerClass""Pin a specific load balancer implementation. Empty uses the cluster default. See Networking & Ingress.

Adapter Networking

KeyDefaultDescription
adapter.networking.portRange.enabledtrueEnable the acceptor port range on the adapter Service. Set to false if no adapters accept inbound connections.
adapter.networking.portRange.start6700First port in the acceptor range.
adapter.networking.portRange.end6750Last port in the acceptor range (inclusive). Your networking team must open this range on the external firewall.

Soft pod anti-affinity spreads adapter replicas across nodes when possible.

Adapter Pipeline Sizing

In-pod pipeline knobs shared by every connector, mapped to the container's CONNCENTRIC_PIPELINE_* environment variables. They are DevOps-only overrides, not Portal settings, because they depend on the pod's heap and CPU rather than on business configuration. Leave every value unset to auto-size at startup; override only for a pod with a measured safe capacity that differs from the auto-sized value.

KeyDefaultDescription
adapter.pipeline.queueCapacity"" (auto)In-pod queue depth. Unset auto-sizes to about 10% of max heap at an estimated 2 KB per message, clamped to the range 500 to 50000.
adapter.pipeline.concurrency"" (auto)Pipeline worker threads. Unset auto-sizes to max(1, availableProcessors - 1).
adapter.pipeline.backpressureLimit"" (auto)Queue depth at which the pipeline applies backpressure. How a connector reacts is connector-specific (a session connector typically disconnects gracefully and recovers on reconnect; a broker connector pauses consumption). Unset auto-sizes to 80% of the effective queue capacity. 0 disables graceful disconnect (not recommended).
adapter.pipeline.drainTimeoutMs"" (30000)Graceful-shutdown drain budget in milliseconds: how long the pipeline is given to finish in-flight messages when the pod stops. Unset uses the application default of 30000. Raise it for slow downstream targets (cross-region brokers, slow third-party APIs) and raise adapter.terminationGracePeriodSeconds to match.

The application-level circuit breaker is not a Helm value. It is adapter application configuration overridden through the PIPELINE_CIRCUIT_BREAKER_* environment variables. See Resilience and Backpressure.

Portal

KeyDefaultDescription
portal.replicaCount1Number of Portal pods.
portal.image.taglatestImage version.
portal.apiBaseUrl""Leave empty when Portal and API share the same domain via Ingress (default). Set to the full API URL only for split-domain architectures.
portal.basePath/Subpath under which the Portal is served. Default / mounts the SPA at the origin root. Set to a value like /conncentric/ when fronting the Portal under a subpath on a shared load balancer, so the config, assets, and OIDC redirect_uri all resolve without a per-customer image rebuild. Leading and trailing slashes are normalized by the container entrypoint.
portal.auth.provider""REQUIRED. Must match security.provider.
portal.auth.authority""REQUIRED. OIDC issuer URL for the frontend login redirect.
portal.auth.clientId""REQUIRED. OIDC client ID for the Portal SPA.
portal.auth.scopeopenid profile emailOIDC scopes to request.
portal.auth.redirectUri""REQUIRED. Portal URL registered as the redirect URI in your OIDC provider.
portal.auth.audience""OIDC audience claim. Leave empty if your provider does not use it.

Installer

KeyDefaultDescription
installer.enabledtrueEnable the post-install/upgrade installer job.
installer.image.repositoryconncentric/essentials-distributionDistribution image containing the base bundle.
installer.image.taglatestDistribution image version.
installer.plugins.essentialstrueInstall the Essentials plugin (pipeline components, performance generator, debug utilities). Recommended.
installer.plugins.fixfalseInstall the FIX plugin (both orchestrator and integration-adapter components).
installer.plugins.kafkafalseInstall the Kafka plugin (integration-adapter component).
installer.customBundleUrls[]URLs to custom .zip bundles applied sequentially after the base distribution (Pass 2+). See Custom Bundles & Extensibility.

Ingress

KeyDefaultDescription
ingress.enabledtrueCreate an Ingress resource.
ingress.classNametraefikIngressClass for the built-in Ingress. Set to your controller (alb, nginx, and so on) on a managed cluster.
ingress.annotationstraefik entrypointController annotations. Replace the traefik default with your controller's annotations when you change the class.
ingress.host""Optional hostname; scopes the Ingress rule to this host. Empty matches all hosts.
ingress.tls[]Optional TLS. Provide secretName (and hosts) to terminate HTTPS at the Ingress.

The Ingress routes /api and /actuator to the Orchestrator, and the Portal path (portal.basePath, default /) to the Portal. It defaults to traefik but exposes ingress.className, ingress.annotations, ingress.host, and ingress.tls, so you can point it at another controller and terminate TLS without replacing it. For an Ingress the chart does not manage, set ingress.enabled: false and front the three paths with your own. See Networking & Ingress for the full networking model.

Prometheus

The chart provisions ServiceMonitor resources for the adapter and orchestrator when the cluster runs the Prometheus Operator. The pod-annotation scrape pattern (prometheus.io/scrape) is always present for annotation-based Prometheus setups; both paths coexist.

KeyDefaultDescription
prometheus.serviceMonitor.enabledfalseCreate ServiceMonitor resources. Requires the Prometheus Operator CRDs; enabling it on a cluster without the operator makes helm install fail with a "no kind ServiceMonitor" error. Leave false for annotation-based Prometheus setups.
prometheus.serviceMonitor.interval30sScrape interval. 30s suits application metrics; tighten to 15s for latency-critical fleets.
prometheus.serviceMonitor.scrapeTimeout10sScrape timeout. Must be less than interval.
prometheus.serviceMonitor.additionalLabels{}Extra labels added to the ServiceMonitor objects, for clusters where the Prometheus Operator selects monitors by label.

Reliability and node pool isolation

For production deployments, isolating the control plane and data plane on separate node pools provides the strongest reliability guarantee. A burst on the data plane cannot contend with the control plane at the kernel scheduler level.

Step 1: Label your nodes

kubectl label nodes <control-node> conncentric.io/node-pool=control-plane
kubectl label nodes <data-node> conncentric.io/node-pool=data-plane

Step 2: Set the matching selectors

orchestrator:
nodeSelector:
conncentric.io/node-pool: control-plane
adapter:
nodeSelector:
conncentric.io/node-pool: data-plane

What you get at each level

LayerGuarantee
Separate node pools (opt-in)Data-plane load cannot contend with the control plane at the kernel scheduler level.
Hard pod anti-affinity (always on)Two Orchestrator replicas cannot share a node. Any single node loss cannot bring down the entire control plane.
PodDisruptionBudget (auto when replicaCount > 1)Voluntary drains cannot evict every Orchestrator replica simultaneously.
Rolling update strategyThe default maxSurge: 0/maxUnavailable: 1 rolls one replica at a time, evicting a replica before scheduling its replacement so the rollout completes on the two-node (or single-node scaled-down) control-plane minimum. The single active writer keeps serving throughout, so the control plane stays available; redundancy briefly drops to one during each replica's roll. Set maxSurge: 1/maxUnavailable: 0 on an N+1 control plane for rollouts that never reduce capacity.
Per-pod resource requests and limitsCPU and memory are guaranteed and capped per pod.