【Kubernetes in Action读书笔记】4.1 保持Pod健康

180 阅读3分钟

【Kubernetes in Action读书笔记】4.1 保持Pod健康

”健康的Pod“可能是个比较模糊的概念。

首先,Pod是什么样的Pod,是手动创建的(=未托管的)Pod,还是由ReplicationController或Deployment等资源创建的(=托管的)Pod。

其次,如何算是健康。

  • 容器(Pod)内的主进程(pid = 1)存活就算健康?
  • 在主进程存活的前提下,容器(Pod)内的Web服务没有连续返回5xx(存活探针探活成功)算健康?
  • 在主进程存活且Web服务正常的前提下,容器(Pod)的数量与预期一致算健康?

k8s的不同组件从不同的角度提供了修复“不健康”Pod的能力。与“Pod健康”相关的组件包括:

  • Kubelet:如果pid = 1的进程退出,Kubelet将重启容器(还是Pod?)
  • 存活探针:确保Pod内的服务正常运行

实验1. 对于未托管的Pod,如果(Pod中)容器崩溃,Kubelet将重启容器(还是Pod?)

  1. 手动创建Pod
apiVersion: v1
kind: Pod
metadata:
  name: kubia-manual
spec:
  containers:
  - image: luksa/kubia
    name: kubia
    ports:
    - containerPort: 8080
      protocol: TCP
$ kubectl create -f kubia-manual.yaml
pod/kubia-manual created
​
$ kubectl get pods
NAME           READY   STATUS    RESTARTS   AGE
kubia-manual   1/1     Running   0          7m33s
  1. 通过kill -9破坏Pod内的容器(=pid为1的进程)
root@kubia-manual:/# curl http://127.0.0.1:8080
You've hit kubia-manual
root@kubia-manual:/# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:01 ?        00:00:00 node app.js
root          12       0  0 09:30 pts/0    00:00:00 bash
root          45      12  0 09:39 pts/0    00:00:00 ps -ef
root@kubia-manual:/# curl http://127.0.0.1:8080
You've hit kubia-manual
​
root@kubia-manual:/# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:01 ?        00:00:00 node app.js
root          12       0  0 09:30 pts/0    00:00:00 bash
root          47      12  0 09:43 pts/0    00:00:00 ps -ef
root@kubia-manual:/# kill -9 1
root@kubia-manual:/# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 09:01 ?        00:00:00 node app.js
root          12       0  0 09:30 pts/0    00:00:00 bash
root          48      12  0 09:43 pts/0    00:00:00 ps -ef

看起来,pid = 1的进程node app.js无法被杀掉。这可能是因为pid = 1的进程很特殊,不会处理SIGINT或SIGTERM这两个信号。参考Why do you need an init process inside your Docker container (PID 1)

所以需要换一种方法验证“容器崩溃,Kubelet将重启容器”的结论。

实验2. 如果存活探针探活失败,Kubernets将重启容器(还是Pod?)

  1. 手动创建Pod
apiVersion: v1
kind: Pod
metadata:
  name: kubia-liveness
spec:
  containers:
  - image: luksa/kubia-unhealthy
    name: kubia
    livenessProbe:
        httpGet:
            path: /
            port: 8080
$ kubectl create -f kubia-unhealthy.yaml
pod/kubia-liveness created
​
$ kubectl get pods
NAME             READY   STATUS              RESTARTS   AGE
kubia-liveness   0/1     ContainerCreating   0          58s
  1. 反复执行kubectl get pods,等待探活失败后,Pod重启
$ kubectl get pods
NAME             READY   STATUS    RESTARTS   AGE
kubia-liveness   1/1     Running   0          2m57s
​
# Liveness:       http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3
​
$ kubectl get pods
NAME             READY   STATUS    RESTARTS       AGE
kubia-liveness   1/1     Running   1 (106s ago)   6m7s
  1. 对存活探针进行抓包

先安装Kubeshark(docs.kubeshark.co/en/install

$ kubeshark tap kubia-liveness

限定Pod抓包

kubeshark-liveness.png

连续3次500后重启,连续5次200后又开始响应500。

手动创建的(=未托管的)Pod的缺点

即使配置了探针,手动创建的(=未托管的)Pod依然有以下缺点

  • Pod所在的节点挂了,Pod无法自动恢复