Podman容器 [2022]

IT知识
555
0
0
2022-11-24

Podman

总目标:在一个 RHEL 服务器上获取、运行和管理作为容器的简单轻量级服务

目标:

  • 解释容器是什么,及如何管理和部署具有软件库和依赖的应用程序
  • 安装容器管理工具,并运行一个简单的无根容器
  • 查找、检索、检查和管理容器映像,从远程容器仓库获得并存储在服务器中
  • 使用选项来运行容器,列出在系统上运行的容器,启动、停止和强制关闭容器
  • 通过在运行的容器中挂载目录,以使用容器永久存储
  • 以 systemd 服务的方式启动、停止和检查容器

章节:

  1. 容器介绍
  2. 运行一个基本的容器
  3. 查找并管理容器映像
  4. 实施高级的容器管理
  5. 为容器附加永久存储
  6. 以服务方式管理容器
  7. 实验
  8. 总结

第一节:容器介绍

目标:

  • 解释容器是什么,及如何管理和部署具有软件库和依赖的应用程序

1.1 容器技术介绍:

  • 应用程序通常依赖于 runtime environment 提供的库、配置文件或服务。传统上,应用程序的 runtime environment 安装在运行在物理主机或虚拟机上的操作系统中。应用程序依赖项与该操作系统一起安装在主机上
  • 在 RHEL 中,使用 RPM 帮助管理应用程序依赖关系。当安装httpd 包时,RPM 系统会确保安装了正确的库和依赖项
  • 应用程序可能需要比操作系统安装的更老或更新的软件版本。或在同一系统上的两个应用程序可能需要同一软件的不同版本,而版本彼此不兼容
  • 解决这些冲突的一种方法是将应用程序打包并部署为容器
  • 容器是与系统的其他部分隔离的一个或多个进程的集合。容器的内容与其他容器的内容是隔离的,不会相互影响
  • 容器是打包应用程序以简化部署和管理的一种方法

1.2 容器和虚拟化的对比:

  • 容器提供了许多与虚拟机相同的优点,例如安全性、存储和网络隔离
  • 这两种技术都将它们的应用程序库和 runtime 资源与主机操作系统或管理程序隔离开来
  • 容器和虚拟机与硬件和底层操作系统交互方式不同
  • 虚拟化:
  • 可以在单一硬件平台运行多操作系统
  • 使用 hypervisor 将硬件拆分成多个虚拟硬件,允许多个操作系统并行运行
  • 需要完整的操作系统来支持应用运行
  • 容器:
  • 在操作系统上直接运行,容器之间分享硬件和操作系统资源,容器中应用轻量化和快速并行运行
  • 共享操作系统内核,将容器化的应用程序进程与系统的其余部分隔离,并使用与该内核兼容的任何软件
  • 比虚拟化要求更少的硬件资源,可以快速启动和停止,减少存储需求

1.3 探索容器的实现:

  • RHEL 实现容器使用核心技术:
  • 用于资源管理的 Control Groups (cgroups)
  • 用于进程隔离的 Namespaces
  • SELinux 和 Seccomp(Secure Computing mode)加强安全边界

1.4 计划使用容器:

  • 容器可移植性好。可以容易的从一个环境转移到另一个环境,比如从开发环境转移到生产环境
  • 可以保存容器的多个版本,根据需要快速访问每个版本
  • 容器通常是临时(ephemeral)的。可将运行中的容器生成的数据永久保存在持久存储(persistent storage)
  • 容器通常在需要时运行,不需要时停止并删除。下一次需要时,将启动一个新的容器进程

1.5 从容器映像(Container Image)运行容器:

  • 容器从容器映像(container image)运行。容器映像是创建容器的蓝图
  • 容器映像打包一个应用程序连同它所有的依赖:
  • 系统库函数
  • 编程语言运行时
  • 编程语言库函数
  • 配置
  • 静态数据文件
  • image 不可更改
  • image 根据规范(OCI)构建,例如 Open Container Initiative(OCI) image 格式规范。这些规范定义了 image 的格式及元数据

1.6 设计基于容器的结构:

  • 可在单个容器中安装由多个服务组成的复杂软件应用程序。例如,可能有一个需要使用数据库和消息队列的 web 服务器。但是将一个容器用于多个服务是很难管理的
  • 更好的设计是在单独的容器中运行每个组件、web服务器、数据库和消息队列。对单个应用程序组件的更新和维护不会影响其他组件或应用程序堆栈

1.7 用 Podman 管理容器:

