The rise of containers - the love and death of Docker and K8s

The rise of containers

For K8s to enable docker, as an ordinary developer, the feeling is that k8s is not the cluster operation of docker? The abandonment of docker by k8s is as unbelievable as fish against water. So what is the relationship between these two technologies, and how Kubernetes is decoupled from Docker step by step, please see below.

Module Guide: From Microservices to Cloud Native

What is Immutable Infrastructure

Hiding the complexity of distributed architecture from application code is a necessary prerequisite for distributed architecture to become a universal architecture style that can be widely promoted.

Definition of Cloud Native

The official definition is too abstract, so I will not copy and paste it. I choose to start with the containerization technology that we are all familiar with, at least visible and tangible.

Goals and types of virtualization

Containers are the common cornerstone of many core technologies in the software industry, such as cloud computing and microservices. The primary goal of the container is to change the process of software distribution and deployment from the traditional release of installation packages and manual deployment to the direct release of deployed virtualized images that contain the entire operating environment.

Operating System Layer Virtualization

Operating system layer virtualization, also known as containerization, is only a subset of virtualization. It can only provide partial ABI compatibility and complete environment compatibility above the operating system kernel.

introduction

As the beginning of the entire module, the purpose of our study in this lesson is to clarify what the "compatibility" of software operation refers to, and to understand what the concept of "virtualization" we often hear refers to. Only when these concepts are clarified and the context is unified, in the subsequent course study, our discussions on containers, orchestration, cloud native, etc. will not cause too much ambiguity.

Docker and K8s love each other

The Evolution of Cloud Native

In the next two lessons, I will take the development of containerization technology as a clue and take you to learn and understand container technology from the perspectives of isolation and packaging.

Today, we will first learn the premise preparation of the isolation technology in the Linux system, so as to lay a good foundation for understanding the idea of ​​"packaging applications with containers" in the next lesson.

Packaging system: LXC

When the file system, access, and resources can be isolated, the container already has all the pre-support conditions it needs to be born, and Linux developers have clearly seen this.

In 2008, when the Linux Kernel 2.6.24 kernel just started to provide cgroups, it immediately released a system-level virtualization function called Linux Containers (LinuX Containers, LXC).

As a result, LXC came on stage with an eye-catching aura. Its appearance prompted the "container" to gradually develop from a technical vocabulary that is only spread in the mouths of developers to a public concept and a common language of the entire software industry. Just like today's "server", "client" and "Internet".

The definition of container in the eyes of LXC is no different from that of OpenVZ and Linux-VServer. They are both a lightweight virtual machine that encapsulates the system, while the definition of container in the eyes of Docker is a technical means of packaging applications. There is no essential difference between these two packaging concepts at the technical level, but the difference in application effect is quite large.

Packaging application: Docker

Docker, which was announced as open source in 2013, is undoubtedly a milestone invention in the history of container development. However, Docker's success does not seem to be driven by much technology. At least for the early open source Docker, there is really no technology that can form a barrier.

In fact, its containerization capability is directly derived from LXC, and its image layered file system is directly derived from AUFS. Not long after Docker was open sourced, someone implemented Docker with just over a hundred lines of shell scripts. The core function of (named Bocker, which provides functions such as docker bulid/pull/images/ps/run/exec/logs/commit/rm/rmi).

Why use Docker instead of LXC? (Why would I use Docker over plain LXC?)

  • Green deployment across machines
  • Application-centric packaging
  • Automatic construction: Docker provides developers with full support for building products in containers. Developers do not need to pay attention to the specific configuration of the target machine, and can use any construction tool chain to automatically build the final product in the container.
  • Multi-version support: Docker supports managing successive versions of containers like Git, and performs operations such as checking differences between versions, submitting or rolling back. From the history, you can see how the container was built step by step, and only incrementally upload or download the changed parts in the new version.
  • Component reuse: Docker allows any existing container to be used as a base image to build more specialized images.
  • Sharing: Docker has a public mirror repository, where tens of thousands of Docker users have uploaded their own images, and also use images uploaded by others.
  • Tool ecology: Docker has opened up a set of interfaces that can be automated and self-extensible. On top of this, users can implement many tools to extend its functions, such as container arrangement, management interface, continuous integration, and so on.

In fact, what made Docker astounding the world as soon as it came out was not some black-tech secret weapon, but its creativity and design concept in line with the historical trend, as well as its fully open ecological operation. It can be seen that at the right time, the right person has an excellent idea, and there is indeed a chance to detonate an era.

== Same as chatgpt shell, huge demand, lowest threshold, resource-rich public warehouse ==

In 2014, Docker open-sourced libcontainer, developed by itself in Golang, which is a core module that bypasses LXC and directly operates namespaces and cgroups. With libcontainer, Docker can directly deal with the system kernel without relying on LXC to provide containerized isolation capabilities. up. (the predecessor of runC, we will talk about this later) (docker began to build its own technical barriers)

