Workload annotations
Pod annotations for workload naming, certificate renewal, secrets, volumes, and discovery, plus admission restrictions and reserved names.
The C8s admission webhook injects every pod in its configured namespace scope.
The confidential.ai/cw annotation names a workload and requests a certificate DNS SAN and
managed Service. Injection does not require it. Namespace selectors control webhook scope;
the node enforcer determines mesh membership. See Architecture.
Set annotations on the pod template when using a Deployment or another controller.
All annotations below use the confidential.ai/ namespace.
Workload naming
| Annotation | Default | Effect |
|---|---|---|
confidential.ai/cw | unset | Optional workload ID, which must be a valid label value. The webhook mirrors it as a pod label. A suitable ID derives the operator-managed headless Service c8s-<value> and the requested certificate SAN c8s-<value>.<namespace>.svc. |
confidential.ai/c8s-injected | unset | Stamped by the webhook after mutation; the node admission inventory uses it to select pods for socket mounts. Setting it yourself does not skip injection. |
For example, confidential.ai/cw: my-inference derives c8s-my-inference. The ID must form a
valid DNS-1035 label after the c8s- prefix to get a managed Service. Otherwise, no managed
Service is created and the ID itself becomes the requested SAN, which must be a valid DNS name.
Without cw, the injected certificate client requests no DNS SAN.
Certificate
The c8s-cert sidecar publishes mesh credentials in /etc/c8s/certs on the private
c8s-certs volume. Only injected platform containers mount it; application containers and
user init containers that request this mount are rejected. Applications serve ordinary TCP or
HTTP inside the pod, and the injected c8s-mesh endpoint handles mesh TLS.
| Annotation | Default | Effect |
|---|---|---|
confidential.ai/c8s-san | derived from cw | Requests a DNS SAN, for example an existing Service name. Ignored when cw is absent; otherwise the value must be a valid DNS name. |
confidential.ai/c8s-renew-interval | operator renewal interval (2h by default) | Go duration for certificate renewal. Negative values are rejected; zero uses the operator default. Requires cw. |
confidential.ai/c8s-get-cert-verbose | false | Enables verbose get-cert logging. Requires cw when set, including "false". |
Any nonempty value for confidential.ai/c8s-cert-volume, confidential.ai/c8s-cert-dir,
confidential.ai/c8s-cert-file, confidential.ai/c8s-key-file, or confidential.ai/c8s-ca-file
is rejected, including a value equal to the injected default.
Credential containers run as UID/GID 1338, with runAsNonRoot: true, a read-only root
filesystem, privilege escalation disabled, all capabilities dropped, and the RuntimeDefault
seccomp profile.
Secrets and volumes
Setting any annotation in this table to a nonempty value requires cw.
| Annotation | Default | Effect |
|---|---|---|
confidential.ai/c8s-secrets | unset | Comma-separated NAME=/store/path pairs; each value lands in the file NAME. Injects the c8s-secret fetcher sidecar and the c8s-secrets volume. See Use application secrets. |
confidential.ai/c8s-secret-dir | /run/c8s/secrets | Fixed destination. A nonempty value other than this path is rejected. |
confidential.ai/c8s-volumes | unset | Comma-separated NAME=/store/path pairs. NAME is a DNS-1123 label of at most 12 characters and selects the node device by its c8s-vol-<NAME> serial. Injects the c8s-volume sidecar. See Create an encrypted volume. |
confidential.ai/c8s-volume-dir | /mnt/c8s-data/c8s-volumes | Mount directory for opened volumes, with one subdirectory per volume. Must be an absolute path at or below /mnt/c8s-data, where an allowlist data rule matches each volume's full mount destination, <VOLUME_DIR>/<NAME>, and its data mount class. |
Admission requires the operator's WorkloadClaimsHostDir configuration for every injected
pod, including pods requesting secrets or volumes. This checks configuration, not the health of
CDS, the node inventory, or the volume daemon. Fetches happen at runtime. The certificate client
retries initial failures; c8s-cert-wait gates workload startup on the first certificate and
fails after three minutes per wait attempt, after which Kubernetes can restart it.
Discovery output
Publishing a discovery document requires c8s-discovery-volume, c8s-discovery-out,
c8s-discovery-cds-cert-url, and c8s-discovery-public-tls-mode together.
Setting any annotation in this table to a nonempty value requires cw.
| Annotation | Default | Effect |
|---|---|---|
confidential.ai/c8s-discovery-out | unset | Absolute output file path directly in /run/c8s/discovery, for example /run/c8s/discovery/discovery.json. |
confidential.ai/c8s-discovery-volume | unset | Existing pod emptyDir volume for the document, mounted into get-cert at /run/c8s/discovery. Must be distinct from the cert, secrets, and encrypted-volume volumes. Use medium: Memory unless the node has encrypted scratch. |
confidential.ai/c8s-discovery-mount-path | /run/c8s/discovery | Fixed destination. A nonempty value other than this path is rejected. |
confidential.ai/c8s-discovery-cds-cert-url | unset | URL advertised for the CDS certificate. |
confidential.ai/c8s-discovery-mesh-ca-url | unset | Optional URL advertised for the mesh CA bundle. |
confidential.ai/c8s-discovery-public-tls-mode | unset | cds or webpki, identifying the certificate the public front door serves. |
Admission effects and probes
Injected pods must leave hostNetwork, hostPID, hostIPC, and shareProcessNamespace
false or unset. The webhook sets enableServiceLinks: false and
automountServiceAccountToken: false.
The webhook rewrites HTTP startup, readiness, and liveness probes aimed at the pod
(httpGet.host empty) to the mesh health listener on port 15021. Forwarded probes require:
- HTTP scheme, an application port number or a port name declared by that container, and empty
httpHeaders. - An absolute path using letters, digits,
/,-,.,_, or~, with no repeated/or.or..path segments; an empty path becomes/. timeoutSecondsof at most five seconds.
Supply the application's path and port; generated forwarding paths and mesh ports are reserved.
Probes with an explicit httpGet.host are left unchanged. TCP and gRPC probes and HTTP lifecycle
hooks are rejected. Exec probes depend on the node's exec mode; locked mode refuses exec.
The plaintext health listener forwards only targets rendered by the injector. It returns a status code and an empty body and does not follow redirects. Choose harmless GET endpoints: probe status, timing, and the effects of triggering a GET remain visible through that listener.
Ephemeral containers cannot use reserved container names or mount volumes holding C8s material.
On an injected pod, they also cannot set targetContainerName to share another container's
process namespace.
Reserved names
The webhook rebuilds its init-container list on every mutation, removing pre-declared init containers with reserved names. A regular or ephemeral container with a reserved name is rejected. Pre-declared reserved volumes must have the required shape.
| Name | Kind | Purpose or required shape |
|---|---|---|
c8s-mesh | container | Per-pod mesh endpoint |
c8s-cert | container | Certificate client |
c8s-cert-wait | container | Startup gate for the first certificate |
c8s-secret | container | Secret fetcher |
c8s-volume | container | Encrypted-volume fetcher |
c8s-certs | volume | Private credential volume; memory-backed emptyDir |
c8s-secrets | volume | Released secrets; memory-backed emptyDir, mounted read-only into workload containers |
c8s-volume-<NAME> | volume | Opened-volume mount point; emptyDir with the default medium |
A hostPath or PVC under a reserved volume name is rejected. The reserved name does not grant
an application access to mesh credentials.
See also
- Run a confidential workload — deploy an application.
- Helm values — operator configuration.
- Architecture — the injected containers and node enforcement.