分类 容器与云 下的文章

通过深入了解容器运行时,理解容器环境是如何建立的。

 title=

在学习 容器镜像 时,我们讨论了容器的基本原理,但现在是深入研究容器 运行时 runtime 的时候了,从而了解容器环境是如何构建的。本文的部分信息摘自 开放容器计划 Open Container Initiative (OCI)的 官方文档,所以无论使用何种容器引擎,这些信息都是一致的。

容器运行机制

那么,当你运行 podman rundocker run 命令时,在后台到底发生了什么?一个分步的概述如下:

  1. 如果本地没有镜像,则从镜像 登记仓库 registry 拉取镜像
  2. 镜像被提取到一个写时复制(COW)的文件系统上,所有的容器层相互堆叠以形成一个合并的文件系统
  3. 为容器准备一个挂载点
  4. 从容器镜像中设置元数据,包括诸如覆盖 CMD、来自用户输入的 ENTRYPOINT、设置 SECCOMP 规则等设置,以确保容器按预期运行
  5. 提醒内核为该容器分配某种隔离,如进程、网络和文件系统( 命名空间 namespace
  6. 提醒内核为改容器分配一些资源限制,如 CPU 或内存限制( 控制组 cgroup
  7. 传递一个 系统调用 syscall 给内核用于启动容器
  8. 设置 SELinux/AppArmor

容器运行时负责上述所有的工作。当我们提及容器运行时,想到的可能是 runc、lxc、containerd、rkt、cri-o 等等。嗯,你没有错。这些都是容器引擎和容器运行时,每一种都是为不同的情况建立的。

容器运行时 Container runtime 更侧重于运行容器,为容器设置命名空间和控制组(cgroup),也被称为底层容器运行时。高层的容器运行时或容器引擎专注于格式、解包、管理和镜像共享。它们还为开发者提供 API。

开放容器计划(OCI)

开放容器计划 Open Container Initiative (OCI)是一个 Linux 基金会的项目。其目的是设计某些开放标准或围绕如何与容器运行时和容器镜像格式工作的结构。它是由 Docker、rkt、CoreOS 和其他行业领导者于 2015 年 6 月建立的。

它通过两个规范来完成如下任务:

1、镜像规范

该规范的目标是创建可互操作的工具,用于构建、传输和准备运行的容器镜像。

该规范的高层组件包括:

2、运行时规范

该规范用于定义容器的配置、执行环境和生命周期。config.json 文件为所有支持的平台提供了容器配置,并详细定义了用于创建容器的字段。在详细定义执行环境时也描述了为容器的生命周期定义的通用操作,以确保在容器内运行的应用在不同的运行时环境之间有一个一致的环境。

Linux 容器规范使用了各种内核特性,包括 命名空间 namespace 控制组 cgroup 权能 capability 、LSM 和文件系统 隔离 jail 等来实现该规范。

小结

容器运行时是通过 OCI 规范管理的,以提供一致性和互操作性。许多人在使用容器时不需要了解它们是如何工作的,但当你需要排除故障或优化时,了解容器是一个宝贵的优势。

本文基于 techbeatly 的文章,并经授权改编。


via: https://opensource.com/article/21/9/container-runtimes

作者:Nived V 选题:lujun9972 译者:geekpi 校对:turbokernel

本文由 LCTT 原创编译,Linux中国 荣誉推出

容器镜像包含一个打包的应用,以及它的依赖关系,还有它在启动时运行的进程信息。

 title=

容器是当今 IT 运维的一个关键部分。 容器镜像 container image 包含了一个打包的应用,以及它的依赖关系,还有它在启动时运行的进程信息。

你可以通过提供一组特殊格式的指令来创建容器镜像,可以是提交给 注册中心 Registry ,或者是作为 Dockerfile 保存。例如,这个 Dockerfile 为 PHP Web 应用创建了一个容器:

FROM registry.access.redhat.com/ubi8/ubi:8.1

RUN yum --disableplugin=subscription-manager -y module enable php:7.3 \
  && yum --disableplugin=subscription-manager -y install httpd php \
  && yum --disableplugin=subscription-manager clean all

ADD index.php /var/www/html

RUN sed -i 's/Listen 80/Listen 8080/' /etc/httpd/conf/httpd.conf \
  && sed -i 's/listen.acl_users = apache,nginx/listen.acl_users =/' /etc/php-fpm.d/www.conf \
  && mkdir /run/php-fpm \
  && chgrp -R 0 /var/log/httpd /var/run/httpd /run/php-fpm \
  && chmod -R g=u /var/log/httpd /var/run/httpd /run/php-fpm

EXPOSE 8080
USER 1001
CMD php-fpm & httpd -D FOREGROUND

这个文件中的每条指令都会在容器镜像中增加一个 layer 。每一层只增加与下面一层的区别,然后,所有这些堆叠在一起,形成一个只读的容器镜像。

它是如何工作的?

你需要知道一些关于容器镜像的事情,按照这个顺序理解这些概念很重要:

  1. 联合文件系统
  2. 写入时复制(COW)
  3. 叠加文件系统
  4. 快照器

联合文件系统

联合文件系统 Union File System (UnionFS)内置于 Linux 内核中,它允许将一个文件系统的内容与另一个文件系统的内容合并,同时保持“物理”内容的分离。其结果是一个统一的文件系统,即使数据实际上是以分支形式组织。

这里的想法是,如果你有多个镜像有一些相同的数据,不是让这些数据再次复制过来,而是通过使用一个叫做 layer 的东西来共享。

 title=

每一层都是一个可以在多个容器中共享的文件系统,例如,httpd 基础层是 Apache 的官方镜像,可以在任何数量的容器中使用。想象一下,由于我们在所有的容器中使用相同的基础层,我们节省了多少磁盘空间。

这些镜像层总是只读的,但是当我们用这个镜像创建一个新的容器时,我们会在它上面添加一个薄的可写层。这个可写层是你创建、修改、删除或进行每个容器所需的其他修改的地方。

写时复制(COW)

当你启动一个容器时,看起来好像这个容器有自己的整个文件系统。这意味着你在系统中运行的每个容器都需要自己的文件系统副本。这岂不是要占用大量的磁盘空间,而且还要花费大量的时间让容器启动?不是的,因为每个容器都不需要它自己的文件系统副本!

容器和镜像使用 写时复制 copy-on-write (COW)机制来实现这一点。写时复制策略不是复制文件,而是将同一个数据实例分享给多个进程,并且只在一个进程需要修改或写入数据时进行复制。所有其他进程将继续使用原始数据。

Docker 对镜像和容器都使用了写时复制的机制。为了做到这一点,在旧版本中,镜像和运行中的容器之间的变化是通过 图驱动 graph driver 来跟踪的,现在则是通过 快照器 snapshotter 来跟踪。

在运行中的容器中执行任何写操作之前,要修改的文件的副本被放在容器的可写层上。这就是发生 的地方。现在你知道为什么它被称为“写时复制”了么。

这种策略既优化了镜像磁盘空间的使用,也优化了容器启动时间的性能,并与 UnionFS 一起工作。

叠加文件系统

叠加文件系统 Overlay File System 位于现有文件系统的顶部,结合了上层和下层的目录树,并将它们作为一个单一的目录来呈现。这些目录被称为 layer 。下层保持不被修改。每一层只增加与下一层的差异(计算机术语为 “diff”),这种统一的过程被称为 联合挂载 union mount

最低的目录或镜像层被称为 下层目录 lowerdir ,上面的目录被称为 上层目录 upperdir 。最后的覆盖层或统一层被称为 合并层 merged

 title=

常见的术语包括这些层的定义:

  • 基础层 Base layer :是你的文件系统的文件所在的地方。就容器镜像而言,这个层就是你的基础镜像。
  • 叠加层 Overlay layer :通常被称为 容器层 container layer ,因为对运行中的容器所做的所有改变,如添加、删除或修改文件,都会写到这个可写层。对这一层所做的所有修改都存储在下一层,是基础层和差异层的联合视图。
  • 差异层 Diff layer 包含了在叠加层所作的所有修改。如果你写的东西已经在基础层了,那么叠加文件系统就会把文件复制到差异层,并做出你想写的修改。这被称为写时复制。

快照器

通过使用层和图驱动,容器可以将其更改作为其容器文件系统的一部分来构建、管理和分发。但是使用 图驱动 graph driver 的工作真的很复杂,而且容易出错。 快照器 SnapShotter 与图驱动不同,因为它们不用了解镜像或容器。

快照器的工作方式与 Git 非常相似,比如有树的概念,并跟踪每次提交对树的改变。一个 快照 snapshot 代表一个文件系统状态。快照有父子关系,使用一组目录。可以在父级和其快照之间进行差异比较(diff),以创建一个层。

快照器提供了一个用于分配、快照和挂载抽象的分层文件系统的 API。

总结

你现在对什么是容器镜像以及它们的分层方法如何使容器可移植有了很好的认识。接下来,我将介绍容器的运行机制和内部结构。

本文基于 techbeatly 的文章,经许可后改编。


via: https://opensource.com/article/21/8/container-image

作者:Nived V 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

学习 kubectl,提升你与 Kubernetes 的互动方式。

 title=

Kubernetes 可以帮你编排运行有大量容器的软件。Kubernetes 不仅提供工具来管理(或者说 编排)运行的容器,还帮助这些容器根据需要进行扩展。有了 Kubernetes 作为你的中央 控制面板 control panel (或称 控制平面 control plane ),你需要一种方式来管理 Kubernetes,而这项工作的工具就是 kubectl。kubectl 命令让你控制、维护、分析和排查 Kubernetes 集群的故障。与许多使用 ctl(“控制”的缩写)后缀的工具一样,如 systemctlsysctlkubectl 拥有大量的功能和任务权限,所以如果你正在运行 Kubernetes,你肯定会经常使用它。它是一个拥有众多选项的命令,所以下面是 kubectl 中简单易用的五个常见任务。

1、列出并描述资源

按照设计,容器往往会成倍增加。在某些条件下,它们可以快速增加。如果你只能通过 podman psdocker ps 来查看正在运行的容器,这可能会让你不知所措。通过 kubectl getkubectl describe,你可以列出正在运行的 吊舱 pod 以及它们正在处理的容器信息。更重要的是,你可以通过使用 --namespacename--selector等选项,只列出所需信息。

get 子命令不仅仅对吊舱和容器有用。它也有关于节点、命名空间、发布、服务和副本的信息。

2、创建资源

如果你只通过类似 OpenShift、OKD 或 Kubernetes 提供的 Web 用户界面(UI)创建过发布,但你想从 Linux 终端控制你的集群,那么可以使用 kubectl createkubectl create 命令并不只是实例化一个新的应用发布。Kubernetes 中还有很多其他组件可以创建,比如服务、配额和 计划任务

Kubernetes 中的计划任务可以创建一个临时的吊舱,用来在你选择的时间表上执行一些任务。它们并不难设置。下面是一个计划任务,让一个 BusyBox 镜像每分钟打印 “hello world”。

$ kubectl create cronjob \
    hello-world \
    --image=busybox \
    --schedule="*/1 * * * *" -- echo "hello world"

3、编辑文件

Kubernetes 中的对象都有相应的配置文件,但在文件系统中查找相应的文件较为麻烦。有了 kubectl edit,你可以把注意力放在对象上,而不是定义文件上。你可以通过 kubectl 找到并打开文件(通过 KUBE_EDITOR 环境变量,你可以设置成你喜欢的编辑器)。

$ KUBE_EDITOR=emacs \
    kubectl edit cronjob/hello-world

4、容器之间的传输文件

初次接触容器的人往往对无法直接访问的共享系统的概念感到困惑。他们可能会在容器引擎或 kubectl 中了解到 exec 选项,但当他们不能从容器中提取文件或将文件放入容器中时,容器仍然会显得不透明。使用 kubectl cp 命令,你可以把容器当做远程服务器,使主机和容器之间文件传输如 SSH 命令一样简单:

$ kubectl cp foo my-pod:/tmp

5、应用变更

对 Kubernetes 对象进行修改,可以通过 kubectl apply 命令完成。你所要做的就是将该命令指向一个配置文件:

$ kubectl apply -f ./mypod.json

类似于运行 Ansible 剧本或 Bash 脚本,apply 使得快速“导入”设置到运行中的 Kubernetes 实例很容易。例如,GitOps 工具 ArgoCD 由于 apply 子命令,安装起来出奇地简单:

$ kubectl create namespace argocd
$ kubectl apply -n argocd \
    -f https://raw.githubusercontent.com/argoproj/argo-cd/vx.y.z/manifests/install.yaml

使用 kubectl

Kubectl 是一个强大的工具,由于它是一个终端命令,它可以写成脚本,并能实现用众多 Web UI 无法实现的功能。学习 kubectl 是进一步了解 Kubernetes、容器、吊舱以及围绕这些重要的云计算创新技术的一个好方法。下载我们的 kubectl 速查表,以获得快速参考,其中包括命令示例,以帮助你学习,并在为你提供注意细节。


via: https://opensource.com/article/21/7/kubectl

作者:Alan Smithee 选题:lujun9972 译者:geekpi 校对:turbokernel

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用 Podman Machine 创建一个基本的 Fedora CoreOS 虚拟机来使用容器和容器化工作负载。

 title=

Fedora CoreOS 是一个自动更新、最小化的基于 rpm-ostree 的操作系统,用于安全地、大规模地运行容器化工作负载。

Podman “是一个用于管理容器和镜像、挂载到这些容器中的卷,以及由这些容器组组成的吊舱的工具。Podman 基于 libpod,它是一个容器生命周期管理库”。

当你使用 Podman Machine 时,神奇的事情发生了,它可以帮助你创建一个基本的 Fedora CoreOS 虚拟机(VM)来使用容器和容器化工作负载。

开始使用 Podman Machine

第一步是安装 Podman。如果你已经安装了最新版本的 Podman,你可以跳过这个步骤。在我的 Fedora 34 机器上,我用以下方式安装 Podman:

$ sudo dnf install podman

我使用的是 podman-3.2.2-1.fc34.x86\_64。

初始化 Fedora CoreOS

Podman 安装完成后,用以下方法初始化它:

❯ podman machine init vm2
Downloading VM image: fedora-coreos-34.20210626.1.0-qemu.x86_64.qcow2.xz: done 
Extracting compressed file

这个命令创建了 vm2,并下载了 .xz 格式的 Fedora CoreOS 的 qcow2 文件并将其解压。

列出你的虚拟机

了解你的虚拟机和它们的状态是很重要的,list 命令可以帮助你做到这一点。下面的例子显示了我所有的虚拟机的名称,它们被创建的日期,以及它们最后一次启动的时间:

❯ podman machine list 
NAME          VM TYPE     CREATED     LAST UP
podman-machine-default* qemu      6 days ago   Currently running
vm2           qemu      11 minutes ago 11 minutes ago

启动一个虚拟机

要启动一个虚拟机,请运行:

❯ podman machine start
Waiting for VM ...

SSH 到虚拟机

你可以使用 SSH 来访问你的虚拟机,并使用它来运行工作负载,而没有任何麻烦的设置:

❯ podman machine ssh  
Connecting to vm podman-machine-default. To close connection, use `~.` or `exit`
Fedora CoreOS 34.20210611.1.0
Tracker: https://github.com/coreos/fedora-coreos-tracker
Discuss: https://discussion.fedoraproject.org/c/server/coreos/
 
Last login: Wed Jun 23 13:23:36 2021 from 10.0.2.2
[core@localhost ~]$ uname -a
Linux localhost 5.12.9-300.fc34.x86_64 #1 SMP Thu Jun 3 13:51:40 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
[core@localhost ~]$

目前,Podman 只支持一次运行一个虚拟机。

停止你的虚拟机

要停止运行中的虚拟机,请使用 stop 命令:

❯ podman machine stop

[core@localhost ~]$ Connection to localhost closed by remote host.
Connection to localhost closed.
Error: exit status 255

我希望这能帮助你开始使用 Podman Machine。请试一试,并在评论中告诉我们你的想法。


via: https://opensource.com/article/21/7/linux-podman

作者:Sumantro Mukherjee 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Podman 是一个无守护程序的容器引擎,用于在你的 Linux 系统上开发、管理和运行 OCI 容器。在这篇文章中,我们将介绍 Podman 以及如何用 nodejs 构建一个小型应用来使用它。该应用将是非常简单和干净的。

安装 Podman

Podman 的命令就与 docker 相同,如果你已经安装了 Docker,只需在终端输入 alias docker=podman

在 Fedora 中,Podman 是默认安装的。但是如果你因为任何原因没有安装,你可以用下面的命令安装它:

sudo dnf install podman

对于 Fedora silverblue 用户,Podman 已经安装在你的操作系统中了。

安装后,运行 “hello world” 镜像,以确保一切正常:

podman pull hello-world
podman run hello-world

如果一切运行良好,你将在终端看到以下输出:

Hello from Docker!
This message shows that your installation appears to be working correctly.
 To generate this message, Docker took the following steps:
  1.The Docker client contacted the Docker daemon.
  2.The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64)
  3.The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
  4.The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
 To try something more ambitious, you can run an Ubuntu container with:
  $ docker run -it ubuntu bash
 Share images, automate workflows, and more with a free Docker ID:
  https://hub.docker.com/
 For more examples and ideas, visit:
  https://docs.docker.com/get-started/

简单的 Nodejs 应用

首先,我们将创建一个文件夹 webapp,在终端输入以下命令:

mkdir webapp && cd webapp

现在创建文件 package.json,该文件包括项目运行所需的所有依赖项。在文件 package.json 中复制以下代码:

{
       "dependencies": {
               "express": "*"
       },
       "scripts": {
               "start": "node index.js"
       }
}

创建文件 index.js,并在其中添加以下代码:

const express = require('express')

const app = express();

app.get('/', (req, res)=> {
       res.send("Hello World!")
});
app.listen(8081, () => {
       console.log("Listing on port 8080");
});

你可以从 这里 下载源代码。

创建 Dockerfile

首先,创建一个名为 Dockerfile 的文件,并确保第一个字符是大写,而不是小写,然后在那里添加以下代码:

FROM node:alpine
WORKDIR usr/app
COPY ./ ./
RUN npm install
CMD ["npm", "start"]

确保你在 webapp 文件夹内,然后显示镜像,然后输入以下命令:

podman build .

确保加了 .。镜像将在你的机器上创建,你可以用以下命令显示它:

podman images

最后一步是输入以下命令在容器中运行该镜像:

podman run -p 8080:8080 <image-name>

现在在你的浏览器中打开 localhost:8080,你会看到你的应用已经工作。

停止和删除容器

使用 CTRL-C 退出容器,你可以使用容器 ID 来删除容器。获取 ID 并使用这些命令停止容器:

podman ps -a
podman stop <container_id>

你可以使用以下命令从你的机器上删除镜像:

podman rmi <image_id>

官方网站 上阅读更多关于 Podman 和它如何工作的信息。


via: https://fedoramagazine.org/getting-started-with-podman-in-fedora/

作者:Yazan Monshed 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

用 Forklift 将你的虚拟化工作负载过渡到 Kubernetes。

 title=

2017 年,KubeVirt 团队 发起 了一个在 Kubernetes 中管理容器及相关的虚拟机(VM)的项目。这个开源项目的意图是让虚拟机成为这个环境中的一等公民。

自从在 2018 年开源峰会 上推出以来,KubeVirt 一直在不断成熟和发展。它在 GitHub 上已经达到了 200 多颗星,甚至在 2021 年 2 月推出了自己的活动:KubeVirt 峰会

 title=

KubeVirt 架构(© 2020,Red Hat OpenShift

KubeVirt 是 OpenShift 虚拟化 的基础,它帮助开发者将虚拟机带入容器化工作流程。

在 Kubernetes 中使用虚拟机

KubeVirt 使你能够在虚拟机上原生使用 Kubernetes。这意味着它们可以连接到使用标准 Kubernetes 方法(如服务、路由、管道等)访问的 吊舱 Pod 网络。应用于虚拟机吊舱的网络策略与应用于应用吊舱的方式相同,它提供一个一致的模型来管理虚拟机到吊舱(或反之)的通信。

这方面的一个真实例子是一家航空公司利用旧的模拟器软件的方式。它注入了人工智能和机器学习 (AI/ML) 的模型,然后在基于虚拟机的模拟器上自动部署和测试它们。这使得它能够使用 Kubernetes 和 Kubeflow 完全自动化地获得测试结果和新的遥测训练数据。

 title=

(Konveyor, CC BY-SA 4.0

Konveyor.io 是一个开源项目,帮助现有工作负载(开发、测试和生产)过渡到 Kubernetes。其工具包括将容器从一个 Kubernetes 平台转移到另一个平台的 Crane;将工作负载从 Cloud Foundry 带到 Kubernetes的 Move2Kube;以及分析 Java 应用,使其对 Kubernetes 等容器化平台中的运行时更加标准和可移植,从而使其现代化的 Tackle

这些工具在转化模式中很有用,但许多项目希望在早期阶段利用 Kubernetes,以变得更加敏捷和富有成效。在基础设施方面,这些好处可能包括蓝/绿负载均衡、路由管理、声明式部署,或(取决于你的部署方式)由于不可变的基础设施而更容易升级。在开发方面,它们可能包括将持续集成/持续开发 (CI/CD) 管道与平台整合,使应用更快地投入生产,自我提供资源,或整合健康检查和监控。

KubeVirt 可以通过在 Kubernetes 环境中以虚拟机来运行工作负载帮助你。它能让你的工作负载迅速使用 Kubernetes,享受它的好处,并随着时间的推移稳步实现工作负载的现代化。但是,仍然有一个问题,就是把你的虚拟机从传统的虚拟化平台带到现代的 Kubernetes 平台。这就是 Konveyor 的 Forklift 项目的意义所在。

关于 Forklift

Forklift 使用 KubeVirt 将不同来源的虚拟化工作负载迁移到 Kubernetes。它的设计目标是使任务变得简单,以便你可以从一两台机器到数百台机器迁移任何东西。

迁移是一个简单的、三阶段的过程:

  1. 连接到一个现有的虚拟化平台(称为“源提供者”)和一个 Kubernetes 环境(“目标提供者”)。
  2. 将网络和存储资源从源提供者映射到目标提供者,在两者中寻找等价的资源。
  3. 选择要迁移的虚拟机,分配网络和存储映射,制定迁移计划。然后运行它。

如何开始

要开始使用 Forklift,首先,你需要一个兼容的源提供商。你还需要一个带有 KubeVirt 0.40 或更新版本的 Kubernetes 环境和裸机节点(尽管为了测试,你可以使用嵌套虚拟化)。用读-写-执行 (RWX) 功能配置你的存储类,并使用 Multus 配置你的网络,以匹配你的虚拟机在源提供者中使用的网络。(如果你不能这样做,也不用担心。你也可以选择重新分配 IP 地址。)

最后,使用提供的操作器在你的 Kubernetes 上安装 Forklift,并进入用户界面,开始运行你的第一次测试迁移。

Forklift 是 Red Hat 的 虚拟化迁移工具套件 的上游版本。因此,如果你想在生产环境中使用它,你可以考虑使用该工具的支持版本。

迁移愉快!


via: https://opensource.com/article/21/6/migrate-vms-kubernetes-forklift

作者:Miguel Perez Colino 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出