Skip to content

Deployment manifest

apiVersion: odysseus/v1
kind: Deployment
metadata:
name: worker
spec:
image: registry.delta-telematics.ca/acme/worker:2.1.0
replicas: 2
networks: [acme-network]
environment:
QUEUE: jobs
resources:
limits: {cpu: "1", memory: 512Mi}
requests: {cpu: 250m, memory: 256Mi}
Validated against Manifest · testdata/docs-examples/minimal-deployment.yaml
apiVersion: odysseus/v1
kind: Deployment
metadata:
name: api
labels:
app: api
spec:
image: registry.delta-telematics.ca/acme/api:1.4.2
replicas: 3
environment:
LOG_LEVEL: info
networks: [acme-network, traefik-public]
resources:
limits: {cpu: "1", memory: 512Mi}
requests: {cpu: 250m, memory: 256Mi}
healthCheck: # required for rolling
type: exec
command: "wget -qO- http://localhost:8080/healthz"
interval: 10s
timeout: 15s
retries: 3
startPeriod: 20s
secrets:
- name: DB
vaultPath: deployments/api/db
dependsOn:
- job: api-migrate
condition: complete
placement:
affinity: {label: role, value: app}
onNodeFailure: reschedule
ingress:
host: api.example.com
port: 8080
tls: {enabled: true, certResolver: letsencrypt}
healthCheck: {path: /healthz, interval: 10s, timeout: 3s} # LB probe — the zero-downtime part
compress: true
headers:
response:
set: {X-Frame-Options: DENY}
retry: {attempts: 3, initialInterval: 100ms}
update:
strategy: rolling
allow_concurrent_versions: true # required attestation
max_surge: 1
max_unavailable: 0
health_timeout: 90s
min_healthy_time: 15s
progress_deadline: 10m
failure_action: rollback
Validated against Manifest · testdata/docs-examples/routed-deployment.yaml

Generated from DeploymentSpec. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
canary CanarySpec no — in-place 0.74.0
capAdd string[] no — recreate 0.74.0
capDrop string[] no — recreate 0.74.0
command string[] no — recreate 0.74.0
dependsOn DependencyRef[] no — in-place 0.7.6
dns string[] no — recreate 0.74.0
dnsSearch string[] no — recreate 0.74.0
entrypoint string[] no — recreate 0.74.0
environment object no — recreate 0.1.0
expose integer[] no — recreate 0.74.0
extraHosts string[] no — recreate 0.74.0
healthCheck HealthCheckSpec no — recreate 0.1.0
hostname string no — recreate 0.74.0
image string no — recreate 0.1.0
imagePullSecret string no — recreate 0.74.0
ingress IngressSpec no — recreate 0.9.4
init boolean no — recreate 0.21.1
logging LoggingConfig no — recreate 0.74.0
networkAliases string[] no — recreate 0.74.0
networks string[] no — recreate 0.1.0
onNodeFailure string no — in-place 0.9.4
placement PlacementSpec no — recreate 0.7.6
ports PortMapping[] no — recreate 0.74.0
privileged boolean no — recreate 0.74.0
probe ProbeSpec no — recreate 0.74.0
readOnly boolean no — recreate 0.74.0
replicas integer no — in-place 0.1.0
resources ResourceSpec no — recreate 0.1.0
restartPolicy string no — recreate 0.74.0
restartRetries integer no — recreate 0.7.6
scaling ScalingSpec no — in-place 0.1.0
secrets SecretSpec[] no — recreate 0.1.0
securityOpt string[] no — recreate 0.74.0
stack string no — recreate 0.74.0
stopGracePeriod integer no — recreate 0.74.0
ulimits Ulimit[] no — recreate 0.21.1
update UpdatePolicy no — in-place 0.11.0
user string no — recreate 0.74.0
volumes VolumeSpec[] no — recreate 0.1.0
workingDir string no — recreate 0.74.0

