In this lesson, we discuss key concepts about how applications consume computational resources, key Linux tools, and why these concepts are important to understand how containers work.
Hi everyone! I am a Director in VMware’s Cloud Native Field Engineering and Education organization. My team works with customers to both teach Kubernetes and Cloud Native concepts as well as help implement solutions in this fast-changing space.View Profile
Hi everyone, this is Jonathon Smith, Director of Field Engineering and Education for Cloud Native Applications.
Today I wanted to provide a brief introduction to some key container concepts. First, let’s start with the seminal question, what are containers? Now I promise to answer that question by the end of the presentation, but bear with me, I may need to take a circuitous route to get there.
First, containers take their name from their real life counterparts, we can leverage a container of any sort for this analogy, but the de-facto standard visualization is of course, the shipping container. When you’re shipping items to the other side of the world, containers make it easy to package goods together into a single shipment. The standard shape and size makes packing lots of containers onto a ship efficient, the walls provide isolation, preventing items from getting mixed together, they are portable, designed to be easily moved and shipped, and there’s a clear separation of concerns. One party is responsible for packing the container with the right items, and another party is responsible for making sure the container gets to its destination.
Containers in virtual life if you will, have very similar properties. Containers are essentially abstractions that provide a standardized way for you to package your application, its configuration and dependencies together into one logical object. These virtual containers are standardized in both how the contents are created, and largely, how they expose resources to your application. The packaging provides a logical separation between applications, it also provides efficiency, allowing many applications to run inside a single host. They are portable, because all dependencies are packaged together with the application, providing a consistent runtime environment regardless of the target system, whether that’s an on premises data center, the public cloud, or even your local laptop.
There’s also a separation of concerns. Developers are able to focus on writing containerized applications, provided some guard rails and best practices are are provided, and operations teams are able to focus on running containers at scale, usually leveraging a container orchestration platform.
Before we go any further however, let’s zoom in a little bit on what an application really is. To humans, applications are software programs developed to perform specific tasks, and execute on a computer. They are written in human readable language and compiled into something the computer understands.
To computers, applications are binary instructions that tell the computer how to execute tasks. The tasks are represented as processes in the operating system, and all computation is primarily based on managing the utilization of three key components of a computer, the CPU, memory and I/O, or input, output. The CPU executes instructions, which is your application on data that is read into memory from the disk or network, and access to these resources is mediated by the operating system, which manages how much of each resource is provided to each process or application.
This is an example ah of a top command on a Linux system that displays all currently running processes. As you can see, we have a process identifier, or a PID that’s unique to each process, we display the user that’s running the process, and a lot of resource information ah such as the CPU percent, and the memory percentage used by that process.
So now that we understand applications a little bit better, let’s dive back into what a container is, and explain ah how that matters to ah ah an application, and how those things fit together. Of course it’s an unfair comparison to compare virtual machines to containers, because they work together ah quite commonly, but let’s go ahead and and talk through ah some of the distinctions here.
So of course, if we start off in building a virtual machine, we start off with hardware, and we have a host operating system, and then we have to install a hypervisor. The hypervisor is what allows you to divide up that single physical infrastructure into many smaller virtual machines. Within those virtual machines, you’re able install an a unique operating system, and of course this operating can system can be ah any operating system you like, and inside of that operating system, applications can be installed along with their dependencies.
In the container world, we start at the same place, we have to have hardware and infrastructure and an operating system, but we also now have a new component, the container runtime, and of course Docker is the most common container runtime used today. In addition to the container runtime, now we have the applications and their dependencies and libraries packaged together, and this is only possible because the container runtime manages that packaging and is able to understand ah what a container actually is, and how that packaging works, and make that operate within the context of the operating system.
Of course, to the container runtime, it doesn’t really care if it’s running on bare metal, or if it’s running on a virtual machine, um but certainly ah both options are possible and quite common.
Okay, so I showed you a lotta boxes and said, “This is a container”, but what are containers really, and how do I put my applications into those container boxes? I just wanna remind you, in my earlier definition, I did use the term logical object, and why? Because containers don’t really exist, and let’s go into that a little bit further. Containers leverage namespaces and control groups, otherwise known as cgroups, which are Linux Kernal features and they provide the functionality that we expect, the isolation, the packaging and so on.
Namespaces allow the operating system to limit what a process can see, such as other processes, ah the file system and more. We’re not gonna go into all the different types of namespaces, but certainly process isolation and file system isolation are are two of the, ah the the key components. Cgroups on the other hand, limit what resources a process can do, or use, how much CPU, how much memory, and so on, and so this again, mediated by cgroups and a-allows ah you to leverage this ah ah ah appropriately.
All right, so now that we’ve got a little bit more information, we can s- describe containers slightly differently. A container is a process which is extracted from tarballs of your application and its dependency, it’s anchored to namespaces, which provides the necessary isolation we desire, and it’s controlled by cgroups which helps us with resource utilization management.
And now that we have some of the underlying technology that makes containers possible out of the way, let’s take a look at the Dockerfile, which is the container specification. The Dockerfile provides a set of instructions for how you want your container to be built and run. In this example, you can see that the image is built from another image, in this case, Node Alpine. We install, ah we set up a directory, install some dependencies, and we copy over our source code, and then we define a port that allows us to expose the process to the outside world, and finally, we run the application, in this case, Node ah leveraging ah an application file called server.js.
And this is a bit more of the same thing, but leveraging a visual reference. The container runtime is a client server application. The Docker command line uses and API to connect to the container runtime, and the container runtime actually performs all the work. When you execute a docker build, the container runtime builds an image from the Docker file that you’ve already defined, and then that image can be stored in a n- container registry, so it’s exc- s- er so it is accessible to other systems, and a container really is simply a runnable image, and when you perform a Docker run, it takes that image, unpacks it, the container runtime unpacks it, and executes it as a process, a process like any other process on your operating system.
And so, in conclusion, containers don’t really exist, but of course they’re abstractions, and like most abstractions, ah they have the ability to be very good or very bad, and in this case, ah container abstractions provide a lot of value, are and are really ah a pretty amazing technology. So w- even though containers don’t exist, long live containers.
Thank you for your time, and hopefully this provides a little bit of background ah that helps you understand a little bit more about what containers are, and how they work.
Have questions about the material in this lesson?
We’ve got answers!
Post your questions in the Kubernetes community Slack. Questions about this lesson are best suited for the #kubernetes-novice channel.
Not yet a part of the Kubernetes Slack community? Join the discussion here.
Have feedback about this course or lesson? We want to hear it!
Send your thoughts to KubeAcademy@VMware.com.