Jenkins-agent产生大量僵尸进程导致docker服务异常

220 阅读3分钟

一、项目背景

Jenkins-agent产生大量的僵尸进程, 主机的进程数达到了3w+. 导致agent服务无法正常提供服务

# 最大pid进程数
$ cat /proc/sys/kernel/pid_max
32768

top 命令的结果 (贴图为后补, 实际值已超过最大进程数)

ps aux结果

docker服务异常

$ docker ps
runtime/cgo: pthread_create failed: Resource temporarily unavailable
SIGABRT: abort
PC=0x7efca7dad387 m=0 sigcode=18446744073709551610
goroutine 0 [idle]:
runtime: unknown pc 0x7efca7dad387
stack: frame={sp:0x7ffdbda3a6c8, fp:0x0} stack=[0x7ffdbd23ba98,0x7ffdbda3aad0)
00007ffdbda3a5c8: 000055af6e558e7f <runtime.(*mheap).growAddSpan+271> 00007ffdbda3a600
00007ffdbda3a5d8: 000055af6e54fe0e <runtime.(*mTreap).end+78> 0000000000000000
00007ffdbda3a5e8: 00007efc00000001 0000000000000000
00007ffdbda3a5f8: 00007ffdbda3a630 000055af6e57e7d7 <runtime.step+327>
00007ffdbda3a608: 000055af708fbdf2 0000000000d08e00
00007ffdbda3a618: 0000000000d08e00 00007ffdbda3a658
00007ffdbda3a628: 000055af6e57e7a3 <runtime.step+275> 00007ffdbda3a6d8
00007ffdbda3a638: 000055af6e57daba <runtime.pcvalue+346> 000055af70918a3f

......

这里有一行报错是,runtime/cgo: pthread_create failed: Resource temporarily unavailable

二、原因分析

大量的僵尸进程由服务jenkins-agent引起, 子进程终止后会等待父进程发送wait系统调用来收割(reap)子进程,若没有收到wait会进程zombie状态。

即父进程在子进程终止后并没有进程回收, 导致大量的僵尸进程堆积.

当僵尸进程达到pid_max最大进程数,主机pid资源耗尽, 导致 docker服务异常.

三、临时解决

因为docker服务已经异常, 无法正常提供服务, 所以直接重启docker服务即可

$ systemctl restart docker

修改最大pid_max值

$ echo "kernel.*pid_max*=65535" >> /etc/sysctl.conf
$ sysctl -p

此处修改后只能暂时处理问题, 但当僵尸进程数达到阈值, 问题依旧会发生

四、 永久解决

docker-compose.yaml 添加 init: true 参数, 让jenkins-agent父进程对僵尸进程进行处理

注意: version版本: 2.4+ 或者3.7+版本才可以使用init参数 (对应链接文档搜索关键字)

文档:「Bug」Jenkins Slave 卡顿与僵尸进程

文档: 僵尸进程与孤儿进程

version: '3.7'
services:
  jenkins_agent:
    image: 'jenkins/agent:latest'
    user: root
    network_mode: host
    environment:
      TZ: "Asia/Shanghai"
    container_name: jenkins_new
    restart: always
    init: true
    volumes:
      - '/data/server/jenkins_new:/home/jenkins'
      - '/data/server:/data/server'
      - '/usr/bin/docker:/usr/bin/docker'
      - '/var/run/docker.sock:/var/run/docker.sock'
      - '/data/server/.kube/kustomize:/usr/bin/kustomize'
      - '/data/server/.kube/kubectl:/usr/bin/kubectl'
      - '/data/server/.kube/config:/home/jenkins/.kube/config'
    command: bash -c "apt-get update && apt-get install -y sudo && echo 'jenkins ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && su jenkins -c 'sudo docker login --username devops --password devops harbor.baibu.la && java -jar /usr/share/jenkins/agent.jar -jnlpUrl http://192.168.20.144:8888/computer/ops-20-155/slave-agent.jnlp -secret 56cef3a131bddb2f472523fb24867b560757648bdaeaf2128792665f4935878f -workDir /home/jenkins'"

容器重新加载配置(修改yaml后需要down再up, restart无法重新加载新的配置文件)

docker-compose down
docker-compose up -d

Jenkins-agent启动命令前后对比

添加前

添加后

测试截图是否有僵尸进程产生

完成 !