当前位置: 欣欣网 > 码农

【运维干货分享】什么是容器,它是如何工作的?

2024-07-27码农


container

如果想了解什么是容器以及它们如何工作?

这篇文章解释了容器化的基础知识,包括定义、优点和用例。

如果你刚了解容器世界,那么学习基础知识至关重要。

这将帮助你有效地学习Docker等工具和Kubernetes等编排工具

我们先从linux容器聊起。

什么是容器?

在典型的虚拟化环境中,一个或多个虚拟机使用 Xen、Hyper-V 等虚拟机管理程序运行在物理服务器之上。

另一方面,容器运行在操作系统内核之上。可以将其称为操作系统级虚拟化。在了解底层容器概念之前,需要了解两个关键的 Linux 概念。

用户空间

用户空间:运行用户程序(应用程序、进程)所需的所有代码称为用户空间。当您启动程序操作(例如创建文件)时,用户空间中的进程会对内核空间进行系统调用。

内核空间

内核空间:这是操作系统的核心,其中包含内核代码,与系统硬件、存储等进行交互。

容器进程隔离

当启动一个应用程序(例如 Nginx Web 服务器)时,实际上是在启动一个进程。进程是一组独立的指令,具有有限的隔离性。

但是,如果可以隔离该进程以及仅运行和操作该进程所需的文件和配置,该怎么办?这正是容器的作用。

通过为流程创建隔离的环境,容器可以在不同系统之间实现更高的安全性、一致性和可移植性。

当容器启动时,它会在主机操作系统的内核中启动一个进程。然而,值得注意的是,容器不仅仅是一个进程——它可以包含并行运行的多个进程和服务,所有这些都在同一个隔离环境中。

因此,虽然容器确实作为一个进程启动,但它并不仅限于单个进程。它是一个更复杂的系统,可以包含多个流程和服务,使其成为软件开发和部署的更通用的解决方案。

例如,当启动 Nginx 服务时,它会启动一个 Nginx 父进程,该进程会生成缓存管理器、缓存加载器和工作进程等子进程

启动 Nginx 容器时,将在其自己的隔离环境中启动主 Nginx 进程。

每个容器都有自己独立的用户空间,可以在单个主机上运行多个容器。然而,需要注意的是,容器并不拥有整个操作系统。

与具有自己的内核的虚拟机不同,容器仅包含与特定发行版相关的必要文件,并使用共享的主机内核。

事实上,可以在单个主机上运行基于不同 Linux 发行版的容器,所有容器共享相同的内核空间。这使得容器成为在隔离环境中运行应用程序的轻量级且高效的解决方案。

例如,可以在 Ubuntu 服务器上运行基于 RHEL、CentOS 或 SUSE 的容器。这是因为 Linux 发行版之间的唯一区别是用户空间,而内核空间保持不变

容器是单进程嘛?

一个容器可以有多个父进程吗?

不可以,一个容器不能有多个父进程。容器运行一个主进程,该进程在容器启动时启动。主进程负责启动和管理容器需要运行的任何子进程。

为什么只有一个父进程?

容器主要设计为每个容器运行一个进程。

这样做的原因是为了促进隔离并保持容器的稳定性。当单个进程在容器中运行时,与该进程相关的任何更改或问题只会影响运行该进程的容器,而不会影响其他容器或主机系统。

例如,假设想要运行一个带有 Web 服务器和数据库的 Web 应用程序。我们不需要在单个容器中运行 Web 服务器和数据库,而是需要在同一主机上的单独容器中运行它们。

例如,如果 Web 服务器代码中存在错误或漏洞,它不会影响其他容器或主机系统,因为 Web 服务器在容器内是隔离的。

同样,如果对 Web 服务器配置或设置进行更改,它只会影响运行该进程的容器,而不会影响其他容器或主机系统。这促进了容器的隔离性和可维护性,使其更易于管理和部署。

是否可以在容器内运行多个进程?

通过运行进程管理器(例如supervisord)可以在容器内运行多个进程。

进程管理器充当容器的主进程,它可以生成和管理多个子进程。这允许多个服务或进程在单个容器内运行,但它们全部由单个父进程(进程管理器)管理。

命名空间和控制组

