8. podman -- 使用 systemd 來管理某個容器



 

通過 systemd 來管理容器,

  • 並非是讓 systemd 來管理 podman 這個程序的 start,stop,...,而是讓 systemd 來管理某個容器的 start,stop,...

  • 實現某個容器需要在開機的時候自動運行,

  • 實現某個容器通過 systemctl start 來啟動,systemctl stop 來刪除

 

1. podman generate 的幫助文檔

systemd 的時候說過,可以自定義 unitservice 之類,

podman 中,通過下面的命令,將某個容器加入到 systemd 的管理范圍

podman generate

Generate structured data based on containers, pods or volumes

 
man podman-generate

┌────────┬─────────────────────────┬────────────────────────────────────┐
│Command │ Man Page                │ Description                        │
├────────┼─────────────────────────┼────────────────────────────────────┤
│kube    │ podman-generate-kube    │ Generate Kubernetes YAML based on  │
│        │                         │ containers, pods or volumes.       │
├────────┼─────────────────────────┼────────────────────────────────────┤
│systemd │ podman-generate-systemd │ Generate systemd unit file(s) for  │
│        │                         │ a container or pod.                │
└────────┴─────────────────────────┴────────────────────────────────────┘

 
podman generate 能生成 systemdunit 文件,另外一個是 k8sYAML 文件,很明顯,此處應該使用

man podman-generate-systemd
podman generate systemd

Generate systemd unit file(s) for a container or pod


 

2. --name 選項

Use the name of the container for the start, stop, and description in the unit file

也就是說,這個選項並不是接受一個參數,來作為服務的名字,

而是使用容器的名字按照規則來命名 unit

對於容器來說,命名規則是:

container-name.service 或者是 container-id.service

也就是說,如果容器名為 test,那么配置完成后就是 systemctl start container-test.service

當然也可以通過下面參數來修改 unit 名的前綴

--container-prefix string

Systemd unit name prefix for containers (default "container")

 
例子:
 

 

如上,

首先(1)運行一個名為 test_http 的容器,

其次(2)通過 generate 生成能被 systemd 管理的 unit 的配置文件

如上描述,該 unit 的名字為 前綴 container 和 容器名的組合


 

3. --files

 

至此,雖然已經有了給出的配置文件,但后續還需要自己寫入指定的位置總是麻煩,

可以通過 --files | -f 參數來完成:

Generate files instead of printing to stdout.
The generated files are named container-name.service 或者是 container-id.service and will be placed in the current working directory.

  • 默認情況下,會將生成內容打印再屏幕上,上圖的樣子;使用 -f 就會直接在當前目錄生成文件。

  • 同樣,也不接受參數

  • 因為是當前目錄下生成,因此需要 copysystemd 的目錄下,

(/etc/systemd/system/xxxx 通常是 /usr/lib/systemd/system/xxxx 的鏈接)

 
修改如上的例子:

 

 

如上,

(1)運行一個名為 test-thhp 的容器

(2)切換到 systemd 目錄,生成配置文件的時候使用了 --files 參數,當前目錄下也出現了預期的文件。

podman stop 該容器,緊接着 systemctl startps 能看到容器的狀態為 Up

(3)systemctl stop,發現容器的狀態為 Exited


 

4. --new

 

關於這個參數,先看實例

 

 

如上,

(2)中生成 systemd 配置文件的時候,多了一個 --new

(3)差別在於 systemctl stop 的時候,podman ps -a 查看,容器已經被刪除,

而上個例子中,沒有 --new 選項,systemctl stop 的時候,容器是 Exited


 

5. 普通用戶來創建 systemd 管理的容器

5.1 問題

 
前面的示例都是在 root 用戶下進行的操作,

但是不同用戶的 podman 操作都是隔離的,

前面說過,root 的 podman 有 httpd 這個鏡像,切換到 xyz 用戶的時候,那么就得重新下載這個鏡像了。

使用 systemd 來管理容器也有類似的情況

 

 

如上,

(1)通過 systemctl stop 刪除了容器

(2)切換到用戶 xyz,並 systemctl start 容器,

啟動后發現 podman ps -a 並不看到容器

(3)退出,切換到 root,發現(2)啟動的是 root 下的容器

 