canary: Canary shifts traffic to the new version in weighted steps and promotes or aborts on the thresholds it carries. See CanarySpec.

capAdd: CapAdd grants individual Linux capabilities, e.g. NET_ADMIN.

capDrop: CapDrop removes capabilities the runtime would otherwise grant. “ALL” followed by a narrow capAdd is the safe shape.

command: Command overrides the image’s CMD, as argv. Empty leaves the image default.

dependsOn: SP-6, ruling JD4

dns: DNS are custom resolvers for the container, overriding the daemon’s.

dnsSearch: DNSSearch are the search domains appended to unqualified names.

entrypoint: Entrypoint overrides the image’s ENTRYPOINT, as argv.

environment: Environment are plain environment variables set on every container. Never put a credential here — use secrets:, which resolves from Vault at dispatch and never stores the value.

expose: Expose are ports reachable only from other containers on the same network.

extraHosts: ExtraHosts are additional /etc/hosts entries, each written “name:address”.

healthCheck: HealthCheck is the container probe. Only type: exec produces a real healthcheck; an http or tcp declaration is refused rather than left inert.

hostname: Hostname is the container’s own hostname. Leave it unset to take the container name.

image: Image is the fully-qualified container image reference, including an explicit tag. Never “:latest” in production: an unpinned tag makes a rollback impossible to describe.

imagePullSecret: ImagePullSecret names the registry credential used to pull the image.

ingress: Ingress is the WP3 typed ingress block (IG1/IG3/IG9/IG12). G1: the manifest surface had no ingress support before this task — authors had to hand-write traefik.* labels, which ValidateIngress now rejects outright whenever ingress: is also set.

init: Init runs Docker’s tiny init as PID 1 so orphaned processes are reaped. Omit it to take the platform default, which is on; set false only for an image that already runs its own init.

logging: Logging selects the Docker logging driver and its options.

networkAliases: NetworkAliases are extra DNS names the container answers to on its networks, for discovery by other containers.

networks: Networks are the Docker networks the container joins. Names are tenant-prefixed for you; a backend should stay off traefik-public.

onNodeFailure — A node hosting several deployments takes the most conservative policy among them — keep beats approve beats reschedule. The policy is resolved across the node, not per deployment, so setting reschedule on one deployment does not override a keep on another sharing the node.

onNodeFailure: OnNodeFailure is the WP6 (ND5) per-deployment node-failure policy: reschedule | approve | keep (empty = cluster default). #71 NF-4: without this field the manifest surface could not opt into keep/approve.

placement: SP-4; shared: Jobs place too

ports: Ports publishes container ports on the host. Container-to-container traffic needs no entry here — use a shared network instead.

privileged: Privileged gives the container full access to the host’s devices and capabilities. It is an escape from container isolation, not a permission level — prefer capAdd with the specific capability.

probe: Probe declares an external blackbox target for monitoring. It is observability ONLY and never gates a rollout — that is healthCheck’s job, and confusing the two is how an inert probe comes to satisfy a readiness gate it was meant to guard.

readOnly: ReadOnly mounts the container’s root filesystem read-only. Anything that must be written needs a volume or a tmpfs mount.

replicas: Replicas is how many container instances to keep running. 0 is accepted and means “declared but stopped”.

resources: Resources are the CPU and memory limits and requests, written as limits/requests rather than as four flat keys.

restartPolicy: RestartPolicy is what Docker does when the container exits. The accepted values differ by kind and are enforced by each kind’s own validator.

restartRetries: RestartRetries caps Docker’s on-failure restart attempts. It is only meaningful for a workload whose restart policy is on-failure.

scaling: Scaling turns on autoscaling between a floor and a ceiling of replicas, driven by the metrics it names.

secrets: Secrets are references to material in Vault, injected as environment variables at dispatch. The value never appears in this document.

securityOpt: SecurityOpt are the runtime’s security options, e.g. “no-new-privileges:true” or a seccomp profile.

