一、Pod的生命周期
Pod 遵循一个预定义的生命周期,起始于 Pending 阶段,如果至少 其中有一个主要容器正常启动,则进入 Running 阶段,之后取决于 Pod 中是否有容器以失败状态结束而进入 Succeeded 或者 Failed 阶段。
在 Pod 运行期间,Kubernetes能够重启容器以处理一些失效场景。 在 Pod 内部,Kubernetes 跟踪不同容器的状态,并确定使 Pod 重新变得健康所需要采取的动作。
当我们运行一个Pod的时候,可以通过如下命令来查看Pod的运行状态:
kubectl get pod
输出结果如下,其中的status字段就是Pod的状态。
[root@kubernetes-master01 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-nginx 1/1 Running 3 86m
上面输出结果中的Status字段是一个PodStatus对象,其中包含一个phase字段。下面是phase字段的值与值的定义:
取值 | 描述 |
Pending(悬决) | Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。 |
Running(运行中) | Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。 |
Succeeded(成功) | Pod 中的所有容器都已成功终止,并且不会再重启。 |
Failed(失败) | Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。 |
Unknown(未知) | 因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。 |
Pod是一个或多个容器的封装,那么容器的状态又有哪些呢?容器的状态有三种:
- Waiting(等待):如果容器并不处在 Running 或 Terminated 状态之一,它就处在 Waiting 状态。 处于 Waiting 状态的容器仍在运行它完成启动所需要的操作:例如,从某个容器镜像 仓库拉取容器镜像,或者向容器应用 Secret 数据等等。 当你使用 kubectl 来查询包含 Waiting 状态的容器的 Pod 时,你也会看到一个 Reason 字段,其中给出了容器处于等待状态的原因。
- Running(运行中):Running状态表明容器正在执行状态并且没有问题发生。如果配置了 postStart 回调,那么该回调已经执行且已完成。如果你使用 kubectl 来查询包含 Running 状态的容器的 Pod 时,你也会看到 关于容器进入 Running 状态的信息。
- Terminated(已终止):处于 Terminated 状态的容器已经开始执行并且或者正常结束或者因为某些原因失败。 如果你使用 kubectl 来查询包含 Terminated状态的容器的 Pod 时,你会看到 容器进入此状态的原因、退出代码以及容器执行期间的起止时间。如果容器配置了 preStop 回调,则该回调会在容器进入 Terminated 状态之前执行。
根据容器的运行状态,容器会按照重启策略来进行容器的恢复工作。容器的重启策略是使用restartPolicy这个参数在yaml文件中指定的,Pod的重启策略包括Always、OnFailure和Never,默认值为Always。
- Always:当容器失效时,由Kubernetes自动重启该容器。
- OnFailure:当容器终止运行且退出码不为0时,由Kubernetes自动重启该容器。
- Never:不论容器运行状态如何,Kubernetes都不会重启该容器。
接下来我们来运行一个busybox的容器的Pod,并进行postStart与preStop的设置。
我们编辑一个文件pod-nginx-post-pre.yaml,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: pod-nginx-post-pre
spec:
containers:
- name: nginx
image: nginx
lifecycle:
postStart:
exec:
command: ['sh','-c','touch /tmp/file; echo Pod postStart >> /tmp/file;']
preStop:
exec:
command: ['sh','-c','echo Pod preStop >> /tmp/file;']
Pod pod-nginx-post-pre是运行了一个nginx容器,并在其中设置了两个钩子函数:
- postStart:在容器开始之后,创建一个文件tmp目录下的file了,并打印Pod postStart到文件中。
- preStop:在容器即将关闭之前,打印Pod preStop到tmp目录下的file文件中。
创建这个Pod:
[root@kubernetes-master01 k8s-yaml]# kubectl apply -f pod-nginx-post-pre.yaml
pod/pod-nginx-post-pre created
登录到这个Pod中,并查看file中的内容:
[root@kubernetes-master01 k8s-yaml]# kubectl exec -it pod-nginx-post-pre -- /bin/sh
# cat /tmp/file
Pod postStart
已经按照要求,在/tmp/file中有内容Pod postStart。
对于preStop的演示,因为容器在关闭之前执行preStop这个函数,容器关闭之后,里面的日志与文件都没了,所以不好演示效果。一般preStop这个钩子函数用于容器在关闭之前需要进行的资源清理工作。
二、配置liveness probe
Kubernetes中使用存活探测器liveness probe来知道什么时候要重启容器。 例如,存活探测器liveness probe可以捕捉到死锁(应用程序在运行,但是无法继续执行后面的步骤)。 这样的情况下重启容器有助于让应用程序在有问题的情况下更可用。
接下来配置一个pod-busy-live.yaml的文件,文件内容如下:
apiVersion: v1
kind: Pod
metadata:
name: pod-busy-live
spec:
containers:
- name: busybox
image: busybox
command: ['sh','-c','touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600;']
livenessProbe:
exec:
command: ['cat /tmp/healthy;']
initialDelaySeconds: 5
periodSeconds: 5
上面的文件中是busybox的容器,执行的命令如下,起初创建一个文件/tmp/healthy,睡眠30秒后,删除/tmp/healthy,然后睡眠600秒。
['sh','-c','touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600;']
其中的livenessProbe是存活探针,其中的配置的功能如下:
- command: [‘cat /tmp/healthy;’]:检查是否有文件/tmp/healthy。
- initialDelaySeconds:第一次探测前,等待的时间,本例子中是5秒。
- periodSeconds:除了第一次探测外,每次探测的间隔,本例子中是5秒。
创建这个Pod:
[root@kubernetes-master01 k8s-yaml]# kubectl apply -f pod-busy-live.yaml
pod/pod-busy-live created
查看这个Pod的状态:
[root@kubernetes-master01 k8s-yaml]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-busy-live 1/1 Running 0 11s
持续的查看Pod的状态,当过了30秒后,Pod的状态中的RESTARTS字段变为了1,说明Pod重启过了。
[root@kubernetes-master01 k8s-yaml]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-busy-live 1/1 Running 1 54s
通过如下指令,查看Pod中的具体运行情况:
[root@kubernetes-master01 k8s-yaml]# kubectl describe pod pod-busy-live
在输出结果的最下面,显示容器因为liveness probe检测失败,所以重启了。
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/pod-busy-live to kubernetes-worker01
Normal Pulled 15m (x3 over 17m) kubelet, kubernetes-worker01 Successfully pulled image "busybox"
Normal Created 15m (x3 over 17m) kubelet, kubernetes-worker01 Created container busybox
Normal Started 15m (x3 over 17m) kubelet, kubernetes-worker01 Started container busybox
Normal Killing 14m (x3 over 16m) kubelet, kubernetes-worker01 Container busybox failed liveness probe, will be restarted
Normal Pulling 14m (x4 over 17m) kubelet, kubernetes-worker01 Pulling image "busybox"
Warning Unhealthy 12m (x16 over 17m) kubelet, kubernetes-worker01 Liveness probe failed: OCI runtime exec failed: exec failed: container_linux.go:367: starting container process caused: exec: "cat /tmp/healthy;": stat cat /tmp/healthy;: no such file or directory: unknown
三、配置readiness probe
Kubernetes使用就绪探测器readiness probe可以知道容器什么时候准备好了并可以开始接受请求流量,例如一个Java应用,是否可以正常的给消费者调用? 这可以用于对慢启动容器进行检测,以使容器满足对外服务的状态了,才提供服务。 当一个 Pod 内的所有容器都准备好了,才能把这个 Pod 看作就绪了。 这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。 在 Pod 还没有准备好的时候,会从 Service 的负载均衡器中被剔除的。
就绪探针的例子如下,我们一个文件pod-nginx-ready.yaml,内容如下:
apiVersion: v1
kind: Pod
metadata:
name: pod-nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
hostPort: 80
readinessProbe:
httpGet:
path: /
port: 80
在这个Pod中,我们运行了一个nginx,并启动了就绪检查readiness probe,其中采用的方式是http的检查。
创建这个Pod:
[root@kubernetes-master01 k8s-yaml]# kubectl apply -f pod-nginx-ready.yaml
pod/pod-nginx created
查看Pod的运行状态:
[root@kubernetes-master01 k8s-yaml]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-nginx 0/1 Running 0 5s
接下来,我们登陆到Pod中,关闭nginx:
[root@kubernetes-master01 k8s-yaml]# kubectl exec -it pod-nginx -- sh
# nginx -s stop
2021/03/16 08:46:54 [notice] 34#34: signal process started
# command terminated with exit code 137
现在,我们来查看Pod的运行状态,发现RESTARTS为1,容器已经重启了一次:
[root@kubernetes-master01 k8s-yaml]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod-nginx 1/1 Running 1 96s
容器探针是由Kubernetes容器执行的定期诊断。 要执行诊断,Kubernetes需要调用由容器实现的处理程序,有三种类型的处理程序:
- ExecAction: 在容器内执行指定命令。如果命令退出时返回码为 0 则认为诊断成功。
- TCPSocketAction: 对容器的 IP 地址上的指定端口执行 TCP 检查。如果端口打开,则诊断被认为是成功的。
- HTTPGetAction: 对容器的 IP 地址上指定端口和路径执行 HTTP Get 请求。如果响应的状态码大于等于 200 且小于 400,则诊断被认为是成功的。
每次探测都将获得以下三种结果之一:
- Success(成功):容器通过了诊断。
- Failure(失败):容器未通过诊断。
- Unknown(未知):诊断失败,因此不会采取任何行动。
针对运行中的容器,Kubernetes可以选择是否执行以下三种探针,以及如何针对探测结果作出反应:
- liveness Probe:指示容器是否正在运行。如果存活态探测失败,则 kubelet 会杀死容器, 并且容器将根据其重启策略决定未来。如果容器不提供存活探针, 则默认状态为 Success。
- readiness Probe:指示容器是否准备好为请求提供服务。如果就绪态探测失败, 端点控制器将从与 Pod 匹配的所有服务的端点列表中删除该 Pod 的 IP 地址。 初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。
- startup Probe: 指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被禁用,直到此探针成功为止。如果启动探测失败,Kubernetes将杀死容器,而容器依其重启策略进行重启。 如果容器没有提供启动探测,则默认状态为 Success。