Skip to main content
Version: v0.7.x

Single Cluster Setup

This guide walks you through installing OpenChoreo on a single Kubernetes cluster. Choose the mode that fits your needs:

ModeBest ForDomainTLSCluster
k3d (Local)Local development.localhostNok3d
Try OutQuick evaluation on cloudnip.io (free)Yes (Let's Encrypt)Any Kubernetes
ProductionProduction workloadsCustom domainYes (required)Any Kubernetes

Prerequisites​

Required tools:

  • Docker v26.0+ with at least 8 GB RAM and 4 CPU cores allocated
  • k3d v5.8+
  • kubectl v1.32+
  • Helm v3.12+
# Verify prerequisites
docker --version && docker info > /dev/null
k3d --version
kubectl version --client
helm version --short
Colima Users

Set K3D_FIX_DNS=0 when creating clusters to avoid DNS issues. See k3d-io/k3d#1449.


Step 1: Create Your Kubernetes Cluster​

Create a pre-configured k3d cluster optimized for OpenChoreo:

curl -s https://raw.githubusercontent.com/openchoreo/openchoreo/release-v0.7/install/k3d/single-cluster/config.yaml | k3d cluster create --config=-

This creates a cluster named openchoreo with:

  • 1 server + 2 agent nodes
  • Port mappings: Control Plane (8080/8443), Data Plane (9080/9443), Build Plane (10081/10082), Observability (11081/11082)
  • kubectl context set to k3d-openchoreo
# Verify cluster is running
kubectl get nodes

Step 2: Configure Domain & TLS​

No configuration needed! Local setup uses .localhost domains automatically:

ServiceURL
Console (Backstage)http://openchoreo.localhost:8080
APIhttp://api.openchoreo.localhost:8080
Deployed Appshttp://<component>-<env>.openchoreoapis.localhost:9080
tip

The .localhost domain resolves to 127.0.0.1 on most systems without any /etc/hosts configuration.


Step 3: Install Control Plane​

helm install openchoreo-control-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-control-plane \
--version 0.7.0 \
--namespace openchoreo-control-plane \
--create-namespace \
--values https://raw.githubusercontent.com/openchoreo/openchoreo/release-v0.7/install/k3d/single-cluster/values-cp.yaml

Verify Control Plane:

kubectl get pods -n openchoreo-control-plane
# Expected: controller-manager, cluster-gateway-*, kgateway-* pods in Running state

Step 4: Install Data Plane​

The Data Plane uses Gateway API with kgateway for traffic routing. No traditional Ingress controller is needed.

helm install openchoreo-data-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-data-plane \
--version 0.7.0 \
--namespace openchoreo-data-plane \
--create-namespace \
--values https://raw.githubusercontent.com/openchoreo/openchoreo/release-v0.7/install/k3d/single-cluster/values-dp.yaml

Register the data plane with the control plane:

curl -s https://raw.githubusercontent.com/openchoreo/openchoreo/release-v0.7/install/add-data-plane.sh | bash -s -- --enable-agent --control-plane-context k3d-openchoreo --name default

This script creates a DataPlane resource with agent-based communication enabled. The agent provides secure WebSocket-based connectivity between the control plane and data plane without requiring direct Kubernetes API access.

Verify the DataPlane was created and agent mode is enabled:

# Check DataPlane resource
kubectl get dataplane -n default

# Verify agent mode is enabled
kubectl get dataplane default -n default -o jsonpath='{.spec.agent.enabled}'

The agent.enabled field should show true, and the Ready condition should have status True once the agent successfully connects to the control plane.

Optional: View the Data Plane's CA certificate (used for agent authentication):

kubectl get secret cluster-agent-tls \
-n openchoreo-data-plane \
-o jsonpath='{.data.ca\.crt}' | base64 -d

This shows the client CA certificate that the control plane uses to verify the data plane agent's identity.

Verify Data Plane:

kubectl get pods -n openchoreo-data-plane
# Expected: cluster-agent-*, kgateway-*, external-secrets-*, fluent-bit-* pods

kubectl get dataplane -A
# Expected: default dataplane exists

Step 5: Install Build Plane (Optional)​

The Build Plane enables OpenChoreo's built-in CI capabilities. Skip this if you only deploy pre-built container images.

helm install openchoreo-build-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-build-plane \
--version 0.7.0 \
--namespace openchoreo-build-plane \
--create-namespace \
--values https://raw.githubusercontent.com/openchoreo/openchoreo/release-v0.7/install/k3d/single-cluster/values-bp.yaml

Register the build plane:

curl -s https://raw.githubusercontent.com/openchoreo/openchoreo/release-v0.7/install/add-build-plane.sh | bash -s -- --enable-agent --control-plane-context k3d-openchoreo --name default

This script creates a BuildPlane resource with agent-based communication enabled. The agent establishes an outbound WebSocket connection to the cluster gateway, providing secure communication without exposing the Kubernetes API server.

Verify the BuildPlane was created and agent mode is enabled:

# Check BuildPlane resource
kubectl get buildplane -n default

# Verify agent mode is enabled
kubectl get buildplane default -n default -o jsonpath='{.spec.agent.enabled}'

The agent.enabled field should show true, and the Ready condition should have status True once the agent successfully connects to the control plane.

Optional: View the Build Plane's CA certificate (used for agent authentication):

kubectl get secret cluster-agent-tls \
-n openchoreo-build-plane \
-o jsonpath='{.data.ca\.crt}' | base64 -d

This shows the client CA certificate that the control plane uses to verify the build plane agent's identity.

Verify Build Plane:

kubectl get pods -n openchoreo-build-plane
kubectl get buildplane -A

Step 6: Install Observability Plane (Optional)​

The Observability Plane provides centralized logging and monitoring with OpenSearch.

Minimal (Non-HA) - Uses a single OpenSearch instance:

helm install openchoreo-observability-plane oci://ghcr.io/openchoreo/helm-charts/openchoreo-observability-plane \
--version 0.7.0 \
--namespace openchoreo-observability-plane \
--create-namespace \
--values https://raw.githubusercontent.com/openchoreo/openchoreo/release-v0.7/install/k3d/single-cluster/values-op.yaml

Configure Observer Integration (required for logs in Backstage):

Step 1: Configure DataPlane to use observer

kubectl patch dataplane default -n default --type merge -p '{"spec":{"observer":{"url":"http://observer.openchoreo-observability-plane:8080","authentication":{"basicAuth":{"username":"dummy","password":"dummy"}}}}}'

Step 2: Configure BuildPlane (if installed)

kubectl patch buildplane default -n default --type merge -p '{"spec":{"observer":{"url":"http://observer.openchoreo-observability-plane:8080","authentication":{"basicAuth":{"username":"dummy","password":"dummy"}}}}}'

Verify Observability Plane:

kubectl get pods -n openchoreo-observability-plane
kubectl wait --for=condition=Ready pod --all -n openchoreo-observability-plane --timeout=600s

Verification & Access​

Verify All Components​

# Check all planes
kubectl get pods -n openchoreo-control-plane
kubectl get pods -n openchoreo-data-plane
kubectl get pods -n openchoreo-build-plane # If installed
kubectl get pods -n openchoreo-observability-plane # If installed

# Check plane resources
kubectl get dataplane,buildplane -A
kubectl get organizations,projects,environments -A

Verify Agent Connections (for k3d mode with agent-based communication):

# Verify DataPlane agent is connected
echo "=== DataPlane Agent Status ==="
kubectl get pods -n openchoreo-data-plane -l app=cluster-agent

echo "=== DataPlane Agent Connection Logs ==="
kubectl logs -n openchoreo-data-plane -l app=cluster-agent --tail=5 | grep "connected to control plane"

# Verify BuildPlane agent is connected (if installed)
echo "=== BuildPlane Agent Status ==="
kubectl get pods -n openchoreo-build-plane -l app=cluster-agent

echo "=== BuildPlane Agent Connection Logs ==="
kubectl logs -n openchoreo-build-plane -l app=cluster-agent --tail=5 | grep "connected to control plane"

# Check cluster-gateway registration
echo "=== Gateway Registration ==="
kubectl logs -n openchoreo-control-plane -l app=cluster-gateway | grep "agent registered" | tail -5

Expected: You should see "connected to control plane" messages in agent logs and "agent registered" messages in cluster-gateway logs.

Access URLs​

ServiceURL
Console (Backstage)http://openchoreo.localhost:8080
APIhttp://api.openchoreo.localhost:8080
Deployed Appshttp://<component>-<env>.openchoreoapis.localhost:9080
Argo Workflowshttp://localhost:10081 (if Build Plane installed)
OpenSearch Dashboardhttp://localhost:11081 (if Observability installed)

Default credentials: admin@openchoreo.dev / Admin@123


Next Steps​

After completing this single-cluster setup you can:

  1. Deploy your first component to get started with OpenChoreo
  2. Test the GCP microservices demo to see multi-component applications in action
  3. Deploy additional sample applications from the OpenChoreo samples
  4. Experiment with deployments and observe how components interact within the platform

Troubleshooting​

Certificates not issuing (Try Out / Production)​

kubectl describe certificate -n openchoreo-control-plane
kubectl get challenges -A
kubectl describe clusterissuer letsencrypt-prod

Common issues:

  • "contact email has forbidden domain": The default email try-out-user@openchoreo.dev is used. If you need to change it, update the ClusterIssuer before creating certificates.
  • Challenges stuck pending: Ensure LoadBalancer is publicly accessible for HTTP-01 validation

Agent not connecting​

# Check agent pods
kubectl get pods -n openchoreo-data-plane -l app=cluster-agent
kubectl logs -n openchoreo-data-plane -l app=cluster-agent --tail=20

# Check cluster-gateway in control plane
kubectl get pods -n openchoreo-control-plane -l app=cluster-gateway
kubectl logs -n openchoreo-control-plane -l app=cluster-gateway --tail=20 | grep "agent"

Expected output from agent logs:

  • "level":"INFO","msg":"connected to control plane","component":"agent"
  • "level":"INFO","msg":"starting agent","component":"agent"

Expected output from cluster-gateway logs:

  • "level":"INFO","msg":"agent registered","component":"connection-manager"
  • "level":"INFO","msg":"agent connected successfully","component":"agent-server"

Common issues:

  • "connection refused": Wait for cluster-gateway to be ready in the control plane
  • "certificate signed by unknown authority": Verify that the agent CA configuration is correct
  • "WebSocket connection failed": Check that the cluster-gateway service is accessible

Pods stuck in Pending state​

kubectl describe pod <pod-name> -n <namespace>

Common issues:

  • Insufficient resources: Scale up nodes or reduce resource requests
  • PVC issues: Check storage class availability

Gateway not receiving traffic​

# Check Gateway status
kubectl get gateway -n openchoreo-data-plane
kubectl describe gateway gateway-default -n openchoreo-data-plane

# Check HTTPRoutes
kubectl get httproute -A

# Verify kgateway pods
kubectl get pods -n openchoreo-data-plane -l app.kubernetes.io/name=kgateway

Clean Up​

k3d cluster delete openchoreo