stack: Stack is the logical grouping this deployment belongs to, emitted as the com.docker.compose.project label so tools such as Portainer group its containers together. Empty defaults to “odysseus”.

stopGracePeriod: StopGracePeriod is how many seconds the container gets to exit after SIGTERM before it is killed.

ulimits: Ulimits are the container’s POSIX resource limits. A per-container ulimit overrides the daemon’s defaults, which is the supported way to raise a file-descriptor ceiling — never a hand-edited daemon.json.

update: Update embeds types.UpdatePolicy directly (WP4 RM-1, G3 ruling): the types struct carries yaml tags, so the manifest inherits them 1:1 and strict parsing covers the nested fields via registeredKinds.

user: User is the UID:GID or username the container process runs as.

volumes: Volumes are the named volumes and bind mounts attached to each container.

workingDir: WorkingDir is the directory the process starts in, overriding the image’s WORKDIR.

Generated from ResourceSpec. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
limits ResourceValues no — recreate 0.1.0
requests ResourceValues no — recreate 0.1.0

Generated from Ulimit. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
hard integer no — recreate 0.21.1
name string no — recreate 0.21.1
soft integer no — recreate 0.21.1

Generated from HealthCheckSpec. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
command any no — recreate 0.1.0
interval string no — recreate 0.1.0
path string no — recreate 0.1.0
port integer no — recreate 0.1.0
retries integer no — recreate 0.1.0
startPeriod string no — recreate 0.1.0
timeout string no — recreate 0.1.0
type string no — recreate 0.1.0

command: Command is the probe command, in either the shell-string or the argv-list form (see ShellOrArgv). Both land on the same stored []string.

interval — There is no floor. Clamping an interval upward would delay failure detection, so unlike the timeout it is not safety-monotonic — a longer timeout can only reduce spurious kills, a longer interval can only slow detection. odysseus spec-audit reports the value; nothing rejects or changes it.

timeout — There is a 10s floor for exec probes: a timed-out exec is SIGKILLed and reparented to a PID 1 that never reaps it, so a shorter value is refused outright on create (code healthcheck_timeout_below_floor). On a DEPLOYMENT update that omits healthCheck entirely, the stored value is restored first and THEN clamped up to the floor if it predates this rule — silently, unless you are reading the response, where it is disclosed as healthcheck_timeout_clamped. Omit timeout to take Docker’s 30s default, which already clears the floor; state it explicitly only to set a tighter bound than the default.

type: http, tcp, exec

Generated from VolumeSpec. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
distributedVolumeId string no — recreate 0.63.0
readOnly boolean no — recreate 0.1.0
source string no — recreate 0.1.0
target string no — recreate 0.1.0