By 2015, under the leadership and initiative of Docker, a number of companies jointly formulated the "Open Container Initiative , OCI", which is a specification file on the container format and runtime, which includes runtime Standard (runtime-spec), container image standard (image-spec) and image distribution standard (distribution-spec, the distribution standard has not yet been officially released).

  • The runtime standard defines how to run a container, how to manage the state and life cycle of the container, and how to use the underlying features of the operating system (namespaces, cgroup, pivot_root, etc.);
  • The container image standard specifies the format, configuration, and metadata format of the container image, which you can understand as a static description of the image;
  • The image distribution standard stipulates the network interaction process of image push and pull.

Therefore, in order to comply with the OCI standard, Docker promotes its own architecture to continue to evolve.

**First of all, it separates libcontainer, encapsulates and reconstructs it into a runC project, and donates it to the Linux Foundation for management. **runC is the first reference implementation of OCI Runtime, which puts forward the slogan of "Make Standard Containers Available Everywhere".

In order to be compatible with all standard-compliant OCI Runtime implementations , Docker further refactored the Docker Daemon subsystem, abstracting the part that interacts with the runtime into the containerd project .

**This is a core module responsible for managing container execution, distribution, monitoring, network, construction, logging and other functions. It will create a containerd-shim adaptation process for each container runtime. **Works with runC by default , but it is also possible to switch to other OCI Runtime implementations (however, it is not actually done, and finally containerd is still tightly bound to runC).

Later, in 2016, Docker donated containerd to CNCF management.

It can be said that the donation hosting of the two projects runC and containerd not only reflects Docker's pursuit of open source beliefs, but also reflects Docker's helplessness to save itself under the attack of many cloud computing companies. These two projects will also become the future of Docker's demise. And the foreshadowing of survival (you will understand this contradictory statement by the end of this lesson).

2

Package cluster:

If Kubernetes is a container engine represented by Docker, it changes the software release process from distributing binary installation packages to directly distributing the entire virtualized operating environment, so that applications can be deployed greenly across machines; The container orchestration framework is to virtualize the cluster environment that large-scale software systems rely on, so that the cluster can realize green deployment across data centers, and can automatically expand and shrink according to actual conditions.

Although as early as 2013, Pivotal (the company holding the Spring Framework and Cloud Foundry) proposed the concept of "cloud native", but to achieve service, resilience (Resilience), elasticity (Elasticity), observability ( Observability) software system is still very difficult. At that time, it could only rely on the superb personal abilities of architects and programmers, and cloud computing itself could not help much.

However, in the cloud era, cloud computing vendors cannot fully utilize the powerful capabilities of the cloud, which makes cloud computing manufacturers extremely regretful and anxious.

So it can be said that until the birth of Kubernetes, everyone finally waited for the hope of breaking the situation, and recognized that this is the operating system of the cloud-native era, which is the best way for complex software to obtain resilience, elasticity, and observability under cloud computing. The path is also one of the key engines for manufacturers to accelerate the arrival of the cloud computing era.

Docker relies on an excellent concept, and it detonated an era with a "good idea". I believe that even if there is no Docker, there will be Cocker or Eocker, but it is indeed accidental that such a product was made by DotCloud, which was established only three years ago (and closed down three years later).

The success of Kubernetes is not only supported by Google's deep technical foundation and design concepts ahead of the times, but more importantly, the emergence of Kubernetes is in line with the vital interests of all major cloud computing companies and has extensive support from industry giants. Therefore, it Success is an inevitability.

3

The relationship between Kubernetes and Docker is very delicate, so we grasp the changing process of the relationship between the two, which is a good clue to understand the evolution of Kubernetes architecture and the specifications of CRI and OCI.

How is Kubernetes decoupled from Docker step by step?

In the perception of general users, k8s is a tool for managing and orchestrating many docker containers. Later, I heard that k8s will abandon docker. It feels incredible like a fish against water, but k8s slowly decouples docker as the version changes. , can be regarded as the history of cloud native development, which is of great significance for understanding the current k8s architecture. For me, the reason for spending more time here is that this process is exactly the same as that used to replace or upgrade an application or component in an enterprise-level architecture. Abstraction and refactoring during the replacement process are also the norm for large-scale applications. .

In the early days of Kubernetes open source, it was completely dependent on and bound to Docker, and did not think too much about the possibility of using other container engines in the future. Until Kubernetes 1.5, the way Kubernetes manages containers is through the internal DockerManager, which sends instructions to the Docker Engine in HTTP mode, and operates the addition, deletion, modification, and query of images through Docker, as shown by the arrow on the far right line in the above figure (the Kubelet is an agent program in the cluster nodes, responsible for communicating with the Master that manages the cluster, and the meaning of other nodes will be explained in the introduction below).

Now, we can straighten out the call relationship between Kubernetes and the container engine at this stage, and combine the refactored calls after Docker donated containerd and runC mentioned above to sort out the complete call chain together:

  • Kubernetes Master → kubelet → DockerManager → Docker Engine → containerd → runC

