k8s容器内如何避免僵尸进程

之前有文章讨论了僵尸进程,以及脚本中出现僵尸进程时候,主进程调用wait可以一定程度上避免出现僵尸进程。但是我发现,并不是在调用完wait后,僵尸进程就一定不会存在了。

参考:github.com/milvus-io/m...

那么如何在k8s环境中,避免僵尸进程的出现呢?

本文提出两种方案来避免僵尸进程的出现。

僵尸进程产生的原理

参考:juejin.cn/post/728895...

一:操作系统中

实际上,任何一个进程都会存在僵尸进程阶段,只不过,如下两种情况就可以避免僵尸进程出现:

  • 情况1: 如果父进程还存在,但是父进程没有正确调用wait/waitpid,则僵尸进程就不会消失。
  • 情况2: 如果父进程早于子进程结束,那么子进程结束后,会由init进程(进程号为1)接管,init调用wait,同样不会出现僵尸进程。

二:容器环境中

容器环境中,进程号为1的进程是容器主进程,该进程不具备回收僵尸进程的能力,因此,当容器内产生孤儿进程托管给主进程(进程号为1)的进程后,就变成了没有人处理的僵尸进程

解决方法

方法一:

  • k8s 中 pause 容器 是所有容器的 父容器(parent container),它有2个作用

    • 它是pod中 Linux命名空间 共享的基础
    • 启用 PID 命名空间 共享,pod 中 PID 1 的 init 进程有它维护,并接收收割僵尸进程

那么,如果把pause进程变成进程号为1的容器主进程,是不是就可以处理孤儿进程了呢?

答案是肯定的~~~ 有如下两种方法,能够将pause容器变成主进程

  • kubelet 通过配置 --docker-disable-shared-pid=false 开启共享 pid namespace,也可以在 yml 中指定
  • 可以在yaml编排文件中指定
yaml 复制代码
cat << EOF >> test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test
spec:
  selector:
    matchLabels:
      app: pod1
  replicas: 1
  template:
    metadata:
      labels:
        app: pod1
    spec:
      shareProcessNamespace: true
      containers:
      - name: sshd
        image: circleci/sshd:0.1
        env:
        - name: PUBKEY
          value: "abc"
      - name: pod1
        image: busybox
        securityContext:
          capabilities:
            add:
            - SYS_PTRACE
        stdin: true
        tty: true
        ports:
        - name: p80
          containerPort: 80
        - name: p22
          containerPort: 22
EOF

在编排文件的spec中,加入 shareProcessNamespace: true 开启后,可以在容器中,看到如下进程列表:

bash 复制代码
[root@sc-master-1 ~]# kubectl  -n milvus-1 exec -it elasticsearch-etcd-2 --  ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
65535          1       0  0 03:09 ?        00:00:00 /pause
1001           7       0  1 03:09 ?        00:03:55 etcd
1001       53340       0  0 07:46 pts/0    00:00:00 ps -ef

如上,可以看到pause容器变成了进程号为1的主进程,将会负责处理孤儿进程。

参考:www.xiexianbin.cn/kubernetes/...

方法二:

参考一: www.xiexianbin.cn/docker/dock...

参考二:cloud-atlas.readthedocs.io/zh_CN/lates...

参考三:cloud-atlas.readthedocs.io/zh_CN/lates...

tini 是一个针对容器开发的、精简的 init 服务。tini 的作用是生成子进程、避免僵尸进程生成、转发信号量(pid 为 1 时)到子进程并等待它退出。使用 tini 可以优雅的结束容器内的进程。

参考:github.com/krallin/tin...

背景:

  • Linux 中 pid 为 1 的 init 进程可以接受中断信号量,并将该信号量转发到所有子进程
  • 非 init 需要程序实现转发信号的功能才能关闭其他程序,一般的 bash、sh 不具备上述功能
  • 使用 docker stop 时,容器内 pid 为 1 进程将接受中断信号量

打包镜像:

dockerfile 复制代码
FROM rockylinux:9.2.20230513

