容器生命週期管理是容器化應用程式佈署的關鍵環節。Podman 提供了全面的命令集,方便開發者和系統管理員有效地管理容器。從啟動、停止、重啟已有的容器,到建立新的容器例項,Podman 提供了直觀的命令列介面。此外,podman pause 和 podman unpause 命令允許暫停和還原容器內的程式,而無需完全停止容器,這對於需要暫時凍結應用程式但又不想重新啟動的場景非常有用。刪除容器時,可以選擇刪除已停止的容器或強制刪除正在執行的容器,並可搭配批次操作提高效率。
管理執行中的容器
當容器停止運作時,可以觀察到其狀態顯示已離開並伴隨 0 的離開程式碼。
啟動已停止的容器
使用 podman start 命令可以還原已停止的容器。如下所示:
$ podman start d8bbd5da64d0
此命令簡單地重新啟動之前停止的容器。若再次檢查容器狀態,將發現其已啟動並正在執行,如下所示:
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d8bbd5da64d0 docker.io/library/nginx:latest nginx -g daemon... 8 minutes ago Up 1 second ago 0.0.0.0:8080->80/tcp unruffled_saha
Podman 會保留容器的組態、儲存和後設資料,只要其處於停止狀態。當還原容器時,實際上是在其中啟動了一個新的程式。
重啟執行中的容器
若需要重啟正在執行的容器,可以使用 podman restart 命令,如下所示:
$ podman restart <Container_ID_or_Name>
此命令會立即重啟容器內的程式,並賦予新的程式 ID(PID)。
建立與啟動容器
podman create 命令允許建立容器但不立即啟動它。如下所示:
$ podman create -p 8080:80 docker.io/library/nginx
可以透過 podman start 命令來啟動建立好的容器:
$ podman start <Container_ID_or_Name>
這對於準備環境而不立即執行,或掛載容器檔案系統非常有用。
刪除容器
podman rm 命令用於從主機中刪除容器。預設情況下,它刪除已停止的容器,但可以使用 -f 選項強制刪除正在執行的容器。
刪除已停止的容器範例
$ podman stop d8bbd5da64d0
$ podman rm d8bbd5da64d0
執行上述命令後,容器的儲存、組態和後設資料將被丟棄。
列出容器
使用 podman ps 命令可以列出容器。結合 -a 選項,可以列出所有(包括停止和正在執行的)容器。
篩選與格式化輸出
podman ps 命令支援多種篩選條件和格式化選項。例如,可以使用 --filter 選項按狀態篩選容器:
$ podman ps --filter status=exited
也可以使用 --format 選項自定義輸出格式,如下所示:
$ podman ps -a --format "{{.ID}} {{.Command}}" --no-trunc
上述命令輸出容器的 ID 和執行的命令,且不會截斷命令輸出。
批次操作
透過結合 shell 的擴充套件功能,可以批次停止和刪除容器,如下所示:
$ podman stop $(podman ps -qa)
$ podman rm $(podman ps -qa)
或者,使用 podman container prune 命令刪除所有停止的容器:
$ podman container prune
暫停與還原容器
本文介紹了 podman pause 和 podman unpause 命令,用於暫停和還原執行中的容器的程式。這些命令利用控制群組(cgroups)實作特定的目的。
暫停與停止容器的區別在於,暫停只是凍結容器的程式,而不終止它們;停止則是終止容器的主程式。
暫停與還原範例
$ podman pause <Container_ID_or_Name>
$ podman unpause <Container_ID_or_Name>
這些命令對於需要臨時凍結容器程式的場景非常有用。
管理執行中的容器
當容器執行時,Podman 提供了多種命令來監控和修改容器的狀態。本章節將探討如何使用這些命令。
暫停和取消暫停容器
podman stop 命令只是向容器中的父行程傳送 SIGTERM/SIGKILL 訊號,而 podman pause 命令則使用 cgroups 暫停行程而不終止它。當容器被取消暫停時,同一個行程將被透明地還原。
例項:使用 podman pause 和 unpause 命令
首先,讓我們啟動一個 Fedora 容器,使其每 2 秒列印一個日期和時間字串,如下所示:
$ podman run --name timer docker.io/library/fedora bash -c "while true; do echo $(date); sleep 2; done"
在另一個終端機視窗中,我們可以使用以下命令檢查容器的 PID:
$ podman ps --format "{{ .Pid }}" --filter name=timer
816807
現在,讓我們暫停正在執行的容器:
$ podman pause timer
如果我們回到 timer 容器,我們會看到輸出已經暫停,但容器尚未離開。取消暫停操作將使其還原執行:
$ podman unpause timer
取消暫停後,timer 容器將再次開始列印日期輸出。檢視 PID,我們發現它沒有變化,正如預期的那樣:
$ podman ps --format "{{ .Pid }}" --filter name=timer
816807
檢查 cgroups 狀態
我們可以檢查暫停/取消暫停容器的 cgroups 狀態。在第三個終端機視窗中,以 root 身份開啟一個終端機並存取 cgroupfs 控制器的階層結構(請替換正確的容器 ID):
$ sudo –i
$ cd /sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/user.slice/libpod-<CONTAINER_ID>.scope/container
現在,檢視 cgroup.freeze 檔案的內容。這個檔案儲存了一個布林值,其狀態會隨著我們暫停/取消暫停容器而在 0 和 1 之間變化。嘗試再次暫停和取消暫停容器以測試這些變化。
清理提示
由於 echo 迴圈是使用 bash –c 命令發出的,我們需要向行程傳送 SIGKILL 訊號。要做到這一點,我們可以停止容器並等待 10 秒的逾時,或者簡單地執行 podman kill 命令,如下所示:
$ podman kill timer
檢查容器內部的行程
當容器正在執行時,容器內部的行程在 namespace 層級是隔離的,但使用者仍然可以完全控制正在執行的行程並檢查其行為。Podman 提供了多種工具來加速這項任務。
使用 podman top 命令
podman top 命令提供了容器內部正在執行的行程的完整檢視。下面的例子顯示了 nginx 容器內部正在執行的行程:
$ podman top f2666ed4a46a
USER PID PPID %CPU ELAPSED TTY TIME COMMAND
root 1 0 0.000 3m26.540290427s ? 0s nginx: master process nginx -g daemon off;
nginx 26 1 0.000 3m26.540547429s ? 0s nginx: worker process
nginx 27 1 0.000 3m26.540788803s ? 0s nginx: worker process
nginx 28 1 0.000 3m26.540914386s ? 0s nginx: worker process
nginx 29 1 0.000 3m26.541040023s ? 0s nginx: worker process
nginx 30 1 0.000 3m26.541161213s ? 0s nginx: worker process
nginx 31 1 0.000 3m26.541297546s ? 0s nginx: worker process
nginx 32 1 0.000 3m26.54141773s ? 0s nginx: worker process
nginx 33 1 0.000 3m26.541564289s ? 0s nginx: worker process
nginx 34 1 0.000 3m26.541685475s ? 0s nginx: worker process
nginx 35 1 0.000 3m26.541808977s ? 0s nginx: worker process
nginx 36 1 0.000 3m26.541932099s ? 0s nginx: worker process
nginx 37 1 0.000 3m26.54205111s ? 0s nginx: worker process
結果與 ps 命令的輸出非常相似,而不是 Linux top 命令產生的互動式輸出。
自訂格式化輸出
可以對輸出套用自訂格式化。下面的例子只列印 PID、命令和引數:
$ podman top f2666ed4a46a pid comm args
PID COMMAND COMMAND
1 nginx nginx: master process nginx -g daemon off;
26 nginx nginx: worker process
27 nginx nginx: worker process
28 nginx nginx: worker process
29 nginx nginx: worker process
30 nginx nginx: worker process
31 nginx nginx: worker process
32 nginx nginx: worker process
33 nginx: worker process
34 nginx: worker process
35 nginx: worker process
36 nginx: worker process
37 nginx: worker process
詳細檢查容器行程
我們可能需要更詳細地檢查容器行程。如前所述,一旦啟動了一個全新的容器,它將從編號 0開始分配 PID,而在底層,容器引擎將把這個容器的 PID 與主機上的真實 PID 對映起來。因此,我們可以使用 podman ps --namespace 命令的輸出來提取給定容器的主機上的原始 PID。有了這些資訊,我們就可以進行進階分析。
下面的例子展示瞭如何將 strace 命令(用於檢查行程的系統呼叫)附加到容器內部正在執行的行程:
$ sudo strace –p <PID>
有關 strace 命令的用法詳情超出了本文的範圍。請參閱 man strace 以取得更多進階範例和對命令選項的更深入的解釋。
另一個有用的命令是 pidstat。一旦我們獲得了 PID,我們就可以用以下方式檢查資源使用情況:
$ pidstat –p <PID> [<interval> <count>]
末尾套用的整數分別代表命令的執行間隔和必須列印使用統計資料的次數。有關更多用法選項,請參閱 man pidstat。
處理無回應的行程
當容器中的行程變得無回應時,可以使用 podman kill 命令處理其突然終止。預設情況下,它向容器內部的行程傳送 SIGKILL 訊號。下面的例子建立了一個 httpd 容器,然後殺死它:
$ podman run --name custom-webserver -d docker.io/library/httpd
$ podman kill custom-webserver
管理執行中的容器
當容器在主機上執行時,管理員需要能夠監控其資源使用情況並對容器進行故障排除。Podman 提供了一系列命令來實作這些功能。
監控容器統計資訊
當多個容器在同一主機上執行時,監控它們的 CPU、記憶體、磁碟和網路資源使用情況至關重要。管理員可以使用 podman stats 命令來實作這一點。
使用 podman stats 命令
$ podman stats
此命令會開啟一個類別似 top 的自重新整理視窗,顯示所有執行中容器的統計資訊。預設輸出的欄位包括:
- ID:執行中的容器 ID
- NAME:執行中的容器名稱
- CPU %:總 CPU 使用率百分比
- MEM USAGE / LIMIT:記憶體使用量與限制
- MEM %:總記憶體使用率百分比
- NET IO:網路輸入/輸出(I/O)操作
- BLOCK IO:磁碟 I/O 操作
- PIDS:容器內的 PID 數量
- CPU TIME:總消耗的 CPU 時間
- AVG CPU %:平均 CPU 使用率百分比
若需要靜態輸出,可以使用 --no-stream 選項:
$ podman stats --no-stream
自定義輸出格式
為了便於解析或擷取,可以使用 JSON 或 Go 範本格式化輸出。以下範例以 JSON 格式輸出統計資訊:
$ podman stats --format=json
[
{
"id": "e263f68bbb83",
"name": "infallible_sinoussi",
"cpu_time": "33.518ms",
"cpu_percent": "2.05%",
"avg_cpu": "2.05%",
"mem_usage": "19.3MB / 33.38GB",
"mem_percent": "0.06%",
"net_io": "-- / --",
"block_io": "-- / --",
"pids": "13"
}
]
同樣地,可以使用 Go 範本自定義輸出欄位。以下範例僅輸出容器 ID、CPU 使用率百分比、總記憶體使用量(以位元組為單位)和 PID 數量:
$ podman stats -a --no-stream --format "{{ .ID }} {{ .CPUPerc }} {{ .MemUsageBytes }} {{ .PIDs }}"
內容解密:
podman stats命令提供了即時的容器資源使用情況。- 使用
--no-stream選項可以取得靜態輸出,便於進一步處理。 --format選項允許自定義輸出格式,支援 JSON 和 Go 範本,能夠根據需求擷取特定的統計資訊。
檢查容器資訊
Podman 的 podman inspect 命令可以用於列印容器的組態和執行階段資訊。
使用 podman inspect 命令
$ podman inspect <Container_ID_or_Name>
此命令會以 JSON 格式輸出容器的組態資訊。其中一些值得注意的欄位包括:
- Path:容器的進入點路徑。
- Args:傳遞給進入點的引數。
- State:容器的目前狀態,包括執行的 PID、OCI 版本和健康檢查狀態等資訊。
- Image:用於執行容器的映像檔 ID。
- Name:容器名稱。
- MountLabel 和 ProcessLabel:與 SELinux 相關的標籤設定。
- EffectiveCaps:套用到容器的有效許可權。
- GraphDriver:儲存驅動程式的型別和相關的 Overlay 目錄資訊。
- Mounts:容器內的掛載點。
- NetworkSettings:容器的網路設定,包括內部 IP 位址、暴露的連線埠和連線埠對映。
- Config 和 HostConfig:容器的執行階段組態和主機組態。
自定義 podman inspect 輸出
可以使用 --format 選項來擷取特定的欄位。以下範例僅輸出容器內執行的行程的主機繫結 PID:
$ podman inspect <ID or Name> --format "{{ .State.Pid }}"
內容解密:
podman inspect命令提供了詳細的容器組態和執行階段資訊。- 使用
--format選項可以根據需求擷取特定的資訊,支援 Go 範本格式化輸出。
實際操作範例
建立一個測試容器
# podman run --name logger -d docker.io/library/fedora bash -c "while true; do echo test >> /tmp/test.log; sleep 5; done"
此命令會建立一個名為 logger 的容器,並在其中執行一個迴圈,每 5 秒向 /tmp/test.log 檔案寫入字串。
檢查 OverlayFS 的 MergedDir
# podman inspect logger --format "{{ .GraphDriver.Data.MergedDir }}"
/var/lib/containers/storage/overlay/27d89046485db7c775b108a80072eafdf9aa63d14ee1205946d74623fc195314/merged
檢查 MergedDir 可以幫助我們瞭解 OverlayFS 如何合併各個層。
檢視 MergedDir 中的檔案
# cat /var/lib/containers/storage/overlay/27d89046485db7c775b108a80072eafdf9aa63d14ee1205946d74623fc195314/merged/tmp/test.log
test
test
test
test
test
[...]
內容解密:
- 建立測試容器,模擬實際應用場景,用於後續的檢查操作。
- 使用
podman inspect命令查詢 MergedDir 路徑,瞭解 OverlayFS 的儲存結構。 - 直接檢視 MergedDir 中的檔案,驗證容器的寫入操作是否正確反映在檔案系統中。
綜上所述,Podman 提供了一系列強大的工具來管理和監控執行中的容器,包括 podman stats 和 podman inspect 命令。這些工具對於維護容器的健康狀態和除錯問題至關重要。透過這些命令,管理員可以獲得有關容器資源使用情況和組態的詳細資訊,從而更好地進行最佳化和故障排除。