Wanaku Operator custom resources
This page lists the fields, ports and status conditions of the custom resources that the Wanaku Operator manages. To install the operator and deploy these resources, see Deploy with the Wanaku Operator.
Standard listener ports
The operator uses the embedded listeners described in the Wanaku configuration guide:
| Listener | Server port |
|---|---|
| Management API and admin UI | 8080 |
| MCP | 8081 |
| Inference proxy | 8083 |
| A2A proxy | 8084 |
The server-<router> Service exposes all four ports. Health probes use the named management port. When authentication is enabled, the oauth2-proxy ports are 4180 (MCP), 4181 (management), 4183 (inference) and 4184 (A2A). See Exposure for the listeners that the operator exposes outside the cluster.
NOTE
The Docker Compose setup in the Wanaku repository uses the reverse mapping: 4180 for the management proxy and 4181 for the MCP proxy. Use the ports of the deployment that you run.
Management and A2A use WANAKU_MGMT_LISTEN and WANAKU_A2A_LISTEN; MCP and inference use the embedded pipeline configuration. Changing listener ports through custom configuration also requires matching Service, probe, and exposure changes.
Wanaku Barn listens on 8180. Its barn-<router> Service exposes 8080 and forwards to 8180, keeping the internal Barn URL unchanged. In Docker Compose, both processes use host networking, so Wanaku Server reaches Barn at http://localhost:8180.
WanakuRouter (wanaku.ai/v1alpha1)
WanakuRouter deploys the Wanaku execution proxy. The spec supports:
| Field | Type | Description |
|---|---|---|
spec.imagePullPolicy | string | Image pull policy applied to the managed workloads |
spec.exposure | object | How the Server listeners are exposed outside the cluster. See Exposure |
spec.barn | object | The Wanaku Barn deployment. See Wanaku Barn |
spec.barn.enabled | bool | Whether Wanaku Barn is deployed (required for WanakuServiceCatalog) |
spec.barn.image, spec.barn.imagePullPolicy | string | Container image and pull policy for Wanaku Barn |
spec.barn.env | list | Extra environment variables for Wanaku Barn. See Environment variables |
spec.barn.storage | object | size (default 5Gi), storageClassName and existingClaim for the Barn data |
spec.router | object | Deprecated name of spec.barn (without storage). The operator reads it only when spec.barn is not set |
spec.server | object | The Wanaku router engine: variant, image, env, imagePullPolicy, configMapRef |
spec.server.variant | string | standard (default) or headless. See Server variants |
spec.server.configMapRef | object | name and key (default wanaku.yaml) of a ConfigMap key that holds a custom wanaku.yaml. See Server configuration |
spec.auth | object | Authentication via oauth2-proxy instances placed in front of Wanaku |
spec.auth.enabled | bool | Whether the oauth2-proxies are deployed |
spec.auth.issuerUrl | string | Full public OIDC issuer URL, including the realm (for example, https://keycloak.example.com/realms/wanaku) |
spec.auth.internalIssuerUrl | string | Optional in-cluster URL of the same issuer (for example, http://keycloak.keycloak.svc:8080/realms/wanaku) |
spec.auth.clientId | string | OIDC client ID used by the proxies (default wanaku-mcp-router) |
spec.auth.secretName | string | Secret holding the OIDC credentials and shared cookie secret |
spec.auth.image, spec.auth.imagePullPolicy, spec.auth.env | mixed | oauth2-proxy image and configuration |
When authentication is enabled, the operator deploys two oauth2-proxy instances: one protecting the MCP port (4180) and one protecting the management port (4181), sharing the same cookie secret for single sign-on.
Authentication
The operator uses these rules for authentication:
- The proxies validate tokens. The Wanaku Server does not validate tokens.
- Browsers use
issuerUrlfor the login page. - The proxies use
internalIssuerUrlfor token and key requests. If you do not setinternalIssuerUrl, the proxies useissuerUrl. - The operator sets
WANAKU_AUTH_ISSUER(andWANAKU_AUTH_UPSTREAM_ISSUERwheninternalIssuerUrlis set) on the Wanaku Server. MCP clients then discover the authorization server through/.well-known/oauth-protected-resource. - Requests to the MCP endpoints and to
/api/without a valid token get401. They are not redirected to the login page. /healthzand/healthdo not require a token.
The Secret named in spec.auth.secretName must contain two keys:
| Key | Content |
|---|---|
client-secret | The OIDC client secret of clientId |
cookie-secret | 16, 24 or 32 bytes, or the base64 encoding of such a value |
To create the Secret, use these commands:
kubectl create secret generic wanaku-oidc-secret -n wanaku \
--from-literal=client-secret=<client secret from Keycloak> \
--from-literal=cookie-secret="$(openssl rand -hex 16)"The operator reads the Secret before it deploys the proxies. If the Secret is missing or not valid, the operator does not deploy the proxies. When the Secret changes, the operator restarts the proxies.
The AuthConfigured condition reports the authentication configuration:
| Status | Reason | Meaning |
|---|---|---|
True | Configured | Authentication is configured. |
True | AuthDisabled | spec.auth.enabled is not true. The exposed endpoints are not protected. The operator records one Warning event. |
True | DeprecatedIssuerFormat | issuerUrl has no /realms/ path. The operator appends /realms/wanaku. Set the full issuer URL. |
False | SecretNotFound, SecretKeyMissing, InvalidCookieSecret | The Secret is missing or not valid. |
False | DeprecatedFields | The resource uses spec.auth.authServer or spec.auth.authProxy. These fields have no effect. Replace them with enabled, issuerUrl, clientId and secretName. |
Earlier operator versions appended /realms/wanaku to issuerUrl. Resources that set only the Keycloak base URL continue to work, with the DeprecatedIssuerFormat reason.
Server variants
The Wanaku Server has two container images:
| Variant | Default image | Admin UI |
|---|---|---|
standard | quay.io/wanaku/wanaku-server:0.3.1 | Embedded at /admin/ |
headless | quay.io/wanaku/wanaku-server-headless:0.3.1 | None |
To deploy the headless variant, set spec.server.variant: headless:
spec:
server:
variant: headlessThe variant selects the default image. If you set spec.server.image, the operator uses that image, and the variant only controls how the operator advertises the admin UI.
The headless variant keeps the management APIs, MCP, inference, A2A, persistence, probes and authentication. The probes use /healthz, which does not depend on the admin UI. In the headless variant:
GET /andGET /admin/return404.status.endpoints.adminUiis not set. The standard variant sets it when the management listener is exposed.- When authentication is enabled, the management proxy returns
401for requests without a token on all paths, instead of a redirect to the login page.
Server configuration
The Wanaku Server reads its governance posture, forwards, credential bindings, LLM connections, evaluators and action policies from a wanaku.yaml file. Without a custom file, the Server uses the default posture: mode: enforce, no_match: deny and on_failure: deny. With this posture, the Server denies each tools/call, resources/read and prompts/get request that no evaluator matches. See Governance posture.
To supply your own wanaku.yaml, put it in a ConfigMap in the namespace of the router:
kubectl create configmap wanaku-config --from-file=wanaku.yaml -n wanakuThen reference the ConfigMap in spec.server.configMapRef:
spec:
server:
configMapRef:
name: wanaku-config
key: wanaku.yamlThe operator uses these rules for the custom file:
- It copies the file into the
<router>-server-configConfigMap and mounts it as/etc/wanaku/wanaku.yamlin the Wanaku Server. - When Barn is enabled, it adds the
wanaku-barnplugin to thepluginslist of the file. If the file already declares a plugin with the idwanaku-barn, the operator does not change the file. - It watches the referenced ConfigMap. When the content changes, the Server restarts with the new file.
- It does not accept the name
<router>-server-config, because the operator owns that ConfigMap. - If the ConfigMap or the key does not exist, or the file is not a YAML mapping, the
Reconciledcondition isFalsewith the reasonInvalidServerConfig. The message tells which part is missing or not valid. The operator does not change the Server until you correct the reference.
The operator does not validate the Wanaku settings in the file. The Server validates them at startup. If a setting is not valid, the Server does not start. Use kubectl logs deployment/<router>-server to see the error.
The Server reads secrets that the file names from environment variables. Set these variables in spec.server.env, with valueFrom.secretKeyRef to read them from a Secret. See Environment variables.
Wanaku Barn
Wanaku Barn is optional. Set spec.barn.enabled: true to deploy it:
spec:
barn:
enabled: true
storage:
size: 10GiWhen Barn is enabled, the operator does these steps:
- It creates the
<router>-barnDeployment, thebarn-<router>Service and the Barn PVC. The probes use/q/health/started,/q/health/readyand/q/health/live. - It sets the Barn persistence folder to the PVC mount path. The data does not depend on the home directory of the container user.
- It writes the
<router>-server-configConfigMap and mounts it as/etc/wanaku/wanaku.yamlin the Wanaku Server. The file points thewanaku-barnplugin servicewanaku-barn-apiathttp://barn-<router>:8080. The Server then proxies/api/plugins/wanaku-barn/wanaku-barn-api/...to Barn. When the file changes, the Server restarts. If you setspec.server.configMapRef, the operator adds the plugin to your file. See Server configuration. - It publishes the internal Barn URL in
status.barnUrl. Other clients, for example the Camel Integration Capability (REGISTRATION_URL) and the semantic router (WSR_BARN_URL), use this URL. - It reports the Barn availability in the
BarnAvailablecondition.Readyrequires it.
The operator selects the Barn PVC in this order:
spec.barn.storage.existingClaim. The operator does not create or change this PVC.- The legacy
barn-volume-claimPVC, when this router owns it. <router>-barn-data, which the operator creates withstorage.sizeandstorage.storageClassName.
WanakuServiceCatalog resources wait while Barn is not available. Their Ready condition has the reason BarnUnavailable, and the operator tries again every 15 seconds.
When you set spec.barn.enabled: false, the operator deletes the Barn Deployment, the Barn Service and the Server plugin configuration. It keeps the Barn PVC, so that the data is not lost. To delete the data, delete the PVC manually.
Values that you set earlier through PUT /api/v1/plugins/wanaku-barn/config override the operator configuration. The admin UI plugin archive is a separate installation step (POST /api/v1/plugins/install). The headless Server does not need it.
Exposure
spec.exposure selects the Server listeners that the operator exposes outside the cluster, and how it exposes them.
| Field | Description |
|---|---|
enabled | Creates the Ingress resources. The default is true. When false, the operator removes the Ingresses that it created and exposes nothing. |
listeners | The listeners to expose, each on its own host. See below. |
host | Shared host for the management and MCP listeners. The operator uses it only when listeners is not set. |
ingressClassName | Ingress class. |
annotations | Annotations for every generated Ingress. |
The operator supports two exposure modes:
- Shared host (
listenersis not set): whenhostis set, both listeners use that host. The management listener uses the path/, and the MCP listener uses the path/default/mcp. Only the default Wanaku namespace is reachable through MCP; use one host per listener for other namespaces and OAuth discovery. Thehostis required. Inference and A2A are not exposed. Withoutspec.exposure, the operator exposes nothing. - One host per listener (
listenersis set): each exposed listener gets its own Ingress, named<router>-<listener>, for the path/. All MCP endpoints, including/<namespace>/mcp, are reachable.
Each entry in listeners (management, mcp, inference, a2a) has these fields:
| Field | Description |
|---|---|
enabled | Exposes the listener. The default is true for management and mcp, and false for inference and a2a. |
host | Public host. Required for every exposed listener. |
spec:
exposure:
enabled: true
listeners:
management: {}
mcp:
host: mcp.wanaku.example.com
a2a:
enabled: trueThe operator uses these rules:
- When authentication is enabled, each exposed listener goes through its oauth2-proxy port. Inference and A2A accept only bearer tokens; requests without a token get
401. A2A agent cards (/<namespace>/a2a/<agent>/.well-known/...) do not require a token. - When the A2A listener is exposed, the operator sets
WANAKU_A2A_PUBLIC_URLon the Server. Agent proxy URLs then use the public host. - When the MCP listener is exposed, the operator sets
WANAKU_MCP_PUBLIC_URLon the Server tohttps://<MCP host>. The admin UI then shows the public MCP address of each namespace. A value inspec.server.envtakes precedence. - When you disable a listener, change the mode or set
enabled: false, the operator deletes the Ingresses that are no longer necessary.
status.endpoints contains the public URL of each exposed listener, for example https://mcp.wanaku.example.com/default/mcp. The ExposureReady condition is True with the reason Exposed when the operator created the Ingresses, and with the reason NotExposed when nothing is exposed.
WanakuServiceCatalog (wanaku.ai/v1alpha1)
WanakuServiceCatalog deploys packaged service catalogs to a router:
| Field | Type | Description |
|---|---|---|
spec.routerRef | string | Name of the WanakuRouter resource. The referenced router must have spec.barn.enabled: true |
spec.catalogs | list | Catalogs to deploy, each with a name and a configMapRef |
The referenced ConfigMap must contain the packaged catalog (catalog.zip), created with wanaku service package (see Deploy a catalog with the Wanaku Operator).
WanakuSemanticRouter (wanaku.ai/v1alpha1)
WanakuSemanticRouter runs one Wanaku Semantic Router (WSR) runtime. One runtime serves one semantic route as one MCP tool. The runtime registers itself with the router as an MCP forward when it starts, and removes the forward when it stops.
| Field | Type | Description |
|---|---|---|
spec.routerRef | string | Name of the WanakuRouter that the runtime registers with (required) |
spec.source.semanticRoute.name | string | A semantic route published in Wanaku Barn |
spec.source.catalog | object | A pinned service catalog in Wanaku Barn: name, service, revision, sha256 and optional main |
spec.source.configMapRef | object | Route files in a ConfigMap: name, main and optional items. The ConfigMap must also contain semantic-router.properties and the files that it references. Without items, every key is a file in one directory and main is the key of the main route file. With items (key, path), each key is placed at its relative path, and main is the path of the main route file |
spec.forward.name | string | Forward name. The default is the resource name. Forward names are unique in a router |
spec.forward.namespace | string | Wanaku namespace of the forward. The default is default |
spec.dependencies | list | Extra Maven dependencies (group:artifact:version) |
spec.wanakuTokenSecretRef, spec.barnTokenSecretRef | object | Secret name and key (default token) of a bearer token for the router management API or for Barn |
spec.image, spec.imagePullPolicy | string | Runtime image (default quay.io/wanaku/wanaku-semantic-router:0.3.0) and pull policy |
spec.env | list | Extra environment variables, for example the expert provider credentials. See Environment variables |
spec.properties | map | Deployment and Camel component properties. The operator passes each entry to the runtime as -p KEY=VALUE |
Set exactly one source. The semanticRoute and catalog sources need Wanaku Barn on the router (spec.barn.enabled: true).
The runtime needs the credentials of the expert that the semantic route uses. For the default TypeSafe AI expert, set TYPESAFE_API_KEY from a Secret. Without it, the runtime stops at startup with WSR command failed: IllegalArgumentException:
spec:
env:
- name: TYPESAFE_API_KEY
valueFrom:
secretKeyRef:
name: llm-credentials
key: api-key
properties:
camel.component.typesafe-ai.model: my-modelDo not put credential values in spec.properties. Use an environment reference such as {{env:TYPESAFE_API_KEY}} and set the variable through spec.env.
The operator creates these resources:
- The
<name>-wsrDeployment with one replica. It uses a rolling update: the new pod registers the forward again with a new instance label, so the old pod does not remove it at shutdown. - The
<name>-wsrService on port 8090. It publishes addresses of pods that are not ready, because the router discovers the tool while the runtime registers, before the pod is ready.
The runtime registers the forward with the pod IP (WSR_MCP_ADDRESS=http://$(POD_IP):8090/mcp), not with the Service address. During a rolling update, the Service also sends traffic to the old pod. Thus the router can discover the tool on the old pod, or on no pod when the old pod crash-loops. status.mcpAddress shows the Service address.
The probes use the WSR health endpoints on port 8091 (/api/v1/health/started, /ready and /live). The pod is ready only after the runtime registered the forward. The startup probe allows 10 minutes, because the runtime resolves Maven dependencies at startup.
The status contains these conditions and fields:
| Condition | Status False means |
|---|---|
Reconciled | Validation failed (ValidationError) or a Kubernetes API call failed (ReconcileError). |
Available | The runtime pod is not ready. The reason comes from the pod, for example CrashLoopBackOff. A failed startup shows the WSR status message as the last termination message. |
Registered | The router has no forward with this name (NotRegistered), the forward belongs to another registrant (ForeignForward), the forward is unavailable (ForwardUnavailable), or the operator cannot reach the router (RouterUnreachable). |
Ready | One of the conditions above is False. |
status.forwardName, status.mcpAddress and status.wanakuEndpoint (the router MCP endpoint for the forward namespace, when the router exposes MCP) describe the registration.
When you delete the resource, Kubernetes stops the runtime. The runtime removes the forward if it still owns it. If the router is already gone, the runtime cannot remove the forward.
WanakuIntegration (wanaku.ai/v1alpha1)
WanakuIntegration runs one Camel Integration Capability (CIC) runtime. The runtime loads Camel routes, serves the tagged routes as MCP tools, and registers itself with the router as an MCP forward. It removes the forward when it stops.
| Field | Type | Description |
|---|---|---|
spec.routerRef | string | Name of the WanakuRouter that the runtime registers with (required) |
spec.routes.configMapRef | object | Route files in a ConfigMap: name, main (the key of the main route file) and optional items (key, path), as for WanakuSemanticRouter |
spec.routes.routesRef | string | A routes reference that the runtime downloads, for example datastore://orders.camel.yaml |
spec.routes.serviceCatalog | object | A service catalog in Wanaku Barn: name and system |
spec.dependencies, spec.repositories | list | Extra Maven dependencies (group:artifact:version) and repositories |
spec.mcp.port | int | MCP server port (default 9090). The health endpoints use the same port |
spec.mcp.tags | string | Route tags that the runtime serves as MCP tools |
spec.registration.enabled | bool | Registers the runtime with the router (default true) |
spec.registration.name, spec.registration.namespace | string | Forward name (default: the resource name) and Wanaku namespace (default default) |
spec.registration.tokenSecretRef | object | Secret name and key (default token) of a bearer token for the router management API |
spec.image, spec.imagePullPolicy, spec.env | mixed | Runtime image (default quay.io/wanaku/camel-integration-capability:0.3.0) and configuration |
Set exactly one routes source. datastore:// references and service catalogs need Wanaku Barn on the router (spec.barn.enabled: true).
The operator creates the <name>-cic Deployment and the <name>-cic Service. They follow the same rules as the semantic router workload: one replica, a rolling update that is safe with the ownership label (cic.instance), and a Service that publishes the addresses of pods that are not ready. The probes use the Camel health endpoints on the MCP port (/observe/health/ready and /observe/health/live). When registration is enabled, the pod is ready only after the runtime registered the forward.
The status uses the same conditions as WanakuSemanticRouter: Reconciled, Available, Registered (only when registration is enabled) and Ready.
Environment variables
The env lists of WanakuRouter (spec.server.env, spec.barn.env, spec.auth.env) and of WanakuSemanticRouter and WanakuIntegration (spec.env) use the same format. Each entry has a name and either a value or a valueFrom.secretKeyRef (name and key) that reads the value from a Secret in the same namespace:
env:
- name: LOG_LEVEL
value: debug
- name: TYPESAFE_API_KEY
valueFrom:
secretKeyRef:
name: llm-credentials
key: api-keyUse valueFrom for credentials, so that their values are not stored in the custom resource.
WanakuRouter conditions
The operator sets Ready=True only when all required workloads are available. The operator records the observed generation in status.observedGeneration and in each condition.
| Condition | When the operator sets it | Status False means |
|---|---|---|
Reconciled | Always | Spec validation failed (ValidationError) or a Kubernetes API call failed (ReconcileError). The message contains the error. |
ServerAvailable | Always | The <router>-server Deployment is not available. |
ExposureReady | Always | Exposed when the operator created the Ingresses, NotExposed when nothing is exposed. See Exposure. |
AuthConfigured | Always | The authentication configuration is not valid. See Authentication. |
AuthProxyAvailable | spec.auth.enabled: true | The <router>-oauth2-proxy Deployment is not available. |
BarnAvailable | spec.barn.enabled: true | The <router>-barn Deployment is not available. |
Ready | Always | One of the conditions above is False. The reason and the message identify the first failed condition. |
A workload condition uses these reasons:
Available: all replicas are available.Progressing: the rollout continues.ImagePullBackOff,ErrImagePull,CrashLoopBackOff,CreateContainerConfigErrorand similar: a pod container cannot start. The message contains the container message and the last termination message.Unschedulable: the scheduler cannot place a pod.ProgressDeadlineExceeded: the rollout did not complete in the Deployment progress deadline.NotFound: the Deployment does not exist.
When Ready changes to False, or the failure reason changes, the operator records a Warning event on the custom resource. While the router is not ready, the operator checks the workloads again every 30 seconds.
Next steps
- Deploy with the Wanaku Operator: install the operator and deploy a router.
- Build and deploy a service catalog: package a catalog for
WanakuServiceCatalog. - Wanaku Operator on OperatorHub: install the operator with OLM.