Control Plane Operations
This section provides runbooks for operating the self-hosted NVCF control plane, including encryption key rotation, service management, and upgrades.
Encryption Key Management
Self-hosted NVCF uses a two-tier encryption hierarchy to protect secrets stored in the Encrypted Secret Store (ESS):
When a user stores a secret through the NVCF API, ESS encrypts it with the active NEK for that namespace. The NEK itself is stored in Cassandra, encrypted by the MEK. To decrypt a secret, ESS retrieves the NEK from Cassandra, decrypts it using the MEK from OpenBAO, then decrypts the secret.
Key Rotation Runbooks
- control-plane-runbook-mek-rotation. Rotate the master encryption key stored in OpenBAO.
Basic Operations
Service Reference
The following table lists all NVCF control plane services with their namespace, resource name, and resource type. Use these values in the commands throughout this section.
Pod Annotations
Set pod annotations for a service in environments/<environment-name>.yaml, for example to opt its
pods into a log or metrics agent. Each key is passed to the chart unchanged; unset keys render
nothing.
Annotation values must be strings, so quote numbers and booleans ("8080", "true"), and do not
set keys the charts manage themselves, such as checksum/config. A change rolls the Deployments and
NATS. OpenBao uses the OnDelete update strategy, so its pods pick up new annotations only when
they are restarted. Keys starting with nvcf.nvidia.com/nats-worker-auth are reserved for the auth
callout’s restart on a worker auth change, and setting them fails the render.
Restarting a Service
Restarting a Deployment:
Restarting a StatefulSet:
StatefulSets using RollingUpdate restart one pod at a time in reverse ordinal
order. Check the update strategy before using the commands below. OpenBao uses
OnDelete, so kubectl rollout restart alone does not replace its pods. For
OpenBao 2.6.2 to 2.6.3, use the
OpenBao patch upgrade runbook.
For OpenBao, verify every member’s seal state after each replacement, not just Kubernetes readiness. For example:
Restarting all Deployments in a namespace:
Checking Service Health
List pods and their status:
Check logs for a service:
Describe a pod for events and conditions:
Scaling a Service
To temporarily take a service offline (for example, during maintenance), scale it to zero, perform the work, then scale it back:
Scaling infrastructure StatefulSets (Cassandra, NATS, OpenBao) to zero will cause a full outage. Only do this if you understand the implications for data availability and quorum.
Upgrading Services
For a stack upgrade, follow the staged 1.0.2-to-1.0.4 procedure. It covers the stack combination in docs editions 1.0.2 and 1.0.3 and the required hostname-policy, NVCA and control-plane ordering. Older source stacks must complete their intermediate migration steps first.
The commands below are for targeted fixes to individual services. A spot upgrade bypasses the stack’s coordinated versions and migrations. Review the specific chart’s compatibility and rollback limits before using this path.
When to Spot Upgrade
Pre-Upgrade Checklist
Before upgrading any chart:
-
Note the current chart version and app version:
-
Back up the current Helm values:
-
Review release notes for the target version. Check for breaking changes, required value changes, or new dependencies.
-
Verify the cluster is healthy before starting: all pods running, no pending operations.
Spot Upgrading a Helm Chart
The following commands work for any Deployment-based service. Replace the placeholders with values from the [Service Reference] table above.
Example: upgrading the NVCF API chart:
Always pass your values file (-f values.yaml) during upgrade. If you omit it, Helm
resets all values to chart defaults, which can break your deployment. If you no longer
have the original values file, back up the current values first with helm get values.
Upgrading StatefulSet-Based Services
Cassandra, NATS, and OpenBao are deployed as StatefulSets. The helm upgrade command is the
same, but rollout depends on the update strategy. The following rolling-update
description does not apply to OpenBao’s OnDelete strategy:
- Rolling update: StatefulSets restart pods one at a time in reverse ordinal order, waiting for each pod to become ready before proceeding to the next.
- Quorum preserved: For 3-replica clusters, at most one pod is unavailable at a time, maintaining quorum throughout the upgrade.
Service-specific notes:
Rolling Back
The commands below are not a data-downgrade procedure for OpenBao. Use a separately validated recovery plan for stateful data services.
If an upgrade causes issues, roll back to the previous Helm revision:
helm rollback reverts both the chart version and the values. If you made intentional
value changes alongside the version upgrade, you will need to re-apply them after the
rollback.
Disabling Admin Issuer Proxy
Admin Issuer Proxy is a bootstrap helper. POST /v1/admin/keys returns a 12-hour admin JWT, signed by OpenBao as the NVCF API’s in-cluster issuer, carrying function, secret, registry-credential, cluster-group listing and cluster-management scopes.
It does not authenticate callers. The stack relies on the gateway in front of it for that.
It exists so a new install with no identity provider can mint its first admin token, and nvcf-cli init uses it.
An install whose callers already get tokens from their own identity provider has no use for it, and can remove it.
nvcf-cli init and nvcf-cli refresh both call POST /v1/admin/keys through the same generateAdminTokenViaAPI function. Once the proxy is removed, both fail:
It is not a graceful failure. The message is bare because the Gateway returns an empty body for an unrouted host, and Cobra then prints usage as though the command were mistyped, which points the operator at their own typing rather than at the missing component. Neither command has a flag to supply a token you already hold, so there is no fallback inside the CLI.
What to do instead: obtain the admin token from your own identity provider and supply it as NVCF_TOKEN, the same credential init would have written. The CLI resolves a token in the order environment variable, then config file, then the state file init writes, so setting it by either of the first two makes init unnecessary rather than merely working around it:
Every other nvcf-cli command works unchanged from there. Operators following the CLI guide or the end-to-end installation example should skip the nvcf-cli init step on a stack where this proxy is disabled.
Configuration
This value controls two things that must stay in step:
The NVCF UI health list drops its Admin Issuer Proxy entry at the same time, so the UI does not report a missing component.
A related value, adminIssuerProxy.gateway.enabled: false, removes only the api-keys.<domain>/v1/admin/keys route and keeps the service reachable inside the cluster. Use it when nvcf-cli init is still needed from inside the cluster but the endpoint should not be on the public edge.
Setting adminIssuerProxy.enabled: false removes the route as well, so the two are not combined.
Removing it from an existing install
Setting the value to false on a stack where the proxy is already installed does not remove anything. The release condition stops Helmfile managing the release, and the migration stops creating the OpenBao grant, but both already exist and stay as they are.
Removal is two steps, and both are required.
- Uninstall the release. This removes everything the chart owns: the Deployment, Service, ServiceAccount, HTTPRoute and ReferenceGrant, plus the PodDisruptionBudget if
adminIssuerProxy.podDisruptionBudget.enabledis set.
- Revoke the OpenBao grant. This is the step that is easy to miss.
OpenBao state is not owned by the Helm release, so uninstalling leaves the signing capability in place: any pod running as the admin-issuer-proxy service account in the api-keys namespace can still authenticate to OpenBao and sign admin-scoped tokens for the NVCF API issuer.
Until these three objects are deleted, removing the Deployment has reduced the exposed surface without withdrawing the capability.
Retrieve the root token as described in Troubleshooting, then:
Verify all three are gone:
No output means the grant is withdrawn.
Re-enabling is simpler than disabling. Setting adminIssuerProxy.enabled: true reinstalls the release, and the next migration run recreates all three OpenBao objects, so nothing has to be restored by hand.
Verifying at the edge
The route’s hostname may have no DNS record, which does not by itself make it unreachable. A load balancer that forwards the Host header passes the request to the Gateway regardless. Check the edge, not only the cluster:
--resolve rather than -H "Host: ...": the Host header is an HTTP header and does not set the TLS server name, so against a load-balancer IP the certificate would be checked against that IP and the request could fail before the Gateway ever saw it.
Read the two results together. Exit 0 with 404 means no route is attached, which is the outcome you want. Exit 0 with anything else means the route is still being served.
A non-zero curl exit means the request never reached the Gateway, so the check is inconclusive rather than a pass. The printed status will be 000.
If curl exits with a certificate error (exit 60), the edge is presenting a certificate that does not cover this hostname. This is expected when the route’s hostname has no certificate of its own. Re-run with -k to get past the TLS check and read the routing result.
Only do this when diagnosing that specific failure: -k disables certificate verification and says nothing about whether the edge’s TLS is sound.
Worker NATS Authentication
Every worker connects to NATS to receive its function’s requests. nats.workerAuth sets how it authenticates:
Use token when workers run outside the control-plane cluster, as in a multi-cluster install. In nkey mode, the shared key leaves the cluster on every worker launch.
Token mode needs an NVCF API that tells workers their account (NVCF_NATS_ACCOUNT), and a worker-utils image that reads it. An older worker-utils asks for the account Worker, which is refused, so its workers can’t connect to NATS.
Configuration
This value changes three releases:
The auth callout sends worker tokens to the NVCF API’s in-cluster Service, http://api.nvcf.svc.cluster.local:8080/v2/nvcf/webhook/nats-auth. If the API runs elsewhere, set the URL:
Any value other than nkey or token fails the deployment with nats.workerAuth must be nkey or token. In token mode, an empty webhook URL fails it too.
Switching an existing install
- Set
nats.workerAuth: tokenand sync the stack. - New workers authenticate with their worker tokens. Workers that were already running keep the shared NKey and stay connected until they’re replaced, for example by redeploying their functions.
- Once no worker started before the switch is running, rotate the shared NATS NKey, because those workers held it.
Switching back to nkey restores the shared key for new workers and restarts the auth callout the same way.
Verifying
The auth callout logs successful logins, with the account and the user it assigned. Worker logins in token mode show the account APP and a user named after the function version:
If new workers don’t appear there, look for refused logins:
The auth callout samples its logs: per message, the first 100 lines a second, then 1 in 100, so a burst of worker logins can drop lines. While debugging, log every login and turn on debug logs, which include each webhook request to the NVCF API, in environments/<environment-name>.yaml:
Only natsAuthCalloutService.serviceConfig.logging reaches the auth callout; the stack ignores other serviceConfig keys. A change restarts the auth callout.
With the settings above, if the auth callout logged nothing for a worker, its login didn’t reach the auth callout. Check the worker’s own logs for its NATS connection error.
Observability
For observability configuration and reference architecture, see self-hosted-observability.