国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

聊聊容器與pod中的僵尸進程

運維 系統運維
在類UNIX系統中,僵尸進程是指完成執行(通過 exit 系統調用,或運行時發生致命錯誤或收到終止信號所致),但在操作系統的進程表中仍然存在其進程控制塊,處于"終止狀態"的進程。

[[423832]]

三種狀態的進程模型

按進程在執行過程中的不同情況至少要定義三種狀態:

  • 運行(running)態:進程占有處理器正在運行的狀態。進程已獲得CPU,其程序正在執行。在單處理機系統中,只有一個進程處于執行狀態;在多處理機系統中,則有多個進程處于執行狀態。
  • 就緒(ready)態:進程具備運行條件,等待系統分配處理器以便運行的狀態。當進程已分配到除CPU以外的所有必要資源后,只要再獲得CPU,便可立即執行,進程這時的狀態稱為就緒狀態。在一個系統中處于就緒狀態的進程可能有多個,通常將它們排成一個隊列,稱為就緒隊列。
  • 等待(wait)態:又稱阻塞態或睡眠態,指進程不具備運行條件,正在等待某個時間完成的狀態。也稱為等待或睡眠狀態,一個進程正在等待某一事件發生(例如請求I/O而等待I/O完成等)而暫時停止運行,這時即使把處理機分配給進程也無法運行,故稱該進程處于阻塞狀態。

引起進程狀態轉換的具體原因如下:

  • 運行態→等待態:等待使用資源;如等待外設傳輸;等待人工干預。
  • 等待態→就緒態:資源得到滿足;如外設傳輸結束;人工干預完成。
  • 運行態→就緒態:運行時間片到;出現有更高優先權進程。
  • 就緒態—→運行態:CPU 空閑時選擇一個就緒進程。

五種狀態的進程模型

五態模型在三態模型的基礎上增加了新建態(new)和終止態(exit)。

新建態:對應于進程被創建時的狀態,尚未進入就緒隊列。創建一個進程需要通過兩個步驟:1.為新進程分配所需要資源和建立必要的管理信息。2.設置該進程為就緒態,并等待被調度執行。

終止態:指進程完成任務到達正常結束點,或出現無法克服的錯誤而異常終止,或被操作系統及有終止權的進程所終止時所處的狀態。處于終止態的進程不再被調度執行,下一步將被系統撤銷,最終從系統中消失。終止一個進程需要兩個步驟:1.先等待操作系統或相關的進程進行善后處理(如抽取信息)。2.然后回收占用的資源并被系統刪除。

引起進程狀態轉換的具體原因如下:

  • NULL→新建態:執行一個程序,創建一個子進程。
  • 新建態→就緒態:當操作系統完成了進程創建的必要操作,并且當前系統的性能和虛擬內存的容量均允許。
  • 運行態→終止態:當一個進程到達了自然結束點,或是出現了無法克服的錯誤,或是被操作系統所終結,或是被其他有終止權的進程所終結。
  • 運行態→就緒態:運行時間片到;出現有更高優先權進程。
  • 運行態→等待態:等待使用資源;如等待外設傳輸;等待人工干預。
  • 就緒態→終止態:未在狀態轉換圖中顯示,但某些操作系統允許父進程終結子進程。
  • 等待態→終止態:未在狀態轉換圖中顯示,但某些操作系統允許父進程終結子進程。
  • 終止態→NULL:完成善后操作。

linux的進程狀態

無論進程還是線程,在 Linux 內核里其實都是用 task_struct{}這個結構來表示的。它其實就是任務(task),也就是 Linux 里基本的調度單位。

Linux進程狀態有:

  • TASK_RUNNING : 就緒態或者運行態,進程就緒可以運行,但是不一定正在占有CPU,對應進程狀態的R。
  • TASK_INTERRUPTIBLE:睡眠態,但是進程處于淺度睡眠,可以響應信號,一般是進程主動sleep進入的狀態,對應進程狀態S。
  • TASK_UNINTERRUPTIBLE:睡眠態,深度睡眠,不響應信號,典型場景是進程獲取信號量阻塞,對應進程狀態D。
  • TASK_ZOMBIE:僵尸態,進程已退出或者結束,但是父進程還不知道,沒有回收時的狀態,結束之前的一個狀態,對應進程狀態Z。
  • EXIT_DEAD:結束態,進程已經結束,也就是進程結束退出那一瞬間的狀態,對應進程狀態X。
  • TASK_STOPED:停止,調試狀態,對應進程狀態T。

孤兒進程

