Deploy controllers using a Helm chart
- Prerequisites
- Add the HashiCorp Helm repository
- Create the controller Secret
- Create the TLS Secret when TLS is enabled
- Prepare the controller configuration
- List available chart versions
- Install a Boundary controller
- Verify the deployment
- Upgrade the controller
The controller chart is intended for operator-managed Boundary control planes on Kubernetes. It can run multiple controller replicas and uses Helm hook Jobs for database initialization. It can also optionally use hook Jobs for database migration, database repair, and admin bootstrap.
You must provide any required external dependencies such as PostgreSQL, KMS access, Boundary Enterprise license data, and TLS material, if necessary.
Prerequisites
Before installing the controller Helm chart, make sure the following are available:
- A Kubernetes cluster running version 1.34 or later.
- Helm 3 or later configured with access to the target Kubernetes cluster.
- A reachable PostgreSQL 15 or later database for Boundary controller state.
- A valid Boundary controller HCL configuration.
- KMS configuration for the
root,recovery, andworker-authpurposes. - A Boundary Enterprise license and database URL.
- An existing Kubernetes Secret containing
admin-usernameandadmin-passwordwhenbootstrapAdmin.enabled=true. - A Kubernetes TLS Secret containing
tls.crtandtls.keywhentls.disabled=false. - A ServiceAccount that the controller deployment and hook Jobs can use.
The controller chart deploys a stateless Boundary control plane. PostgreSQL stores the persistent controller state, not the controller pods.
Complete the following steps to deploy a controller using the Helm chart.
Add the HashiCorp Helm repository
Add the Helm repository and confirm the chart is visible:
$ helm repo add hashicorp https://helm.releases.hashicorp.com; \
helm repo update; \
helm search repo hashicorp/boundary-controller
Example output:
NAME CHART VERSION APP VERSION DESCRIPTION
hashicorp/boundary-controller 0.1.0 1.0.0 Official HashiCorp Boundary Controller Helm Chart
Create the controller Secret
The chart reads sensitive values from an existing Kubernetes Secret referenced by secretRefs.secretName. At a minimum, create a Secret with the database URL and Boundary Enterprise license. Include the bootstrap admin credentials when bootstrapAdmin.enabled=true.
Refer to the Kubernetes Secrets documentation for instructions on creating Secrets.
Set secretRefs.keys.* to match the key names you used in your Secret. If your controller.config uses migration_url = "env://BOUNDARY_PG_MIGRATION_URL", also include the migration URL key referenced by secretRefs.keys.migrationUrl.
Create the TLS Secret when TLS is enabled
If tls.disabled=false, create a Kubernetes TLS Secret before installation. Refer to the Kubernetes Secrets documentation for instructions. The Secret must contain tls.crt and tls.key entries, and its name must match tls.secretName (default: boundary-controller-tls).
When TLS is disabled, the chart does not mount this Secret.
Prepare the controller configuration
The chart reads the Boundary controller HCL from the controller.config key in your values file. Set this value before installing the chart.
For a base controller configuration, refer to the controller configuration guidance in the controller stanza reference.
A usable controller configuration includes:
- An API listener
- A cluster listener
- An operations listener
- A
controllerblock withlicenseanddatabase.url - A
public_cluster_addrso workers can reach the cluster listener - KMS stanzas for
root,recovery, andworker-auth
Refer to the following example controller configuration using AWS KMS:
disable_mlock = true
listener "tcp" {
address = "0.0.0.0:9200"
purpose = "api"
tls_disable = true
tls_cert_file = "/etc/boundary/tls/tls.crt"
tls_key_file = "/etc/boundary/tls/tls.key"
}
listener "tcp" {
address = "0.0.0.0:9201"
purpose = "cluster"
}
listener "tcp" {
address = "0.0.0.0:9203"
purpose = "ops"
tls_disable = true
tls_cert_file = "/etc/boundary/tls/tls.crt"
tls_key_file = "/etc/boundary/tls/tls.key"
}
controller {
name = "boundary-controller"
description = "Boundary controller running in Kubernetes"
public_cluster_addr = "boundary-controller-cluster.boundary.svc.cluster.local:9201"
license = "<your-license-here>"
database {
url = "postgres://<user>:<password>@<host>:5432/<dbname>?sslmode=require"
}
}
kms "aead" {
purpose = "root"
aead_type = "aes-gcm"
key = "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6sFo="
key_id = "global_root"
}
kms "aead" {
purpose = "recovery"
aead_type = "aes-gcm"
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
key_id = "global_recovery"
}
kms "aead" {
purpose = "worker-auth"
aead_type = "aes-gcm"
key = "ATTK2pMjMTEJGlAkUJAePnFMlNLQaXBnhSqJHVlJeKQ="
key_id = "global_worker-auth"
}
events {
audit_enabled = true
sysevents_enabled = true
observations_enabled = true
sink "stderr" {
name = "all-events"
description = "All events sent to stderr"
event_types = ["*"]
format = "hclog-text"
}
}
List available chart versions
Use the following command to see any available published versions of the controller chart:
$ helm search repo hashicorp/boundary-controller --versions
Install a Boundary controller
Create a values file that contains controller.config and the Kubernetes overrides you need:
secretRefs:
secretName: boundary-controller-secrets
serviceAccount:
name: default
tls:
disabled: false
controller:
config: |
disable_mlock = true
listener "tcp" {
address = "0.0.0.0:9200"
purpose = "api"
tls_disable = true
tls_cert_file = "/etc/boundary/tls/tls.crt"
tls_key_file = "/etc/boundary/tls/tls.key"
}
listener "tcp" {
address = "0.0.0.0:9201"
purpose = "cluster"
}
listener "tcp" {
address = "0.0.0.0:9203"
purpose = "ops"
tls_disable = true
tls_cert_file = "/etc/boundary/tls/tls.crt"
tls_key_file = "/etc/boundary/tls/tls.key"
}
controller {
name = "boundary-controller"
description = "Boundary controller running in Kubernetes"
public_cluster_addr = "boundary-controller-cluster.boundary.svc.cluster.local:9201"
license = "<your-license-here>"
database {
url = "postgres://<user>:<password>@<host>:5432/<dbname>?sslmode=require"
}
}
kms "aead" {
purpose = "root"
aead_type = "aes-gcm"
key = "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6sFo="
key_id = "global_root"
}
kms "aead" {
purpose = "recovery"
aead_type = "aes-gcm"
key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
key_id = "global_recovery"
}
kms "aead" {
purpose = "worker-auth"
aead_type = "aes-gcm"
key = "ATTK2pMjMTEJGlAkUJAePnFMlNLQaXBnhSqJHVlJeKQ="
key_id = "global_worker-auth"
}
events {
audit_enabled = true
sysevents_enabled = true
observations_enabled = true
sink "stderr" {
name = "all-events"
description = "All events sent to stderr"
event_types = ["*"]
format = "hclog-text"
}
}
service:
api:
type: LoadBalancer
cluster:
type: ClusterIP
ops:
type: ClusterIP
Run the following command to install the release:
$ helm install boundary-controller hashicorp/boundary-controller \
--version 0.1.0 \
--namespace boundary \
--create-namespace \
--values my-values.yaml \
--wait
Verify the deployment
Check the rendered resources after installation:
$ kubectl get deployment,pods,svc,jobs,pdb --namespace boundary; \
kubectl logs --namespace boundary deployment/boundary-controller
Confirm that:
- The database initialization job completes successfully when
database.init.enabled=true. - The bootstrap admin job completes successfully when
bootstrapAdmin.enabled=true. - The controller pods become Ready.
- The API, cluster, and ops services match your intended exposure model.
- Boundary API requests succeed against the controller API listener.
- Workers can reach
public_cluster_addrand register successfully.
Upgrade the controller
To upgrade the controller deployment, run:
$ helm upgrade boundary-controller hashicorp/boundary-controller \
--version 0.1.0 \
--namespace boundary \
--values my-values.yaml \
--rollback-on-failure \
--wait
For database migration scenarios, refer to Controller Helm chart examples.
Next steps
To deploy workers, refer to Deploy workers using a Helm chart.
More information
- To view supported Helm values so that you can configure or update controllers, refer to Controller values.
- To view example configurations, refer to Controller Helm chart examples.
- For frequently asked questions, refer to the Controller chart FAQ.