Kubernetes Operator Guide
This guide covers deploying and managing Wanaku using the Kubernetes Operator. The operator automates the creation, configuration, and lifecycle management of Wanaku routers, capabilities, and service catalogs on Kubernetes and OpenShift clusters.
Overview
The Wanaku Operator manages three custom resource definitions (CRDs):
- WanakuRouter — deploys and configures the MCP router gateway
- WanakuCapability — deploys capability services (HTTP tools, Camel integrations, etc.) and connects them to a router
- WanakuCamelRoute — packages inline Camel routes into service catalogs and deploys them to a router
- WanakuServiceCatalog — deploys packaged service catalogs (Camel routes + Wanaku rules) to a router
When you create these custom resources, the operator automatically provisions:
- Deployments with health probes
- Services for internal and external access
- ConfigMaps for configuration
- Secrets for OIDC credentials
- Routes (OpenShift) or Ingress (Kubernetes)
- ServiceAccounts and RBAC policies
Prerequisites
Before installing the operator, ensure you have:
- Kubernetes 1.27+ or OpenShift 4.12+
kubectlorocCLI installed and configuredhelmCLI (version 3.x or later)- Cluster admin or namespace admin permissions
- Keycloak instance (for authentication) — see Keycloak Setup
- Or plan to use
wanaku.http.auth=noneenvironment variable for unauthenticated access (development only)
- Or plan to use
Installation
1. Create a Namespace
kubectl create namespace wanaku2. Install the Operator via Helm
helm install wanaku-operator ./apps/wanaku-operator/deploy/helm/wanaku-operator \
--namespace wanaku \
--set operatorNamespace=wanakuThe operator watches for WanakuRouter, WanakuCapability, WanakuCamelRoute, and WanakuServiceCatalog resources in the namespace specified by operatorNamespace. By default, it watches only the namespace where it's installed (current-namespace scope).
To watch all namespaces, override the environment variables during Helm install:
helm install wanaku-operator ./apps/wanaku-operator/deploy/helm/wanaku-operator \
--namespace wanaku \
--set app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_ROUTER_NAMESPACES=JOSDK_ALL_NAMESPACES \
--set app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_CAPABILITY_NAMESPACES=JOSDK_ALL_NAMESPACES \
--set app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_SERVICE_CATALOG_NAMESPACES=JOSDK_ALL_NAMESPACES3. Verify the Operator
kubectl get pods -n wanakuYou should see the operator pod running. Check its logs to confirm startup:
kubectl logs -n wanaku -l app=wanaku-operatorCRD Reference
WanakuRouter (wanaku.ai/v1alpha1)
Defines a Wanaku router instance.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
spec.auth.authServer | string | No | "" | Keycloak server address (format: http://address). Leave empty if running without auth. |
spec.auth.authProxy | string | No | "" | OIDC proxy address. Use "auto" to enable Wanaku's built-in OIDC proxy, or set to Keycloak's address. Empty defaults to Keycloak's address. |
spec.auth.authRealm | string | No | "wanaku" | Keycloak realm name. |
spec.imagePullPolicy | string | No | "IfNotPresent" | Global image pull policy for all operator-managed deployments (Always, IfNotPresent, Never). |
spec.ingress.host | string | No | "" | Ingress hostname for Kubernetes clusters. OpenShift auto-generates Routes; set this only on vanilla Kubernetes. |
spec.router.image | string | No | quay.io/wanaku/wanaku-router-backend:latest | Router container image. |
spec.router.env | list | No | [] | List of {name, value} environment variables for the router (e.g., to set wanaku.http.auth=none). |
spec.router.imagePullPolicy | string | No | inherits spec.imagePullPolicy | Override pull policy for router pod only. |
Example (minimal, with Keycloak):
apiVersion: "wanaku.ai/v1alpha1"
kind: WanakuRouter
metadata:
name: wanaku-dev
spec:
auth:
authServer: http://keycloak:8080NOTE
WanakuRouter does not define spec.secrets. OIDC client secrets are configured on WanakuCapability resources only.
Example (unauthenticated, development only):
apiVersion: "wanaku.ai/v1alpha1"
kind: WanakuRouter
metadata:
name: wanaku-dev-noauth
spec:
router:
env:
- name: wanaku.http.auth
value: noneWanakuCapability (wanaku.ai/v1alpha1)
Defines capability services that register with a router.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
spec.auth.authServer | string | No | "" | Keycloak server address (same as WanakuRouter). |
spec.auth.authProxy | string | No | "" | OIDC proxy address (same as WanakuRouter). |
spec.auth.authRealm | string | No | "wanaku" | Keycloak realm name. |
spec.secrets.oidcCredentialsSecret | string | No | "" | OIDC client secret. Required if using Keycloak. |
spec.imagePullPolicy | string | No | "IfNotPresent" | Global image pull policy for all capabilities. |
spec.routerRef | string | Yes | — | Name of the WanakuRouter CR this capability registers with. Must exist in the same namespace. |
spec.capabilities[].name | string | Yes | — | Unique capability service name. Used as deployment/service name. |
spec.capabilities[].image | string | Yes | — | Container image for this capability. |
spec.capabilities[].type | string | No | "" | Capability type identifier (e.g., camel-integration-capability). |
spec.capabilities[].serviceCatalog | string | No | "" | Service catalog name (must be deployed via WanakuServiceCatalog or wanaku service deploy). |
spec.capabilities[].serviceCatalogSystem | string | No | "" | System name within the service catalog (subdirectory inside the catalog ZIP). |
spec.capabilities[].env | list | No | [] | List of {name, value} environment variables for this capability. |
spec.capabilities[].imagePullPolicy | string | No | inherits spec.imagePullPolicy | Override pull policy for this capability only. |
Example:
apiVersion: "wanaku.ai/v1alpha1"
kind: WanakuCapability
metadata:
name: wanaku-capabilities
spec:
auth:
authServer: http://keycloak:8080
secrets:
oidcCredentialsSecret: wanaku-oidc-secret
routerRef: wanaku-dev
capabilities:
# HTTP capability for generic HTTP tools
- name: wanaku-http
image: quay.io/wanaku/wanaku-tool-service-http:latest
# Camel integration capability with service catalog reference
- name: employee-system
type: camel-integration-capability
image: quay.io/wanaku/camel-integration-capability:latest
serviceCatalog: employee-system-v2
serviceCatalogSystem: employee-systemNOTE
The operator constructs the router's internal service URL as http://internal-{routerRef}:8080. Capabilities use this to register themselves.
WanakuServiceCatalog (wanaku.ai/v1alpha1)
Deploys packaged service catalogs (Base64-encoded ZIPs containing Camel routes and Wanaku rules) to a router via its REST API.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
spec.routerRef | string | Yes | — | Name of the WanakuRouter CR to deploy catalogs to. Must exist in the same namespace. |
spec.catalogs[].name | string | Yes | — | Catalog name (used as identifier in the router's catalog store). |
spec.catalogs[].configMapRef | string | Yes | — | Name of the ConfigMap containing the Base64-encoded ZIP under key catalog.zip. |
Example:
apiVersion: "wanaku.ai/v1alpha1"
kind: WanakuServiceCatalog
metadata:
name: my-service-catalogs
spec:
routerRef: wanaku-dev
catalogs:
- name: finance-catalog
configMapRef: finance-catalog-data
- name: hr-catalog
configMapRef: hr-catalog-dataHow to create the ConfigMap:
# Package your service catalog (creates finance-catalog.b64)
wanaku service package --path=finance-catalog
# Create ConfigMap from the Base64-encoded file
kubectl create configmap finance-catalog-data \
--from-file=catalog.zip=finance-catalog.b64 \
-n wanakuTIP
See Service Catalogs and Service Templates for details on creating and packaging catalogs.
WanakuCamelRoute (wanaku.ai/v1alpha1)
Packages inline Camel routes and MCP metadata into a service catalog automatically, then deploys the resulting capability to a router.
See the dedicated WanakuCamelRoute CRD guide for the full schema, examples, and troubleshooting notes.
Deployment Examples
Minimal Router + HTTP Capability
# router.yaml
apiVersion: "wanaku.ai/v1alpha1"
kind: WanakuRouter
metadata:
name: wanaku-dev
spec:
auth:
authServer: http://keycloak:8080
---
# capabilities.yaml
apiVersion: "wanaku.ai/v1alpha1"
kind: WanakuCapability
metadata:
name: wanaku-capabilities
spec:
auth:
authServer: http://keycloak:8080
secrets:
oidcCredentialsSecret: wanaku-oidc-secret
routerRef: wanaku-dev
capabilities:
- name: wanaku-http
image: quay.io/wanaku/wanaku-tool-service-http:latestApply:
kubectl apply -f router.yaml -n wanaku
kubectl wait wanakurouter/wanaku-dev --for=condition=Ready --timeout=120s
kubectl apply -f capabilities.yaml -n wanaku
kubectl wait wanakucapability/wanaku-capabilities --for=condition=Ready --timeout=120sRouter + Service Catalog
# router.yaml (same as above)
---
# service-catalog.yaml
apiVersion: "wanaku.ai/v1alpha1"
kind: WanakuServiceCatalog
metadata:
name: my-catalogs
spec:
routerRef: wanaku-dev
catalogs:
- name: employee-system-v2
configMapRef: employee-catalog-dataCreate the ConfigMap first:
wanaku service package --path=employee-system -o employee-system.b64
kubectl create configmap employee-catalog-data --from-file=catalog.zip=employee-system.b64 -n wanakuThen apply the CRs:
kubectl apply -f router.yaml -n wanaku
kubectl apply -f service-catalog.yaml -n wanakuLifecycle Operations
Checking Status
List all Wanaku resources:
kubectl get wanakurouter,wanakucapability,wanakucamelroute,wanakuservicecatalog -n wanakuGet detailed status:
kubectl describe wanakurouter wanaku-dev -n wanaku
kubectl describe wanakucapability wanaku-capabilities -n wanaku
kubectl describe wanakuservicecatalog my-catalogs -n wanakuThe status section shows:
Readycondition (true/false)- Deployed capabilities or catalogs
- Error messages (if reconciliation failed)
Check router logs:
kubectl logs -n wanaku deployment/wanaku-devCheck capability logs:
kubectl logs -n wanaku deployment/wanaku-httpUpdating Resources
Edit the custom resource directly:
kubectl edit wanakurouter wanaku-dev -n wanakuOr update your YAML and reapply:
# Edit router.yaml locally
kubectl apply -f router.yaml -n wanakuThe operator detects changes and reconciles automatically. For deployments, this triggers a rolling update.
Example: change router image tag
spec:
router:
image: quay.io/wanaku/wanaku-router-backend:1.0.0Removing Resources
Delete the custom resources in reverse order (catalogs first, then capabilities, then router):
kubectl delete wanakuservicecatalog my-catalogs -n wanaku
kubectl delete wanakucamelroute my-camel-route -n wanaku
kubectl delete wanakucapability wanaku-capabilities -n wanaku
kubectl delete wanakurouter wanaku-dev -n wanakuThe operator cleans up all managed Kubernetes objects (deployments, services, configmaps, etc.).
Uninstalling the Operator
helm uninstall wanaku-operator -n wanakuWARNING
Uninstalling the operator does not delete the CRDs or existing custom resources. To fully clean up:
kubectl delete wanakurouter --all -n wanaku
kubectl delete wanakucapability --all -n wanaku
kubectl delete wanakuservicecatalog --all -n wanaku
kubectl delete crd wanakurouters.wanaku.ai wanakucapabilities.wanaku.ai wanakucamelroutes.wanaku.ai wanakuservicecatalogs.wanaku.aiRunning Without Authentication
For development or testing, you can disable authentication by setting the wanaku.http.auth environment variable on the router:
apiVersion: "wanaku.ai/v1alpha1"
kind: WanakuRouter
metadata:
name: wanaku-dev-noauth
spec:
router:
env:
- name: wanaku.http.auth
value: noneWith this setting:
- You don't need a Keycloak instance
- Leave
spec.auth.authServerempty - Capabilities don't require OIDC credentials either (the router accepts unauthenticated registration)
IMPORTANT
Never use wanaku.http.auth=none in production. This disables all authentication and authorization checks.
Helm Chart Values
The operator's Helm chart exposes these key configuration options in values.yaml:
| Value | Type | Default | Description |
|---|---|---|---|
app.image | string | quay.io/wanaku/wanaku-operator:latest | Operator container image. |
app.imagePullPolicy | string | IfNotPresent | Image pull policy for operator pod. |
app.ports.http | int | 8081 | HTTP port for operator's health and metrics endpoints. |
app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_ROUTER_NAMESPACES | string | JOSDK_WATCH_CURRENT | Watch scope for WanakuRouter resources (JOSDK_WATCH_CURRENT = current namespace only, JOSDK_ALL_NAMESPACES = cluster-wide). |
app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_CAPABILITY_NAMESPACES | string | JOSDK_WATCH_CURRENT | Watch scope for WanakuCapability resources. |
app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_CAMEL_ROUTE_NAMESPACES | string | JOSDK_WATCH_CURRENT | Watch scope for WanakuCamelRoute resources. |
app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_SERVICE_CATALOG_NAMESPACES | string | JOSDK_WATCH_CURRENT | Watch scope for WanakuServiceCatalog resources. |
Example: customize operator image and watch all namespaces
helm install wanaku-operator ./apps/wanaku-operator/deploy/helm/wanaku-operator \
--namespace wanaku \
--set app.image=quay.io/myorg/wanaku-operator:1.0.0 \
--set app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_ROUTER_NAMESPACES=JOSDK_ALL_NAMESPACES \
--set app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_CAPABILITY_NAMESPACES=JOSDK_ALL_NAMESPACES \
--set app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_CAMEL_ROUTE_NAMESPACES=JOSDK_ALL_NAMESPACES \
--set app.envs.QUARKUS_OPERATOR_SDK_CONTROLLERS_WANAKU_SERVICE_CATALOG_NAMESPACES=JOSDK_ALL_NAMESPACESTroubleshooting
Operator pod not starting
Check pod status:
kubectl get pods -n wanaku
kubectl describe pod -n wanaku -l app=wanaku-operatorCommon causes:
- Image pull errors: verify the operator image exists and is accessible
- RBAC issues: ensure the ServiceAccount has correct ClusterRole bindings (check Helm chart RBAC templates)
- Resource limits: the pod may be pending due to insufficient cluster resources
Check operator logs:
kubectl logs -n wanaku -l app=wanaku-operatorLook for startup errors or Java exceptions.
CRDs not reconciling
Check custom resource status:
kubectl describe wanakurouter wanaku-dev -n wanakuLook at the Status.Conditions section for error messages.
Common issues:
Router not ready: the
WanakuRouterCR is not inReadystate- Check router deployment logs:
kubectl logs -n wanaku deployment/wanaku-dev - Verify Keycloak is reachable if using authentication
- Verify OIDC secret exists:
kubectl get secret wanaku-oidc-secret -n wanaku
- Check router deployment logs:
Capability deployment stuck: check if
routerRefmatches an existingWanakuRoutershellkubectl get wanakurouter -n wanakuService catalog deployment failed: verify the ConfigMap exists and has key
catalog.zipshellkubectl get configmap finance-catalog-data -n wanaku -o yaml
Operator reconciliation logs:
kubectl logs -n wanaku -l app=wanaku-operator --followWatch for errors during CR reconciliation.
Capabilities not connecting to router
Check capability pod logs:
kubectl logs -n wanaku deployment/wanaku-httpLook for errors like:
Connection refused— router service not reachable401 Unauthorized— OIDC credentials mismatch503 Service Unavailable— router not ready
Verify internal service exists:
kubectl get svc -n wanakuThe operator creates a service named internal-{routerRef} for capabilities to connect to.
Verify OIDC credentials match:
All capabilities must use the same oidcCredentialsSecret. Check the secret value:
kubectl get secret wanaku-oidc-secret -n wanaku -o jsonpath='{.data.client-secret}' | base64 -dCompare this to the Keycloak client secret (should match exactly).
Router or capability pods crash-looping
Check pod events:
kubectl describe pod -n wanaku <pod-name>Check application logs:
kubectl logs -n wanaku <pod-name>Common causes:
- Configuration errors: invalid environment variables or missing secrets
- Startup probe failures: pod not becoming healthy in time (increase
initialDelaySecondsif needed) - Java heap issues: increase memory limits in the CR (capabilities and router use JVM-based containers)
Example: increase router memory limit
spec:
router:
env:
- name: JAVA_OPTS
value: "-Xmx1g"(This requires the router image to honor JAVA_OPTS. Check the container entrypoint.)
Ingress/Route not working
OpenShift (Routes):
kubectl get route -n wanaku
kubectl describe route wanaku-dev -n wanakuRoutes are auto-generated. If missing, check if the WanakuRouter has spec.ingress.host set (it should be empty on OpenShift).
Kubernetes (Ingress):
kubectl get ingress -n wanaku
kubectl describe ingress wanaku-dev -n wanakuOn vanilla Kubernetes, you must set spec.ingress.host in the WanakuRouter CR:
spec:
ingress:
host: wanaku.example.comVerify your Ingress controller is installed and configured (e.g., NGINX, Traefik).
How to manually inspect operator-managed resources
The operator creates these resources for each custom resource. You can inspect them directly:
For WanakuRouter wanaku-dev:
kubectl get deployment wanaku-dev -n wanaku
kubectl get service wanaku-dev -n wanaku
kubectl get service internal-wanaku-dev -n wanaku
kubectl get configmap wanaku-dev-config -n wanakuFor WanakuCapability wanaku-capabilities with capability wanaku-http:
kubectl get deployment wanaku-http -n wanaku
kubectl get service wanaku-http -n wanaku
kubectl get configmap wanaku-http-config -n wanakuWARNING
Do not manually edit operator-managed resources (deployments, services, etc.). The operator reconciles them continuously and will overwrite manual changes. Always edit the custom resource instead.
Next Steps
- Configure authentication: see Keycloak Setup
- Create service catalogs: see Service Catalogs
- Use service templates: see Service Templates
- Configure advanced settings: see Configuration Guide
- Browse sample CRs: check apps/wanaku-operator/samples