1、Podman 直接与镜像注册表、容器和镜像存储进行交互 2、Podman 中没有使用守护进程,而是直接使用 runC 容器运行时 3、适用于 Docker 的命令在 Podman 中也是同样可用的 4、Podman 和 Docker 的镜像具有兼容性
  • RHEL 提供了一套容器工具,可以实现:
  • podman:它直接管理容器和容器 image
  • skopeo:可以使用它检查inspect、复制、删除和签名 image
  • buildah:可以使用它创建新的容器 image
  • 这些工具与开放容器倡议(OCI)是兼容的。它们可以用于管理任何由兼容 oci 的容器引擎(如Docker)创建的 Linux 容器
  • 这些工具专门为在 RHEL 下的单节点容器主机上运行容器而设计
  • 在本章中,将学习 podman 和 skopeo 命令来运行和管理容器和image
  • 注:buildah 内容可以参考 Introduction to Containers, Kubernetes, and OpenShift (DO180)

1.8 运行无根(非root)的容器:

  • 在容器主机上,用户能以根用户或普通用户运行容器。非特权用户运行的容器称为无根容器
  • 无根容器更安全,但有一些限制。例如,无根容器不能通过容器主机的特权端口(<=1024这个不让用)发布网络服务
  • 可以直接作为根用户运行容器,但这在一定程度上削弱了系统的安全性

1.9 管理大量容器:

  • 越来越多的新应用程序使用容器实现,并彼此依赖。管理越来越多的容器很快就会成为一项难以应付的任务
  • 在生产中大规模部署容器需要适应以下挑战:
  • 平台必须为客户提供容器的可用性
  • 环境必须能增加或减少运行的容器,并负载平衡流量来响应应用程序负载变化
  • 平台应该检测到容器或主机的故障并做出相应的反应
  • 开发人员需要一个自动化的工作流程,以透明和安全地向客户交付新的应用程序版本
  • Kubernetes 是一种编排服务,可以更容易地跨容器主机部署、管理和伸缩基于容器的应用程序。它在启动新容器时管理 DNS 更新。它使用负载均衡将流量重定向到容器,还允许管理员手动或自动地伸缩提供服务的容器数量。它还支持用户定义的运行状况检查,以监视容器,并在容器失败时重新启动它们
  • Red Hat 提供名为 Red Hat OpenShift 的 Kubernetes 发行版。OpenShift 是一组构建在 Kubernetes 基础设施之上的模块化组件和服务。它添加了一些额外的特性,例如基于 web 的远程管理、多租户、监视和审计、应用程序生命周期管理以及为开发人员提供的自助服务实例等等
  • 注:Red Hat OpenShift 超出了本课程的范围,可以在 https://www.openshift.com了解更多有关它的信息

第二节:运行一个基本的容器

目标:

  • 安装容器管理工具,并运行一个简单的无根容器

2.1 安装容器管理工具:

ID

HOST

COMMENT

1

classroom

yum repo

2

bastion

router

3

utility

container-server: Quay

4

servera

container-client: podman

[kiosk@foundation]

$ rht-clearcourse 0
$ rht-setcourse rh134
$ for i in classroom bastion utility servera; do
rht-vmctl start $i
done

要在系统上运行和管理容器,使用 yum 安装 container-tools 模块(module)

