Skip to content

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:

ListenerServer port
Management API and admin UI8080
MCP8081
Inference proxy8083
A2A proxy8084

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:

FieldTypeDescription
spec.imagePullPolicystringImage pull policy applied to the managed workloads
spec.exposureobjectHow the Server listeners are exposed outside the cluster. See Exposure
spec.barnobjectThe Wanaku Barn deployment. See Wanaku Barn
spec.barn.enabledboolWhether Wanaku Barn is deployed (required for WanakuServiceCatalog)
spec.barn.image, spec.barn.imagePullPolicystringContainer image and pull policy for Wanaku Barn
spec.barn.envlistExtra environment variables for Wanaku Barn. See Environment variables
spec.barn.storageobjectsize (default 5Gi), storageClassName and existingClaim for the Barn data
spec.routerobjectDeprecated name of spec.barn (without storage). The operator reads it only when spec.barn is not set
spec.serverobjectThe Wanaku router engine: variant, image, env, imagePullPolicy, configMapRef
spec.server.variantstringstandard (default) or headless. See Server variants
spec.server.configMapRefobjectname and key (default wanaku.yaml) of a ConfigMap key that holds a custom wanaku.yaml. See Server configuration
spec.authobjectAuthentication via oauth2-proxy instances placed in front of Wanaku
spec.auth.enabledboolWhether the oauth2-proxies are deployed
spec.auth.issuerUrlstringFull public OIDC issuer URL, including the realm (for example, https://keycloak.example.com/realms/wanaku)
spec.auth.internalIssuerUrlstringOptional in-cluster URL of the same issuer (for example, http://keycloak.keycloak.svc:8080/realms/wanaku)
spec.auth.clientIdstringOIDC client ID used by the proxies (default wanaku-mcp-router)
spec.auth.secretNamestringSecret holding the OIDC credentials and shared cookie secret
spec.auth.image, spec.auth.imagePullPolicy, spec.auth.envmixedoauth2-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 issuerUrl for the login page.
  • The proxies use internalIssuerUrl for token and key requests. If you do not set internalIssuerUrl, the proxies use issuerUrl.
  • The operator sets WANAKU_AUTH_ISSUER (and WANAKU_AUTH_UPSTREAM_ISSUER when internalIssuerUrl is 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 get 401. They are not redirected to the login page.
  • /healthz and /health do not require a token.

The Secret named in spec.auth.secretName must contain two keys:

KeyContent
client-secretThe OIDC client secret of clientId
cookie-secret16, 24 or 32 bytes, or the base64 encoding of such a value

To create the Secret, use these commands:

shell
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:

StatusReasonMeaning
TrueConfiguredAuthentication is configured.
TrueAuthDisabledspec.auth.enabled is not true. The exposed endpoints are not protected. The operator records one Warning event.
TrueDeprecatedIssuerFormatissuerUrl has no /realms/ path. The operator appends /realms/wanaku. Set the full issuer URL.
FalseSecretNotFound, SecretKeyMissing, InvalidCookieSecretThe Secret is missing or not valid.
FalseDeprecatedFieldsThe 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:

VariantDefault imageAdmin UI
standardquay.io/wanaku/wanaku-server:0.3.1Embedded at /admin/
headlessquay.io/wanaku/wanaku-server-headless:0.3.1None

To deploy the headless variant, set spec.server.variant: headless:

yaml
spec:
  server:
    variant: headless

The 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 / and GET /admin/ return 404.
  • status.endpoints.adminUi is not set. The standard variant sets it when the management listener is exposed.
  • When authentication is enabled, the management proxy returns 401 for 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:

shell
kubectl create configmap wanaku-config --from-file=wanaku.yaml -n wanaku

Then reference the ConfigMap in spec.server.configMapRef:

yaml
spec:
  server:
    configMapRef:
      name: wanaku-config
      key: wanaku.yaml

The operator uses these rules for the custom file:

  • It copies the file into the <router>-server-config ConfigMap and mounts it as /etc/wanaku/wanaku.yaml in the Wanaku Server.
  • When Barn is enabled, it adds the wanaku-barn plugin to the plugins list of the file. If the file already declares a plugin with the id wanaku-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 Reconciled condition is False with the reason InvalidServerConfig. 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:

yaml
spec:
  barn:
    enabled: true
    storage:
      size: 10Gi

When Barn is enabled, the operator does these steps:

  • It creates the <router>-barn Deployment, the barn-<router> Service and the Barn PVC. The probes use /q/health/started, /q/health/ready and /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-config ConfigMap and mounts it as /etc/wanaku/wanaku.yaml in the Wanaku Server. The file points the wanaku-barn plugin service wanaku-barn-api at http://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 set spec.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 BarnAvailable condition. Ready requires it.

The operator selects the Barn PVC in this order:

  1. spec.barn.storage.existingClaim. The operator does not create or change this PVC.
  2. The legacy barn-volume-claim PVC, when this router owns it.
  3. <router>-barn-data, which the operator creates with storage.size and storage.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.

FieldDescription
enabledCreates the Ingress resources. The default is true. When false, the operator removes the Ingresses that it created and exposes nothing.
listenersThe listeners to expose, each on its own host. See below.
hostShared host for the management and MCP listeners. The operator uses it only when listeners is not set.
ingressClassNameIngress class.
annotationsAnnotations for every generated Ingress.

The operator supports two exposure modes:

  • Shared host (listeners is not set): when host is 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. The host is required. Inference and A2A are not exposed. Without spec.exposure, the operator exposes nothing.
  • One host per listener (listeners is 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:

FieldDescription
enabledExposes the listener. The default is true for management and mcp, and false for inference and a2a.
hostPublic host. Required for every exposed listener.
yaml
spec:
  exposure:
    enabled: true
    listeners:
      management: {}
      mcp:
        host: mcp.wanaku.example.com
      a2a:
        enabled: true

The 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_URL on the Server. Agent proxy URLs then use the public host.
  • When the MCP listener is exposed, the operator sets WANAKU_MCP_PUBLIC_URL on the Server to https://<MCP host>. The admin UI then shows the public MCP address of each namespace. A value in spec.server.env takes 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:

FieldTypeDescription
spec.routerRefstringName of the WanakuRouter resource. The referenced router must have spec.barn.enabled: true
spec.catalogslistCatalogs 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.

FieldTypeDescription
spec.routerRefstringName of the WanakuRouter that the runtime registers with (required)
spec.source.semanticRoute.namestringA semantic route published in Wanaku Barn
spec.source.catalogobjectA pinned service catalog in Wanaku Barn: name, service, revision, sha256 and optional main
spec.source.configMapRefobjectRoute 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.namestringForward name. The default is the resource name. Forward names are unique in a router
spec.forward.namespacestringWanaku namespace of the forward. The default is default
spec.dependencieslistExtra Maven dependencies (group:artifact:version)
spec.wanakuTokenSecretRef, spec.barnTokenSecretRefobjectSecret name and key (default token) of a bearer token for the router management API or for Barn
spec.image, spec.imagePullPolicystringRuntime image (default quay.io/wanaku/wanaku-semantic-router:0.3.0) and pull policy
spec.envlistExtra environment variables, for example the expert provider credentials. See Environment variables
spec.propertiesmapDeployment 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:

yaml
spec:
  env:
    - name: TYPESAFE_API_KEY
      valueFrom:
        secretKeyRef:
          name: llm-credentials
          key: api-key
  properties:
    camel.component.typesafe-ai.model: my-model

Do 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>-wsr Deployment 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>-wsr Service 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:

ConditionStatus False means
ReconciledValidation failed (ValidationError) or a Kubernetes API call failed (ReconcileError).
AvailableThe 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.
RegisteredThe 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).
ReadyOne 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.

FieldTypeDescription
spec.routerRefstringName of the WanakuRouter that the runtime registers with (required)
spec.routes.configMapRefobjectRoute files in a ConfigMap: name, main (the key of the main route file) and optional items (key, path), as for WanakuSemanticRouter
spec.routes.routesRefstringA routes reference that the runtime downloads, for example datastore://orders.camel.yaml
spec.routes.serviceCatalogobjectA service catalog in Wanaku Barn: name and system
spec.dependencies, spec.repositorieslistExtra Maven dependencies (group:artifact:version) and repositories
spec.mcp.portintMCP server port (default 9090). The health endpoints use the same port
spec.mcp.tagsstringRoute tags that the runtime serves as MCP tools
spec.registration.enabledboolRegisters the runtime with the router (default true)
spec.registration.name, spec.registration.namespacestringForward name (default: the resource name) and Wanaku namespace (default default)
spec.registration.tokenSecretRefobjectSecret name and key (default token) of a bearer token for the router management API
spec.image, spec.imagePullPolicy, spec.envmixedRuntime 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:

yaml
env:
  - name: LOG_LEVEL
    value: debug
  - name: TYPESAFE_API_KEY
    valueFrom:
      secretKeyRef:
        name: llm-credentials
        key: api-key

Use 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.

ConditionWhen the operator sets itStatus False means
ReconciledAlwaysSpec validation failed (ValidationError) or a Kubernetes API call failed (ReconcileError). The message contains the error.
ServerAvailableAlwaysThe <router>-server Deployment is not available.
ExposureReadyAlwaysExposed when the operator created the Ingresses, NotExposed when nothing is exposed. See Exposure.
AuthConfiguredAlwaysThe authentication configuration is not valid. See Authentication.
AuthProxyAvailablespec.auth.enabled: trueThe <router>-oauth2-proxy Deployment is not available.
BarnAvailablespec.barn.enabled: trueThe <router>-barn Deployment is not available.
ReadyAlwaysOne 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, CreateContainerConfigError and 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 ​