84. Virtual Machines vs. Containers Revisited – Part 4

Support Mobycast



In episode #83 of Mobycast, we learned that containers are normal Linux processes. But they take advantage of powerful operating system functionality that gives these processes their container superpowers. In particular, we learned about namespaces and control groups and how these features give rise to containers.

This week on Mobycast, Jon and Chris wrap up their four-part series by discussing the runtimes and platforms used to run containers in production. We dive deep on ContainerD and RunC, arguably the most important container runtime out there. We also revisit our pseudo code example of how to build a container from scratch, bringing us full circle on our quest to understand the differences between virtual machines and containers.

Show Details

In this episode, we cover the following topics:
  • Container runtimes
    • Responsible for:
      • Setting up namespaces and cgroups for containers
      • Running commands inside those namespaces and cgroups
    • Types of runtimes
      • Low-level
        • Handles tasks related to containers such as:
          • Creating a container
          • Attaching a process to an existing container
      • High-level
        • Handles “high level” tasks such as:
          • Image creation
          • Image management
        • Defers container tasks to “low level” runtime
  • Container standards
    • Open Container Initiative (OCI)
      • Established in June 2015 by Docker and others
      • Contains two specifications:
        • Runtime Specification (runtime-spec)
          • runc is an implementation of OCI runtime-spec
        • Image Specification (image-spec)
  • Runc
    • Low-level container runtime
    • CLI tool for spawning and running containers according to the OCI specification
    • Container runtime originally developed as part of Docker
      • Later lifted out as separate open source project
  • Containerd
    • High-level container runtime
    • Provides abstraction layer for the syscalls and OS-specific functionality required to run container
      • Platforms can build on top of abstraction layer without having to drop down to kernel
      • Much nicer to work with abstractions (Container, Task, Snapshot) than to manage calls to clone() and mount()
    • Available as daemon for Linux and Windows
    • Designed to be embedded into a larger system (like Docker)
      • Used by container platforms like Docker and Kubernetes
    • Under the hood, containerd uses runc
    • Only deals with core container management
      • Push/pull functionality
      • Image management
      • Container lifecycle APIs
        • Create, execute and manage containers and their tasks
      • Snapshot management
    • Out of scope
      • Networking
        • Very complicated, much more platform specific than abstracting Linux calls
        • Instead, containerd exposes events so consumers can subscribe to events they care about
          • E.g. hook events to add interfaces to network namespace
    • Exposes functionality via GRPC API
      • Listens on Linux socket
  • Runtime platforms
    • Docker
      • Uses containerd, plus shim
      • Shim allows for daemon-less containers
        • e.g. You can upgrade Docker daemon without restarting containers
    • rkt
      • Application container engine, part of CoreOS (RedHat)
      • rkt has no centralized “init” daemon
        • Instead it launches containers directly from client commands
      • Was part of CNCF, but archived in August 2019
        • Reasons cited by CNCF:
          • “end user adoption has severely declined”
          • “project activity and the number of contributors has also steadily declined over time”
        • containerd and CRI-O are now the CNCF container runtime projects
    • CRI-O
      • Implementation of the Kubernetes CRI (Container Runtime Interface) to enable using OCI runtimes
      • Lightweight alternative to using Docker, Moby or rkt as the runtime for k8s
      • Allows k8s to use any OCI-compliant runtime as the container runtime for running pods
      • Supports runc and Kata Containers
  • Revisit pseudo code example of creating a container
    • Steps:
      • Create root filesystem for container
        • Spin up busybox in Docker container, and then export filesystem
      • Run “launcher” process that sets up “child” namespace
      • Launcher process forks new child process (now under new namespaces)
        • Child process then forks new process for container
          • chroot (to our root filesystem)
          • mount any other FS
          • set cgroups (e.g. apply CPU constraints)
We’d love to hear from you! You can reach us at:

Coming soon…

Show Buttons
Hide Buttons