[student@servera]

  • podman-1.6.4-10.module+el8.2.0+6064+4ca4827e.x86_64,当前系统默认(不支持开机自启
  • podman-1.9.3-2.module+el8.2.1+6867+366c07d6.x86_64,练习环境|考试环境(千万不要自己安装
$ yum module list container*
$ sudo yum module -y install container-tools
[sudo] password for student: `redhat`

容器工具模块包括安装多个工具的软件包。本章使用是 podman 和 skopeo

2.2 选择容器 image 和 registry:

  • 容器 registry 是用于存储和检索容器 image 的存储库。开发人员将 image 上传或推送到 registry。用户可以从 registry 下载或拉取这些容器 image 到本地系统,以便运行容器
  • 可以使用包含第三方 image 的 public registry,也可以使自建的 private registry。容器 image 的来源很重要,是否可以信任 images 中的代码。不同的 registry 对于是否以及如何提供、评估和测试提交给它们的 images 有不同的策略
  • https://catalog.redhat.com/software/containers/explored (https://hub.docker.com/search?type=image)
  • Red Hat 通过两个主要的 registry 分发经过认证的 images ,用户可以使用 Red Hat 账户访问这些 registry:
  • registry.redhat.io 基于红帽官方产品的 images
  • registry.connect.redhat.com 用于基于第三方产品的 images
  • 红帽正在逐步淘汰一个较老的registry:registry.access.redhat.com
  • 红帽容器目录(https://access.redhat.com/containers)提供了一个基于 web 的界面,可以索这些 registry 以获得认证的 images
  • **注:**本课程运行一个基于 Red Hat Quay 的私有 registry,以提供容器 images

2.3 容器 image 的命名格式:

  • registry_name/user_name/image_name:tagregistry_name:是存储 image 的 registry 名称,一般是 registry 的域名
  • user_name:是 image 所属的用户或组织
  • image_name:必须在用户 userspace 中唯一
  • tag:用于区分 image 版本,如果 image 名称中不含有 tag,将默认使用 latest tag

2.4 运行容器:

要在本地系统上运行容器,必须首先下载(pull)容器 image。使用 Podman 从 registry 中下载 images

在 pull images 时,应始终使用完整的 image 名称。podman pull 命令从 registry 中提取指定的 image 并保存到本地:

[kiosk@foundation]

firefox https://registry.lab.example.com

[student@servera]

$ podman login --help
$ podman login -u admin -p redhat321 \
--tls-verify=false registry.lab.example.com
$ podman search \
--tls-verify=false registry.lab.example.com/
$ podman pull \
--tls-verify=false registry.lab.example.com/ubi8/ubi
$ podman pull \
--tls-verify=false registry.lab.example.com/ubi7/ubi

下载后,Podman 在本地存储 image,可以使用 podman images 命令列出:

$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.lab.example.com/ubi7/ubi latest 87dd8ec61bbc 5 months ago 215 MB
  • 显示 image tag 是 latest,image id 是 87dd8ec61bbc

要从这个 image 运行一个容器,使用 podman run 命令,将从容器 image 创建并启动一个新的容器。如果需要,使用 -it 选项与容器交互。it 选项将终端分配给容器,并允许向其发送键盘指令

$ podman run -it \
registry.lab.example.com/ubi8/ubi:latest
[root@99901bb00fc1 /]# <Ctrl-D>
$ podman ps --all
$ podman ps

如果运行一个容器使用完整 image name,但 image 还没有本地存储,则 podman run命令将先从 registry 中下载 image,再运行

注:-t = -tty ;-i = --interactive ;-d = --detach(background running)

当访问一个容器时,Podman 可使用容器 name 或生成的 ID。当使用 podman run 运行容器时,使用 --name 选项设置容器名,容器名称必须是唯一的。如果 podman run 命令不包含容器名称,那么podman将生成一个随机名称

$ podman run -it --name=rhel8 registry.lab.example.com/ubi8/ubi
[root@acd94b972f65 /]# exit
$ podman ps --all
$ podman ps

podman run --rm 可以在不与容器交互的情况下在容器中运行快速命令,然后在命令完成后删除容器

$ podman run --rm=true registry.lab.example.com/ubi8/ubi \
cat /etc/os-release
$ podman ps --all
$ podman ps

2.5 分析容器的隔离:

容器提供了资源的 runtime 隔离。容器利用 Linux namespace 为资源(如进程、网络通信和卷)提供独立的、隔离的环境

在容器中运行的进程与主机上的所有其他进程是隔离的

查看容器内运行的进程:

$ podman run -it registry.lab.example.com/ubi7/ubi /bin/bash
[root@10855645141e /]# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 2.4 0.1 11840 2764 pts/0 Ss 20:30 0:00 /bin/bash
root 14 0.0 0.1 51768 3212 pts/0 R+ 20:31 0:00 ps aux

注意,容器内的用户名和 ID 与主机上的用户名和 ID 不同:

[root@10855645141e /]# id
uid=0(root) gid=0(root) groups=0(root)
[root@10855645141e /]# exit
$ id
uid=1000(student) gid=1000(student) groups=1000(student),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

第三节:查找并管理容器映像

目标:

  • 查找、检索、检查和管理容器映像,从远程容器仓库下载并存储在服务器中

3.1 配置容器 registries:

podman 在主机上使用 registry.conf 来配置容器 registry 信息

$ grep -A 1 ^\\[regis.*search /etc/containers/registries.conf
[registries.search]
registries = ['registry.access.redhat.com', 'registry.redhat.io', 'docker.io']

podman 可以访问的 registry 列表在 [registry.search] 中配置。如果没有在命令行中指定 image 完整域名,那么 podman 将按照顺序搜索此段内容,帮助补全域名路径

ID

配置文件

存在

范围

优先级

1

/etc/containers/registries.conf

Y

所有用户


2

$HOME/.config/containers/registries.conf

N

指定用户

优先

  • 方法一
$ sudo vim /etc/containers/registries.conf
# The initial configuration format
#[registries.search]
#registries = ['registry.lab.example.com']
#[registries.insecure]
#registries = ['registry.lab.example.com']
#[registries.block]
#registries = []
...
# The second version of the configuration format
unqualified-search-registries = ["registry.lab.example.com"]
[[registry]]
insecure = true
blocked = false
location = "registry.lab.example.com"
...
  • 方法二
$ wget -P /etc/yum.repos.d/ http://materials/updates.repo
$ yum update -y
$ mkdir -p .config/containers
$ wget http://materials/registries.conf -P .config/containers

podman info 命令显示 Podman 的配置信息:

$ podman info | grep -A 5 ^registries
registries:
blocked: null
insecure:
- registry.lab.example.com
search:
- registry.lab.example.com

3.2 registry 安全:

不安全的 registry 列在 registries.conf 的 [registry.inscure]中。到该 registry 的连接不受 TLS 加密保护

如果一个 registry 既可搜索又不安全,那么它可以在[registries.search] 和 [registries.insecure] 中同时写入

registries 也可以配置为需要身份验证。使用 podman login 登录

$ podman logout registry.lab.example.com

3.3 搜索容器 image:

podman search 命令搜索特定容器 image 的 registry:

$ podman search ubi
$ podman search registry.lab.example.com/
ERRO[0000] error searching registry "registry.lab.example.com": couldn\'t search registry "registry.lab.example.com": unable to retrieve auth token: invalid username/password: unauthorized: access to the requested resource is not authorized
$ podman login -u admin -p redhat321 registry.lab.example.com
Login Succeeded!
$ podman search registry.lab.example.com/
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
example.com registry.lab.example.com/rhel8/mariadb-103 0
example.com registry.lab.example.com/rhel8/httpd-24 0
example.com registry.lab.example.com/library/nginx 0
example.com registry.lab.example.com/ubi7/ubi 0
example.com registry.lab.example.com/ubi8/ubi 0

添加 --no-trunc 选项,可以查看更多的 image 描述(不省略描述): [kiosk@foundation]

VMware 连接网络适配器 2
$ nmcli con up ens192
$ ping -c 4 www.redhat.com
$ su -
Asimov
# scp root@servera:/etc/yum.repos.d/*.repo /etc/yum.repos.d
# sed -i -e '/nameserver.*172/d' -e '/nameserver/inameserver 172.25.254.250' /etc/resolv.conf
# yum module -y install container-tools
# <Ctrl-D>

[kiosk@foundation]

$ podman login -u `红帽帐号` registry.redhat.io
Password: `红帽密码`
$ podman search registry.redhat.io/rhel8
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
redhat.io registry.redhat.io/openjdk/openjdk-8-rhel8 OpenJDK 1.8 Image for Java Applications base... 0
...
$ podman search --no-trunc registry.redhat.io/rhel8
INDEX NAME DESCRIPTION STARS OFFICIAL AUTOMATED
redhat.io registry.redhat.io/openjdk/openjdk-8-rhel8 OpenJDK 1.8 Image for Java Applications based on UBI8 0
...

下表为一些其他 podman search 命令选项:

Option

Description


–limit <number>

Limits the number of listed images per registry

限制显示一部份

–filter <filter=value>

Filters output based on conditions provided. Supported filters include:- stars=<number>: Show only images with at least this number of stars- is-automated=<true|false>: Show only images automatically built- is-official=<true|false>: Show only images flagged as official

过滤

–tls-verify <true|false>

Enable or disables HTTPS certificate validation for all used registries. Default=true

true=https, false=http

3.4 使用红帽容器目录(Red Hat Container Catalog):

  • 红帽维护包含经过认证的容器映像的 registry: https://access.redhat.com/containers
  • 使用这个 registry 可以防范可能由未经测试的映像造成的已知漏洞

3.5 查看容器的 images:

可在将 image 下载到系统之前查看 image 信息。skopeo inspect 命令可以检查 registry 中的远程容器 image 并显示有关它的信息

$ skopeo inspect docker://registry.redhat.io/rhel8/python-36
{
"Name": "registry.redhat.io/rhel8/python-36",
"Digest": "sha256:ffe84f452974d21370c22008c872730171b0d3f11f89f00aba5c42409d26c6a7",
"RepoTags": [
...

还可使用 podman inspect 检索本地保存的 image 信息,会比 skopeo inspect 提供更多信息

$ podman inspect registry.lab.example.com/ubi7/ubi

3.6 删除本地容器图像:

容器映像是只读的。容器的更新意味着 image 的更新

当更新后的 image 可用时,发布者更改 latest tag 以将其与新 image 关联。管理员可以删除较旧的 image,pull 最新的 image,并且只使用最新的 image 来运行容器

由红帽提供的 image 受益于红帽在管理 RHEL 和其他产品的安全漏洞和缺陷方面的长期经验。红帽安全团队加固这些 images。当发现新的漏洞时,它们将被重新构建,并通过质保流程

podman rmi 移除本地存储的 image

$ podman images
$ podman ps --all
$ podman rm d8e3578d277f
$ podman rmi registry.lab.example.com/ubi7/ubi
Untagged: registry.lab.example.com/ubi7/ubi:latest
Deleted: 87dd8ec61bbc977ed1b2bd29ba089489a8a0281e2e0f62bf43c3fb9c20414194
$ podman images

第四节:实施高级的容器管理

目标:

  • 使用选项来运行容器,列出在系统上运行的容器,启动、停止和强制关闭容器

4.1 用 Podman 管理容器:

可以使用 Podman 运行容器,并管理正在运行或已停止的容器。在本节中,将学习如何使用 Podman 管理容器的整个生命周期

img

$ podman ps --all
$ podman start ce079e808857
$ podman ps
$ podman stop ce079e808857
$ podman ps --all

4.2 配置容器:

  • podman run 命令从容器 image 启动容器。当运行一个容器时,它将在容器内启动一个进程,可以是一个应用程序,比如web 或数据库服务器
  • 要访问容器的网络,客户端必须连接到容器主机上的端口,这些端口将网络流量传递到容器中的端口
  • 可以向容器传递一些环境变量,而不需要修改容器 image

4.3 将主机端口映射到容器:

将容器主机上的网络端口映射到容器中的端口时,容器将收发到主机端口的网络流量

例如,可以将容器主机上的端口 8000 映射到容器上的端口 8080

podman run -p hostport:containerport 可以映射主机端口到容器

$ podman run -d -p 8000:8080 registry.lab.example.com/rhel8/httpd-24
40e4b0d0dce24a853fb7b67e7eb96ee7d8d968925ec04c00e9a9e6532b0c2c9f
$ podman ps

可使用 podman port containerID|name 来列出端口映射,或使用 -a 选项列出所有正在使用的端口映射

$ podman port -a
40e4b0d0dce2 8080/tcp -> 0.0.0.0:8000

必须确保主机上的防火墙允许外部客户端连接到它的映射端口。上例中,可能要在主机上的防火墙规则中添加端口 8000/tcp:

$ sudo firewall-cmd --permanent --add-port=8000/tcp
$ sudo firewall-cmd --reload

4.4 传递环境变量以配置容器:

可以将环境变量传递给容器,环境变量的值用以配置其应用程序

podman inspect 命令可详细显示容器 image 信息

$ podman inspect registry.lab.example.com/rhel8/mariadb-103 | egrep '"url|"usage'
"url": "https://access.redhat.com/containers/#/registry.access.redhat.com/rhel8/mariadb-103/images/1-102",
"usage": "podman run -d -e MYSQL_USER=user -e MYSQL_PASSWORD=pass -e MYSQL_DATABASE=db -p 3306:3306 rhel8/mariadb-103",
...
  • url 标签指向 Red Hat Container Catalog 中的一个 web 页面,该页面记录了环境变量和关于如何使用容器 image 的信息
  • usage 标签是运行 image 的典型 podman 命令用例
  • 该 image 的 url 标签文档中提供的页面显示容器使用端口 3306,并可以使用以下环境变量来配置数据库服务:
  • MYSQL_USER:MySQL 帐户的用户名
  • MYSQL_PASSWORD:用户帐户的密码
  • MYSQL_DATABASE:数据库名称
  • MYSQL_ROOT_PASSWORD:root 用户的密码(可选)

podman run -e 可以将环境变量传递到容器中

$ podman run -d --name mydb \
-e MYSQL_USER=tom \
-e MYSQL_PASSWORD=mima \
-e MYSQL_DATABASE=mydb \
-e MYSQL_ROOT_PASSWORD=redhat \
-p 3306:3306 registry.lab.example.com/rhel8/mariadb-103
--name 选项可为容器分配名称,如果没有设置,podman 将分配一个随机名称

4.5 管理容器:

启动容器只是容器生命周期的第一步。生命周期还包括停止、重启或删除容器。用户还可以检查容器状态和元数据,以便进行调试

podman ps 可以列出运行中的容器

$ podman ps
  1. 容器 id,16进制,随机生成
  2. 容器 image
  3. 容器启动时执行的命令
  4. 容器创建的时间
  5. 容器运行时间
  6. 容器暴露的端口或端口映射的信息
  7. 容器名称

podman ps -a 命令列出所有容器,包括停止的。podman 并不会删除停止的容器,将保留容器在本地的文件和状态

$ podman ps -a

podman stop 命令停止容器运行

$ podman stop my-httpd-container

podman rm 在主机上删除容器(需要先停止运行容器)

podman rm -f 可删除正在运行的容器

podman rm -a 删除主机中所有停止运行的容器

$ podman rm my-database

podman restart 重新启动一个停止的容器。该命令将创建一个与已停止容器具有相同 ID的新容器,并重用其状态和文件系统

$ podman restart my-httpd-container

podman kill 命令发出 Unix SIGKILL 信号,终止容器运行

$ sudo podman kill my-httpd-container

4.6 在容器中运行命令:

容器启动时执行 image 的 entry point 命令。但是,可能需要执行其他命令来管理运行中的容器

podman exec 命令在一个已经运行的容器中启动一个额外的进程:

$ podman exec 95cbef42ce31 cat /etc/redhat-release

如果希望附加交互式 shell,必须指定 -it 选项来打开交互式会话并为 shell 分配一个伪终端

$ podman exec -it my_webserver /bin/bash
bash-4.4$ hostname
bash-4.4$ exit

Podman 记得使用的最后一个容器。可使用 -l 选项在最新的 Podman 命令中替换以前的容器 ID 或名称

$ podman exec -l cat /etc/redhat-release

第五节:为容器附加永久存储

目标:

  • 通过在运行的容器中挂载目录,以使用容器永久存储(persistent storage)

5.1 准备永久储存地点:

  • 容器中的存储是短暂的,意味着它的内容在删除容器后会丢失
  • 如想在重新启动容器时保留容器使用的数据,临时存储是不够的
  • 例如,容器可能是一个数据库服务器,当容器重新启动时,必须保存数据库本身
  • 必须为容器提供永久存储

5.2 从主机提供持久存储:

  • 提供永久存储的一种简单方法是使用容器主机上的目录。容器化应用将这些主机目录视为容器存储的一部分。
  • 当删除容器时,系统不会回收主机目录中的内容。新容器可以挂载它来访问数据
  • 永久存储可以驻留在任何地方,从本地硬盘分区到远程网络文件系统

5.3 准备主机目录:

  • 在准备主机目录时,必须对其进行配置,以便容器内的进程能够访问它。配置包括:
  • 配置目录的所有权和权限
  • 设置适当的 SELinux context
  • 容器内的应用程序必须能够访问主机目录
  • 还必须使用适当的SELinux context 配置主机目录(container_file_t)。额外的保护将防止在容器内运行的应用程序访问共享目录外的主机文件
  • 如果没有来自 SELinux 的额外保护,这些应用程序可能拥有对主机系统上所有文件的根访问权,并且能够危及主机和其他容器

5.4 卷挂载:

-z, 共享。Podman labels the content with a shared content label -Z, 独占。Only the current container can use a private volume

创建并配置主机目录之后,下一步是将该目录挂载到容器中。 podman run --volume|-v host_dir:container_dir

--volume host_dir:container_dir:z

通过 Z 选项,Podman 自动将 SELinux container_file_t context 应用到主机目录

$ mkdir -p ~/www/html/
$ echo hello > ~/www/html/index.html
$ chmod -R o+w ~/www/
$ podman run -d -p 8080:8080 -v /home/student/www:/var/www:Z registry.lab.example.com/rhel8/httpd-24

第六节:以服务方式管理容器

目标:

  • 以 systemd 服务的方式启动、停止和检查容器

6.1 服务器启动时自动启动容器

  • 当将数据库或 web 服务器等服务部署为容器时,通常希望这些容器与服务器一起自动启动
  • 通过为无根(rootless)容器创建 systemd user unit 文件,可使用 systemctl 命令来管理它们,类似常规服务
  • 通过 enable 这些服务,可以确保容器在主机启动时启动
  • 如果容器以“无根”模式运行,可以非特权用户帐户管理这些服务,以提高安全性
  • 要对许多基于容器的应用程序和服务进行更复杂的伸缩和编排,可使用基于 Kubernetes 的企业编排平台,如Red Hat OpenShift Container Platform

6.2 常规用户运行 Systemd 服务

systemd 可以管理 user service,普通用户可以为自己的服务创建 unit 文件,并使用systemctl 命令管理这些服务

当用户服务类型为非根用户时,通过文本或图形控制台或使用 SSH 打开第一个会话时,该服务将自动启动。当关闭最后一次会话时,服务将停止

这种行为与系统服务不同,系统服务在系统启动时启动,在系统关闭时停止

但也可以更改此默认行为,通过运行 loginctl enable-linger 命令强制 service 在服务器启动时启动并在关闭时停止。逆向操作,请使用 loginctl disable-linger 命令

查看当前状态,使用 loginctl show-user username 命令

$ loginctl enable-linger
$ loginctl show-user user | grep Linger
Linger=yes
$ loginctl disable-linger
$ loginctl show-user user | grep Linger
Linger=no

6.3 创建和管理 Systemd User Services:

要定义 systemd user service,创建 ~/.config/systemd/user/ 目录来存储 unit 文件,语法与 system unit file 相同

要控制新 user service,使用 systemctl --user 选项

下面的示例列出 ~/.config/systemd/user/ 中的 unit 文件,强制 systemd 重新加载其配置,然后 enable 和 start myapp user service

$ man -k systemd
$ man systemd.unit
$ mkdir ~/.config/systemd/user
$ ls ~/.config/systemd/user/myapp.service
$ systemctl --user daemon-reload
$ systemctl --user enable myapp.service
$ systemctl --user start myapp.service
更新 podman 版本
$ podman --version
podman version 1.6.4
$ sudo wget -P /etc/yum.repos.d/ http://materials/updates.repo
[sudo] password for student: `student`
$ sudo yum -y update
$ podman --version # --new支持;开机自启fix
podman version 1.9.3

:要使用 systemctl --user 命令,必须在控制台登录或直接通过 SSH 登录,不能使用 sudo 或 su 命令。systemctl 命令与每个用户的 systemd --user 进程交互。只有当用户第一次从控制台或 SSH 登录时,系统才会启动该进程

下表总结了 systemd 系统和 user services 之间的区别:


System Services

User services

Storing custom unit files

/etc/systemd/system/unit.service

~/.config/systemd/user/unit.service

Reloading unit files

# systemctl daemon-reload

$ systemctl --user daemon-reload

Starting and stopping a service

# systemctl start UNIT# systemctl stop UNIT

$ systemctl --user start UNIT$ systemctl --user stop UNIT

Starting a service when the machine starts

# systemctl enable UNIT

$ loginctl enable-linger**$ systemctl --user enable UNIT

6.4 使用 Systemd 服务管理容器:

  • 如果容器主机运行少量的容器,可以设置基于用户的 systemd unit 文件,并配置它们以通过自动启动容器
  • 这是一种简单的方法,适用于不需要扩展的小型部署
  • 对于更实际的生产,可以考虑使用 OpenShift

6.5 创建用于运行容器的专用用户帐户:

  • 为简化无根容器的管理,可以创建一个专用的用户帐户,用于管理所有容器
  • :为对所有容器进行分组而创建的帐户必须是常规用户帐户。当使用 useradd 创建帐户时,该命令在 /etc/subuid 文件中为用户的容器保留一系列用户 id。但当使用 useradd --system(或 -r)选项创建系统帐户时,该命令不会保留一个范围。因此,不能使用系统帐户启动无根容器

6.6 创建 Systemd unit 文件

从现有的容器中,podman 命令可以帮助生成 systemd unit 文件

下面的例子使用 podman generate systemd 命令为现有的 web 容器创建 unit 文件:

$ cd ~/.config/systemd/user/
$ podman generate systemd --help
$ podman generate systemd --name web --files --new

podman generate systemd 命令使用一个容器作为模型来创建配置文件。在创建文件之后,须删除容器

podman generate systemd 的选项

  • –name container_name:name 选项指定容器的名称,用作模板来生成 unit 文件。Podman 还使用该名称来生成 unit 文件的名称:containers-container_name.service
  • –files:files 选项指示 Podman 在当前目录中生成 unit 文件。如没有这个选项,Podman将在标准输出中显示该文件
  • –new:new 选项指示 Podman 配置 systemd 服务,以便在服务启动时创建容器,并在服务停止时删除。在这种模式下,容器是临时的,通常需要持久存储来保存数据。没有 --new 选项,Podman 配置服务启动和停止现有的容器,而不删除

下例在运行 podman generate systemd --new 时,unit 文件中的开始和停止指令:

$ podman run -d --name web -p 8080:8080 \
registry.lab.example.com/rhel8/httpd-24:1-105
$ podman generate systemd --name web --new
  1. 启动时,systemd 执行 podman run 命令创建并启动一个新容器
  2. 停止时,systemd 执行 podman stop 命令来停止容器
  3. 当 systemd 关闭了容器,systemd 使用 podman rm 命令删除容器

相反,下例显示在运行 podman generate systemd 命令时不带 --new 选项时的开始和停止指令:

$ podman run -d --name www -p 8888:8080 \
registry.lab.example.com/rhel8/httpd-24:1-105
$ podman generate systemd --name www
  1. 启动时,systemd 执行 podman start 命令来启动已存在的容器
  2. 停止时,systemd 执行 podman stop 命令来停止容器。 注:systemd 不会删除容器

6.7 使用 Systemd 启动和停止容器

使用 systemctl 命令控制容器

$ systemctl --user start container-web
$ systemctl --user stop container-web
$ systemctl --user status container-web

重要:使用 systemctl 命令管理的容器由 systemd 控制。systemd 监视容器状态,并在它们失败时重新启动它们。不要使用 podman 命令来启动或停止这些容器。这样做可能会干扰 systemd 监视

6.8 配置在主机启动时启动的容器

默认情况下,已启用的 systemd user service 在用户打开第一个会话时启动,在用户关闭最后一个会话时停止。 要让 user service 随服务器自动启动,请运行 loginctl enable-linger 命令:

$ loginctl enable-linger

要使容器在主机启动时启动:

$ systemctl --user enable container-web

要在主机启动时禁用容器启动:

$ systemctl --user disable container-web

6.9 使用 Systemd 管理以 root 运行的容器:

  • 还可以配置希望作为 root 用户运行的容器,以便使用 Systemd unit 文件管理它们
  • 优点是可以将这些 unit 文件配置为与普通 unit 单元文件完全相同的工作方式,而不需要一个特定的用户
  • 设置这些容器的过程与前面介绍的无根容器类似,不同之处在于:
  • 不需要设置专用用户
  • 当使用 podman generate systemd 创建 unit 文件时,请在 /etc/systemd/system 中运行,而不是在 ~/.config/systemd/user 中
  • 当用 systemctl 配置容器的服务时,将不会使用 --user 选项
  • 不需要以 root 用户身份运行:loginctl enable-linger

6.10 规模化编排容器:

  • 在本章学习了如何在单个主机上通过命令行手动配置和管理容器,以及如何配置Systemd 以便容器与服务器一起自动启动。这在很小的范围内非常有用,有助于了解许多关于容器的知识
  • 然而,大多数企业需要部署更多容器。Kubernetes 通常用于管理由多个协作容器组成的复杂应用程序
  • Red Hat OpenShift 是一个 Kubernetes 平台,它添加了基于 web 的用户界面、监控、在集群中的任何位置运行容器的能力、自动缩放、日志记录和审计等
  • 讨论这些工具超出了本课程的范围。如果想了解更多信息,Red Hat 培训还提供了其他课程,从免费的技术概览课程: Deploying Containerized Applications(DO080)开始,到 Introduction to Containers, Kubernetes, and OpenShift(DO180)。更多信息,请访问 https://www.redhat.com/training
  • 也可以从 https://www.openshift.com了解更多关于 Kubernetes 和 Red Hat OpenShift 的信息

总结

  • 容器提供了一种轻量级的方式来分发和运行应用程序及其依赖关系,而这些依赖关系可能与主机上安装的软件发生冲突
  • 容器从容器映像运行,您可以从容器注册表下载或自己创建
  • 由 Red Hat Enterprise Linux 提供的 Podman 可在单个主机上直接运行和管理容器以及容器映像
  • 容器可以作为 root 用户运行,也可以作为非特权的无根容器运行,以提高安全性
  • 你可以映射容器主机上的网络端口,以将流量传递到在其容器中运行的服务。 您还可以使用环境变量在容器中配置软件
  • 容器存储是临时的,但是你可以使用例如容器主机上目录的内容将持久性存储附加到容器
  • 你可以将 Systemd 配置为在系统启动时自动运行容器