一個父進程退出,而它的一個或多個子進程還在運行,那么那些子進程將成為孤兒進程。孤兒進程將被init進程(進程號為1,也有可能是容器中的init)所收養,并由init進程對它們完成狀態收集工作。孤兒進程是沒有父進程的進程,孤兒進程這個重任就落到了init進程身上,init進程就好像是一個民政局,專門負責處理孤兒進程的善后工作。每當出現一個孤兒進程的時候,內核就把孤 兒進程的父進程設置為init,而init進程會循環地wait()它的已經退出的子進程。這樣,當一個孤兒進程凄涼地結束了其生命周期的時候,init進程就會代表黨和政府出面處理它的一切善后工作。因此孤兒進程并不會有什么危害。

僵尸進程

在類UNIX系統中,僵尸進程是指完成執行(通過 exit 系統調用,或運行時發生致命錯誤或收到終止信號所致),但在操作系統的進程表中仍然存在其進程控制塊,處于"終止狀態"的進程。我們從上面的概念中得知,僵尸進程仍然存在在進程表中。進程會占用系統系統資源,僵尸進程過多會導致資源泄露,最主要的資源就是PID。我們來看一下linux系統中的PID。這個最大值可以我們在 /proc/sys/kernel/pid_max 這個參數中看到。

  1. [root@k8s-dev]# cat /proc/sys/kernel/pid_max 
  2. 32768 

Linux 內核在進行初始化時,會根據CPU 的數目對 pid_max 進行設置。

  • 如果CPU 的數目小于等于32,那么 pid_max 會被設置為32768;
  • 如果CPU 的數目大于32,那么 pid_max = 1024 * (CPU 數目)。

所以如果超過這個最大值,那么系統就無法創建出新的進程了,比如你想 SSH 登錄到這臺機器上就不行了。清理僵尸進程:了解了僵尸進程的危害,我們來看看怎么清理僵尸進程:收割僵尸進程的方法是通過kill命令手工向其父進程發送SIGCHLD信號。如果其父進程仍然拒絕收割僵尸進程,則終止父進程,使得init進程收養僵尸進程。init進程周期執行wait系統調用收割其收養的所有僵尸進程。為避免產生僵尸進程,實際應用中一般采取的方式是:

將父進程中對SIGCHLD信號的處理函數設為SIG_IGN(忽略信號);

  • fork兩次并殺死一級子進程,令二級子進程成為孤兒進程而被init所“收養”、清理。
  • docker容器中的進程

容器中的PID

在Docker中,進程管理的基礎就是Linux內核中的PID名空間技術。在不同PID名空間中,進程ID是獨立的;即在兩個不同名空間下的進程可以有相同的PID。

Linux內核為所有的PID名空間維護了一個樹狀結構:最頂層的是系統初始化時創建的root namespace(根名空間),再創建的新PID namespace就稱之為child namespace(子名空間),而原先的PID名空間就是新創建的PID名空間的parent namespace(父名空間)。通過這種方式,系統中的PID名空間會形成一個層級體系。父節點可以看到子節點中的進程,并可以通過信號等方式對子節點中的進程產生影響。反過來,子節點不能看到父節點名空間中的任何內容,也不可能通過kill或ptrace影響父節點或其他名空間中的進程。

在Docker中,每個Container都是Docker Daemon的子進程,每個Container進程缺省都具有不同的PID名空間。通過名空間技術,Docker實現容器間的進程隔離。另外Docker Daemon也會利用PID名空間的樹狀結構,實現了對容器中的進程交互、監控和回收。注:Docker還利用了其他名空間(UTS,IPC,USER)等實現了各種系統資源的隔離,由于這些內容和進程管理關聯不多,本文不會涉及。

容器退出

當創建一個Docker容器的時候,就會新建一個PID名空間。容器啟動進程在該名空間內PID為1。當PID1進程結束之后,Docker會銷毀對應的PID名空間,并向容器內所有其它的子進程發送SIGKILL。

當執行docker stop命令時,docker會首先向容器的PID1進程發送一個SIGTERM信號,用于容器內程序的退出。如果容器在收到SIGTERM后沒有結束, 那么Docker Daemon會在等待一段時間(默認是10s)后,再向容器發送SIGKILL信號,將容器殺死變為退出狀態。這種方式給Docker應用提供了一個優雅的退出(graceful stop)機制,允許應用在收到stop命令時清理和釋放使用中的資源。

docker kill可以向容器內PID1進程發送任何信號,缺省是發送SIGKILL信號來強制退出應用。

容器中的僵尸進程

產生原因

