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

AnnotationDefaultEffect
confidential.ai/cwunsetOptional 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-injectedunsetStamped 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.

AnnotationDefaultEffect
confidential.ai/c8s-sanderived from cwRequests 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-intervaloperator 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-verbosefalseEnables 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.

AnnotationDefaultEffect
confidential.ai/c8s-secretsunsetComma-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/secretsFixed destination. A nonempty value other than this path is rejected.
confidential.ai/c8s-volumesunsetComma-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-volumesMount 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.

AnnotationDefaultEffect
confidential.ai/c8s-discovery-outunsetAbsolute output file path directly in /run/c8s/discovery, for example /run/c8s/discovery/discovery.json.
confidential.ai/c8s-discovery-volumeunsetExisting 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/discoveryFixed destination. A nonempty value other than this path is rejected.
confidential.ai/c8s-discovery-cds-cert-urlunsetURL advertised for the CDS certificate.
confidential.ai/c8s-discovery-mesh-ca-urlunsetOptional URL advertised for the mesh CA bundle.
confidential.ai/c8s-discovery-public-tls-modeunsetcds 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 /.
  • timeoutSeconds of 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.

NameKindPurpose or required shape
c8s-meshcontainerPer-pod mesh endpoint
c8s-certcontainerCertificate client
c8s-cert-waitcontainerStartup gate for the first certificate
c8s-secretcontainerSecret fetcher
c8s-volumecontainerEncrypted-volume fetcher
c8s-certsvolumePrivate credential volume; memory-backed emptyDir
c8s-secretsvolumeReleased secrets; memory-backed emptyDir, mounted read-only into workload containers
c8s-volume-<NAME>volumeOpened-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