成人容器(第01部分):术语实用指南

您可能会问,如果容器的概念看起来非常简单明了,为什么还要处理术语呢? 但是,经常错误地使用术语会阻碍容器的发展。 例如,人们通常认为“容器”和“图像”这两个术语可以互换使用,尽管实际上它们之间存在重要的概念差异。 另一个例子:在容器世界中,“存储库”并不代表您的想法。 此外,容器技术不仅仅是docker。



因此,在不了解术语的情况下,很难理解docker与CRI-O,rkt或lxc / lxd有何不同; 或评估开放容器计划在标准化容器技术中的作用。

引言


Linux容器入门非常简单,但是很快就发现这种简单性令人误解。 这通常是这样的:仅花了几分钟安装docker或其他容器引擎后,您已经输入了第一个命令。 只需几分钟-您已经创建了该容器的第一个映像,并将其放入了公共领域。 然后,您习惯性地转到生产环境的体系结构,然后突然意识到,为此,您需要首先处理所有这些背后的术语和技术。 更糟糕的是,下面列出的许多术语可以互换使用,这给初学者造成了很多困惑。

  • 货柜
  • 图片
  • 容器图片
  • 影像层
  • 登记处
  • 资料库
  • 标签
  • 基本图片
  • 平台图片
  • 层数

掌握了本文档中阐述的术语后,您将更好地了解容器的技术基础。 此外,它将帮助您和您的同事说相同的语言,并根据要解决的任务的具体情况有意识地,有目的地设计容器环境的体系结构。 反过来,从IT社区和整个行业的角度来看,对容器技术的普遍了解有助于新架构和解决方案的出现。 请注意,本文适用于已经了解如何运行容器的读者。

容器:基础知识


在继续使用容器术语之前,我们将确定实际上是容器本身的东西。 术语“容器”一次意味着两件事。 像常规的Linux程序一样,容器可以处于以下两种状态之一:工作状态和非工作状态。 在空闲状态下,容器是磁盘上存储的一个文件或一组文件。 术语“容器映像”和“容器存储库”就是这种状态。 输入容器启动命令时,容器引擎将解压缩必要的文件和元数据并将其传输到Linux内核。 启动容器与启动常规Linux进程非常相似,并且需要对Linux内核进行API调用。 此API调用通常会启动附加隔离,并挂载容器映像中文件的副本。 启动容器后,它只是一个Linux进程。 启动容器的过程以及磁盘上存储的容器映像的格式由标准定义和规范。

容器映像有多种格式( DockerAppcLXD ),但是行业正在逐渐朝着单一的“ 开放容器倡议”标准(有时称为“开放容器”或简称OCI)发展。 该标准定义了容器映像格式规范,该规范定义了用于存储容器映像的磁盘格式以及元数据,而元数据又定义了诸如硬件体系结构和操作系统(Linux,Windows等)之类的内容。 单一行业范围的图像格式是创建软件生态系统的关键,该软件生态系统允许开发人员,开放源代码项目和软件供应商创建兼容的图像和各种工具,例如电子签名,扫描,组装,启动,移动和管理容器图像。

此外,还有几种容器引擎,例如DockerCRI-ORailcarRKTLXC 。 容器引擎获取容器的图像并将其转换为容器(即运行过程)。 转换过程也由OCI标准定义,该标准包括容器运行时规范和称为RunC的运行时引用实现,RunC是由适当的开发社区监管的开源模型。 创建容器时,许多容器引擎都使用此模型与主机内核进行交互。

支持容器映像格式规范和OCI标准的容器执行环境的工具可在各种容器平台,容器引擎以及各种云平台和本地体系结构上的支持工具的生态系统内实现可移植性。 了解容器系统的术语,标准和体系结构将使您能够与其他专家进行富有成效的交流,并设计可扩展且受支持的容器化应用程序和环境,以确保在未来几年内容器的有效使用。

基本词汇


容器图片


在最简单的定义中,容器映像是从注册表服务器下载的文件,并且在容器启动时在本地用作安装点。 尽管经常使用“容器映像”一词,但这可能意味着不同的含义。 事实是,尽管Docker,RKT甚至LXD都按照刚刚描述的原理工作-即它们下载已删除的文件并将其作为容器运行-这些技术中的每一种都以自己的方式解释了容器映像。 LXD使用单片(单层)映像进行操作,而docker和RKT使用OCI映像,该映像可以包含多个层。

