Discover millions of ebooks, audiobooks, and so much more with a free trial

From $11.99/month after trial. Cancel anytime.

Podman for DevOps: Containerization reimagined with Podman and its companion tools
Podman for DevOps: Containerization reimagined with Podman and its companion tools
Podman for DevOps: Containerization reimagined with Podman and its companion tools
Ebook904 pages6 hours

Podman for DevOps: Containerization reimagined with Podman and its companion tools

Rating: 0 out of 5 stars

()

Read preview

About this ebook

As containers have become the new de facto standard for packaging applications and their dependencies, understanding how to implement, build, and manage them is now an essential skill for developers, system administrators, and SRE/operations teams. Podman and its companion tools Buildah and Skopeo make a great toolset to boost the development, execution, and management of containerized applications.
Starting with the basic concepts of containerization and its underlying technology, this book will help you get your first container up and running with Podman. You'll explore the complete toolkit and go over the development of new containers, their lifecycle management, troubleshooting, and security aspects. Together with Podman, the book illustrates Buildah and Skopeo to complete the tools ecosystem and cover the complete workflow for building, releasing, and managing optimized container images. Podman for DevOps provides a comprehensive view of the full-stack container technology and its relationship with the operating system foundations, along with crucial topics such as networking, monitoring, and integration with systemd, docker-compose, and Kubernetes.
By the end of this DevOps book, you'll have developed the skills needed to build and package your applications inside containers as well as to deploy, manage, and integrate them with system services.

LanguageEnglish
Release dateApr 28, 2022
ISBN9781803248967
Podman for DevOps: Containerization reimagined with Podman and its companion tools

Related to Podman for DevOps

Related ebooks

Enterprise Applications For You

View More

Related articles

Reviews for Podman for DevOps

Rating: 0 out of 5 stars
0 ratings