在來例子:
 

 

如上,普通用戶的操作

(1)運行容器 t1

(2)切換到 systemd 目錄,試圖生成配置文件

但是遇到了紅框中的 permission denied,

使用 sudo 的時候,又說找不到 t1 這個容器,即使 t1 是 Up 的,

因為 sudo 了,那自然身份就是 root,root 就找不到 xyz 的 t1 這個容器

 

5.2 解決

 

運行 systemctl 的時候,有兩種模式

  • --system (系統級別,默認,因此平時都不寫這個選項)

  • --user 用戶級別

 
此處就是使用用戶級別來解決這個問題

用戶級別 systemd 的目錄:

  • /usr/lib/systemd/user/ 優先級低

  • /etc/systemd/user/ 里面的文件也是上面這個鏈接

  • ~/.config/systemd/user/ 優先級最高

  • ~/.local/share/systemd/user/

 

如上,

(1)(2)正常的啟動服務,生成配置文件

到(3)的時候

  • 需要重新加載 unit,因此使用 daemon-reloadreload 是重載指定的服務,如 apache 重載自己的配置,和 daemon-reload 是不一樣的。

  • 對於 su - xyz 的方式,能順利創建 配置文件,但是在加載服務的時候會報錯

https://access.redhat.com/discussions/6029491

Make sure that you aren't working in a 'sudo' or 'su' session.
The command only works when ssh-ing into your system or logging in to console.
 

因此,通過 ssh 的方式重開一個終端,進行 daemon-reload 的操作,

  • 注意這些操作都不要忘記 --user

  • 操作沒錯,遇到問題,看看是不是 su - 的方式切換用戶,使用 ssh

 

繼續:
 

 

如上,

(4)手動刪除掉 t1 這個容器

(5)通過 systemctl --user 來啟動,停止 t1 這個容器

 

6. loginctl

6.1 問題

 
對於 --system 的服務來說,

enable 的服務會在系統啟動時啟動,系統關閉時停止。
 
而 --user 的服務(非 root 用戶的情況下),有說:
當打開會話的時候,服務會自動啟動,
但是當所有會話都關閉的時候,服務會自動停止
(服務時伴隨會話啟停,而非伴隨系統啟停)

 
舉個下面這個例子來測試:

運行一個 http 容器 ,宿主機 8000 端口(server1:8000)映射到 容器的 80,

配置 --user 級別的 systemd 來管理,

在 active 的狀態下,退出所有宿主機 server1 的會話,

從另一主機 server2 訪問 server1:8000,

如果如上所說的話,那么應該訪問失敗。
 
測試如下:
 

 
如上:
(1)運行容器 http-server,並映射本地 8000 端口到容器的 80 端口,測試訪問宿主機上的 8000 端口,訪問成功

(2)生成 systemd 的配置文件,並重載 --user 級別的 unit

(是需要 ssh 之類的操作到 containers 用戶,而非 su - containers)

 

 
如上,systemctl start/enable 來管理這個容器

 

 

如上,因為測試是要訪問宿主機 server1 的 8000 端口,

所以需要在 server1 中,root 狀態下放行 8000 端口和 http 服務

 

 

如上,
退出了所有 server1 的會話,

ssh containers@server1 后查看到,容器是 active / up 的狀態,

此時,在 server2 中,訪問 server1:8000 端口,訪問正常

退出這最后一個會話,

再回到 server2 中,訪問 server1:8000,訪問失敗

  • 由此,側面印證了,--user 級別的服務,退出所有會話后,服務自動停止

 

6.2 解決 -- loginctl

 

如果需要會話關閉后,服務也一直在運行(linger)

需要使用 loginctl enable-linger

loginctl enable-linger [USER...]
loginctl disable-linger [USER...]

If enabled for a specific user,
a user manager is spawned for the user at boot and kept around after logouts.
This allows users who are not logged in to run long-running services.

 

loginctl show-user USER

 

 

修改並測試

 

 

如上,
(1)enable-linger

(2)容器狀態為 active / up,

(3)server2 訪問正常;
退出 server1 的所有會話,

(4)和前面不一樣,雖然 server1 的所有會話都已經退出,但是 server2 中,訪問依舊正常


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM