在容器化應用程式管理中,暫停和還原容器扮演著重要的角色,允許我們在不終止應用程式的情況下,暫時停止其執行,並在需要時快速還原。Podman 提供了 podman pausepodman unpause 命令來實作這個功能。不同於 podman stop 命令會傳送 SIGTERMSIGKILL 訊號終止容器行程,podman pause 利用控制群組(cgroups)的 freeze 子系統,將容器內的行程狀態凍結,使其暫停執行,而 podman unpause 則解除凍結,還原行程的執行。這種機制在除錯、資源排程和應用程式維護等場景下非常實用,例如,我們可以在更新容器組態或進行系統維護時暫停容器,避免服務中斷,並在完成操作後還原容器的執行。此外,cgroups 的 freeze 子系統提供了一個精細的行程控制機制,可以更有效地管理容器資源,並提高系統整體的穩定性和效能。

暫停與還原容器:控制群組的妙用

Podman 使用控制群組(cgroups)來實作容器的暫停和還原。podman pause 命令會暫停容器內的所有行程,而 podman unpause 命令則會還原這些行程。

podman pause vs podman stop:有什麼區別?

podman pausepodman stop 命令的功能不同。podman pause 只是暫停容器的行程,容器的狀態仍然保留。而 podman stop 則會停止容器的執行,並釋放相關資源。

玄貓在此總結了 Podman 容器管理的各項技巧,希望能幫助大家更有效地使用 Podman。

玄貓解析:容器執行時的管理與行程檢視

在容器化的世界中,有效地管理執行中的容器至關重要。podman 提供了多種指令,讓我們可以暫停、還原容器,甚至深入檢視容器內部的行程。本文將以玄貓的角度,探討這些實用技巧。

容器的暫停與還原:pauseunpause 指令

podman stop 指令透過傳送 SIGTERM/SIGKILL 訊號來終止容器中的父行程。但有時候,我們可能只是想暫時停止容器的執行,而不是完全終止它。這時候,podman pause 指令就派上用場了。

podman pause 利用 cgroups 的特性,在不終止行程的情況下暫停容器。當容器被還原時,相同的行程會無縫接續執行。

小提示: 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 指令暫停容器:

$ podman pause timer

回到 timer 容器的視窗,你會發現輸出停止了,但容器並沒有離開。接下來,使用 podman unpause 指令還原容器:

$ podman unpause timer

容器會再次開始輸出日期和時間。再次檢查 PID,你會發現它沒有改變:

$ podman ps --format "{{ .Pid }}" --filter name=timer
816807

深入 Cgroups:探索容器的凍結狀態

我們還可以透過 cgroups 來檢查容器的暫停/還原狀態。開啟第三個終端視窗,取得 root 許可權,然後進入 cgroupfs 控制器層級:

$ sudo –i
$ cd /sys/fs/cgroup/user.slice/user-1000.slice/user@1000.service/user.slice/libpod-<CONTAINER_ID>.scope/container

注意:<CONTAINER_ID> 替換為正確的容器 ID。

檢視 cgroup.freeze 檔案的內容。這個檔案包含一個布林值,當我們暫停/還原容器時,它的狀態會在 0 和 1 之間切換。你可以多次暫停和還原容器來驗證這個變化。

清理技巧:終止 bash -c 啟動的迴圈

如果迴圈是透過 bash -c 命令啟動的,我們需要傳送 SIGKILL 訊號來終止行程。可以使用 podman stop 指令並等待 10 秒超時,或者直接使用 podman kill 指令:

$ podman kill timer

檢視容器內部的行程: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 nginx: worker process
34 nginx nginx: worker process
35 nginx nginx: worker process
36 nginx nginx: worker process
37 nginx nginx: worker process

進階行程檢視:stracepidstat 指令

有時候,我們需要更詳細地檢視容器行程。當一個新的容器啟動時,它會從 0 開始分配 PID。容器引擎會將這些容器的 PID 對映到主機上的真實 PID。

透過 podman ps --namespace 指令,我們可以提取容器行程在主機上的原始 PID,然後使用 stracepidstat 等工具進行進階分析。

例如,以下指令將 strace 指令附加到容器內部的行程:

$ sudo strace –p <PID>

strace 指令用於檢視行程的系統呼叫(syscalls)。

另一個有用的指令是 pidstat,它可以檢視容器行程的資源使用情況:

$ pidstat –p <PID> [<interval> <count>]

intervalcount 引數分別表示指令的執行間隔和輸出統計資訊的次數。

強制終止無回應的行程:podman kill 指令

當容器中的行程變得沒有回應時,可以使用 podman kill 指令來強制終止它。預設情況下,這個指令會傳送 SIGKILL 訊號給容器內部的行程。

例如,以下指令建立一個 httpd 容器,然後終止它:

$ podman run --name custom-webserver -d docker.io/library/httpd
$ podman kill custom-webserver

玄貓在本篇文章中詳細介紹瞭如何監控和修改容器的狀態,以及如何檢視容器內部執行的行程。掌握這些技巧,能幫助你更好地管理和除錯容器化應用程式。

容器執行管理:探討與實戰技巧

在容器化技術中,有效管理執行中的容器至關重要。這不僅包括啟動和停止容器,還涉及到監控資源使用情況、檢測容器組態以及進行故障排除。作為一位在分散式系統和容器化領域有多年經驗的技術專家,玄貓將分享一些關於容器管理的實戰技巧和深入見解。

停止與訊號控制:優雅地結束容器生命週期

停止容器最常用的方式是使用 podman stop 命令。這個命令會向容器的主行程傳送一個 SIGTERM 訊號,允許應用程式有機會優雅地關閉。

podman stop <容器名稱或ID>

有時候,應用程式可能沒有正確處理 SIGTERM 訊號,導致容器無法正常停止。在這種情況下,可以使用 --signal 選項傳送其他訊號,例如 SIGKILL,強制終止容器。

podman stop --signal SIGKILL <容器名稱或ID>

玄貓提醒: 強制終止容器可能會導致資料丟失或應用程式狀態不一致,應謹慎使用。

容器統計監控:掌握資源使用情況

當多個容器在同一主機上執行時,監控它們的資源使用情況至關重要。podman stats 命令提供了一個方便的方式來檢視容器的 CPU、記憶體、磁碟 I/O 和網路 I/O 等統計資訊。

podman stats

這個命令會開啟一個類別似 top 的介面,即時顯示所有執行中容器的統計資訊。

如果需要將統計資訊匯出到檔案或進行程式化處理,可以使用 --no-stream 選項和格式化選項。

podman stats --no-stream --format json

這個命令會以 JSON 格式輸出容器的統計資訊。

玄貓建議: 使用 Go 範本可以自定義輸出格式,只顯示需要的欄位。

podman stats -a --no-stream --format "{{ .ID }} {{ .CPUPerc }} {{ .MemUsageBytes }} {{ .PIDs }}"

容器資訊檢測:深入瞭解容器組態

podman inspect 命令允許檢測容器的組態和執行時資訊。這個命令會輸出一個包含容器所有組態的 JSON 物件。

podman inspect <容器名稱或ID>

這個 JSON 物件包含大量資訊,包括容器的 entry point、引數、狀態、映象 ID、網路設定、環境變數等等。

可以使用 --format 選項提取特定的欄位。例如,要取得容器的主行程 ID,可以使用以下命令:

podman inspect <容器名稱或ID> --format "{{ .State.Pid }}"

玄貓經驗分享: podman inspect 命令在故障排除和理解容器引擎的行為方面非常有用。

實戰案例:分析 OverlayFS 合併層

OverlayFS 是一種常用的容器儲存驅動,它透過將多個層合併成一個單一的檔案系統檢視來工作。podman inspect 命令可以幫助我們瞭解 OverlayFS 的合併層。

首先,執行一個新的容器:

podman run --name logger -d docker.io/library/fedora bash -c "while true; do echo test >> /tmp/test.log; sleep 5; done"

這個容器會每 5 秒向 /tmp/test.log 檔案寫入一行文字。

然後,使用 podman inspect 命令取得 OverlayFS 的合併目錄:

podman inspect logger --format "{{ .GraphDriver.Data.MergedDir }}"

這個命令會輸出合併目錄的路徑。在這個目錄中,可以找到容器中建立的 /tmp/test.log 檔案。

cat /var/lib/containers/storage/overlay/27d89046485db7c775b108a80072eafdf9aa63d14ee1205946d74623fc195314/merged/tmp/test.log