严格来说,注册表服务器上的容器映像不是单个文件。 人们使用“容器映像”一词时,通常指的是存储库,并表示一组多层容器映像,以及包含有关这些层的其他信息的元数据。

另外,容器图像的概念暗含暗示了这种图像的格式的存在。

容器图片格式


最初,每个容器引擎(包括LXD,RKT和Docker)都有自己的映像格式。 其中一些格式仅允许一层,而其他格式则支持多层的树结构。 如今,几乎所有主要的容器工具和引擎都已转换为OCI格式,该格式决定了应如何在容器映像中排列图层和元数据。 本质上,OCI格式定义了一个容器映像,该映像由用于每个层的单独的tar文件和一个包含元数据的通用manifest.json文件组成。

开放容器倡议(OCI)标准最初基于Docker V2图像格式 ,已成功地将容器引擎,云平台和工具(安全扫描器,签名工具,创建和移动容器)的大型生态系统成功组合在一起,并允许您保护知识和技术方面的投资工具。

集装箱发动机


容器引擎是软件的一部分,它接受用户请求,包括命令行参数,下载图像,并从最终用户的角度出发,启动容器。 有很多容器引擎,包括docker,RKT,CRI-O和LXD。 此外,许多云平台,PaaS服务和容器平台都有自己的引擎,这些引擎可以理解Docker或OCI格式的映像。 具有图像格式的行业标准可确保所有这些平台的互操作性。

