4.9 Kubernetes Container Process Startup
Kubernetes Container Process Startup explains how containers are launched, managed, and maintained within a Kubernetes cluster environment.
Kubernetes Container Process Startup is the sequence of low-level operating system operations that transform a prepared OCI runtime specification into a running process inside an isolated container environment, executed by a low-level runtime such as runc on behalf of the higher-level container runtime. It covers namespace entry, filesystem assembly, capability and permission enforcement, and the final handoff to the container's entrypoint process.
From Specification to Process
The OCI Runtime Specification
Before a process can start, the runtime prepares a configuration bundle consisting of a root filesystem and a config.json file describing namespaces, mounts, environment variables, the entrypoint command, resource limits, and security settings. This bundle conforms to the OCI Runtime Specification, a standard that allows different low-level runtimes to interpret the same input consistently.
Invoking the Low-Level Runtime
The higher-level runtime, such as containerd through its shim, invokes a low-level OCI runtime binary, most commonly runc, passing it the bundle path. runc performs the actual system calls needed to create the container process, then exits once the container is running, leaving supervision to the shim.
Namespace Construction
clone and unshare System Calls
runc uses the clone system call with namespace flags such as CLONE_NEWPID, CLONE_NEWNS, and CLONE_NEWUTS to create a new process that simultaneously enters new PID, mount, and UTS namespaces. Network and IPC namespaces are typically joined rather than created fresh, since they are inherited from the pod's sandbox.
PID Namespace and Init Process
Inside its new PID namespace, the container's main process becomes PID 1. This carries specific responsibilities under Linux semantics, including default signal handling behavior that differs from ordinary processes and the obligation to reap any orphaned child processes created within the namespace.
Mount Namespace and Filesystem Assembly
A new mount namespace isolates the container's view of the filesystem. Within it, runc performs a pivot_root operation to switch the container's root filesystem to the assembled image layers, then mounts additional filesystems such as /proc, /sys, and /dev, along with any volumes specified in the pod spec.
Security Enforcement at Startup
Capability Dropping
Before executing the entrypoint, runc applies the Linux capability set defined in the security context, typically dropping capabilities not explicitly requested and retaining only those needed, following the principle of least privilege for containerized processes.
Seccomp Filter Application
If a seccomp profile is specified, either the runtime default or a custom profile, runc installs a corresponding BPF filter that restricts which system calls the container process is permitted to make, blocking or trapping disallowed syscalls at the kernel level.
User and Group Resolution
The runtime resolves the effective UID and GID the process will run as, based on runAsUser, runAsGroup, and runAsNonRoot settings, and applies user namespace remapping if configured, before the process image is executed.
AppArmor and SELinux Labeling
On systems where these mandatory access control frameworks are enabled, runc applies the configured AppArmor profile or SELinux label to the container process, constraining its access to host resources beyond what standard namespace and capability restrictions provide.
cgroup Attachment
Joining the Prepared cgroup
Before or immediately after process creation, runc attaches the new process to a cgroup path that was prepared according to the container's resource requests and limits, ensuring CPU, memory, and I/O accounting and enforcement begin from the very first moment the process exists.
cgroup v1 Versus cgroup v2 Handling
Depending on the host's cgroup configuration, runc interacts with either the legacy cgroup v1 hierarchy of separate controller mounts or the unified cgroup v2 hierarchy, translating the same logical resource limits into the appropriate interface files for whichever version is active.
Final Process Execution
The execve Handoff
Once namespaces, filesystem, security restrictions, and cgroup membership are all in place, runc performs an execve call that replaces its own process image with the container's actual entrypoint binary, at which point the container's application code begins executing.
Environment and Working Directory Setup
Environment variables assembled from the pod spec, ConfigMaps, Secrets, and downward API references are passed into the execve call, along with the working directory specified in the container image or overridden by the pod spec, establishing the initial execution context for the application.
Signaling Successful Start
After execve succeeds, the container is considered started from the runtime's perspective. The shim reports this back through the CRI, and the kubelet updates the container's status, which subsequently becomes eligible for liveness, readiness, and startup probe evaluation.