Containerd 2.0: The Easiest Way to Manage Containers

Containerd 2.0: The Easiest Way to Manage Containers

ยท

11 min read

Introduction to Containerd

Containerd is an open source container runtime that manages the complete container lifecycle of its host system. It was originally created by Docker and donated to the CNCF in March of 2017 to be governed and managed as an independent open source project.

Containerd builds upon runC to provide a daemon for managing container lifecycles including image transfer, storage, container execution and supervision. Whereas Docker engine focuses on end user experience and building container images, Containerd focuses on container runtime operations and low-level storage and execution.

Containerd serves as an integration point for higher level container management platforms and orchestrators like Docker and Kubernetes. It provides a stable runtime and execution environment abstracted away from the host operating system.

Containerd is commonly used to:

  • Manage OCI compatible container images

  • Execute containers based on those images

  • Fetch container images from remote repositories

  • Interact with container networking

  • Monitor and gather container metrics

  • Integrate with orchestrators like Kubernetes

By decoupling the container runtime from Docker engine, Containerd offers a simple and robust runtime environment for building custom container platforms. It strikes a balance between host operating system transparency and portability across distros and platforms.

Why Upgrade to Containerd 2.0?

Containerd 2.0 comes with significant improvements and new features compared to previous versions:

CRI Integration: Containerd 2.0 has built-in integration with the Container Runtime Interface (CRI), making it easy to integrate with Kubernetes. This replaces Docker's cri-containerd plugin.

Simplified Architecture: The architecture has been simplified by merging cri-containerd features directly into the main containerd daemon. This makes it more lightweight and efficient.

Better Performance: Several performance enhancements improve startup times, I/O throughput, and CPU/memory usage. Workloads will launch faster and utilize resources more efficiently.

Enhanced Snapshots: Snapshots are 25-50% faster in Containerd 2.0, with lower memory overhead. This makes saving and restoring container state much quicker.

Prune Support: Containerd 2.0 adds native support for pruning unused images, containers, and snapshots from disk. This saves disk space.

Helm Chart Support: Container charts can now be pushed/pulled from OCI registries, facilitating deployment workflows.

Windows Improvements: Support for Windows containers has been improved with faster launch times and lower resource usage.

Client Library Updates: Client libraries like Go and Python have been updated to support new Containerd 2.0 features.

OCI Runtime Spec: Containerd 2.0 implements the full Open Container Initiative (OCI) runtime specification. This improves interoperability.

Security Enhancements: Several security improvements have been added around read-only containers and rootless mode.

By upgrading to Containerd 2.0, you can take advantage of these new capabilities to improve security, performance, efficiency and management of your container workloads. The simplified architecture also makes Containerd more lightweight and suitable for embedded systems.

Installing Containerd 2.0

Containerd 2.0 can be installed on most Linux distributions and OSes including RHEL, CentOS, Fedora, Ubuntu, Debian, ArchLinux, openSUSE and SLES.

The easiest way to install containerd is using the distribution's package manager.

Install using a Package Manager

On Debian/Ubuntu systems, you can install containerd using apt:

sudo apt update
sudo apt install containerd

RHEL, CentOS, and Fedora use dnf:

sudo dnf check-update
sudo dnf install containerd

openSUSE/SLES:

sudo zypper refresh
sudo zypper install containerd

Arch Linux:

sudo pacman -Syu containerd

The package manager will handle installing any dependencies and setting up the configuration for you.

Compile and Install from Source

You can also build containerd from source. This requires having a Go environment set up.

Clone the containerd repository:

git clone https://github.com/containerd/containerd.git

Enter the containerd directory and compile the source:

cd containerd
make

Finally install containerd:

sudo make install

When installing from source, you may need to manually install dependencies like runc and gRPC.

The containerd binary, configuration files, and runtime data will be installed to /usr/local by default. The configuration file is located at /etc/containerd/config.toml.

System Requirements

Containerd 2.0 has the following minimum requirements:

  • Linux kernel 4.4 or later

  • glibc 2.17 or later

  • runc 1.0.0-rc92 or later

  • iptables 1.6 or later

It's recommended to use the latest stable kernel, runc, and glibc versions for the best experience.

Upgrades and Migrations

To upgrade from containerd 1.x to 2.0, stop the old containerd service, install the new version, and restart containerd. The containerd datastore format is compatible across versions.

Migrating data from other runtimes like Docker or cri-o is also possible using tools like crictl.

Configuring Containerd 2.0

Containerd 2.0 introduces a new config.toml configuration file that allows you to customize various settings. This replaces the older /etc/containerd/config.toml file used in previous versions.

The config.toml file uses TOML syntax and is located by default at /etc/containerd/config.toml. This file contains all the default configuration values which you can override as needed.

