Linux for DevOps
How the previous 15 Linux fundamentals directly power containers, Kubernetes, CI/CD, and infrastructure automation — the concepts that actually show up on the job.
Why Every DevOps Engineer Needs Real Linux Fundamentals
Docker, Kubernetes, Terraform, and CI/CD runners are not separate from Linux — they’re built directly on top of the kernel features covered earlier in this series. A DevOps engineer debugging a “pod stuck in CrashLoopBackOff” or a “container using 100% CPU” is really debugging a Linux process, using Linux tools, on a Linux host.
Containers Are Linux Processes
A “container” is just a regular Linux process with extra isolation, using two kernel features:
- Namespaces — isolate what a process can see: its own PID tree, network interfaces, mount points, and hostname (
pid,net,mnt,uts,ipc,usernamespaces). - cgroups (control groups) — limit what a process can use: CPU shares, memory limits, I/O bandwidth.
# Prove a container is just a host process with namespaces
docker run -d --name web nginx
docker inspect --format '{{.State.Pid}}' web
ps -ef | grep $(docker inspect --format '{{.State.Pid}}' web) # visible from the HOST too
# Inspect its cgroup memory limit directly
cat /sys/fs/cgroup/memory/docker/$(docker inspect --format '{{.Id}}' web)/memory.limit_in_bytes
Mapping Fundamentals to Real DevOps Tasks
| Fundamental | Where It Shows Up in DevOps Work |
|---|---|
| Processes & signals | Kubernetes sends SIGTERM then waits terminationGracePeriodSeconds before SIGKILL on pod shutdown |
| Filesystem & mounts | Kubernetes Volumes/PVCs are just bind-mounts and network filesystems under the hood |
| Permissions & users | Container runAsUser/runAsNonRoot securityContext maps directly to Linux UID/GID |
| Networking | Kubernetes Services/iptables/IPVS rules, CNI plugins configuring routes and interfaces |
| systemd | The container runtime (containerd, docker) and kubelet themselves run as systemd services on the node |
| Logs | kubectl logs reads the container’s stdout/stderr, which the runtime redirects to files the kubelet tails |
| Kernel/cgroups | Pod CPU/memory requests/limits are implemented as cgroup settings on the node |
A Real Debugging Flow: “Pod OOMKilled”
kubectl describe pod myapp-xyz | grep -A5 "Last State"
# Reason: OOMKilled
# On the NODE itself (this is where Linux fundamentals matter):
dmesg -T | grep -i "killed process" # kernel OOM killer log entry
cat /sys/fs/cgroup/memory/.../memory.limit_in_bytes # confirm the cgroup limit that was hit
journalctl -u kubelet --since "10 min ago"
This is a kernel-level event (the OOM killer, part of the memory management subsystem covered in the Kernel article) surfaced through Kubernetes — you can’t fully explain it without the underlying Linux concept.
CI/CD Runners Are Just Linux Boxes
# A typical CI job step is executing exactly like an interactive shell would:
#!/usr/bin/env bash
set -euo pipefail
whoami # what user is this running as? (often a restricted service account)
env | sort # what environment variables are actually visible?
df -h # is the runner's disk full? (a common flaky-CI cause)
ulimit -a # file descriptor / process limits on this runner
Most “flaky CI” issues trace back to Linux fundamentals: disk full (df -h), too many open files (ulimit -n), zombie build processes not reaped, or environment variables missing because a non-login shell doesn’t source .bashrc.
Production Considerations
- Always set
resources.requests/resources.limitsin Kubernetes manifests — under the hood these are cgroup settings, and without them a single pod can starve others on the same node. securityContext.runAsNonRoot: trueis a real Linux UID check, not a Kubernetes abstraction — pair it with an image that actually has a non-root user created.- When a container “hangs” on shutdown, check whether your entrypoint process correctly handles
SIGTERM— many app frameworks need explicit signal handling ortini/dumb-initas PID 1.
Quick Interview Answer
“Containers aren’t a separate technology from Linux — they’re regular processes isolated with namespaces and constrained with cgroups. That’s why real Linux fundamentals — signals, processes, cgroups, filesystems, users/permissions — directly explain Kubernetes behavior: OOMKilled is the kernel’s OOM killer, pod termination is SIGTERM/SIGKILL, resource requests/limits are cgroup settings, and
runAsNonRootis a plain Linux UID check.”
Common Mistakes
- Treating Kubernetes/Docker concepts as entirely separate from Linux instead of as a layer built directly on kernel primitives — this shows up as an inability to explain why something happens, only that it happens.
- Debugging OOMKilled pods purely from
kubectloutput without checking the node’sdmesg/kernel logs for the actual OOM killer event. - Not testing signal handling (
SIGTERM) in an application’s entrypoint, leading to slow or forceful (SIGKILL) container termination in production.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form