Then in 2016, Kubernetes version 1.5 began to introduce the "Container Runtime Interface" (Container Runtime Interface, CRI), which is a specification standard that defines how the container runtime should be connected to the kubelet. Since then, the DockerManager inside Kubernetes has been changed to Replaced by the general-purpose KubeGenericRuntimeManager (in fact, DockerManager can still be seen before 1.6.6), and the communication between kubelet and KubeGenericRuntimeManager is through the gRPC protocol.

However, since CRI is a specification released after Docker, Docker definitely does not support CRI, so Kubernetes also provides DockerShim service as an adaptation layer between Docker and CRI, which communicates with Docker Engine in the form of HTTP, thus realizing Full functionality of the original DockerManager.

At this point, Docker is just a default dependency for Kubernetes, not indispensable before, and their call chain is now:

  • Kubernetes Master → kubelet → KubeGenericRuntimeManager → DockerShim → Docker Engine → containerd → runC

Then in 2017, the CRI-O (Container Runtime Interface Orchestrator) project jointly sponsored by Google, RedHat, Intel, SUSE, and IBM released its first official version.

On the one hand, we can see from the name that it must be implemented in full compliance with the CRI specification; on the other hand, it can support all container engines that meet the OCI runtime standard, and it still works with runC by default. If It is no problem at all to switch to other OCI runtimes such as Clear Containers, Kata Containers, etc. (Part of the runtime interaction mentioned above is abstracted for the containerd project, which is responsible for managing the core modules of container execution, distribution, monitoring, network, construction, logging and other functions. It will create a containerd-shim suitable for each container runtime . configuration process )

But here, although the open source version of Kubernetes fully supports users to freely choose (according to the environment of the user's host machine) whether to use CRI-O, cri-containerd, or DockerShim as CRI implementation, but in RedHat's own extended custom Kubernetes enterprise Version, that is, in OpenShift 4, the call chain no longer has the presence of Docker Engine:

  • Kubernetes Master → kubelet → KubeGenericRuntimeManager → CRI-O → runC

Of course, because Docker still has an absolute advantage in the market share of container engines at this time, for ordinary users, if there is no clear benefit, there is no motivation to replace Docker with other engines. Therefore, even if CRI-O took a fierce posture to directly dig out the foundation of Docker, it actually did not bring much immediate and visible impact to Docker. However, we can imagine that Docker must be filled with an indescribable sense of crisis at this time.

The time continued to 2018. Containerd, donated by Docker to CNCF, released version 1.1 under the careful incubation of CNCF. The biggest difference between version 1.1 and version 1.0 is that it has perfectly supported the CRI standard at this time, which means that the original The cri-containerd used as the CRI adapter is no longer needed.

At this point, if we observe the call chain from Kubernetes to the container runtime, we will find that the call steps will be reduced by two steps compared with the steps of interacting with containerd through DockerShim, Docker Engine, which means that as long as the user is willing to abandon the Docker feelings, In terms of container orchestration, at least one HTTP call can be omitted to obtain performance benefits. And according to the test data officially given by Kubernetes, these free benefits are quite considerable.

In this way, Kubernetes announced support for containerd 1.1 from version 1.10, and the existence of Docker Engine can be completely erased in the call chain:

Kubernetes Master → kubelet → KubeGenericRuntimeManager → containerd → runC

Today, which container runtime to use depends on the container runtime environment on the host machine when you install Kubernetes, but for cloud computing vendors, such as domestic Alibaba Cloud ACK, Tencent Cloud TKE, etc. directly provide In the Kubernetes container environment, the container runtime used is generally containerd. After all, the operating performance is the core productivity and competitiveness for them.

Draw a timeline diagram to describe it, and it will be clear when combined with the call diagram.

summary

After learning this lesson, we can try to make a judgment: in the future, with the continuous development and growth of Kubernetes, it will be a high probability event that Docker Engine will experience from indispensable, default dependency, optional, until eliminated. On the surface, this matter is the joint effort of cloud computing giants such as Google and RedHat, but it is the trend of technological development that actually eliminates it. It's like Docker relied on LXC when it was born, and finally replaced LXC with libcontainer.

At the same time, we should also see the other side of the matter: even LXC has not died yet, but has developed LXD that is more focused on competing with system-level virtualization such as OpenVZ. It is believed that Docker itself is difficult to completely die out. Yes, the CLI interface that has become a habit, the mirror warehouse that has formed a mature ecology, etc., should exist for a long time, but in the field of container arrangement, the future Docker is likely to exist only in the form of runC and containerd. After all, they initially All stem from the blood of Docker.

One Lesson, One Thought

In early January 2021, Kubernetes announced that it will remove Dockershim from Kubelet in version v1.23, so how do you see the future development of containerization?

Guess you like

Origin blog.csdn.net/wdays83892469/article/details/129945509