Some of the key settings that can be configured include:

  • DisabledPlugins - Allows disabling default plugins. This can help increase security by reducing attack surface.

  • Plugins - Specify additional plugins to enable. Useful for adding support for new runtimes like Firecracker.

  • Debug - Turn on debugging output. Useful for troubleshooting issues.

  • GRPCMaxSendMsgSize - Adjust gRPC message size limits. May need tweaking for large snapshots or persisted data.

  • GRPCMaxRecvMsgSize - Adjust gRPC receive message size.

  • CgroupParent - Specify parent cgroup for all containers.

  • DefaultRuntime - Configure the default OCI runtime to use. Options like runc or crun may be specified.

  • SandboxImage - Customize the base layer sandbox image for untrusted workloads.

  • Root - Path to a local directory where containerd can store persistent data. Defaults to /var/lib/containerd

  • State - Path to directory where containerd will store transient state. Defaults to /run/containerd

  • GRPCAddress - Address for GRPC API to listen on. Defaults to /run/containerd/containerd.sock

  • DebugAddress - Address for pprof and expvar handlers. Disabled by default.

In most cases, the defaults will work fine but the config.toml file gives you granular control over containerd's configuration if needed. Always refer to the containerd documentation for details on available configuration options.

Containerd Architecture

Containerd is composed of several components and services that work together to create, manage, and run containers. Some key architectural components include:

  • Containerd daemon (containerd) - The main containerd daemon that manages container lifecycle operations like creating images and containers, pulling images, executing containers, distributing images, etc. The daemon exposes gRPC APIs that clients use to communicate with it.

  • Containerd shim - Responsible for monitoring the state of the container process. There is one shim per container created. The shim also proxies stdio/stderr between the daemon and container process.

  • RunC - A low-level runtime that handles creating containers from images and managing container lifecycles like start, stop, delete, etc. Containerd uses runC to interface with the OS kernel and run containers.

  • CNI - Containerd integrates with CNI (Container Network Interface) to configure networking for containers. It delegates this responsibility to CNI plugins.

  • Snapshotters - Snapshotters are used to manage layered filesystems and container storage. Containerd supports several snapshotters like overlayfs, btrfs, zfs, etc.

  • OCI Runtime Spec - Containerd adheres to the Open Container Initiative (OCI) runtime specification which defines config JSON and runtime bundles for interfacing between container engines and runtimes.

  • GRPC API - The primary API exposed by containerd for clients is the GRPC API which uses protocol buffers over HTTP/2. There are also REST endpoints exposed.

Key services provided by containerd include image management, container execution, networking, storage, and events/monitoring. At a high level containerd relies on runC for container execution while providing image management, networking, and higher level orchestration itself. The daemon handles all operations using various components and exposing GRPC APIs.

Using the Containerd CLI

The containerd CLI tool ctr allows you to manage containers and images directly via the Containerd API. Here are some common operations with ctr:

List Containers

To view all containers managed by Containerd:

ctr containers ls

Start a Container

Start a new container from an image:

ctr containers start docker.io/library/alpine:latest myalpine

Stop a Container

Stop a running container:

ctr containers stop myalpine

Remove a Container

Remove a stopped container:

ctr containers rm myalpine

Pull an Image

Download an image from a registry:

ctr images pull docker.io/library/alpine:latest

List Images

View downloaded images:

ctr images ls

Remove an Image

Delete an image from local storage:

ctr images rm docker.io/library/alpine:latest

The ctr tool provides full control over Containerd and its contents without any abstraction. It allows managing containers and images directly using Containerd's underlying capabilities.

Integrating with Kubernetes

One of the key advantages of containerd 2.0 is its seamless integration with Kubernetes through the Container Runtime Interface (CRI). The CRI allows Kubernetes to work with a wide variety of container runtimes without needing to be customized for each one.

To set up containerd's CRI plugin, first ensure the containerd-ctr binary is installed on all your Kubernetes nodes. Then configure the Kubernetes container runtime in the containerd config file:

