Quadlet | 结合Systemd优雅启动容器(containers)

实践 | Practices 2024年8月14日

在Quadlet还未出现之前

我一直使用generate systemd生成systemd单元文件以便启动Podman容器

但现在看来

还可以更优雅


示例环境

OS

Podman Version

Quadlet小知识

什么是Quadlet?

Quadlet 是 Podman 中的一个功能,用于简化容器、Pod 和网络的系统级管理,通过 systemd 配置文件直接定义和管理容器服务。

核心概念

Quadlet 允许使用 .container, .pod, .network 文件直接定义容器或 Pod,这些文件会自动转换为 systemd 单元文件。

  • 类似于 docker-compose 的功能,但更紧密集成在 systemd 生态中,符合 Linux 原生服务管理方式。
  • Quadlet 通过少量配置简化了 Podman 容器的管理和自启动。

优势

  • 与 systemd 集成:容器可作为 systemd 服务管理,支持开机启动、自动重启等。
  • 简化配置:比手动写复杂的 systemd 服务文件更简单,减少容器管理复杂性。
  • 自动生成:Quadlet 会根据 .container 文件自动生成标准的 systemd 文件,便于统一管理。
  • 模块化:支持容器、Pod、网络独立定义,便于维护和扩展。

工作原理

  1. 在 /etc/containers/systemd/ 或 ~/.config/containers/systemd/ 目录中创建 .container 或 .pod 文件。
  2. 使用 systemctl 启动或管理容器,Podman 会自动解析并运行定义的容器。
  3. Quadlet 将配置文件自动转化为对应的 systemd 单元文件,位于 /etc/systemd/system/。

总结

Quadlet 是 Podman 提供的 systemd 友好型容器管理工具,特别适合需要将容器作为系统服务运行的场景。
它简化了复杂的 systemd 服务文件编写过程,同时保留了 Podman 的无守护进程优势,非常适合自建服务和自动化部署。

需要安装吗?

自Podman 4.4后

Quadlet合并至Podman

因此不需要安装

Quadlet使用流程

  1. 编写Quadlet配置文件
  2. 使用systemd重载新的单元文件(此时systemd会生成相应容器的单元文件,相应容器交予systemd接管)
  3. 使用 systemctl start/stop/status 管理相应的容器

Quadlet配置文件路径

对于Root用户来说,Quadlet的配置文件位于以下两个目录

  • /etc/containers/systemd/
  • /usr/share/containers/systemd/

对于其他用户来说则是以下目录

  • $XDG_CONFIG_HOME/containers/systemd/ or ~/.config/containers/systemd/
  • /etc/containers/systemd/users/$(UID)
  • /etc/containers/systemd/users/

Quadlet使用流程

编写Quadlet配置文件

让我们以Scrutiny容器的Quadlet配置文件为例来说明一下

可以看到配置文件以.container结尾且位于/usr/share/containers/systemd/

➜  ~ ll /usr/share/containers/systemd/scrutiny.container
-rw-r--r-- 1 root root 585 May 22 02:31 /usr/share/containers/systemd/scrutiny.container
➜  ~

查看配置文件如下所示

➜  ~ cat  /usr/share/containers/systemd/scrutiny.container
[Unit]
Description=WebUI for smartd S.M.A.R.T monitoring
After=network-online.target
Wants=network-online.target
Before=shutdown.target

[Container]
AutoUpdate=registry
AddCapability=SYS_RAWIO
AddDevice=/dev/sda
AddDevice=/dev/sdb
AddDevice=/dev/sdc
AddDevice=/dev/sdd
AddDevice=/dev/sde
ContainerName=scrutiny
Image=ghcr.io/analogj/scrutiny:master-omnibus
PublishPort=10.7.7.7:41523:8080
PublishPort=10.7.7.7:41524:8086
Volume=scrutiny:/opt/scrutiny/config
Volume=scrutiny:/opt/scrutiny/influxdb
Volume=/run/udev:/run/udev:ro
Timezone=Asia/Shanghai

[Install]
WantedBy=multi-user.target default.target
➜  ~

可以看到大致有三部分组成分别为

  • Unit
  • Container
  • Install

除Container外,其余配置将会被同步至Systemd单元文件

以上述配置为例,详解一下各部分配置

Unit