玄貓總結: 透過 podman stop 命令,我們可以優雅地停止容器,並透過 --signal 選項傳送其他訊號來強制終止容器。podman stats 命令讓我們掌握容器的資源使用情況,而 podman inspect 命令則可以深入瞭解容器的組態和執行時資訊。這些工具和技巧對於有效地管理和監控容器至關重要。

為何我深入研究 Podman 容器日誌:一次意外的探索之旅

身為一個熱愛容器技術的工程師,我時常需要深入瞭解容器的運作方式。最近,在研究 Podman 時,我決定探索一下容器日誌的儲存位置。這不僅僅是為了除錯,更是為了更全面地理解容器的底層機制。

容器日誌的秘密基地:探索 LowerDir 與 UpperDir

在 Podman 中,容器的檔案系統是根據 overlayfs 技術構建的。overlayfs 使用了 LowerDir 和 UpperDir 這兩個概念。LowerDir 包含了基礎映像檔的唯讀層,而 UpperDir 則是容器的可寫入層。

為了找到容器的日誌檔,我首先檢查了 LowerDir:

# podman inspect logger \
--format "{{ .GraphDriver.Data.LowerDir}}"
/var/lib/containers/storage/
overlay/4c85102d65a59c6d478bfe6bc0bf32e8c79d9772689f62451c7196
380675d4af/diff

這個指令可以找到 LowerDir 的路徑。但當我嘗試在 LowerDir 中尋找日誌檔時,卻一無所獲。

# cat /var/lib/containers/storage/
overlay/4c85102d65a59c6d478bfe6bc0bf32e8c79d9772689f62451c7196
380675d4af/diff/tmp/test.log
cat: /var/lib/containers/storage/
overlay/4c85102d65a59c6d478bfe6bc0bf32e8c79d9772689f62451c7196
380675d4af/diff/tmp/test.log: No such file or directory

這讓我意識到,LowerDir 僅包含唯讀的映像檔層,而日誌檔通常是在容器執行時寫入的。

接著,我找到了 UpperDir 的路徑:

# podman inspect logger --format "{{ .GraphDriver.Data.UpperDir }}"
/var/lib/containers/storage/
overlay/27d89046485db7c775b108a80072eafdf9aa63d14ee1205946d746
23fc195314/diff

UpperDir 包含了容器啟動後所有寫入的檔案和目錄,包括日誌檔。

# cat /var/lib/containers/storage/
overlay/27d89046485db7c775b108a80072eafdf9aa63d14ee1205946d746
23fc195314/diff/tmp/test.log
test
test
test
test
[...]

在這裡,我終於找到了容器的日誌檔。

容器日誌的最佳實踐:STDOUT 與 STDERR 的妙用

容器日誌除了儲存在檔案中,還有一個更常見與推薦的做法:利用標準輸出 (STDOUT) 和標準錯誤 (STDERR) 串流。

標準串流是作業系統中行程間通訊的通道。當程式透過互動式 shell 執行時,這些串流會直接連線到使用者的終端,實作輸入、輸出和錯誤的流動。

在容器中,最佳實踐是將日誌訊息輸出到 STDOUT 和 STDERR。Podman 會根據啟動容器時的選項,將這些串流連線到本地檔案系統中的日誌檔。

實戰演練:透過 STDOUT 擷取容器日誌

讓玄貓來示範如何透過 STDOUT 擷取容器日誌。首先,我們在分離模式下啟動一個容器:

$ podman run -d -i -t registry.fedoraproject.org/f29/httpd

這個指令會啟動一個 httpd 容器,並將 STDOUT 和 STDERR 串流連線到日誌檔。

接著,我們可以找到容器的 ID,並在 /var/lib/containers/storage/overlay-containers/ 目錄下找到對應的資料夾:

# cd /var/lib/containers/storage/overlay-containers/
c6afe22eac7c22c35a303d5fed45bc1b6442a4cec4a9060f392362bc4
cecb25d/

最後,我們可以在 userdata/ctr.log 檔案中找到容器的日誌:

# cat userdata/ctr.log
2021-09-27T15:42:46.925288013+00:00 stdout P => sourcing
10-set-mpm.sh ...
2021-09-27T15:42:46.925604590+00:00 stdout F
...

注意事項:log_driver 的設定

需要注意的是,上述方法只有在 containers.conf 檔案中的 log_driver 欄位設定為 k8s-file 時才有效。在較新的 Fedora Linux 發行版中,預設值可能已更改為 journald。在這種情況下,可以使用 journalctl 指令來檢視日誌。