Kubernetes Pod YAML Explained Field by Field
A Pod is the smallest schedulable unit in Kubernetes, and almost every workload ultimately comes down to a Pod's YAML definition. These notes collect a fully annotated Pod YAML reference, with kubectl explain as the authoritative source — for example: kubectl explain pod.spec.volumes.
Why bother reading Pod YAML
Day to day we deploy applications with Deployments and StatefulSets, but their spec.template section is essentially a Pod template. When you're debugging containers that won't start, failing probes, or wrong mount paths, you always end up going through the Pod definition field by field. Rather than flipping through the docs every time, it pays to go over the common fields once and for all.
When you're unsure about a field, the most reliable approach is to ask the API itself:
# Show the documentation for a specific field
kubectl explain pod.spec.containers.livenessProbe
# Recursively list all sub-fields under a field
kubectl explain pod.spec.volumes --recursive
kubectl explain reads the cluster's OpenAPI schema directly, so it matches your exact cluster version — more accurate than any annotation table copied from somewhere.
Fully annotated reference
Below is the complete annotated reference (the comments are for quick lookup only; kubectl explain is authoritative):
apiVersion: v1 //API version
kind: pod //resource kind, pod
metadata: //metadata
name: String //metadata: the pod's name
namespace: String //metadata: the pod's namespace
labels: //metadata: list of labels
- name: String //metadata: label name
annotations: //metadata: list of custom annotations
- name: String //metadata: custom annotation name
spec: //detailed definition of the containers in the pod
containers: //list of containers in the pod; there can be several
- name: String //container name
image: String //image name for the container
imagesPullPolicy: [Always|Never|IfNotPresent]//image pull policy: always pull, never pull, or pull only when not present locally
command: [String] //container startup command list (if unset, the startup command baked into the image is used)
args: [String] //container startup argument list
workingDir: String //container working directory
volumeMounts: //storage volumes mounted inside the container
- name: String //name of a shared storage volume defined in the Pod; must match a name defined in the volumes[] section
mountPath: String //absolute mount path of the volume inside the container; should be under 512 characters
readOnly: boolean //whether the mount is read-only; defaults to read-write
ports: //list of ports the container needs to expose
- name: String //port name
containerPort: int //port the container exposes
hostPort: int //port the host listens on (the container port mapped onto the host); defaults to the same as containerPort. When hostPort is set, a second replica of this container cannot start on the same host
protocol: String //port protocol, TCP or UDP; defaults to TCP
env: //environment variables to set before the container runs
- name: String //environment variable name
value: String //environment variable value
resources: //resource limits and resource requests
limits: //resource limit settings
cpu: Srting //CPU limit in cores; used for the docker run --cpu-shares parameter
memory: String //memory limit, in units like MiB or GiB; used for the docker run --memory parameter
requeste: //resource request settings
cpu: String //CPU request in cores; the initial amount available at container startup
memory: String //memory request in MiB or GiB; the initial amount available at container startup
livenessProbe: //health check for containers in the pod; after a number of failed probes the container is restarted automatically. Probe methods: exec, httpGet, tcpSocket
exec: //exec probe method
command: [String] //command or script for the exec method
httpGet: //health check via httpGet; requires path and port
path: String //URL path (the part after the domain or IP address)
port: number //port to probe
host: String //domain name or IP address
scheme: Srtring //protocol for the check, e.g. http
httpHeaders: //custom request headers
- name: Stirng //header name
value: String //header value
tcpSocket: //health check via tcpSocket
port: number //port number to probe
initialDelaySeconds: 0//delay before the first probe after the container starts, in seconds
timeoutSeconds: 0 //probe response timeout in seconds, default 1; on timeout the container is considered unhealthy and will be restarted
periodSeconds: 0 //probe interval in seconds, default 10
successThreshold: 0 //number of consecutive successes before the probe is considered successful
failureThreshold: 0 //number of consecutive failures before the probe is considered failed
securityContext: //security settings
privileged: false //
restartPolicy: [Always|Never|OnFailure]//restart policy: always restart on termination; never restart; or restart only on abnormal exit (non-zero exit code) — on Pod termination the exit code is reported to the master and the Pod is not restarted
nodeSelector: object //Node labels specified as key:value pairs; the Pod will be scheduled onto Nodes carrying these labels
imagePullSecrets: //Secrets to use when pulling images, specified as name:secretkey
- name: String //referenced Secret name
hostNetwork: false //whether to use host networking; defaults to false. When true, the Pod uses the host's network instead of the docker bridge, and a second replica cannot start on the same machine
volumes: //list of shared storage volumes defined on this pod
- name: String //shared volume name; within a Pod each volume gets one name, referenced by spec[].containers[].volumeMounts[].name. Many types exist, e.g. emptyDir, hostPath
emptyDir: {} //emptyDir volume: a temporary directory sharing the Pod's lifecycle; empty object
hostPath: //hostPath volume: mounts a directory from the Pod's host, specified via volumes[].hostNetwork.path
path: string //directory on the Pod's host, used as the mount directory inside the container
secret: //secret volume: mounts a predefined cluster secret object into the container
secretName: String //volume name
items: //used when mounting only specific keys from a Secret object
- key: String //the key
path: String //relative path of the mapped file
configMap: //configMap volume: mounts a predefined cluster configMap object into the container
name: String //name of the configMap to use
items: //used when mounting only specific keys from a ConfigMap object
- key: String //the key
path: String //relative path of the mapped file
A closer look at a few key fields
1) command and args
command corresponds to the container runtime's entrypoint, and args are the arguments passed to it. When neither is set, the image's own ENTRYPOINT and CMD are used; when only args is set, the image's ENTRYPOINT is kept and CMD is overridden; when command is set, both the image's ENTRYPOINT and CMD are ignored. When debugging a container that exits immediately on startup, first check whether these two fields have accidentally overridden the image's default startup command.
2) resources: requests vs. limits
requests drives scheduling — the scheduler uses it to decide whether a node has enough capacity left. limits is the runtime ceiling — exceeding the memory limit gets the container OOMKilled, while exceeding the CPU limit only throttles it (the container is not killed). With neither set, the Pod runs at the BestEffort QoS class and is the first to be evicted when the node runs short on resources. In production, at least fill in requests.
3) Health probes
livenessProbe determines whether a container is still alive; once failures reach failureThreshold, the kubelet restarts the container. Alongside it there is readinessProbe (determines readiness; on failure the Pod is only removed from the Service endpoints, the container is not restarted), with an identical field structure. Give initialDelaySeconds enough headroom for the application to start — otherwise the probe declares the app dead before it's even up, and it gets stuck in a restart loop.
4) volumes and volumeMounts
Storage is declared in two stages: first define the volume in spec.volumes (types like emptyDir, hostPath, secret, configMap), then reference it by name in the container's volumeMounts and specify the mount path. The name on both sides must match exactly — one of the most common sources of errors for newcomers. An emptyDir is destroyed when the Pod is deleted, so it only suits temporary data; hostPath mounts a host directory directly, so the data is "lost" once the Pod moves to another node — it's generally reserved for node-level scenarios like log collection.
Pitfalls and caveats
The annotation table above circulates widely in the community, but several spelling mistakes have crept into copied versions. Copying it verbatim will cause apply errors or silently ignored fields:
kind: podshould bekind: Pod; resource kinds are capitalized;imagesPullPolicy— the correct field name isimagePullPolicy, no s;requesteunderresourcesshould be spelledrequests;- hostPath's path field is
volumes[].hostPath.path; thehostNetwork.pathin the comments is a typo.
When a field name is misspelled, depending on the cluster's validation policy it may be rejected outright, or it may be ignored as an unknown field — the latter is sneakier: the configuration looks applied but has no effect. So once more: verify field names with kubectl explain before you start, or run kubectl apply --dry-run=server -f pod.yaml to let the API Server validate first.
Comments in YAML should use #, not //. The // comments in the table above are quick-reference annotations only — delete them or convert them to # before copying anything into a real YAML file.
Wrapping up
Pod YAML has many fields, but the ones you actually use cluster in a few areas: labels under metadata, the containers' image and startup command, resources, the three kinds of probes, and volume mounts. The annotation table is handy for quickly locating a field, but for field names and default values always defer to the output of kubectl explain — it reads the current cluster's schema, so it never goes stale and never carries transcription errors.
COMMENTS