当你使用kuberentes的时候,有没有遇到过Pod在启动后一会就挂掉然后又重新启动这样的恶性循环?你有没有想过kubernetes是如何检测pod是否还存活?虽然容器已经启动,但是kubernetes如何知道容器的进程是否准备好对外提供服务了呢?让我们通过来一探究竟。首先pod在kubernetes中有5个状态,我们大体了解一下这5个状态,如下表:
名称 | 描述 |
Pending | 系统已经接受pod实例的创建,但其中所包含容器的一个或者多个image还没有创建成功。Pending包含调度计算与通过网络创建image,所以此phase的时间可能会有点长。 |
Running | Pod已经被调度到某个node上,pod包含的所有容器已经创建完成,至少有一个容器正常运行或者处于启动与重启动过程。 |
Succeeded | Pod中的所有容器正常终止,并且不会再次启动。 |
Failed | Pod中所有容器已终止运行,至少有一个容器非正常结束,比如退出码非零,被系统强制杀死等。 |
Unknow | 无法取得pod状态,一般是网络问题引起。 |
我们可以通过kubectl describe pods {podName}来查看status状态,了解到pod状态以后,达到这个状态的过程是如何呢?pod的生命周期到底是如何的呢?我们下面来一探究竟。
pod周期的过程如下5步:
1.初始化容器阶段初始化pod中每一个容器,他们是串行执行的,执行完成后就退出了
2.启动主容器main container
3.在main container刚刚启动之后可以执行post start命令
4.在整个main container执行的过程中可以做两类探测:liveness probe(存活探测)和readiness probe(就绪探测)
5.在main container结束前可以执行pre stop命令
如下图:
其中liveness probe(存活探测)和readiness probe(就绪探测)、post start 、pre stop我们将详细说明。
定义liveness probe探针
曾经的我在部署海量docker服务时遇到过这样的问题,某台服务器上跑了100个docker服务。有一天有1个docker宕机了,需要重新部署,这时候我花了很多时间找出问题节点并重新删除、安装,这时候我在想如果有一种方式能自动检测并重启,那该多好。
毫无疑问,liveness probe能帮我们解决这个问题,它的作用是确定何时重启容器。例如,当应用程序处于运行状态但无法做进一步操作,liveness探针将捕获到deadlock,重启处于该状态下的容器,使应用程序在存在bug的情况下依然能够继续运行下去(谁的程序还没几个bug呢)。
在K8S中 我们只需在yaml文件中定义liveness probe字段便可解决。如下:
我们在运行容器时执行command命令 touch一个文件,再过60秒后,删除这个文件
然后让liveness probe 每隔5s检测一次,我们将会看到容器在运行一段时间后,restart。
apiVersion: v1
kind: Pod
metadata :
name: liveness
namespace: default
spec:
containers:
- name: livenesscontainers
image: nginx
imagePullPolicy: IfNotPresent
command: ["/bin/bash","-c","touch /tmp/health;sleep 60;rm -rf /tmp/health;sleep 3600;"]
livenessProbe:
exec:
command: ["test","-e","/tmp/health"]
initialDelaySeconds: 1
periodSeconds: 3
其中command: ["test","-e","/tmp/health"] 为探测的命令,如果命令执行成功,将返回0,kubelet就会认为该容器是活着的并且很健康.。
initialDelaySeconds: X (代表开启容器后X秒后再进行生命探测,如果结果为0,kubelet就会杀掉这个容器并重启它。)
periodSeconds: Y (代表每隔Y秒后探测一次)
定义一个liveness HTTP请求
该探针将向容器中的server的8080端口发送一个HTTP GET请求。如果server的/healthz
路径的handler返回一个成功的返回码,kubelet就会认定该容器是活着的并且很健康。如果返回失败的返回码,kubelet将杀掉该容器并重启它。
apiVersion: v1
kind: Pod
metadata :
name: liveness
namespace: default
spec:
containers:
- name: livenesscontainers
image: nginx
imagePullPolicy: IfNotPresent
ports:
- name:http
containersPort:8080
command: ["/bin/bash","-c","touch /tmp/health;sleep 60;rm -rf /tmp/health;sleep 3600;"]
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 3
periodSeconds: 3
定义readiness探针
有时,应用程序暂时无法对外部流量提供服务。 例如,应用程序可能需要在启动期间加载大量数据或配置文件。 在这种情况下,你不想杀死应用程序,但你也不想发送请求。 Kubernetes提供了readiness probe来检测和减轻这些情况。 Pod中的容器可以报告自己还没有准备,不能处理Kubernetes服务发送过来的流量。
Readiness probe的配置跟liveness probe很像。唯一的不同是使用 readinessProbe
而不是livenessProbe
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
如pod生命周期图,当容器启动以后Kubernetes会发送一个postStart事件,并且在容器退出之前理解发送一个preStop事件。这两个钩子,我们也可以运用起来,比如,您需要在下载github上的文件后再做一些事情....
下面是这个Pod的配置文件:
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
在这个配置文件里面,可以看到postStart命令写了一个message文件在容器的/usr/share目录里面。preStop命令优雅的退出nginx。如果容器因为失败而退出这是非常有用的。其中postStart是在执行完containers的command命令后再执行的,所以我们可以利用这个性质,做一些特定的事情。
现在我们已经学习完了pod的生命周期,了解到了pod的基本机制,下一节我们将继续深入探讨pod,感兴趣的朋友,可以继续更进,在此小编祝大家生活愉快。有技术交流的朋友请加微信:laughing_jk。
~~您身边喜欢绿色的朋友
帅吉帅哥(Spring)