概括地说,我们可以说大多数容器引擎实际上并不启动容器本身,而是通过与OCI兼容的运行时启动,例如runc。 通常,容器运行时会执行以下操作:

  • 处理参数,用户输入
  • 处理通过API传递的参数(通常是容器编排系统)
  • 从注册表服务器下载容器映像
  • 使用图形驱动程序(块或文件,取决于驱动程序)将容器映像解压缩并将其保存到磁盘
  • 为容器准备安装点,通常在写时复制存储中(再次,块或文件,具体取决于驱动程序)
  • 使用以下方法准备要传递给运行时以正确运行容器的元数据:
    • 容器映像隐含的特定默认设置(例如ArchX86
    • 用户输入以覆盖容器映像中包含的默认值(例如,CMD,ENTRYPOINT)
    • 容器映像指定的默认参数(例如, SECCOM规则)
  • 调用容器运行时

货柜


容器在操作系统中已经存在了一段时间,因为实际上这只是容器映像的运行实例。 容器是标准的Linux进程,通常使用clone()系统调用而不是fork()或exec()创建。 另外,通常使用cgroupsSELinuxAppArmor将其他隔离措施应用于容器。

集装箱主机


容器主机是运行容器化进程的系统,为简单起见,通常将其称为容器。 例如,这可以是位于公共云中或在公司数据中心的裸机上运行的RHEL Atomic Host虚拟机。 当注册表服务器中的容器映像(换句话说,存储库)下载到本地容器主机时,他们说它属于本地缓存。

您可以使用以下命令确定哪些存储库与本地缓存同步:

  [root @ rhel7〜]#docker images -a

储存标签图像ID的虚拟尺寸
 Registry.access.redhat.com/rhel7最新6883d5422f4e 3周前201.7 MB 

注册表服务器


注册表服务器本质上是一个文件服务器,用于存储Docker存储库。 通常,注册表服务器由DNS名称以及(可选)端口号指定。 Docker生态系统的大多数好处是由将存储库下载和上传到注册表服务器的能力驱动的。

如果docker守护程序在本地缓存中找不到存储库的副本,它将自动从注册表服务器下载。 在大多数Linux发行版中,docker守护进程将为此使用docker.io站点,但是在某些发行版中,可以按自己的方式进行配置。 例如,红帽企业Linux首先尝试从registry.access.redhat.com下载,然后才尝试从docker.io(Docker Hub)下载。

在此必须强调,注册表服务器被隐式认为是可信的。 因此,您必须确定您对注册表内容的信任程度,并分别允许或拒绝它。 除安全性外,还有其他方面应事先解决,例如,软件许可问题或合规性监视。 docker允许用户下载软件的简单性使得信任问题变得非常重要。

红帽企业Linux允许您配置默认的Docker注册表。 此外,RHEL7和RHEL7 Atomic允许您通过配置文件添加或锁定注册表服务器:

  vi / etc / sysconfig /泊坞窗

RHEL7和RHEL 7 Atomic默认使用Red Hat注册表服务器:

  ADD_REGISTRY ='-添加注册表Registry.access.redhat.com'

在某些情况下,出于安全原因,阻止公共docker注册表(例如DockerHub)是有意义的:

  #BLOCK_REGISTRY ='-块注册表'

红帽还提供其集成注册表服务器作为OpenShift容器平台的一部分 ,以及独立的公司注册表服务器Quay Enterprise和云,私有和公共存储库Quay.io。

容器编排


人们通常从安装容器主机开始,首先只是下载他们需要的容器映像。 然后,他们继续创建自己的映像,并将其上传到注册表服务器,以供团队其他成员使用。 一段时间后,需要组合多个容器,以便可以将它们作为一个单元部署。 最后,在某些时候,必须将这些单元作为生产传送带的一部分(开发-QA生产)。 人们通常是这样认识到他们需要编排系统的。

容器编排系统仅实现两件事:

  1. 在群集计算机之间动态分配容器负载(这通常称为“分布式计算”)
  2. 提供标准的应用程序描述文件(kube yaml,docker compose等)

这两件事实际上提供了一系列好处:

  1. 彼此独立管理组成应用程序的容器的能力,使您可以有效地解决以下任务:
    • 处置大型容器主机集群
    • 单个容器级别的故障(不再响应进程,内存耗尽)
    • 容器主机级别的故障转移(驱动器,网络,重新启动)
    • 容器引擎级别的故障转移(损坏,重新启动)
    • 分别缩放容器的大小
  2. 易于在云和传统环境中的新环境中部署同一应用程序的新实例,例如:
    • 在业务流程系统控制的显影机上
    • 在私有名称空间的共享开发环境中
    • 在内部公共命名空间的通用开发环境中,以确保可见性和测试性能
    • 在质量检查的内部环境中
    • 在测试负载环境中动态提供并撤消云中
    • 在参考环境中验证与生产环境的兼容性
    • 在生产环境中
    • 在灾难恢复环境中
    • 在包含更新的容器主机,容器引擎或编排工具的新生产环境中
    • 在新的生产环境中,与主要生产环境没有什么不同,但是位于不同的区域

开源社区和软件供应商提供了许多不同的编排工具。 最初,其中三大工具包括SwarmMesosKubernetes ,但如今Kubernetes实际上已成为行业标准,因为甚至DockerMesosphere都宣布了对它们的支持,更不用说几乎所有主要的服务提供商了。 但是,如果您正在寻找公司的业务流程系统,我们建议您仔细查看Red Hat OpenShift

高级词典


容器运行时


容器运行时是一个低级组件,通常用作容器引擎的一部分,但也可以手动用于测试容器。 OCI标准定义了运行时的参考实现,称为runc 。 这是使用最广泛的实现,但是还有其他与OCI兼容的运行时,例如crunrailcarkatacontainer 。 Docker,CRI-O和许多其他容器引擎都使用runc。

容器运行时负责以下事项:

  • 获取容器引擎提供的容器的安装点(为了进行测试,它可能只是一个目录)
  • 获取容器引擎提供的容器元数据(在测试过程中,这可能是手动组装的config.json文件)
  • 与OS内核通信以启动容器化的进程(通过克隆系统调用)
  • 配置cgroup
  • 配置SELinux策略
  • 配置App Armor规则

有点历史上的题外话:当Docker引擎首次出现时,它使用LXC作为运行时环境。 然后,Docker开发人员为运行容器编写了自己的库,称为libcontainer。 它是用Golang语言编写的,并成为Docker引擎的一部分。 在建立OCI组织之后,Docker将源代码libcontainer引入了该项目,并将该库作为一个独立的实用程序runc发布,该实用程序随后成为OCI标准内容器运行时的参考实现,并在其他容器引擎(例如CRI-O)中使用。 Runc是一个非常简单的实用程序,它仅等待将安装点(目录)和元数据(config.json)传递给它。 有关runc的更多信息,请参见此处

要更深入地了解,请参阅了解容器标准容器运行时

图像层


存储库通常被称为容器的图像或图像,尽管实际上存储库由一层或多层组成。 存储库中的图像层通过父子关系相互连接,并且每个图像层都包含与父层的差异。

让我们看一下本地容器主机上的存储库层。 从1.7版本开始,Docker就没有内置的工具来查看本地存储库中的图像层 (但是有用于在线注册的工具),我们将使用Dockviz实用程序。 请注意,每个层都有一个标记和一个通用唯一标识符(UUID) 。 要查看通常在同一台计算机上唯一的缩写UUID,我们使用以下命令(如果需要完整的UUID,请使用带有-no-trunc选项的同一命令):

docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock nate / dockviz images -t

  ├─2332d8973c93虚拟大小:187.7 MB
  │└─ea358092da77虚拟大小:187.9 MB
  │└─a467a7c6794f虚拟大小:187.9 MB
  │└─ca4d7b1b9a51虚拟大小:187.9 MB
  │└─4084976dd96d虚拟大小:384.2 MB
  │└─943128b20e28虚拟大小:386.7 MB
  │└─db20cc018f56虚拟大小:386.7 MB
  │└─45b3c59b9130虚拟大小:398.2 MB
  │└─91275de1a5d7虚拟大小:422​​.8 MB
  │└─e7a97058d51f虚拟大小:422​​.8 MB
  │└─d5c963edfcb2虚拟大小:422​​.8 MB
  │└─5cfc0ce98e02虚拟大小:422​​.8 MB
  │└─7728f71a4bcd虚拟大小:422​​.8 MB
  │└─0542f67da01b虚拟大小:422​​.8 MB标签:docker.io/registry:最新

如您所见,docker.io/registry存储库实际上由许多层组成。 但是,更重要的是,原则上用户可以从此阶梯中的任何步骤``启动''容器,例如通过输入以下命令(这是完全正确的,但没有人可以保证已经对其进行了测试或可以完全正常工作)。 通常,图像收集器标记(创建名称)应该用作起点的那些层:

  docker运行-it 45b3c59b9130 bash

存储库的排列方式类似,因为只要收集器创建新图像,差异就会另存为另一层。 在存储库中创建新层的主要方法有两种。 首先,当手动创建图像时,每个更改确认都会创建一个新层。 如果收集器使用Docker文件创建映像,则文件中的每个指令都会创建一个新层。 因此,始终能够查看层之间存储库中发生的更改总是很有用的。

标签


尽管用户本人可以指定用于在存储库中安装和启动容器的起始层,但他根本不需要这样做。 当图像收集器创建新的存储库时,它们通常会标记最适合此角色的图层。 这些标记称为标签,代表图像收集器可用来告知图像使用者哪些层最适合使用的工具。 通常,标签用于指示存储库中的软件版本。但是,OCI和任何其他标准都没有规范标签的使用,这为协作期间的混乱开辟了无限的范围。因此,如果标签不仅用于标记软件版本,我们建议仔细记录标签。

此外,还有一个特殊标签-最新标签,通常指向存储库中包含最新软件的层。像任何其他标签一样,该标签仅指向图像层,因此也可能被错误地使用。

要远程查看存储库中可用的标记,请运行以下命令(jq实用程序使输出更具可读性):

卷曲-s Registry.access.redhat.com/v1/repositories/rhel7/tags | q
 {
 "7.0-21": "e1f5733f050b2488a17b7630cb038bfbea8b7bdfa9bdfb99e63a33117e28d02f",
 "7.0-23": "bef54b8f8a2fdd221734f1da404d4c0a7d07ee9169b1443a338ab54236c8c91a",
 "7.0-27": "8e6704f39a3d4a0c82ec7262ad683a9d1d9a281e3c1ebbb64c045b9af39b3940",
 "7.1-11": "d0a516b529ab1adda28429cae5985cab9db93bfd8d301b3a94d22299af72914b",
 "7.1-12": "275be1d3d0709a06ff1ae38d0d5402bc8f0eeac44812e5ec1df4a9e99214eb9a",
 "7.1-16": "82ad5fa11820c2889c60f7f748d67aab04400700c581843db0d1e68735327443",
 "7.1-24": "c4f590bbcbe329a77c00fea33a3a960063072041489012061ec3a134baba50d6",
 "7.1-4": "10acc31def5d6f249b548e01e8ffbaccfd61af0240c17315a7ad393d022c5ca2",
 “ 7.1-6”:“ 65de4a13fc7cf28b4376e65efa31c5c3805e18da4eb01ad0c8b8801f4a10bc16”,
 “ 7.1-9”:“ e3c92c6cff3543d19d0c9a24c72cd3840f8ba3ee00357f997b786e8939efef2f”,
 “ 7.2”:“ 6c3a84d798dc449313787502060b6d5b4694d7527d64a7c99ba199e3b2df834e”,
 “ 7.2-2”:“ 58958c7fafb7e1a71650bc7bdbb9f5fd634f3545b00ec7d390b2075db511327d”,
 “ 7.2-35”:“ 6883d5422f4ec2810e1312c0e3e5a902142e2a8185cd3a1124b459a7c38dc55b”,
 “ 7.2-38”:“ 6c3a84d798dc449313787502060b6d5b4694d7527d64a7c99ba199e3b2df834e”,
 “最新”:“ 6c3a84d798dc449313787502060b6d5b4694d7527d64a7c99ba199e3b2df834e”
  }

资料库


使用docker命令时,在命令行上指定存储库而不是映像。例如,在下面的命令rhel7中,这是存储库。

 docker pull rhel7

实际上,此命令会自动扩展为以下内容:

 码头工人拉注册表.access.redhat.com / rhel7:latest

但是,许多人认为这是容器的图像或图像。实际上,为了获取本地可访问存储库的列表,使用了docker images子命令。正式地,这些存储库可以看作是容器的图像,但重要的是要清楚地了解这些存储库实际上是由图层组成的,并包含一个称为“清单”(manifest.json)的文件中包含的元数据:

 码头工人图像

储存标签图像ID的虚拟尺寸
 Registry.access.redhat.com/rhel7最新6883d5422f4e 4周前201.7 MB
 Registry.access.redhat.com/rhel最新6883d5422f4e 4周前201.7 MB
 Registry.access.redhat.com/rhel6最新05c3d56ba777 4周前166.1 MB
 registry.access.redhat.com/rhel6/rhel latest 05c3d56ba777 4 weeks ago 166.1 MB
  ...

, . docker ( , ) , «rhel7» .

, docker URL. , , URL .



, :

 REGISTRY/NAMESPACE/REPOSITORY[:TAG]

完整的URL包含服务器名称,名称空间以及可选的标签。实际上,在指定URL时有很多细微差别,并且在探索docker生态系统时,您会发现很多事情都是可选的。特别是,请看下面的命令:所有命令都是正确的,并导致相同的结果:

 码头工人拉注册表.access.redhat.com / rhel7 / rhel:latest
 码头工人拉注册表.access.redhat.com / rhel7 / rhel
 码头工人拉注册表.access.redhat.com / rhel7
 docker pull rhel7 / rhel:最新

命名空间


命名空间是用于将存储库拆分为组的工具。DockerHub公共注册表中,名称空间通常是共享映像的用户的名称,但也可以是组名或逻辑名。

红帽使用名称空间按红帽联合注册表服务器上列出的产品来分隔存储库组下面提供了一个来自registry.access.redhat.com的民意调查示例。请注意,此示例中的最后一行实际上指向其他注册表服务器。这是由于Red Hat正在努力在合作伙伴的注册表服务器上显示存储库:

 Registry.access.redhat.com/rhel7/rhel
Registry.access.redhat.com/openshift3/mongodb-24-rhel7
Registry.access.redhat.com/rhscl/mongodb-26-rhel7
Registry.access.redhat.com/rhscl_beta/mongodb-26-rhel7
注册表-mariadbcorp.rhcloud.com/rhel7/mariadb-enterprise-server:10.0

请注意,有时可能未指定完整的URL。在上面的示例中,每个名称空间都有一个默认存储库。如果用户仅指定fedora命名空间,则具有最新标签的存储库将下载到本地服务器。因此,以下命令导致相同的结果:

 码头工人拉软呢帽
docker pull docker.io/fedora
docker pull docker.io/library/fedora:latest

内核命名空间


, , . , , , , , . , , , . .

Bash Enter, Bash Linux- exec() . , , docker, docker , clone() . clone () , , , , , ..

, Linux - , clone ().


Source: https://habr.com/ru/post/zh-CN416169/


All Articles