容器的隔离是通过使用两个关键的 Linux 内核功能来实现的

  • namespaces

  • cgroup

  • 这个概念在现实世界中的一个有用的类比是公寓楼。虽然它是一栋大型建筑,但每个公寓或公寓都是独立的,每个家庭都有自己的身份和计量公用设施。这种隔离是通过使用混凝土、钢结构和其他材料来实现的。除非被邀请进入,否则您无法看到其他房屋的内部。

    同样,在具有多个容器的单个主机中,您需要将容器与其自己的CPU、内存、IP地址、挂载点和进程隔离。这是通过使用 Linux 内核中的命名空间和控制组来实现的。

    Linux 命名空间

    容器就是拥有一个良好隔离的环境来运行服务(进程)。

    为了实现这种级别的隔离,容器应该有其文件系统、IP 地址、挂载点、进程 ID 等。这可以使用 Linux 命名空间来实现。Linux 命名空间概念被添加到 Linux 内核版本 2.4.19 中,该版本于 2002 年 12 月 18 日发布。这是 Wikipedia 关于 Linux 命名空间的描述。

    命名空间是 Linux 内核的一项功能,它对内核资源进行分区,以便一组进程看到一组资源,而另一组进程看到一组不同的资源。

    Linux 中的关键命名空间包括:

  • PID namespace 负责隔离进程(PID:进程ID)

  • Network namespace 管理网络接口(NET:网络)

  • IPC namespace 管理对IPC资源的访问(IPC:进程间通信)

  • Mount namespace 负责管理文件系统挂载点(MNT:Mount)

  • uts namespace 隔离内核和版本标识符(UTS:Unix 分时系统)

  • usr namespace 隔离用户 ID,这意味着它将主机和容器之间的用户 ID 分开。

  • Control Group namespace 将控制组信息与容器进程隔离。

  • 使用这些命名空间,容器可以拥有其网络接口、IP 地址等。每个容器都有其名称空间,并且在该名称空间内运行的进程不会拥有其外部的任何特权。

    本质上,命名空间为容器设置边界。

    有趣的是,您可以使用 lsns 命令列出 Linux 计算机中的命名空间。

    lsns

    Linux 控制组

    在 Linux 系统上启动服务不需要指定任何内存或 CPU 限制。内核自动分配资源并为正在运行的服务确定优先级。

    但是,如果想对服务的 CPU 和内存使用情况设置明确的限制,则可以使用称为控制组 (CGroup) 的 Linux 内核功能。

    当在一台主机上运行多个容器时,这一点特别有用,因为它可以确保一个容器不会过度利用资源而牺牲其他容器的资源。

    CGroup 管理容器使用的资源,并允许您限制容器的 CPU、内存、网络和 I/O 资源。如果没有资源限制,单个容器可能会使用所有可用的主机资源,从而导致其他容器资源不足并导致它们崩溃。

    值得庆幸的是,像 Docker 这样的工具通过抽象出复杂的后端配置来简化设置资源限制的过程。

    借助 Docker,您可以使用简单的参数轻松指定 CPU 和内存限制,确保容器高效可靠地运行。

    容器的演变

    尽管有些人可能这么认为,容器化并不是一项新技术。事实上,谷歌多年来一直在其基础设施中使用容器技术。容器的概念实际上可以追溯到 20 世纪 70 年代,当时引入了 chroot,这是一个允许更改进程根目录的概念。从那时起,开发了许多基于容器的项目,其中一些早在 2000 年就开始了。

    容器与虚拟机

    下图显示了容器和虚拟机之间的主要区别。

    与虚拟机 (VM) 相比,容器具有多种优势,使其成为部署应用程序的热门选择:

    资源利用和成本:

    虚拟机允许独立运行应用程序,但它们可能未得到充分利用,并且为生产应用程序调整虚拟机的大小可能具有挑战性。

    相比之下,容器需要最少的 CPU 和内存资源,并且可以在虚拟机内运行多个容器,以实现更好的应用程序隔离。调整容器大小只需几秒钟,使其更加高效且更具成本效益。

    配置和部署:

    配置虚拟机并在其上部署应用程序可能需要几分钟到几小时,具体取决于所涉及的工作流程。即使回滚更改也需要时间。相比之下,容器可以秒级部署,回滚也同样快,更加敏捷高效。

    漂移管理

    管理虚拟机中的偏差很困难,需要大量的自动化和流程来确保所有环境都是相似的。然而,遵循不可变的部署模型可以防止虚拟机环境中的偏差。另一方面,容器只需要更新容器映像即可进行更改。通过对开发环境进行更改并重新烘焙容器镜像,可以确保所有环境中使用相同的镜像。这使得管理漂移变得更容易、更高效。

    结论

    我们了解了容器的核心基础以及它与虚拟机的不同之处。接下来我们就可以开始使用以下教程

  • 什么是 Docker 以及它是如何工作的?

  • 如何构建 Docker 镜像并运行 Docker 容器?

  • 如何优化Docker镜像?

  • 翻译自:https://devopscube.com/what-is-a-container-and-how-does-it-work/