容器化后,由于單容器單進程,已經沒有傳統意義上的 init 進程了。應用進程直接占用了 pid 1 的進程號。從而導致以下兩個問題。

常見的使用是 docker run my-container script 。給 docker run進程發送SIGTERM 信號會殺掉 docker run 進程,但是容器還在后臺運行。

2.當進程退出時,它會變成僵尸進程,直到它的父進程調用 wait()( 或其變種 ) 的系統調用。process table 里面會把它的標記為 defunct 狀態。一般情況下,父進程應該立即調用 wait(), 以防僵尸進程時間過長。

如果父進程在子進程之前退出,子進程會變成孤兒進程, 它的父進程會變成 PID 1。因此,init進程就要對這些進程負責,并在適當的時候調用 wait() 方法。通常情況下,大部分應用進程不會處理偶然依附在自己進程上的隨機子進程,所以在容器中,會出現許多僵尸進程。

解決方案

解決這個的辦法就是pid為1的跑一個支持信號轉發且支持回收孤兒僵尸進程的進程就行了,為此有人開發出了tini項目,感興趣可以github上搜下下,現在tini已經內置在docker里了。使用tini可以在docker run的時候添加選項–init即可,底層我猜測是復制docker-init到容器的/dev/init路徑里然后啟動entrypoint cmd,大家可以在run的時候測試下上面的步驟會發現根本不會有僵尸進程遺留。這里不多說,如果是想默認使用tini可以把tini構建到鏡像里(例如k8s目前不支持docker run 的--init,所以需要把tini做到鏡像里),參照jenkins官方鏡像dockerfile和tini的github地址文檔 https://github.com/krallin/tini

k8s pod中的僵尸進程

k8s 可以將多個容器編排到一個 pod 里面,共享同一個 Linux Namespace。這項技術的本質是使用 k8s 提供一個 pause 鏡像,也就是說先啟動一個 pause 容器,相當于實例化出 Namespace,然后其他容器加入這個 Namespace 從而實現 Namespace 的共享。我們來介紹一下 pause。

pause 是 k8s 在 1.16 版本引入的技術,要使用 pause,我們只需要在 pod 創建的 yaml 中指定 shareProcessNamespace 參數為 true,如下:

  1. apiVersion: v1 
  2. kind: Pod 
  3. metadata: 
  4.   name: nginx 
  5. spec: 
  6.   shareProcessNamespace: true 
  7.   containers: 
  8.   - name: nginx 
  9.     image: nginx 
  10.   - name: shell 
  11.     image: busybox 
  12.     securityContext: 
  13.       capabilities: 
  14.         add
  15.         - SYS_PTRACE 
  16.     stdin: true 
  17.     tty: true 

attach到pod中,ps查看進程列表:

  1. / # kubectl attach POD -c CONTAINER  
  2. / # ps ax 
  3. PID   USER     TIME  COMMAND 
  4.     1 root      0:00 /pause 
  5.     8 root      0:00 nginx: master process nginx -g daemon off
  6.    14 101       0:00 nginx: worker process 
  7.    15 root      0:00 sh 
  8.    21 root      0:00 ps ax 

我們可以看到 pod 中的 1 號進程變成了 /pause,其他容器的 entrypoint 進程都變成了 1 號進程的子進程。這個時候開始逐漸逼近事情的本質了:/pause 進程是如何處理 將孤兒進程的父進程置為 1 號進程進而避免僵尸進程的呢?

