Internals, Linux Kernel Primitives and Container Runtime Engineering
Introduction
Chapter 1: What Are Containers Really
- The Process as the Fundamental Unit
- Chroot and the Birth of Isolation Ideas
- From Zones to Linux Containers to Docker
- How a Container Runtime Actually Works
- Containers vs Virtual Machines vs Sandboxes
- What This Book Will Build
Chapter 2: Rust for Systems Programming
- Why Rust for Container Runtimes
- Tooling: Cargo, rustup, Cross-compilation, musl
- Error Handling Patterns for Systems Code
- The unsafe Boundary: When and How
- Linux FFI with libc and bindgen
- Async vs Sync in Runtime Code
- Structuring a Systems Library in Rust
Chapter 3: Linux Kernel Prerequisites
- Minimum and Recommended Kernel Versions
- Required Kernel Configuration Options
- Namespace Support and Detection
- cgroup v1 vs v2: Distribution Defaults
- Essential Tooling: strace, nsenter, lsns, bpftrace
- Building and Testing on Different Distributions
Chapter 4: Linux Namespaces Overview
- The Namespace Abstraction in the Kernel
- How Namespaces Are Structured in Kernel Memory
- The clone and unshare System Calls
- Joining and Leaving Namespaces with setns
- Inspecting Namespaces: /proc, nsenter, lsns
- Namespace Hierarchy and Inheritance
Chapter 5: PID Namespaces and Process Isolation
- How clone Works: Flags, Stack and Child Setup
- fork, vfork, execve: The Process Creation Family
- Nested PID Namespaces and PID Translation
- PID 1: Signal Handling, Zombie Reaping, init Responsibilities
- Signals Across Namespace Boundaries
- Process Tracing and ptrace Interaction
- Implementing Our First PID Namespace Container
Chapter 6: Mount Namespaces and Filesystem Isolation
- The Mount Namespace Data Structures
- chroot: History, Limitations and Security Gaps
- pivot_root: How It Actually Works
- Bind Mounts and Recursive Mounts
- Mount Propagation: Shared, Private, Slave, Unbindable
- Creating a Minimal Container Root Filesystem
- /proc, /sys and Pseudo-filesystem Mounting
- Integrating Mount Namespaces into Our Runtime
Chapter 7: User Namespaces and Privilege
- The User Namespace Concept
- UID and GID Mapping Mechanics
- /proc/self/uid_map, gid_map and setgroups
- Root Inside, Nobody Outside
- The no_new_privs Flag and Privilege Escalation
- Rootless Container Limitations and Workarounds
- Multi-Level User Namespaces
- Rust Implementation of User Namespace Setup
Chapter 8: Network Namespaces and Container Networking
- Network Namespace Isolation
- Virtual Ethernet (veth) Pairs
- Linux Bridges and Layer 2 Forwarding
- IP Addressing and Routing Inside Containers
- NAT and Masquerading with iptables/nftables
- DNS Resolution Configuration
- Loopback Interface Requirements
- Common Networking Topologies
- Rust Implementation of Container Networking
Chapter 9: Completing the Namespace Set
- IPC Namespaces: System V and POSIX IPC
- UTS Namespace: Hostname and Domainname Isolation
- Time Namespaces (kernel 5.6+): Clock Manipulation
- cgroup Namespaces
- When Each Namespace Is Necessary
- Namespace Setup Order and Interactions
- Rust Implementation of Full Namespace Setup
Chapter 10: Control Groups: Architecture and Evolution
- The Control Group Concept
- cgroup v1: Hierarchies, Controllers and Complexity
- Why cgroup v2 Was Designed
- The Unified Hierarchy
- Controller Types and Delegation
- Distribution Defaults and Detection
Chapter 11: cgroup v2 Deep Dive
- Hierarchy Operations: Creating, Moving, Cleaning Up
- Process Placement in cgroups
- CPU Controller: weights, quotas, periods, scheduling
- Memory Controller: limits, accounting, high thresholds
- Swap Control and Memory+Swap Limits
- OOM Killer Behavior and oom.kill_disable
- I/O Controller: throttling, weights, cgroup2 io.stat
- PID Controller: limiting process counts
- Pressure Stall Information (PSI)
- Device Controller: blocking and allowing devices
- Rust Implementation of cgroup v2 Setup
Chapter 12: Linux Capabilities
- The Problem with UID 0
- Capability Sets: Permitted, Effective, Inheritable, etc.
- Capability Inheritance Across execve and clone
- prctl Controls: no_new_privs, dumpable, etc.
- Ambient Capabilities (kernel 4.3+)
- Common Capabilities Used in Containers
- Implementing Capability Dropping
Chapter 13: Mandatory Access Control and System Call Filtering
- System Call Filtering with seccomp
- seccomp Modes: Strict, Filter, BPF
- Writing seccomp Filters in Rust
- The LSM Framework Architecture
- AppArmor vs SELinux for Containers
- Integrating MAC Policies into Our Runtime
- seccomp Default Profiles for Containers
Chapter 14: Container Filesystems and OverlayFS
- The Layered Image Concept
- OverlayFS: How Copy-on-Write Works
- Upperdir, Lowerdir, Workdir
- Whiteouts and Opaque Directories
- File Ownership and UID/GID in Images
- Mounting an OverlayFS Root
- Performance Characteristics and Limitations
- Rust OverlayFS Integration
Chapter 15: Container Images, Manifests and Rootfs Assembly
- Docker Image Format History
- OCI Image Specification
- Image Manifests and Config Blobs
- Content-Addressable Storage
- Image Extraction and Rootfs Assembly
- Building a Minimal Image from Scratch
- Integration with Our Runtime
Chapter 16: Project Architecture and Design
- Runtime Requirements and Goals
- Project Structure and Cargo Configuration
- The Container Config Data Model
- Component Responsibilities
- Communication Between Parent and Child
- Error Handling and Failure Recovery
Chapter 17: Implementing Namespace Setup
- Namespace Config and Validation
- unshare Implementation in Rust
- setns and Namespace File Descriptors
- Ordering of Namespace Operations
- The Initial Process Entry Point
- Testing Namespace Setup
Chapter 18: Implementing Filesystem Configuration
- Mount Specification Parsing
- pivot_root Implementation
- Bind Mount Creation
- Pseudo-filesystem Mounts
- Mount Propagation Configuration
- Cleanup on Failure
Chapter 19: Implementing Resource Control
- cgroup v2 Setup: Hierarchy Creation and Process Placement
- Controller Configuration from Spec
- Capability Dropping Implementation
- seccomp Filter Construction
- Integration into the Startup Sequence
Chapter 20: Process Lifecycle Management
- The Parent-Child Handshake Protocol
- clone/fork + execve Sequence
- File Descriptor Management
- Signal Forwarding from Host to Container
- Process State Monitoring
- Container Shutdown and Cleanup
- Zombie Handling and PID 1 Interaction
Chapter 21: Networking Integration
- Network Config Specification
- veth Pair Creation
- Bridge Attachment and Routing
- IP Address and DNS Configuration
- Integration with Namespace Setup
- Rootless Networking Options
- DNS Configuration
Chapter 22: Rootless Containers
- What Rootless Really Means
- Required User Namespace Configuration
- Rootless cgroup Delegation
- Rootless Mount Namespaces and Privileged Mounts
- Rootless Networking Limitations
- Testing Rootless Execution
Chapter 23: OCI Runtime Specification Compliance
- OCI Runtime Spec Overview
- Bundle Layout and config.json
- Where We Follow the Spec
- Where We Simplify
- Comparison with runc Architecture
- Comparison with crun Implementation Choices
- Path to Full Spec Compliance
Chapter 24: Security Analysis and Threat Modeling
- The Container Security Promise and Its Limits
- Threat Model: What Are We Defending Against
- Namespace Escape Vulnerabilities
- cgroup and Capability Abuse
- seccomp and Kernel Exploits
- Common Misconfigurations That Break Isolation
- Defense-in-Depth Implementation
- Safe Testing of Container Isolation
Chapter 25: Debugging, Observability and Production Readiness
- Debugging with strace: Practical Examples
- eBPF and bpftrace for Container Observability
- Understanding Kernel Logs and dmesg
- Performance Profiling with perf
- Common Failure Modes and How to Fix Them
- Hardening for Production Use
- What We Did Not Implement (and Why)