Topic Overview

Containers vs VMs (Namespaces, Cgroups)

Compare containers and VMs: namespaces, cgroups, and virtualization technologies. Understand isolation, resource management, and when to use each.


Virtual Machines (VMs)

VM runs a complete operating system on virtualized hardware.

VM Architecture

Host OS
  └─ Hypervisor (Virtualization Layer)
      ├─ VM 1 (Guest OS + Apps)
      ├─ VM 2 (Guest OS + Apps)
      └─ VM 3 (Guest OS + Apps)

Characteristics:

  • Full OS: Each VM has its own OS
  • Hardware virtualization: Virtual CPU, RAM, disk
  • Strong isolation: Complete separation
  • Heavy: More resources, slower startup

Containers

Container shares the host OS kernel, isolated by namespaces and cgroups.

Container Architecture

Host OS (Linux Kernel)
  ├─ Container 1 (isolated by namespaces/cgroups)
  ├─ Container 2 (isolated by namespaces/cgroups)
  └─ Container 3 (isolated by namespaces/cgroups)

Characteristics:

  • Shared kernel: All containers share host OS kernel
  • OS-level virtualization: Namespaces, cgroups
  • Lightweight: Less resources, faster startup
  • Less isolation: Share kernel (security consideration)

Linux Namespaces

Namespaces provide isolation for different system resources.

Namespace Types

1. PID Namespace

Isolates process IDs
Container sees only its own processes

2. Network Namespace

Isolated network stack
Own network interfaces, routing tables

3. Mount Namespace

Isolated file system mounts
Own root filesystem

4. UTS Namespace

Isolated hostname, domain name

5. IPC Namespace

Isolated inter-process communication

6. User Namespace

Isolated user IDs

Cgroups (Control Groups)

Cgroups limit and account for resource usage.

Cgroup Features

Resource limits:

  • CPU: Limit CPU usage
  • Memory: Limit memory usage
  • I/O: Limit disk I/O
  • Network: Limit network bandwidth

Example:

Container 1: CPU 50%, Memory 2GB
Container 2: CPU 30%, Memory 1GB
Container 3: CPU 20%, Memory 512MB

Comparison

FeatureContainersVMs
IsolationProcess-levelHardware-level
OSShared kernelFull OS per VM
StartupSecondsMinutes
Resource usageLowHigh
OverheadMinimalSignificant
SecurityLess isolatedMore isolated
Use caseApplicationsFull systems

Examples

Container with Namespaces

# Create network namespace
ip netns add container1

# Create PID namespace (conceptual)
unshare --pid --fork bash

# Isolated process tree
ps aux  # Only sees processes in namespace

Cgroups Example

# Create cgroup
mkdir /sys/fs/cgroup/memory/container1

# Set memory limit (1GB)
echo 1073741824 > /sys/fs/cgroup/memory/container1/memory.limit_in_bytes

# Add process to cgroup
echo $$ > /sys/fs/cgroup/memory/container1/cgroup.procs

Docker Container

# Dockerfile
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
# Run container (uses namespaces and cgroups)
docker run -d --name web --memory=1g --cpus=0.5 nginx

Common Pitfalls

  • Security: Containers share kernel, less isolated. Fix: Use VMs for strong isolation, secure containers
  • Resource limits: Not setting cgroup limits. Fix: Set CPU, memory limits
  • Kernel compatibility: Containers need compatible kernel. Fix: Use VMs for different OS
  • Overhead misunderstanding: Thinking containers always better. Fix: Choose based on use case

Interview Questions

Beginner

Q: What is the difference between containers and virtual machines?

A:

Virtual Machines (VMs):

  • Full OS: Each VM has its own operating system
  • Hardware virtualization: Virtual CPU, RAM, disk
  • Architecture: Host OS → Hypervisor → Guest OS → Apps
  • Isolation: Complete separation
  • Resource usage: High (full OS per VM)
  • Startup: Minutes

Containers:

  • Shared kernel: All containers share host OS kernel
  • OS-level virtualization: Namespaces, cgroups
  • Architecture: Host OS → Containers (isolated)
  • Isolation: Process-level
  • Resource usage: Low (shared kernel)
  • Startup: Seconds

Key Differences:

FeatureContainersVMs
OSShared kernelFull OS
IsolationProcess-levelHardware-level
StartupSecondsMinutes
ResourcesLowHigh

When to use:

  • Containers: Applications, microservices, fast deployment
  • VMs: Full systems, strong isolation, different OS