pause 鏡像的源碼如下:pause.c

  1. #include <signal.h> 
  2. #include <stdio.h> 
  3. #include <stdlib.h> 
  4. #include <string.h> 
  5. #include <sys/types.h> 
  6. #include <sys/wait.h> 
  7. #include <unistd.h> 
  8.  
  9. static void sigdown(int signo) { 
  10.   psignal(signo, "Shutting down, got signal"); 
  11.   exit(0); 
  12. // 關注1 
  13. static void sigreap(int signo) { 
  14.   while (waitpid(-1, NULL, WNOHANG) > 0) 
  15.     ; 
  16.  
  17. int main(int argc, char **argv) { 
  18.   int i; 
  19.   for (i = 1; i < argc; ++i) { 
  20.     if (!strcasecmp(argv[i], "-v")) { 
  21.       printf("pause.c %s\n", VERSION_STRING(VERSION)); 
  22.       return 0; 
  23.     } 
  24.   } 
  25.  
  26.   if (getpid() != 1) 
  27.     /* Not an error because pause sees use outside of infra containers. */ 
  28.     fprintf(stderr, "Warning: pause should be the first process\n"); 
  29.  
  30.   if (sigaction(SIGINT, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0) 
  31.     return 1; 
  32.   if (sigaction(SIGTERM, &(struct sigaction){.sa_handler = sigdown}, NULL) < 0) 
  33.     return 2; 
  34.   // 關注2 
  35.   if (sigaction(SIGCHLD, &(struct sigaction){.sa_handler = sigreap, 
  36.                                              .sa_flags = SA_NOCLDSTOP}, 
  37.                 NULL) < 0) 
  38.     return 3; 
  39.  
  40.   for (;;) 
  41.     pause(); // 編者注:該系統調用的作用是wait for signal 
  42.   fprintf(stderr, "Error: infinite loop terminated\n"); 
  43.   return 42; 

重點關注一下void sigreap(int signo){...}和if (sigaction(SIGCHLD,...) ,這個不就是我們上面說的 除了這種方式外,還可以通過異步的方式來進行回收,這種方式的基礎是子進程結束之后會向父進程發送 SIGCHLD 信號,基于此父進程注冊一個 SIGCHLD 信號的處理函數來進行子進程的資源回收就可以了。

SIGCHLD 信號的處理函數核心就是這一行 while (waitpid(-1, NULL, WNOHANG) > 0) ,其中各參數示意如下:

  • -1:meaning wait for any child process.
  • NULL:?
  • WNOHANG :return immediately if no child has exited.

結論

得出pause 容器的兩個最重要的特性:

  • 在 pod 中作為容器共享namespace的基礎
  • 作為 pod 內的所有容器的父容器,扮演 init 進程(即systemd)的作用。

最后

通過這篇文章的學習,大家能解決容器中出現僵尸進程的問題。

本文轉載自微信公眾號「運維開發故事」

 

責任編輯:姜華 來源: 運維開發故事
相關推薦

2022-01-19 08:01:13

Linuxdocker容器

2024-08-26 08:39:26

PHP孤兒進程僵尸進程

2024-02-05 18:23:23

父進程應用程序程序

2019-11-20 09:15:53

KubernetesPod

2017-12-15 09:40:47

Linux僵尸進程

2022-02-07 11:55:00

linux進程線程

2020-10-10 11:02:09

Linux 系統 數據

2021-10-25 12:23:06

Linux僵尸進程

2021-11-22 08:00:00

Kubernetes容器集群

2021-11-06 10:17:38

Linux僵尸進程

2021-11-08 10:30:30

Linux僵尸命令

2023-11-03 08:22:09

Android系統算法

2020-07-14 07:27:48

容器IoCSpring

2024-05-09 09:55:08

2020-10-22 13:49:37

Docker容器僵死進程

2022-10-12 09:01:52

Linux內核線程

2022-03-04 08:45:11

Docker開源Linux

2025-05-29 08:10:00

Linux進程系統

2025-03-20 09:54:47

2021-03-28 08:32:58

Java
點贊
收藏

51CTO技術棧公眾號

91久久精品一区二区别| 亚洲一区二区三区色| 亚洲欧美日韩一区二区三区在线观看 | 国际精品欧美精品| 日本一区二区三区精品视频| 国产欧美精品一区| 成人在线免费看黄| 久久成人18免费网站| 国产一区二区在线看| 欧美成人黄色| www浪潮av99com| 亚洲一区二区三| 日韩一区二区视频在线观看| 成人性生交大合| a毛片不卡免费看片| 激情小视频网站| 亚洲国产精品网站| 制服丝袜日韩国产| 欧美国产视频在线| 免费成人在线影院| 影音先锋亚洲精品| 成人动态视频| jizzjizz少妇亚洲水多| 在线色视频观看| 韩日视频在线观看| 久久久久久九九| 欧美孕妇与黑人孕交| 欧美综合亚洲图片综合区| 国内精品福利| 老司机在线看片网av| 亚洲不卡1区| 亚洲精品推荐| 自拍偷拍亚洲视频| 亚欧在线免费观看| 日本一区网站| 国内揄拍国内精品少妇国语| 中国av一区二区三区| 风间由美性色一区二区三区| 亚洲大片av| 国产视频一区二区在线播放| 四虎精品在永久在线观看 | 羞羞网站在线看| 555www色欧美视频| 亚洲小说欧美另类社区| 成人免费毛片嘿嘿连载视频…| 91久久久久久| 日韩欧美在线国产| 日韩欧美字幕| 日本一区免费网站| 经典三级在线| 久久精品国产一区二区三 | 九九九久久久精品| 91精品亚洲一区在线观看| 久久夜色精品| 精品一区二区在线观看| 9色精品在线| 麻豆电影传媒二区| 欧美日韩亚洲自拍| 男人影院在线观看| 亚洲精品视频免费在线观看| 在线观看欧美日韩电影| 久久综合伊人77777蜜臀| 久久国产精品黑丝| 欧美变态凌虐bdsm| 成人免费视频免费观看| 国产精品久久久久久久久久东京| 欧美巨猛xxxx猛交黑人97人| 亚洲一本大道在线| 欧美日韩国产综合久久| 欧美午夜无遮挡| www亚洲国产| 亚洲综合欧美日韩| 亚洲久久久久久久久久| 亚洲国产不卡| 国产视频一区欧美| 日韩欧美国产系列| 亚洲欧美色图片| 欧美在线视频观看免费网站| 97超碰人人看人人| 四虎免费在线观看视频| 三级4级全黄60分钟| 激情久久久久久久久久久久久久久久| 丁香色欲久久久久久综合网| 播放灌醉水嫩大学生国内精品| 国产精品久久中文字幕| 国产女大学生av| 中文字幕中文字幕在线中文字幕三区 | www.国产在线视频| 成人黄色片视频| 51国偷自产一区二区三区| www.xxxx欧美| 久久艳片www.17c.com| 国产精品后入内射日本在线观看| 91国产丝袜在线放| 四虎亚洲成人| 日韩三级精品| 日韩视频123| 精品视频中文字幕| 阿v天堂2018| 国产精品综合不卡av| 国产一区二区三区黄| 久久综合中文色婷婷| www.黄色网址.com| 四虎4hu新地址入口2023| 91人人澡人人爽人人精品| 97福利网站在线观看视频| 久草免费在线观看| 日本在线一区二区| 欧美日韩亚洲国产精品| av成人激情| 国产夜色精品一区二区av| 日韩一级免费观看| 精品国产依人香蕉在线精品| 成人精品一区二区三区| 亚洲自拍偷拍色图| 黄色国产精品视频| 91av视频在线免费观看| 美女性感视频久久久| 91精品视频免费| 哪个网站能看毛片| 欧美午夜大胆人体| 精品高清久久| av在线一区二区| 欧美日韩国产影院| 伊人av综合网| 国产精品污www一区二区三区| av在线之家电影网站| 精品久久亚洲| 老司机免费视频一区二区三区| 色偷偷综合社区| 日韩在线综合网| 9lporm自拍视频区在线| 欧美日韩专区| 欧美激情一区二区三区四区| 久久理论片午夜琪琪电影网| 在线观看一区二区三区三州| 亚洲激情av| 亚洲欧洲日韩精品| 高清国产一区二区三区| 黄色一级在线视频| 福利电影一区二区三区| 国产一区在线免费| 99香蕉久久| 国产精品日韩成人| 久久久久久久久久久一区| 极品美鲍一区| 精品电影在线观看| 你懂的网址一区二区三区| 色呦呦在线播放| 精油按摩中文字幕久久| 国产欧美一区二区三区在线| 欧美久久综合网| 3d动漫精品啪啪1区2区免费| 奇米影音第四色| 激情亚洲综合在线| 日韩一级高清毛片| 在线播放你懂得| 成人av在线一区二区三区| yellow视频在线观看一区二区| 神马久久av| 欧美裸体男粗大视频在线观看| 毛片在线不卡| 日韩国产激情在线| 欧美成人黑人| xvideos亚洲人网站| 国产传媒在线观看| 久久亚洲精品小早川怜子| 欧美又大又硬又粗bbbbb| 天堂аⅴ在线最新版在线 | 99视频在线视频| 久久久久久久久伊人| 99久热re在线精彩视频| 天天亚洲美女在线视频| 男人天堂999| 久久精品一区二区| 亚洲 日韩 国产第一区| 亚州综合一区| 蜜月aⅴ免费一区二区三区| 免费久久一级欧美特大黄| 在线观看免费黄色| 欧美激情一区二区三区四区| 成人av男人的天堂| 懂色av噜噜一区二区三区av| 青青草免费在线| av成人免费在线观看| 香蕉久久夜色精品国产使用方法| 亚洲成人在线网| 91福利国产在线观看菠萝蜜| 亚洲欧美日韩在线不卡| 国产精品一区二区三区在线观| 经典一区二区| 久久天堂av综合合色蜜桃网| 亚洲精品美女久久久| 日韩av在线播放不卡| 久久xxxx| 欧美精品久久久久久久| 欧美一区二区中文字幕| 欧美激情五月| 欧美精品情趣视频| 亚洲成人天堂网|