Docker的進程和Cgroup概念詳解
容器里的進程組織或關系
0號進程:containerd-shim
角色:
- containerd-shim 是容器的父進程,負責管理容器的生命周期,接收容器內的執(zhí)行的指令。
- 它通過調用 runc 創(chuàng)建容器,并處理容器內的指令。
特點:
- 容器依賴:
- containerd-shim 是容器的祖宗進程,如果它掛掉,整個容器也會退出。
- 進程管理:
- 如果容器的1號進程結束,containerd-shim 會回收容器命名空間中的所有進程。
- 如果1號進程未結束,但其子進程結束,子進程會成為僵尸進程,需要由1號進程回收。
- 信號處理:
- docker stop 會向容器的1號進程發(fā)送 SIGTERM(-15)信號。
- 如果1號進程沒有信號轉發(fā)能力,它會向容器內的所有進程發(fā)送 SIGKILL(-9)信號。
- 如果1號進程有信號轉發(fā)能力,它會向容器內的所有進程轉發(fā) SIGTERM(-15) 信號。
- docker stop 會向容器的1號進程發(fā)送 SIGTERM(-15)信號。
1號進程:容器內的第一個進程
角色:
- 1號進程是容器內的第一個進程,代表容器的生命周期。
- 它通常是用戶指定的應用程序進程。
特點:
- 生命周期:
- 1號進程結束,容器也會結束。
- 1號進程必須在前臺運行,否則容器會退出。
- 功能缺陷(與操作系統(tǒng)進程的區(qū)別):
- 容器內的1號進程不一定是所有用戶進程的祖先。
- 如果1號進程成為孤兒進程,它會被init進程(0號進程)收養(yǎng)。
- 用戶開發(fā)的1號進程可能缺乏回收僵尸進程和轉發(fā)信號的能力。
應具備的能力:
- 回收僵尸進程::定期調用 wait 或 waitpid 回收僵尸子進程。
- 信號轉發(fā):將接收到的信號(如 SIGTERM)轉發(fā)給子進程。
~# docker container inspect text | grep -i pid pid:41404---------對應的就是容器內的1號進程 ~# ps -elf | grep 41404 pid:41404 ppid:41382---------對應的就是容器內的0號進程
進程收到信號后的三種反應
信號是操作系統(tǒng)向進程發(fā)送的一種通知,用于通知進程發(fā)生了某種事件??梢杂糜谶M程間通信或控制進程行為。
- 忽略(Ignore):
- 進程對信號不做任何處理。
- 示例:忽略 SIGTERM 信號,進程不會被終止。
- 捕獲(Catch):
- 進程可以注冊自定義的處理函數(shù)(handler)來處理捕獲的信號。
- 當信號到達時,觸發(fā) handler 執(zhí)行。
- 示例:trap 'echo "signal received"' SIGTERM
- 默認行為(Default):
- 每個信號都有默認行為,由操作系統(tǒng)定義。
- 示例:
- SIGTERM 的默認行為是終止進程。
- SIGKILL 的默認行為是強制終止進程。
兩個特權信號
SIGKILL (-9)
- 作用: 強制終止進程。
- 特點:
- 無法被忽略。
- 無法被捕獲。
- 使用場景: 當進程無響應時,強制終止進程。
SIGSTOP (-19):
- 作用: 暫停進程的運行
- 特點:
- 無法被忽略。
- 無法被捕獲。
- 恢復運行: 發(fā)送 SIGCONT (-18) 信號。
SIGTERM(-15)信號是可以被進程忽略或者捕獲的
在容器內執(zhí)行 kill 命令的行為
kill -9 1
- 無法殺死容器內的1號進程。
- 原因: 容器內的1號進程被打上了 SIGNAL_UNKILLABLE 標簽。
kill -19 1
- 無法暫停容器內的1號進程。
- 原因: 容器內的1號進程被打上了 SIGNAL_UNKILLABLE 標簽。
kill -15 1
- 有可能殺死容器內的1號進程。
- 如果1號進程沒有注冊 SIGTERM 信號的處理函數(shù),它會忽略該信號。
- 如果1號進程注冊了 SIGTERM 信號的處理函數(shù),它會執(zhí)行該函數(shù)。
Cgroup 介紹
Cgroup(Control Group)是 Linux 內核提供的一種機制,用于限制、控制和監(jiān)控進程組的資源使用。它允許系統(tǒng)管理員對一組進程的資源使用進行精細化管理,包括 CPU、內存、磁盤 I/O 等。Cgroup 是容器技術(如 Docker、Kubernetes)中實現(xiàn)資源隔離和管理的基礎。
為何要用 Cgroup?Cgroup 的主要作用是限制容器或進程組對宿主機資源的使用,防止某個容器或進程過度占用資源,從而影響其他容器或進程的正常運行。通過 Cgroup,可以確保宿主機上的多個容器或進程能夠公平、穩(wěn)定地共享系統(tǒng)資源。
在 Linux 系統(tǒng)中,可以通過以下命令查看和管理 Cgroup
# 查看當前的 Cgroup 控制層級 cat /proc/cgroups # 創(chuàng)建一個新的 Cgroup mkdir /sys/fs/cgroup/cpu/my_cgroup # 將一個進程加入到 Cgroup 中 echo "PID" > /sys/fs/cgroup/cpu/my_cgroup/tasks # 設置 CPU 限制 echo "2" > /sys/fs/cgroup/cpu/my_cgroup/cpu.cfs_quota_us
CPU Cgroup 中與 CFS 相關的參數(shù)
CFS(Completely Fair Scheduler)是 Linux 內核中的一種調度算法,用于公平地分配 CPU 時間給各個進程。Cgroup 中與 CFS 相關的參數(shù)決定了進程組對 CPU 的使用率。
- cpu.cfs_period_us:表示 CPU 的時間周期,單位為微秒 (μs)。例如,設置為 100ms (100,000 μs),表示一個周期為 100 毫秒。
- cpu.cfs_quota_us:表示在該時間周期內,控制組內的進程最多可以使用的 CPU 時間。例如,設置為 50ms (50,000 μs),表示在 100ms 的周期內,進程最多可以使用 50ms 的 CPU 時間。此時,CPU 使用率為 50ms / 100ms = 0.5,即 50%。
- cpu.shares:用于控制同一層級下的多個控制組之間的 CPU 資源分配。當宿主機上的 CPU 資源不足時,cpu.shares 會生效,決定各個控制組之間的 CPU 資源分配比例。cpu.shares 的值越大,分配的 CPU 資源越多。
總結:
- cpu.cfs_quota_us與cpu.cfs_period_us這兩個值決定了每個控制組所有進程可使用cpu資源的最大值
- cpu.shares這個值決定了cpu cgroup子系統(tǒng)下控制組可用cpu的相對比例,不過只有當系統(tǒng)上cpu被占滿時,這個比例才會在各個控制組間起作用
Kubernetes 中的資源管理
在 Kubernetes 中,Pod 的資源請求和限制可以通過 requests 和 limits 來設置。
- requests:表示 Pod 對資源的最低需求。Kubernetes 會根據(jù) requests 來調度 Pod,確保節(jié)點上有足夠的資源。requests 對應 Cgroup 中的 cpu.shares,表示初始的 CPU 資源申請量。實際使用量可以超過 requests,但不會低于它。
- limits:表示 Pod 對資源使用的上限。Kubernetes 會通過 Cgroup 限制 Pod 的資源使用,確保不會超過 limits 設置的值。limits 對應 Cgroup 中的 cpu.cfs_quota_us 和 cpu.cfs_period_us,表示 CPU 使用的硬性上限。
但是要注意,limits 設置的上限是否能達到,還取決于宿主機的實際資源情況。如果宿主機資源不足,Pod 可能無法達到 limits 設置的上限。
memory cgroup
每個容器都有對應的 memory cgroup 控制組,位于 /sys/fs/cgroup/memory/system.slice/docker - xxx
,用于管理容器內存。
主要參數(shù):
- memory.limit_in_bytes:設置容器內所有進程可占用的物理內存上限,子 group 最多只能設置到父級 group 的該值。
- memory.oom_control:默認為 0,表示開啟 OOM 機制;可設為 1 關閉,通過 echo 1 > memory.oom_control 實現(xiàn)。
- memory.usage_in_bytes:只讀參數(shù),顯示容器內所有進程占用的物理內存總量。
示例: 容器啟動時,rss 為 100 M,page cache 為 899 M,內存總使用量為 999 M;隨著進程運行,申請更多內存后,rss 增至 200 M,page cache 減至 699 M,內存總使用量仍為 899 M,但實際進程占用的物理內存增大。
容器的可用磁盤進行配額
默認情況,容器內的可用磁盤空間是沒有限制的。
容器內的文件系統(tǒng) = lowerdir + upperdir
寫入操作
- 在容器內寫容器文件系統(tǒng)里寫東西(任何目錄都沒有掛載任何外部存儲卷)
- 那此時寫入的數(shù)據(jù),都寫到了upperdir層,也就是寫到的宿主機上。
- 所以如果不加以限制,很有可能會導致宿主機磁盤空間寫滿。
如何解決問題?有兩種方式:
- 對容器的可用磁盤進行配額
- 對容器寫操作的目錄,應該掛載一個專門的外部存儲卷(推薦)
到此這篇關于Docker的進程和Cgroup概念的文章就介紹到這了,更多相關Docker Cgroup概念內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Deepin使用docker安裝mysql數(shù)據(jù)庫過程詳解
這篇文章主要介紹了Deepin使用docker安裝mysql數(shù)據(jù)庫過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-06-06docker啟動elasticsearch時內存不足問題及解決方法
這篇文章主要介紹了docker啟動elasticsearch時內存不足問題,本文給大家分享安裝過程及解決方法,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07