Intermediate

Q: Explain how Linux namespaces and cgroups enable containers. How do they provide isolation and resource management?

A:

Linux Namespaces (Isolation):

Provide isolation for system resources:

  1. PID Namespace

    Isolates process IDs
    Container sees only its own processes
    Process 1 in container ≠ Process 1 on host
    
  2. Network Namespace

    Isolated network stack
    Own network interfaces, IP addresses, routing
    
  3. Mount Namespace

    Isolated file system
    Own root filesystem (/)
    
  4. UTS Namespace

    Isolated hostname
    Container can have different hostname
    

Cgroups (Resource Management):

Limit and account for resource usage:

# Memory limit
/sys/fs/cgroup/memory/container1/memory.limit_in_bytes = 1GB

# CPU limit
/sys/fs/cgroup/cpu/container1/cpu.shares = 512

How containers work:

1. Create namespaces (isolation)
2. Create cgroups (resource limits)
3. Run process in namespaces with cgroup limits
4. Process sees isolated environment

Example:

# Container sees:
  - Only its own processes (PID namespace)
  - Its own network (Network namespace)
  - Its own filesystem (Mount namespace)
  - Limited resources (Cgroups)

Senior

Q: Design a container orchestration system that manages thousands of containers. How do you use namespaces, cgroups, and ensure security and resource management?

A:

class ContainerOrchestration {
  private namespaceManager: NamespaceManager;
  private cgroupManager: CgroupManager;
  private securityManager: SecurityManager;
  
  constructor() {
    this.namespaceManager = new NamespaceManager();
    this.cgroupManager = new CgroupManager();
    this.securityManager = new SecurityManager();
  }
  
  // 1. Namespace Management
  class NamespaceManager {
    async createContainer(config: ContainerConfig): Promise<Container> {
      // Create all namespaces
      const namespaces = {
        pid: await this.createPIDNamespace(),
        network: await this.createNetworkNamespace(),
        mount: await this.createMountNamespace(),
        uts: await this.createUTSNamespace(),
        ipc: await this.createIPCNamespace(),
        user: await this.createUserNamespace()
      };
      
      return new Container(namespaces);
    }
    
    async createPIDNamespace(): Promise<PIDNamespace> {
      // Unshare PID namespace
      // Container sees only its processes
    }
    
    async createNetworkNamespace(): Promise<NetworkNamespace> {
      // Create isolated network
      // Own interfaces, routing
    }
  }
  
  // 2. Cgroup Management
  class CgroupManager {
    async setLimits(containerId: string, limits: ResourceLimits): Promise<void> {
      // Set CPU limit
      await this.setCPULimit(containerId, limits.cpu);
      
      // Set memory limit
      await this.setMemoryLimit(containerId, limits.memory);
      
      // Set I/O limit
      await this.setIOLimit(containerId, limits.io);
    }
    
    async setMemoryLimit(containerId: string, limit: number): Promise<void> {
      const cgroupPath = `/sys/fs/cgroup/memory/${containerId}`;
      await fs.writeFile(`${cgroupPath}/memory.limit_in_bytes`, limit.toString());
    }
  }
  
  // 3. Security
  class SecurityManager {
    async secureContainer(container: Container): Promise<void> {
      // Use user namespace (non-root in container)
      await this.createUserNamespace(container);
      
      // Capabilities: Drop unnecessary capabilities
      await this.dropCapabilities(container);
      
      // Seccomp: Restrict system calls
      await this.applySeccomp(container);
      
      // AppArmor/SELinux: Additional security
      await this.applyAppArmor(container);
    }
  }
}

Features:

  1. Namespaces: Complete isolation (PID, network, mount, etc.)
  2. Cgroups: Resource limits (CPU, memory, I/O)
  3. Security: User namespaces, capabilities, seccomp

Key Takeaways

  • VMs: Full OS per VM, hardware virtualization, strong isolation, heavy
  • Containers: Shared kernel, OS-level virtualization, lightweight, fast startup
  • Namespaces: Provide isolation (PID, network, mount, UTS, IPC, user)
  • Cgroups: Limit resources (CPU, memory, I/O, network)
  • Trade-offs: Containers faster/lighter, VMs more isolated
  • Use cases: Containers for apps, VMs for full systems
  • Best practices: Use namespaces for isolation, cgroups for limits, secure containers properly

About the author

InterviewCrafted helps you master system design with patience. We believe in curiosity-led engineering, reflective writing, and designing systems that make future changes feel calm.