ENV TINI_VERSION v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
# Run your program under Tini
# or docker run your-image /your/program ...
COPY <<EOF /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
EOF
RUN dnf update -y && dnf install epel-release -y   && dnf -y install s3cmd  && dnf install -y wget  && dnf -y install net-tools  && dnf install -y telnet  && dnf -y install traceroute  && dnf -y install tcpdump  && dnf install -y fio  && dnf -y install bind-utils  && dnf install -y kubectl-1.24.16-0 && dnf install -y vim && dnf install -y expect  && dnf install -y git && dnf install -y procps && dnf install psmisc -y && chmod +x /tini
ENTRYPOINT ["/tini", "--"]
CMD [ "sleep","100000" ]

#docker run --rm --name app -e MX_MEM=128m -v /tmp/apps:/data -p 18080:8080 -p 17070:7070 registry.knowdee.com/tests/app:v1.0.0


#docker build    -t registry.knowdee.com/library/tools:v-rock9.2  . -f ./tools.dockerfile --progress=plain

# dnf --showduplicates list kubectl

yaml编排文件:

yaml 复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
  name: midware
  namespace: tools
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: midware
  serviceName: midware
  template:
    metadata:
      annotations:
        # prometheus.io/port: "8000"
        # prometheus.io/scrape: "true"
      labels:
        app: midware
    spec:
      tolerations:
      - effect: NoExecute
        key: taint.knowdee.io/apps
        operator: Exists
      containers:
      - args:
        - /bin/sh
        - -c 
        - |
          git config --global user.name "knowdee"
          git config --global user.email "it@knowdee.com"
          sleep 30000s
        envFrom:
        - configMapRef:
            name: midware-config
        volumeMounts:
        - name: kubecfg
          mountPath: /root/.kube
        - mountPath: /data
          name: data
        image: registry.knowdee.com/library/tools:v-rock9.2
        imagePullPolicy: IfNotPresent
        name: midware
        # ports:
        # - containerPort: 8000
        #   name: http
        #   protocol: TCP
        resources:
          requests:
            cpu: "1"
            memory: 512Mi
      dnsPolicy: ClusterFirst
  volumeClaimTemplates:
  - apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      creationTimestamp: null
      name: data
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 200Mi
      volumeMode: Filesystem
  updateStrategy:
    type: RollingUpdate

在启动后的容器中,可以看到:

bash 复制代码
root           1       0  0 06:27 ?        00:00:00 /tini -- /bin/sh -c git config --global user.name "knowdee" git config --global user.email "it@knowdee.com" cp /data/.s3cfg /root/
root           7       1  0 06:27 ?        00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 30000s
root          73       0  0 06:27 pts/0    00:00:00 /bin/bash
root         793      73  0 08:32 pts/0    00:00:00 ps -ef

tini进程为进程号为1的进程,则负责孤儿进程的处理,防止出现僵尸进程。

相关推荐
夜听莺儿鸣3 小时前
502-003_Linux 中断与异常(一):从Linux角度理解中断与异常
linux·中断与异常·linux中断
杨云龙UP4 小时前
TDengine 3.4.2.8 Community 三节点三副本生产集群部署实战(DNode/MNode/taosAdapter/Explorer)
大数据·linux·运维·数据库·tdengine·时序库
向成科技5 小时前
XC3576H工控主板|深度适配Ubuntu 26.04 LTS,释放边缘AI与工业开发新潜能
linux·人工智能·ubuntu·机器人·硬件·主板·边缘ai
Fcy6486 小时前
Linux下 进程间关系与守护进程
linux·运维·服务器·守护进程
码农小韩6 小时前
Linux驱动理论(二)——Linux字符设备驱动
linux·嵌入式软件开发·linux操作系统·linux应用开发·linux驱动理论
well06126 小时前
Linux粘滞位与Makefile机制深度解析
linux·运维·服务器
再写一行代码就下班6 小时前
linux sh脚本在windows修改导致无法使用解决方式
java·linux·centos
额额额对了6 小时前
SPI通信
linux·c语言·汇编·单片机·嵌入式硬件·arm
子木HAPPY阳VIP7 小时前
Ubuntu 关闭防火墙操作步骤
linux·运维·ubuntu
王振超wzc7 小时前
嵌入式开发环境搭建--WM软件安装,Ubuntu操作系统安装
linux·运维·ubuntu