目录
- 1. 概述
- 2. Pod的创建和删除过程
- 2.1 Pod的创建过程
- 2.2 Pod的删除过程
- 3. init container初始化容器
- 4. 钩子函数
- 5. 容器探测
- 5.1 exec方式
- 5.2 tcpSocket方式
- 5.3 httpGet方式
- 6. 重启策略
1. 概述
Pod对象从创建到删除的这段时间范围称为Pod的生命周期,主要包含下面的过程:
- Pod创建
- 运行初始化容器(init container)
- 运行主容器(main container)
- 容器启动后钩子(post start)
- 容器的存活性探测(liveness probe)、就绪性探测(readiness probe)
- 容器删除前钩子(pre stop)
- Pod删除
在整个生命周期中,Pod会出现5种状态:
- 挂起(Pending):API Server已经创建了Pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中
- 运行中(Running):Pod已经被调度到某节点,并且所有容器都已经被kubelet创建完成
- 成功(Succeeded):Pod中的所有容器都已经成功删除并且不会被重启
- 失败(Failed):所有容器都已经删除,但至少有一个容器删除失败,即容器返回了非0值的退出状态
- 未知(Unknown):API Server无法正常获取到Pod对象的状态信息,通常由于网络通信失败所导致
2. Pod的创建和删除过程
2.1 Pod的创建过程
- 用户通过kubectl或其他的API客户端提交需要创建的Pod信息给API Server
- API Server开始生成Pod对象的信息,并将信息存入etcd,然后返回确认信息至客户端
- API Server开始反映etcd中的Pod对象的变化,其它组件使用watch机制来跟踪检查API Server上的变动
- Scheduler发现有新的Pod对象要创建,开始为Pod分配主机并将结果信息更新至API Server
- Node节点上的kubelet发现有Pod调度过来,尝试调度Docker启动容器,并将结果返回至API Server
- API Server将接收到的Pod状态信息存入到etcd中
2.2 Pod的删除过程
- 用户向API Server发送删除Pod对象的命令
- 将Pod标记为terminating状态
- kubelet在监控到Pod对象转为terminating状态的同时启动Pod关闭过程
- 端点控制器监控到Pod对象的关闭行为时,将其从所有匹配到此端点的service资源的端点列表中移除
- 如果当前Pod对象定义了preStop钩子处理器,则在其标记为terminating后会以同步的方式启动执行
- Pod对象中的容器进程收到停止信号
- 宽限期结束后(默认30s),如果Pod中还存在运行的进程,那么Pod对象会收到立即删除的信号
- kubectl请求API Server将此Pod资源的宽限期设置为0从而完成删除操作,此时Pod对于用户已经不可用
3. init container初始化容器
初始化容器是在Pod的主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:
- 初始化容器必须运行完成直至结束,如果某个初始化容器运行失败,那么kubernetes需要重启它直至成功完成
- 初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行
初始化容器有很多的应用场景,下面列出的是最常见的几个:
- 提供主容器镜像中不具备的工具程序或自定义代码
- 初始化容器要先于应用容器串行启动并运行完成,可用于满足应用容器启动的先决要求
接下来做一个案例,模拟下面这个需求:
- 假设主容器运行Nginx,但是要求在运行Nginx之前要能够连接上MySQL和Redis所在的服务器
- 为了简化测试,事先规定好MySQL和Redis所在的IP地址分别为192.168.23.188和192.168.23.189(188的IP目前能ping通,189的IP目前不能ping通)
新建pod-lifecycle.yaml,内容如下。然后进行pod创建
user: bulut
spec:
containers:
- name: nginx-container
image: nginx:latest
initContainers:
- name: init-mysql
image: busybox
command: ['/bin/sh', '-c', 'until ping 192.168.23.188 -c 1; do echo waiting for mysql; sleep 3; done;']
- name: init-redis
image: busybox
command: ['/bin/sh', '-c', 'until ping 192.168.23.189 -c 1; do echo waiting for redis; sleep 3; done;']
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl apply -f pod-lifecycle.yaml
pod/pod-lifecycle created
[root@k8s-master ~]#
查看pod启动状态。只有第一个init成功,卡在第二个init container了
[root@k8s-master ~]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
pod-lifecycle 0/1 Init:1/2 0 28s
[root@k8s-master ~]#
4. 钩子函数
kubernetes在主容器启动之后和删除之前提供了两个钩子函数:
- post start:容器创建之后执行,如果失败会重启容器
- pre stop:容器删除之前执行,执行完成之后容器将成功删除,在其完成之前会阻塞删除容器的操作
钩子处理器支持三种定义方式:
- exec命令:在容器内执行一次命令。语法如下:
lifecycle:
postStart:
exec:
command:
- cat
- /tmp/test.txt
- tcpSocket:在当前容器尝试访问指定的socket
lifecycle:
postStart:
tcpSocket:
port: 8080
- httpGet:在当前容器中向某url发起HTTP请求
lifecycle:
postStart:
httpGet:
path: / # URI地址
port: 80 # 端口号
host: 192.168.23.161 # 主机地址
scheme: HTTP # 支持的协议,http或者https
新建pod-lifecycle.yaml,内容如下。然后进行pod创建
[root@k8s-master ~]# cat pod-lifecycle.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-lifecycle
namespace: dev
labels:
user: bulut
spec:
containers:
- name: nginx-container
image: nginx:latest
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
lifecycle:
postStart:
exec: # 修改Nginx的首页内容
command: ["/bin/sh", "-c", "echo postStart > /usr/share/nginx/html/index.html"]
preStop:
exec: # 停止Nginx的服务
command: ["/usr/sbin/nginx", "-s", "quit"]
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl apply -f pod-lifecycle.yaml
pod/pod-lifecycle created
[root@k8s-master ~]#
访问nginx服务。可以看到postStat起作用了
[root@k8s-master ~]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-lifecycle 1/1 Running 0 64s 10.244.169.150 k8s-node2 <none> <none>
[root@k8s-master ~]#
[root@k8s-master ~]# curl 10.244.169.150:80
postStart
[root@k8s-master ~]#
5. 容器探测
容器探测用于检测容器中的应用实例是否正常工作,kubernetes提供了三种探针来实现容器探测,本文主要讲解liveness probes和readiness probes
- liveness probes:存活性探测,用于检测应用实例当前是否处于正常运行状态,如果不是,k8s会重启容器
- readiness probes:就绪性探测,用于检测应用实例是否可以接受请求,如果不能,k8s不会转发流量到该应用实例
- startupProbe探针,用于判断容器内应用程序是否已经启动,一旦成功将不再进行探测。如果配置了startupProbe探针,就会先禁止其他的探针,直到startupProbe探针成功为止
liveness probes和readiness probes均支持三种探测方式。语法如下,readinessProbe和livenessProbe的语法一样
- exec命令:在容器内执行一次命令。如果命令执行的退出码为0,则认为程序正常,否则不正常
livenessProbe:
exec:
command:
- cat
- /tmp/test.txt
- tcpSocket:在当前容器尝试访问指定的socket。如果能够建立连接,则认为程序正常,否则不正常
livenessProbe:
tcpSocket:
port: 8080
- httpGet:在当前容器中向某url发起HTTP请求。如果返回的状态码在200和399之间,则认为程序正常,否则不正常
livenessProbe:
httpGet:
path: / # URI地址
port: 80 # 端口号
host: 192.168.23.161 # 主机地址
scheme: HTTP # 支持的协议,http或者https
通过命令kubectl explain pod.spec.containers.livenessProbe
查看其它属性,整理如下:
exec
tcpSocket
httpGet
initialDelaySeconds # 容器启动后等待多少秒执行第一次探测
timeoutSeconds # 探测超时时间。默认1秒,最小1秒
periodSeconds # 执行探测的频率。默认是10秒,最小1秒
failureThreshold # 连续探测失败多少次才被认定为失败。默认是3。最小值是1
successThreshold # 连续探测成功多少次才被认定为成功。默认是1
5.1 exec方式
新建pod-lifecycle.yaml,内容如下:
[root@k8s-master ~]# cat pod-lifecycle.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-lifecycle
namespace: dev
labels:
user: bulut
spec:
containers:
- name: nginx-container
image: nginx:latest
livenessProbe:
exec:
command: ["ls", "/tmp"]
[root@k8s-master ~]#
5.2 tcpSocket方式
新建pod-lifecycle.yaml,内容如下:
[root@k8s-master ~]# cat pod-lifecycle.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-lifecycle
namespace: dev
labels:
user: bulut
spec:
containers:
- name: nginx-container
image: nginx:latest
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
livenessProbe:
tcpSocket:
port: 80
[root@k8s-master ~]#
5.3 httpGet方式
新建pod-lifecycle.yaml,内容如下:
[root@k8s-master ~]# cat pod-lifecycle.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-lifecycle
namespace: dev
labels:
user: bulut
spec:
containers:
- name: nginx-container
image: nginx:latest
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
livenessProbe:
httpGet: # 其实就是访问http://127.0.0.1:80/
port: 80
scheme: HTTP
path: /
host: 127.0.0.0
[root@k8s-master ~]#
6. 重启策略
在容器探测中,一旦容器探测出现了问题,kubernetes就会对容器所在的Pod进行重启,其实这是由Pod的默认重启策略决定的。Pod的重启策略有3种:
- Always:容器失效时,自动重启该容器,默认值
- OnFailure:容器终止运行且退出码不为0时重启
- Never:不论状态如何,都不重启该容器
重启策略是针对Pod设定的。首次需要重启的容器,将在其需要的时候立即进行重启,随后再次重启的操作将由kubelet延迟一段时间后进行,且反复的重启操作的延迟时长依次为10s、20s、40s、80s、160s和300s,300s是最大的延迟时长
新建pod-lifecycle.yaml,内容如下:
[root@k8s-master ~]# cat pod-lifecycle.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-lifecycle
namespace: dev
labels:
user: bulut
spec:
containers:
- name: nginx-container
image: nginx:latest
restartPolicy: Never
[root@k8s-master ~]#