0 ratings0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    Book preview

    Podman for DevOps - Alessandro Arrichiello

    Cover.png

    BIRMINGHAM—MUMBAI

    Podman for DevOps

    Copyright © 2022 Packt Publishing

    All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

    Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the authors, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.

    Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

    Group Product Manager: Rahul Nair

    Publishing Product Manager: Niranjan Naikwadi

    Senior Editor: Sangeeta Purkayastha

    Content Development Editor: Nihar Kapadia

    Technical Editor: Nithik Cheruvakodan

    Copy Editor: Safis Editing

    Project Coordinator: Shagun Saini

    Proofreader: Safis Editing

    Indexer: Sejal Dsilva

    Production Designer: Sinhayna Bais

    Marketing Coordinator: Nimisha Dua

    First published: May 2022

    Production reference: 1080422

    Published by Packt Publishing Ltd.

    Livery Place

    35 Livery Street

    Birmingham

    B3 2PB, UK.

    ISBN 978-1-80324-823-3

    www.packt.com

    To my son, Giovanni, for allowing me to steal time from our playtime. To my wife, Tecla, for being my loving partner and supporting me.

    – Alessandro Arrichiello

    To my son, Filippo, who teaches me to learn every day and enjoy the little things in life. To my beloved wife, Anna Veronica, for all the strength and inspiration she brings to our family.

    – Gianni Salinetti

    Foreword

    Containers, their various runtimes, and Kubernetes are seeing fierce momentum in the technology and computing worlds. They are no longer just the darling of system administrators and Kubernetes distributed workloads. Containers are now endemic in Continuous Integration (CI) tasks, cloud workloads, and microservices. Starting with programmers, containers have even broken into the desktop space, where Integrated Development Environments (IDEs) can be the backend into containers for things such as testing language versions or compiling code. We can attribute the latest invigoration to the simplification of container images and the ability to distribute them in container registries. Not bad for a decades-old technology that used to simply focus on the isolation of a computing process.

    Podman for DevOps begins with a detailed exploration of container history, from its inception to now. It then transitions into the various container technologies and arrives at the two most common ones: Docker and Podman (short for Pod Manager). The early chapters provide a comprehensive examination of Docker and Podman and describe the pros and cons of both. These comparisons demonstrate Podman's novelty and strengths.

    Gianni and Alessandro then settle on Podman, beginning with an exploration of its architecture. They then follow the architecture by illustrating the various applications in the Podman stack, such as conmon and network tooling. After laying the groundwork for how Podman works, they meticulously review each Podman command in an example-oriented approach. Finally, Gianni and Alessandro provide a thorough review of Buildah, Podman's best friend and a best-of-breed application for building container images.

    When I write about containers and Podman, one of my challenges when explaining concepts can be providing too many details or oversimplifying things. Gianni and Alessandro have found a perfect medium between both ends by supplying ample amounts of detail. I appreciated the carefully crafted explanations when the topic required them. Not only was the level of detail appropriate, but they also used a very wide scope when writing about Podman and containers. As I read the book, I was able to relate to their superb use of examples and they did not add layers of abstraction that can make learning difficult. Podman for DevOps was a pleasure to read. As a subject matter expert, I am certain it will be a perfect resource for those both new to and experienced with Podman and containers.

    Brent J. Baude, Senior Principal Software Engineer

    Podman Architect

    Contributors

    About the authors

    Alessandro Arrichiello is a solution architect for Red Hat Inc. with a special focus on telco technologies. He has a passion for GNU/Linux systems, which began at age 14 and continues today. He has worked with tools for automating enterprise IT: configuration management and continuous integration through virtual platforms. Alessandro is also a writer for the Red Hat Developer Blog, on which he has authored several articles about container architecture and technology. He now helps telecommunication customers with adopting container orchestration environments such as Red Hat OpenShift and Kubernetes, infrastructure as a service such as OpenStack, edge computing, and data center automation.

    Gianni Salinetti is a solution architect from Rome working for Red Hat Inc. with a special focus on cloud-native computing and hybrid cloud strategies. He started working with GNU/Linux back in 2001 and developed a passion for open source software. His main fields of interest are application orchestration, automation, and systems performance tuning. He is also an advocate of DevSecOps and GitOps practices. He is a former Red Hat instructor, having taught many classes about GNU/Linux, OpenStack, JBoss middleware, Ansible, Kubernetes, and Red Hat OpenShift. He won Red Hat EMEA awards as the best DevOps, cloud, and middleware instructor. He is also an author for the Red Hat Developer Blog and actively contributes to webinars and events.

    About the reviewers

    Nicolò Amato has over 20 years of experience working in the field of IT, 16 of which were at Hewlett Packard Enterprise, Accenture, DXC, and Red Hat Inc. Working in both technical and development roles has given him a broad base of skills and the ability to work with a diverse range of clients. His time was spent designing and implementing complex infrastructures for clients with the aim to migrate traditional services to hybrid, multi-cloud, and edge environments, evolving them into cloud-native services. He is enthusiastic about new technologies and he likes to be up to date – in particular with open source, which he considers one of the essences of technology that regulates the evolution of information technology.

    Pierluigi Rossi is a solution architect for Red Hat Inc. His passion for GNU/Linux systems began 20 years ago and continues today. He has built a strong business and technical know-how on enterprise and cutting-edge technologies, working for many companies on different verticals and roles in the last 20 years. He has worked with virtualization and containerization tools (open source and not). He has also participated in several projects for corporate IT automation. He is now working on distributed on-premises and cloud environments involving IaaS, PaaS (OpenShift and Kubernetes), and automation. He loves open source in all its shades, and he enjoys sharing ideas and solutions with customers, colleagues, and community members.

    Marco Alessandro Fagotto has been in the IT industry for 13 years, ranging across frontend and backend support, administration, system configuration, and security roles. Working in both technical and development roles has given him a broad base of skills and the ability to work with a diverse range of clients. He is a Red Hat Certified Professional, always looking for new technology and solutions to explore due to his interest in the fast evolution of the open source world.

    Table of Contents

    Preface

    Section 1: From Theory to Practice: Running Containers with Podman

    Chapter 1: Introduction to Container Technology

    Technical requirements

    Book conventions

    What are containers?

    Resource usage with cgroups

    Running isolated processes

    Isolating mounts

    Container images to the rescue

    Security considerations

    Container engines and runtimes

    Containers versus virtual machines

    Why do I need a container?

    Open source

    Portability

    DevOps facilitators

    Cloud readiness

    Infrastructure optimization

    Microservices

    Chroot and Unix v7

    FreeBSD jails

    Solaris Containers (also known as Solaris Zones)

    Linux Containers (LXC)

    Docker

    rkt

    OCI and CRI-O

    Podman

    Where are containers used today?

    Summary

    Further reading

    Chapter 2: Comparing Podman and Docker

    Technical requirements

    Docker container daemon architecture

    The Docker daemon

    Interacting with the Docker daemon

    The Docker REST API

    Docker client commands

    Docker images

    Docker registries

    What does a running Docker architecture look like?

    Containerd architecture

    Podman daemonless architecture

    Podman commands and REST API

    Podman building blocks

    The libpod library

    The runc and crun OCI container runtimes

    Conmon

    Rootless containers

    OCI images

    The main differences between Docker and Podman

    Command-line interface comparison

    Running a container

    Summary

    Further reading

    Chapter 3: Running the First Container

    Technical requirements

    Choosing an operating system and installation method

    Choosing between Linux distributions and another OS

    Preparing your environment

    Customizing the container registries search list

    Optional – enable socket-based services

    Optional – customize Podman’s behavior

    Running your first container

    Interactive and pseudo-tty

    Detaching from a running container

    Network port publishing

    Configuration and environment variables

    Summary

    Further reading

    Chapter 4: Managing Running Containers

    Technical requirements

    Managing container images

    Searching for images

    Pulling and viewing images

    Inspecting images' configurations and contents

    Deleting images

    Operations with running containers

    Viewing and handling container status

    Pausing and unpausing containers

    Inspecting processes inside containers

    Monitoring container stats

    Inspecting container information

    Capturing logs from containers

    Executing processes in a running container

    Running containers in pods

    Summary

    Chapter 5: Implementing Storage for the Container's Data

    Technical requirements

    Why does storage matter for containers?

    Containers' storage features

    Storage driver

    Copying files in and out of a container

    Interacting with overlayfs

    Attaching host storage to a container

    Managing and attaching bind mounts to a container

    Managing and attaching volumes to a container

    SELinux considerations for mounts

    Attaching other types of storage to a container

    Summary

    Further reading

    Section 2: Building Containers from Scratch with Buildah

    Chapter 6: Meet Buildah – Building Containers from Scratch

    Technical requirements

    Basic image building with Podman

    Builds under the hood

    Dockerfile and Containerfile instructions

    Running builds with Podman

    Meet Buildah, Podman's companion tool for builds

    Preparing our environment

    Verifying the installation

    Buildah configuration files

    Choosing our build strategy

    Building a container image starting from an existing base image

    Building a container image starting from scratch

    Building a container image starting from a Dockerfile

    Building images from scratch

    Building images from a Dockerfile

    Summary

    Further reading

    Chapter 7: Integrating with Existing Application Build Processes

    Technical requirements

    Multistage container builds

    Multistage builds with Dockerfiles

    Multistage builds with Buildah native commands

    Running Buildah inside a container

    Running rootless Buildah containers with volume stores

    Running Buildah containers with bind-mounted stores

    Running native Buildah commands inside containers

    Integrating Buildah in custom builders

    Including Buildah in our Go build tool

    Quarkus-native executables in containers

    A Buildah wrapper for the Rust language

    Summary

    Further readings

    Chapter 8: Choosing the Container Base Image

    Technical requirements

    The Open Container Initiative image format

    OCI Image Manifest

    Where do container images come from?

    Docker Hub container registry service

    Quay container registry service

    Red Hat Ecosystem Catalog

    Trusted container image sources

    Managing trusted registries

    Introducing Universal Base Image

    The UBI Standard image

    The UBI Minimal image

    The UBI Micro image

    The UBI Init image

    Other UBI-based images

    Summary

    Further reading

    Chapter 9: Pushing Images to a Container Registry

    Technical requirements

    What is a container registry?

    Repository management

    Pushing container images

    Tag management

    Pulling container images

    Authentication management

    Cloud-based and on-premise container registries

    On-premise container registries

    Cloud-based container registries

    Managing container images with Skopeo

    Installing Skopeo

    Verifying the installation

    Copying images across locations

    Inspecting remote images

    Synchronizing registries and local directories

    Deleting images

    Running a local container registry

    Running a containerized registry

    Customizing the registry configuration

    Using a local registry to sync repositories

    Managing registry garbage collection

    Summary

    Further reading

    Section 3: Managing and Integrating Containers Securely

    Chapter 10: Troubleshooting and Monitoring Containers

    Technical requirements

    Troubleshooting running containers

    Permission denied while using storage volumes

    Issues with the ping command in rootless containers

    Monitoring containers with health checks

    Inspecting your container build results

    Troubleshooting builds from Dockerfiles

    Troubleshooting builds with Buildah-native commands

    Advanced troubleshooting with nsenter

    Troubleshooting a database client with nsenter

    Summary

    Further reading

    Chapter 11: Securing Containers

    Technical requirements

    Running rootless containers with Podman

    The Podman Swiss Army knife – subuid and subgid

    Do not run containers with UID 0

    Signing our container images

    Signing images with GPG and Podman

    Configuring Podman to pull signed images

    Testing signature verification failures

    Managing keys with Podman image trust commands

    Managing signatures with Skopeo

    Customizing Linux kernel capabilities

    Capabilities quickstart guide

    Capabilities in containers

    Customizing a container's capabilities

    SELinux interaction with containers

    Introducing Udica

    Summary

    Further reading

    Chapter 12: Implementing Container Networking Concepts

    Technical requirements

    Container networking and Podman setup

    CNI configuration quick start

    Podman CNI walkthrough

    Netavark configuration quick start

    Podman Netavark walkthrough

    Managing networks with Podman

    Interconnecting two or more containers

    Container DNS resolution

    Running containers inside a Pod

    Exposing containers outside our underlying host

    Port Publishing

    Attaching a host network

    Host firewall configuration

    Rootless container network behavior

    Summary

    Further reading

    Chapter 13: Docker Migration Tips and Tricks

    Technical requirements

    Migrating existing images and playing with a command's alias

    Podman commands versus Docker commands

    Behavioral differences between Podman and Docker

    Missing commands in Podman

    Missing commands in Docker

    Using Docker Compose with Podman

    Docker Compose quick start

    Configuring Podman to interact with docker-compose

    Running Compose workloads with Podman and docker-compose

    Using podman-compose

    Summary

    Further reading

    Chapter 14: Interacting with systemd and Kubernetes

    Technical requirements

    Setting up the prerequisites for the host operating system

    Creating the systemd unit files

    Managing container-based systemd services

    Generating Kubernetes YAML resources

    Generating basic Pod resources from running containers

    Generating Pods and services from running containers

    Generating a composite application in a single Pod

    Generating composite applications with multiple Pods

    Running Kubernetes resource files in Podman

    Testing the results in Kubernetes

    Setting up minikube

    Starting minikube

    Running generated resource files in Kubernetes

    Summary

    Further reading

    Other Books You May Enjoy

    Preface

    DevOps best practices encourage the adoption of containers as the foundation of cloud-native ecosystems. As containers have become the new de facto standard for packaging applications and their dependencies, understanding how to implement, build, and manage them is now an essential skill for developers, system administrators, and SRE/operations teams. Podman and its companion tools, Buildah and Skopeo, make a great toolset to boost the development, execution, and management of containerized applications. Starting from the basic concepts of containerization and its underlying technologies, this book will help you get your first container up and running with Podman. The book explores the complete toolkit and illustrates the development of new containers, their life cycle management, troubleshooting, and security aspects.

    By the end of Podman for DevOps, you'll have the skills needed to be able to build and package your applications inside containers as well as deploy, manage, and integrate them with system services.

    Who this book is for

    The book is for cloud developers looking to learn how to build and package applications inside containers, and system administrators who want to deploy, manage, and integrate containers with system services and orchestration solutions. This book provides a detailed comparison between Docker and Podman to aid you in learning Podman quickly.

    What this book covers

    Chapter 1, Introduction to Container Technology, covers the key concepts of container technology, a bit of history, and the underlying foundational elements that make things work.

    Chapter 2, Comparing Podman and Docker, takes you through the architectures of Docker versus Podman, looking at high-level concepts and the main differences between them.

    Chapter 3, Running the First Container, teaches you how to set up the prerequisites for running and managing your first container with Podman.

    Chapter 4, Managing Running Containers, helps you understand how to manage the life cycles of your containers, starting/stopping/killing them to properly manage the services.

    Chapter 5, Implementing Storage for the Container's Data, covers the basics of storage requirements for containers, the various offerings available, and how to use them.

    Chapter 6, Meet Buildah – Building Containers from Scratch, is where you begin to learn the basic concepts of Buildah, Podman's companion tool that is responsible for assisting system administrators as well as developers during the container creation process.

    Chapter 7, Integrating with Existing Application Build Processes, teaches you techniques and methods to integrate Buildah into a build process for your existing applications.

    Chapter 8, Choosing the Container Base Image, covers more about the container base image format, trusted sources, and their underlying features.

    Chapter 9, Pushing Images to a Container Registry, teaches you what a container registry is, how to authenticate them, and how to work with images by pushing and pulling them.

    Chapter 10, Troubleshooting and Monitoring Containers, shows you how to inspect running or failing containers, search for issues, and monitor the health status of containers.

    Chapter 11, Securing Containers, goes into more detail on security in containers, the main issues, and the important step of updating container images during runtime.

    Chapter 12, Implementing Container Networking Concepts, teaches you about Containers Network Interface (CNI), how to expose a container to the external world, and finally, how to interconnect two or more containers running on the same machine.

    Chapter 13, Docker Migration Tips and Tricks, sees you learn how to migrate from Docker to Podman in the easiest way by using some of the built-in features of Podman, as well as some tricks that may help in the process.

    Chapter 14, Interacting with systemd and Kubernetes, shows you how to integrate a container as a system service in the underlying operating host, enabling its management with the common sysadmin's tools. Podman interaction features with Kubernetes will also be explored.

    To get the most out of this book

    In this book, we will guide you through the installation and use of Podman 3 or later, and its companion tools, Buildah and Skopeo. The default Linux distribution used in the book is Fedora Linux 34 or later but any other Linux distribution can be used. All commands and code examples have been tested using Fedora 34 or 35 and Podman 3 or 4, but they should work also with future version releases.

    If you are using the digital version of this book, we advise you to type the commands yourself or access the code from the book's GitHub repository (a link is available in the next section).

    Doing so will help you avoid any potential errors related to the copying and pasting of code.

    Download the example code files

    You can download the example code files for this book from GitHub at https://github.com/PacktPublishing/Podman-for-DevOps. If there's an update to the code, it will be updated in the GitHub repository.

    We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!

    Download the color images

    We also provide a PDF file that has color images of the screenshots and diagrams used in this book. You can download it here: https://static.packt-cdn.com/downloads/9781803248233_ColorImages.pdf.

    Conventions used

    There are a number of text conventions used throughout this book.

    Code in text: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: We just defined a name for our repo, ubi8-httpd, and we chose to link this repository to a GitHub repository push.

    A block of code is set as follows:

    [Unit]

    Description=Podman API Socket

    Documentation=man:podman-system-service(1)

    When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:

    $ podman ps

    CONTAINER ID IMAGE

    COMMAND CREATED STATUS PORTS

    NAMES

    685a339917e7 registry.fedoraproject.org/f29/httpd:latest /

    usr/bin/run-http... 3 minutes ago Up 3 minutes ago

    clever_zhukovsky

    Any command-line input or output is written as follows:

    $ skopeo login -u admin -p p0dman4Dev0ps# --tls-verify=false localhost:5000

    Login Succeeded!

    Bold: Indicates a new term, an important word, or words that you see onscreen. For instance, words in menus or dialog boxes appear in bold. Here is an example: … and prints a crafted HTML page with the Hello World! message when it receives a GET / request.

    Tips or important notes

    Appear like this.

    Get in touch

    Feedback from our readers is always welcome.

    General feedback: If you have questions about any aspect of this book, email us at [email protected] and mention the book title in the subject of your message.

    Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/support/errata and fill in the form.

    Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.

    If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.

    Share Your Thoughts

    Once you've read , we'd love to hear your thoughts! Please click here to go straight to the Amazon review page for this book and share your feedback.

    Your review is important to us and the tech community and will help us make sure we're delivering excellent quality content.

    Section 1: From Theory to Practice: Running Containers with Podman

    This chapter will take you through the basic concepts of container technology, the main features of Podman and its companion tools, the main differences between Podman and Docker, and finally, will put the theory of running and managing containers into practice.

    This part of the book comprises the following chapters:

    Chapter 1, Introduction to Container Technology

    Chapter 2, Comparing Podman and Docker

    Chapter 3, Running the First Container

    Chapter 4, Managing Running Containers

    Chapter 5, Implementing Storage for the Container’s Data

    Chapter 1: Introduction to Container Technology

    Container technology has old roots in operating system history. For example, do you know that part of container technology was born back in the 1970s? Despite their simple and intuitive approach, there are many concepts behind containers that deserve a deeper analysis to fully grasp and appreciate how they made their way in the IT industry.

    We're going to explore this technology to better understand how it works under the hood, the theory behind it, and its basic concepts. Knowing the mechanics and the technology behind the tools will let you easily approach and learn the whole technology's key concepts.

    Then, we will also explore container technology's purpose and why it has spread to every company today. Do you know that 50% of the world's organizations are running half of their application base as containers in production nowadays?

    Let's dive into this great technology!

    In this chapter, we're going to ask the following questions:

    What are containers?

    Why do I need a container?

    Where do containers come from?

    Where are containers used today?

    Technical requirements

    This chapter does not require any technical prerequisites, so feel free to read it without worrying about installing or setting up any kind of software on your workstation!

    Anyway, if you are new to containers, you will find here many technical concepts useful to understand the next chapters. We recommend going through it carefully and coming back when needed. Previous knowledge of the Linux operating system would be helpful in understanding the technical concepts covered in this book.

    Book conventions

    In the following chapters, we will learn many new concepts with practical examples that will require active interaction with a Linux shell environment. In the practical examples, we will use the following conventions:

    For any shell command that will be anticipated by the $ character, we will use a standard user (not root) for the Linux system.

    For any shell command that will be anticipated by the # character, we will use the root user for the Linux system.

    Any output or shell command that would be too long to display in a single line for the code block will be interrupted with the \ character, and then it will continue to a new line.

    What are containers?

    This section describes the container technology from the ground up, beginning from basic concepts such as processes, filesystems, system calls, the process isolation up to container engines, and runtimes. The purpose of this section is to describe how containers implement process isolation. We also describe what differentiates containers from virtual machines and highlight the best use case of both scenarios.

    Before asking ourselves what a container is, we should answer another question: what is a process?

    According to The Linux Programming Interface, an enjoyable book by Michael Kerrisk, a process is an instance of an executing program. A program is a file holding information necessary to execute the process. A program can be dynamically linked to external libraries, or it can be statically linked in the program itself (the Go programming language uses this approach by default).

    This leads us to an important concept: a process is executed in the machine CPU and allocates a portion of memory containing program code and variables used by the code itself. The process is instantiated in the machine's user space and its execution is orchestrated by the operating system kernel. When a process is executed, it needs to access different machine resources such as I/O (disk, network, terminals, and so on) or memory. When the process needs to access those resources, it performs a system call into the kernel space (for example, to read a disk block or send packets via the network interface).

    The process indirectly interacts with the host disks using a filesystem, a multi-layer storage abstraction, that facilitates the write and read access to files and directories.

    How many processes usually run in a machine? A lot. They are orchestrated by the OS kernel with complex scheduling logics that make the processes behave like they are running on a dedicated CPU core, while the same is shared among many of them.

    The same program can instantiate many processes of its kind (for example, multiple web server instances running on the same machine). Conflicts, such as many processes trying to access the same network port, must be managed accordingly.

    Nothing prevents us from running a different version of the same program on the host, assuming that system administrators will have the burden of managing potential conflicts of binaries, libraries, and their dependencies. This could become a complex task, which is not always easy to solve with common practices.

    This brief introduction was necessary to set the context.

    Containers are a simple and smart answer to the need of running isolated process instances. We can safely affirm that containers are a form of application isolation that works on many levels:

    Filesystem isolation: Containerized processes have a separated filesystem view, and their programs are executed from the isolated filesystem itself.

    Process ID isolation: This is a containerized process run under an independent set of process IDs (PIDs).

    User isolation: User IDs (UIDs) and group IDs (GIDs) are isolated to the container. A process' UID and GID can be different inside a container and run with a privileged UID or GID inside the container only.

    Network isolation: This kind of isolation relates to the host network resources, such as network devices, IPv4 and IPv6 stacks, routing tables, and firewall rules.

    IPC isolation: Containers provide isolation for host IPC resources, such as POSIX message queues or System V IPC objects.

    Resource usage isolation: Containers rely on Linux control groups (cgroups) to limit or monitor the usage of certain resources, such as CPU, memory, or disk. We will discuss more about cgroups later in this chapter.

    From an adoption point of view, the main purpose of containers, or at least the most common use case, is to run applications in isolated environments. To better understand this concept, we can look at the following diagram:

    Figure 1.1 – Native applications versus containerized ones

    Figure 1.1 – Native applications versus containerized ones

    Applications running natively on a system that does not provide containerization features share the same binaries and libraries, as well as the same kernel, filesystem, network, and users. This could lead to many issues when an updated version of an application is deployed, especially conflicting library issues or unsatisfied dependencies.

    On other hand, containers offer a consistent layer of isolation for applications and their related dependencies that ensures seamless coexistence on the same host. A new deployment only consists of the execution of the new containerized version, as it will not interact or conflict with the other containers or native applications.

    Linux containers are enabled by different native kernel features, with the most important being Linux namespaces. Namespaces abstract specific system resources (notably, the ones described before, such as network, filesystem mount, users, and so on) and make them appear as unique to the isolated process. In this way, the process has the illusion of interacting with the host resource, for example, the host filesystem, while an alternative and isolated version is being exposed.

    Currently, we have a total of eight kinds of namespaces:

    PID namespaces: These isolate the process ID number in a separate space, allowing processes in different PID namespaces to retain the same PID.

    User namespaces: These isolate user and group IDs, root directory, keyrings, and capabilities. This allows a process to have a privileged UID and GID inside the container while simultaneously having unprivileged ones outside the namespace.

    UTS namespaces: These allow the isolation of hostname and NIS domain name.

    Network namespaces: These allow isolation of networking system resources, such as network devices, IPv4 and IPv6 protocol stacks, routing tables, firewall rules, port numbers, and so on. Users can create virtual network devices called veth pairs to build tunnels between network namespaces.

    IPC namespaces: These isolate IPC resources such as System V IPC objects and POSIX message queues. Objects created in an IPC namespace can be accessed only by the processes that are members of the namespace. Processes use IPC to exchange data, events, and messages in a client-server mechanism.

    cgroup namespaces: These isolate cgroup directories, providing a virtualized view of the process's cgroups.

    Mount namespaces: These provide isolation of the mount point list that is seen by the processes in the namespace.

    Time namespaces: These provide an isolated view of system time, letting processes in the namespace run with a time offset against the host time.

    Now's, let's move on to resource usage.

    Resource usage with cgroups

    cgroups are a native feature of the Linux kernel whose purpose is to organize processes in a hierarchical tree and limit or monitor their resource usage.

    The kernel cgroups interface, similar to what happens with /proc, is exposed with a cgroupfs pseudo-filesystem. This filesystem is usually mounted under /sys/fs/cgroup in the host.

    cgroups offer a series of controllers (also called subsystems) that can be used for different purposes, such as limiting the CPU time share of a process, memory usage, freeze and resume processes, and so on.

    The organizational hierarchy of controllers has changed through time, and there are currently two versions, V1 and V2. In cgroups V1, different controllers could be mounted against different hierarchies. Instead, cgroups V2 provide a unified hierarchy of controllers, with processes residing in the leaf nodes of the tree.

    cgroups are used by containers to limit CPU or memory usage. For example, users can limit CPU quota, which means limiting the number of microseconds the container can use the CPU over a given period, or limit CPU shares, the weighted proportion of CPU cycles for each container.

    Now that we have illustrated how process isolation works (both for namespaces and resources), we can illustrate a few basic examples.

    Running isolated processes

    A useful fact to know is that GNU/Linux operating systems offer all the features necessary to run a container manually. This result can be achieved by working with a specific system call (notably unshare() and clone()) and utilities such as the unshare command.

    For example, to run a process, let's say /bin/sh, in an isolated PID namespace, users can rely on the unshare command:

    # unshare --fork --pid --mount-proc /bin/sh

    The result is the execution of a new shell process in an isolated PID namespace. Users can try to monitor the process view and will get an output such as the following:

    sh-5.0# ps aux

    USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

    root           1  0.0  0.0 226164  4012 pts/4    S    22:56   0:00 /bin/sh

    root           4  0.0  0.0 227968  3484 pts/4    R+   22:56   0:00 ps aux

    Interestingly, the shell process of the preceding example is running with PID 1, which is correct, since it is the very first process running in the new isolated namespace.

    Anyway, the PID namespace will be the only one to be abstracted, while all the other system resources still remain the original host ones. If we want to add more isolation, for example on a network stack, we can add the --net flag to the previous command:

    # unshare --fork --net --pid --mount-proc /bin/sh

    The result is a shell process isolated on both PID and network namespaces. Users can inspect the network IP configuration and realize that the host native devices are no longer directly seen by the unshared process:

    sh-5.0# ip addr show

    1: lo: mtu 65536 qdisc noop state DOWN group default qlen 1000

        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

    The preceding examples are useful to understand a very important concept: containers are strongly related to Linux native features. The OS provided a solid and complete interface that helped container runtime development, and the capability to isolate namespaces and resources was the key that unlocked containers adoption. The role of the

    Enjoying the preview?
    Page 1 of 1