此项共写入了四个参数,分别为

  • Description
    • 对于此Systemd的描述
  • After
    • 在哪个单元后启动
  • Wants
    • 启动此单元需要哪些单元
  • Before
    • 在哪些单元关闭前关闭此单元

Container

  • AutoUpdate=registry
    • 是否自动更新此容器
  • AddCapability=SYS_RAWIO
    • 等效于Podman run 命令行中的 --cap-add SYS_RAWIO
  • AddDevice=/dev/sda
    • 等效于Podman run 命令行中的 --device /dev/sda
  • ContainerName=scrutiny
    • 设定容器名称,等效于Podman run 命令行中的 --name scrutiny
  • Image=ghcr.io/analogj/scrutiny:master-omnibus
    • 启动此容器所需镜像(名称格式需要与Podman Pull命令行中赋予的一致)
  • PublishPort=10.7.7.7:41523:8080
    • 映射容器端口,等效于我们熟悉的 -p
  • Volume=scrutiny:/opt/scrutiny/config
    • 卷映射,等效于我们熟悉的-v
  • Timezone=Asia/Shanghai
    • 时区配置,等效于Podman run 命令行中的--tz Asia/Shanghai

Install

使用Quadlet创建的service单元文件被视为瞬态,所以不能使用传统的 systemctl enable让其自启

但可以在Quadlet配置文件中的[Install]一项添加WantedBy=multi-user.target default.target让其开机自启

配置文件看起来是

[Install]
WantedBy=multi-user.target default.target

如若设定后发现并不可以开机自启,通常是因为容器准备启动时设备网络状态未就绪,容器无法监听对应接口导致启动失败,请正确配置启动顺序(上述演示配置文件已配置完毕)

生成systemd单元文件

使用以下命令生成Systemd单元文件

systemctl daemon-reload

接着我们查看一下生成的单元文件

systemctl cat *.service

若无法查到对应的单元文件,说明Quadlet配置文件有问题,请检查后重试

启动相应容器

systemctl start *.service

Podlet

假如说因我表述能力问题

各位尚未学会如何编写Quadlet配置文件

那么我们可以使用Podlet来自动生成Quadlet配置文件

Github主页

GitHub - containers/podlet: Generate Podman Quadlet files from a Podman command, compose file, or existing object
Generate Podman Quadlet files from a Podman command, compose file, or existing object - containers/podlet

软件版本

使用流程示例

下述操作Copy自Github主页

假如我们有如下命令

podman run \
  --restart always \
  -p 8000:80 \
  -p 8443:443 \
  -v ./Caddyfile:/etc/caddy/Caddyfile:Z \
  -v caddy_data:/data \
  docker.io/library/caddy:latest

可以看到我们现在需要使用caddy:latest镜像生成一个容器

该容器开放80/443端口至host的8000/8443端口,并且映射了相应的主机目录


下面我们使用Podlet来自动生成Quadlet配置文件

$ podlet --file . --install --description Caddy \
  podman run \
  --restart always \
  -p 8000:80 \
  -p 8443:443 \
  -v ./Caddyfile:/etc/caddy/Caddyfile:Z \
  -v caddy_data:/data \
  docker.io/library/caddy:latest

Wrote to file: ./caddy.container

$ cat caddy.container

[Unit]
Description=Caddy

[Container]
Image=docker.io/library/caddy:latest
PublishPort=8000:80
PublishPort=8443:443
Volume=./Caddyfile:/etc/caddy/Caddyfile:Z
Volume=caddy_data:/data

[Service]
Restart=always

[Install]
WantedBy=default.target

可以看到我们只需将Podlet Shell置于原有的Podman shell之上

它就可以为我们自动生成Quadlet配置文件 非常之方便

总结

若您在使用Podman

Quadlet和Podlet 是不可多得的优秀辅助工具

这将使我们更加方便优雅的管理我们的容器

抄袭

GitHub - containers/podlet: Generate Podman Quadlet files from a Podman command, compose file, or existing object
Generate Podman Quadlet files from a Podman command, compose file, or existing object - containers/podlet
GitHub - containers/quadlet
Contribute to containers/quadlet development by creating an account on GitHub.
podman-systemd.unit — Podman documentation
quadlet(5) — Arch manual pages

标签

xzllll

三分钟热度三分钟收获