「Bug」Jenkins Slave 卡頓與僵屍進程


問題描述

出問題的是我們的主 Jenkins Slave,是在 Ubuntu 虛擬機里面,使用 Docker 跑了四個不同環境的 Jenkins Slave,提供 c#/golang/flutter/python 等的構建/測試環境。

而且這台服務器是不關機的,24h 提供服務。

一段時間后,這台 Jenkins Slave 虛擬機的內存就居高不下。這大概是某些構建任務會維護守護進程以加快下一次構建的速度,所以內存沒釋放。

大概過了一個月左右,問題就出現了:明明虛擬機提示還有 2G 的空閑內存(不包含 cached),可 ssh 登錄卻要花將近兩三分鍾,登入后 top/htop 也要黑屏將近一分鍾。。
神奇的是其他的命令(ls/cd/df/du/docker)卻都很正常,沒有什么明顯的卡頓現象。

快速解決方案

對比其他用於加速構建的 Jenkins Slave,它們每天晚上都會關機(節約用電),就一直沒出過問題。

於是將其重啟后,暫時解決了問題。

原因分析

首先列出卡頓的通用排查流程:

  1. 性能問題:CPU/RAM/IO/Network
  2. 僵屍進程導致 Pid 資源不足。
  3. 使用 ICMP-ping、tcp-ping 檢查網卡
  4. 系統問題,檢查 kernel 和 syslog

既然 CPU/RAM 都沒有問題,而且每晚關機的 Slave 也沒問題,這說明卡頓是在長期運行時才會發生。

排查:

  1. 系統負載很正常,排除性能問題。
  2. 內核參數:之前圖方便,給所有的服務器都設了 vm.max_map_count=262144(elasticsearch 6.8+ 需要)
    • 之前遇到過因為這個參數,導致 redis 長期運行后響應緩慢的問題。可能和它有關。
  3. Jenkins Slave 虛擬機中有 66248 個進程,但是其中 66009 個都是僵屍進程

Jenkins Slave 最明顯的問題,就是僵屍進程過多了。

僵屍進程

man ps 中對 僵屍進程(狀態 Z)的解釋如下:

Z defunct ("zombie") process, terminated but not reaped by its parent

在子進程已經終止,但是父進程卻沒有通過 wait 系統調用來收割 (reap) 子進程時,這個子進程會成為一個僵屍進程。top 命令的第二行會顯示僵屍進程的個數。

查看僵屍進程的命令:ps -ef| grep defunc,defunc 意為“死者”。

僵屍進程無法通過 kill 命令殺死(你無法殺死一個已經死掉的進程hhh),只能通過干掉它的父進程來間接的殺死它們。

系統中存在過多的僵屍進程將占用大量的操作系統進程表資源,導致系統卡頓並最終崩潰!

通過前述的 ps 命令,我們發現這些 zombies 的父進程基本都是 jenkins-agent 進程,
重啟服務器時該進程也被重啟,因此服務器恢復正常。但是這顯然只是治標的方法,過一段時間僵屍進程又會堆積,導致服務器卡頓。

嘗試尋找治根的解決方法,搜索 Jenkins zombie 發現如下 Issues、PR:

  1. Handling of zombie processes would be useful
  2. defunct sh and sleep processes when running on slave-jnlp
  3. Wrapper process leaves zombie when no init process present
  4. Start long running containers with --init

最簡單的解決方案,應該就是在通過 docker 啟動 jenkins-agent 時添加 --init 參數,對應的 docker-compose 參數為 docker-compose reference - init

於是在 docker-compose.yml 中添加上這個參數,解決了該問題,示例如下:

version: '3.7'
services:
  android1:  # 這個 key 只是它在 docker-compose 內部的一個別名,在 docker 中不可用。
    container_name: android1  # 這個名字才是容器 在 docker 中的真正名稱。
    image: image-registry.svc.local/jenkins/slave-android:latest  # 私有倉庫,定制的 android 構建用基礎鏡像
    init: true  # 這個必須加上,否則僵屍進程無法回收,僵屍進程累積會導致系統卡頓
    environment:
      - TZ=Asia/Shanghai
    command: -url http://jenkins.ci.svc.local -workDir=/home/jenkins/ <secret> android1
    restart: always
    networks:
      - jenkins-slave


免責聲明!

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



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