distributedVolumeId: DistributedVolumeID mounts a DVM volume by its typed ID (#414). Its PRESENCE is the discriminator — the manifest surface deliberately has no type key (every plain manifest volume is a bind mount, see convertVolumeSpecs), so exactly one of source/distributedVolumeId is set, and the shape validator downstream rejects both-or-neither.

Generated from SecretSpec. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
anchor string no — recreate 0.37.0
mountPath string no — recreate 0.1.0
name string no — recreate 0.1.0
rotation string no — recreate 0.1.0
vaultPath string no — recreate 0.1.0

anchor: Anchor: volume(<id>) | process | external — WP18 S10.

Generated from PlacementSpec. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
affinity PlacementSelector no — recreate 0.7.6
antiAffinity PlacementSelector no — recreate 0.7.6
node string no — recreate 0.7.6
preferredZone string no — recreate 0.7.6
residency ResidencySpec no — recreate 0.74.0

affinity: Affinity steers placement TOWARD nodes carrying a label. It is a preference the scorer weighs, not a filter that refuses — a workload with an unsatisfiable affinity is still placed, just not where it asked.

antiAffinity: AntiAffinity steers placement AWAY from nodes carrying a label, with the same weigh-do-not-refuse semantics as Affinity.

node: Node pins the workload to one node by name, landing on Deployment.NodeID. Leave it unset to let the scheduler choose; an empty value never clears an assignment the scheduler already made.

preferredZone: PreferredZone names an edge zone the scorer prefers.

NOTE, so nobody debugs this twice: no zone is declared in any shipped control-plane config today, so this currently scores against nothing. That is a real finding with its own issue, not a defect in this block.

residency: Residency is where the workload is legally allowed to run (S19, #557).

Generated from DependencyRef. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
condition string no — in-place 0.7.6
deployment string no — in-place 0.7.6
job string no — in-place 0.7.6

condition: deployment: started|healthy; job: complete

job: WP8 JB-6: depend on a job (condition: complete)

Generated from ScalingSpec. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
enabled boolean no — in-place 0.1.0
maxReplicas integer no — in-place 0.1.0
metrics MetricSpec[] no — in-place 0.1.0
minReplicas integer no — in-place 0.1.0
scaleDownCooldown string no — in-place 0.1.0
scaleUpCooldown string no — in-place 0.1.0

Generated from IngressSpec. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
basicAuth BasicAuthMiddleware no — recreate 0.9.4
compress boolean no — recreate 0.9.4
forwardAuth ForwardAuthMiddleware no — recreate 0.9.4
headers HeadersMiddleware no — recreate 0.9.4
healthCheck IngressHealthCheck no — recreate 0.11.0
host string no — recreate 0.9.4
ipAllowList IPAllowListMiddleware no — recreate 0.9.4
middlewares string[] no — recreate 0.9.4
network string no — recreate 0.9.4
pathPrefix string no — recreate 0.9.4
port integer no — recreate 0.9.4
priority integer no — recreate 0.9.4
rateLimit integer no — recreate 0.9.4
redirect RedirectMiddleware no — recreate 0.9.4
retry RetryMiddleware no — recreate 0.11.0
routerName string no — recreate 0.9.4
stickySessions boolean no — recreate 0.9.4
stripPrefix StripPrefixMiddleware no — recreate 0.9.4
tls IngressTLSSpec no — recreate 0.9.4

basicAuth: WP3.1 middleware definitions (IM1) — the types structs are reused verbatim (they carry yaml tags), so the manifest surface mirrors IngressConfig 1:1 by construction and cannot drift.

healthCheck: HealthCheck: Traefik LB probes (WP4 RU4) — types struct reused verbatim.

Generated from UpdatePolicy. Hand edits to this table are overwritten on the next build — change the Go doc comment, or the generator.

Field Type Required Default Mutability Since
allow_concurrent_versions boolean no — in-place 0.11.0
failure_action string no — in-place 0.11.0
health_timeout integer no — in-place 0.1.0
max_failure_ratio number no — in-place 0.11.0
max_surge integer no — in-place 0.1.0
max_unavailable integer no — in-place 0.1.0
min_healthy_time integer no — in-place 0.11.0
progress_deadline integer no — in-place 0.11.0
rollback_on_fail boolean no — in-place 0.1.0
strategy string no — in-place 0.1.0

allow_concurrent_versions: AllowConcurrentVersions is the criterion-3 operator attestation (RU3): old and new versions may briefly coexist. REQUIRED for rolling/canary; never inferred.

failure_action: FailureAction: “pause” (default) or “rollback” (to last stable, RU6).

health_timeout: HealthTimeout is the per-instance healthy DEADLINE (WP4 semantics).

max_failure_ratio: MaxFailureRatio is the tolerated failed-instance fraction [0,1].

min_healthy_time: MinHealthyTime: an instance must STAY healthy this long, unbroken, to count (a health flip resets the clock — RU5/G4).

progress_deadline: ProgressDeadline bounds the whole rollout; resets per healthy instance.

rollback_on_fail: RollbackOnFail is honored as FailureAction “rollback” (retained field).