[plugins."io.containerd.grpc.v1.cri".containerd]
  snapshotter = "overlayfs"
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
    [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
      runtime_type = "io.containerd.runc.v2"

This configures containerd to use the overlayfs snapshotter and the runc OCI runtime for pods and containers managed by Kubernetes.

With the CRI plugin enabled, you can now point your Kubernetes cluster to use containerd as the container runtime:

kubeadm init --cri-socket=/run/containerd/containerd.sock

When configured this way, Kubernetes will directly interface with containerd to manage container lifecycles rather than having to go through Docker.

Some key benefits of using containerd with Kubernetes include:

  • Improved performance - containerd introduces less overhead than Docker. Image pulls, container starts, and stops are faster.

  • Tighter integration - containerd's CRI was designed specifically for Kubernetes, allowing for better integration and efficiency.

  • Active development - containerd is under active development by the CNCF and Docker, so it sees rapid improvement and new features tailored to Kubernetes.

  • No Docker dependency - containerd removes the Docker daemon dependency, simplifying the runtime environment.

Overall, containerd 2.0 offers a lightweight, optimized container runtime for Kubernetes clusters, making it a compelling upgrade for teams running Kubernetes at scale.

Monitoring Containerd

Effective monitoring is crucial for gaining visibility into Containerd and troubleshooting issues. There are several key areas to monitor:

Metrics

Containerd exposes Prometheus metrics out of the box. These metrics provide insight into resource usage, network I/O, storage I/O, and more. Key metrics to monitor include:

  • containerd_containers_count - Number of containers

  • containerd_cpu_usage_seconds_total - Cumulative CPU usage

  • containerd_memory_usage_bytes - Current memory usage

  • containerd_network_transmit_bytes_total - Network transmit I/O

  • containerd_snapshotter_snapshots_count - Number of snapshots

Setting up Prometheus to scrape Containerd metrics is straightforward. This gives you access to interactive graphs and alerts based on metrics.

Logging

Containerd generates detailed log files that are useful for auditing activity and debugging issues. Enable verbose logging and send logs to a centralized logging stack like the ELK stack. Look for errors, warning, and spikes in activity or failures.

Health Checks

Containerd comes with an integrated health check service. This performs periodic checks for things like:

  • Can handle API requests

  • Can access the containers store

  • Can connect to the network

Health check failures should trigger alerts.

Debugging Issues

When troubleshooting issues, key steps include:

  • Check for errors in Containerd logs

  • Review relevant Containerd metrics for anomalies

  • Restart Containerd and confirm it passes health checks

  • Use ctr CLI for debugging containers and images

  • Use profiles like pprof for advanced debugging

Effective monitoring provides the visibility needed to keep Containerd running smoothly. Focus on metrics, logging, health checks, and debugging techniques.

Security Considerations

Containerd provides several important security features for running containers safely and isolating workloads. Some key aspects to consider:

Isolation

Containerd uses namespaces and control groups (cgroups) to isolate containers from each other and prevent processes from accessing or affecting resources outside their container. This is a foundational element of container security.

Read-only containers

Container images can be mounted read-only to prevent any changes being written to the container's filesystem at runtime. This protects against accidentally (or intentionally) modifying the container image.

User namespaces

Containerd allows using user namespaces to run containers with distinct Linux user and group IDs mapped inside the container namespace. This adds an extra layer of isolation between the container and the host machine.

Security options

Several powerful security options are available:

  • Seccomp support allows limiting syscalls made from a container. This restricts what actions are allowed inside the container.

  • SELinux and AppArmor integration to apply mandatory access controls to containers. This restricts what the container can access on the host.

  • NoNewPriv prevents gaining additional privileges inside a container.

  • Rootless mode allows running containers as a non-root user for added security.

Overall, Containerd is designed with strong isolation and security capabilities to safely run untrusted workloads. Leveraging these features is important for securing production container deployments.

Conclusion

Containerd 2.0 offers a powerful and efficient container runtime that can enhance developers' workflows and improve infrastructure resource utilization. This guide provided key steps for installing, configuring, and integrating containerd into cloud-native environments.

Summary

We covered installing containerd 2.0 from binaries or package managers, updating configuration settings, exploring the containerd architecture and CLI, integrating with Kubernetes, and monitoring and securing containerd. While the initial setup process involves some careful configuration, containerd aims to provide a simple and robust container runtime for production environments.

Containerd Use Cases

Containerd shines for running containerized applications across diverse infrastructure. Its flexible architecture allows it to manage containers directly or integrate with orchestrators like Kubernetes. Containerd is well-suited for deploying microservices, data analytics applications, CI/CD pipelines, and other workloads at scale.

Alternatives

Other popular container runtimes like Docker, CRI-O, and Podman provide overlapping functionality. However, containerd focuses on delivering a minimal and highly performant runtime while integrating smoothly with Kubernetes. For many cloud-native use cases, containerd strikes the right balance of capabilities.

Future Outlook

As cloud-native computing matures, we can expect containerd to continue evolving alongside Kubernetes and integrating the latest Linux container runtime features. The project roadmap highlights areas like Windows container support, improved diagnostics/debugging, and resource management capabilities. Containerd is well-positioned to remain a foundational container runtime for the cloud-native ecosystem.

Overall, containerd 2.0 offers an optimized container runtime to power modern applications. This guide provided key steps for adoption. We encourage you to explore containerd further as it continues to develop innovative container management capabilities.

Did you find this article valuable?

Support GCP by becoming a sponsor. Any amount is appreciated!

ย