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 1init 进程有它维护,并接收收割僵尸进程

那么,如果把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 的作用是生成子进程、避免僵尸进程生成、转发信号量(pid1 时)到子进程并等待它退出。使用 tini 可以优雅的结束容器内的进程。

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

背景:

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

打包镜像:

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的进程,则负责孤儿进程的处理,防止出现僵尸进程。

相关推荐
HLC++3 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室4 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
groundhappy7 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
Hui Baby7 小时前
K8S使用CRD和控制器简单应用
云原生·容器·kubernetes
通信小小昕7 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫8 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生9 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.1110 小时前
linux基础IO
linux·运维·服务器
BelongPanda12 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
Zhu75812 小时前
在k8s环境部署Apache Superset最新版
容器·kubernetes·apache