Pod生命周期
- Pod创建过程
- 运行初始化容器过程
- 运行主容器过程
- 容器启动后钩子,容器终止前钩子
- 容器存活性,就绪性探测
- Pod终止过程
在整个Pod生命周期,会出现5中状态:
取值 | 描述 |
---|---|
Pending (悬决) | Pod 已被 Kubernetes 系统接受,但有一个或者多个容器尚未创建亦未运行。此阶段包括等待 Pod 被调度的时间和通过网络下载镜像的时间。 |
Running (运行中) | Pod 已经绑定到了某个节点,Pod 中所有的容器都已被创建。至少有一个容器仍在运行,或者正处于启动或重启状态。 |
Succeeded (成功) | Pod 中的所有容器都已成功终止,并且不会再重启。 |
Failed (失败) | Pod 中的所有容器都已终止,并且至少有一个容器是因为失败终止。也就是说,容器以非 0 状态退出或者被系统终止。 |
Unknown (未知) | 因为某些原因无法取得 Pod 的状态。这种情况通常是因为与 Pod 所在主机通信失败。 |
创建和终止
创建
- 用户通过kubectl或其他api客户端提交创建pod信息给apiserver
- apiserver生产pod对象信息,并存入etcd,然后返回确认信息至客户端
- apiserver反应ectd中pod对象变化,其他组件使用watch机制跟踪apiserver
- scheduler发现有新的pod对象要创建,开始为pod分配主机并将结果信息更新至apiserver
- node节点上kebelet发现有pod调度过来,尝试使用docker启动容器,并将结果送到apiserver
- apiserver将接收到的pod信息存入etcd中
终止
- 用户向apiserver发出删除pod命令
- apiserver中的pod信息会变化,在宽限期(30s),pod被视为dead
- pod标记为terminating标记
- kubelet监控到pod对象转为terminating状态同时启动pod关闭过程
- 端点控制器监控到pod对象的关闭行为时将其从所以匹配到此端点的service资源的端点列表一处
- 如果当前pod对象定义了preStop钩子处理器,则在其标记terminating后会以同步的方式启动
- pod中容器进程收到停止信号
- 宽限期结束,若pod还存在仍在运行的进程,pod对象会受到立即终止信号
- kubelet将pod资源宽限期设置为0从而完成操作,此时pod对于用户已经可不见
初始化容器
初始化容器在Pod的主容器启动之前要运行的容器。(完成主容器前置工作)
- 初始化容器必须运行完成至结束,否则k8s需要重启它直至成功
- 必须按照定义的顺序执行
初始化容器场景:
- 提供主容器镜像中不具备的工具程序或自定义代码
- 初始化容器要咸鱼应用容器串行启动并运行完成,可用于容器启动直至其依赖的条件得到满足(感觉有点类似于docker拉取镜像,如果镜像依赖于其他服务,就先拉取其他镜像资源,一层一层叠加)
案例
-
需要主容器运行nginx
-
运行nginx前需要nginx先连接上mysql和redis所在服务器
-
提前规定服务器地址
-
mysql:192.168.126.129
-
redis: 192.168.126.130
-
创建pod-initcontainer.yaml:
apiVersion: v1
kind: Pod
metadata:
name: pod-initcontainer
namespace: dev
spec:
containers:
- name: main-container
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
initContainers:
- name: test-mysql
image: busybox:1.30
command: ['sh', '-c', 'until ping 192.168.126.129 -c 1 ; do echo waiting for mysql...; sleep 2; done;'] #直到ping通才停止
- name: test-redis
image: busybox:1.30
command: ['sh', '-c', 'until ping 192.168.126.130 -c 1 ; do echo waiting for reids...; sleep 2; done;']
我这两个服务器IP地址有效,可以ping通:
[root@master ~]# cd mine/
[root@master mine]# vim pod-initcontainer.yaml
[root@master mine]# kubectl create -f pod-initcontainer.yaml
pod/pod-initcontainer created
[root@master mine]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
pod-initcontainer 1/1 Running 0 16s
可以尝试切换无法到达的IP进行尝试,主容器应该无法创建
钩子函数
允许用户自己定义行为代码,完成一些指定的功能
钩子函数支持三种方式定义动作:
-
Exec:在容器内执行一次命令
…… lifecycle: postStart: exec: command: - cat - /tmp/healthy #查看/tmp/healthy ……
-
TCPSocket:在当前容器尝试访问指定的socket
…… lifecycle: postStart: tcpSocket: port: 8080 ……
-
HTTPGet:在当前容器中向某个url发起http请求
…… lifecycle: postStart: httpGet: path: / #URI地址 port: 80 #端口号 host: 192.168.109.100 #主机地址 scheme: HTTP #支持的协议,http或者https ……
新建一个pod-hook-exec.yaml:
apiVersion: v1
kind: Pod
metadata:
name: pod-hook-exec
namespace: dev
spec:
containers:
- name: main-container
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
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@master mine]# kubectl create -f pod-hook-exec.yaml
pod/pod-hook-exec created
[root@master mine]# kubectl get pod -n dev -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod-hook-exec 1/1 Running 0 39s 10.244.2.8 node2 <none> <none>
[root@master mine]# curl 10.244.2.8:80
postStart...
容器探测
用于检测容器中应用实例能否正常运行,如果实例状态不符合预期,那么k8s就会把问题实例摘除,不承担业务流量,k8s提供两种探针实现:
-
liveness probes:存活性探针,检测应用实例是否处于正常状态,若不是k8s会重启实例
-
readlness probes:就绪性探针,用于检测应用实例是否可以接受请求,如果不能,k8s不会转发流量
三种探测方式:
-
Exec:在容器内执行一次命令,如果命令执行退出码为0,认为程序正常,否则不正常
…… livenessProbe: exec: command: - cat - /tmp/healthy ……
-
TCPSocket:将会尝试访问一个用户容器的端口,如果能够建立这条连接,则认为程序正常,否则不正常
…… livenessProbe: tcpSocket: port: 8080 ……
-
HTTPGet:调用容器内Web应用的URL,如果返回的状态码在200和399之间,则认为程序正常,否则不正常
…… livenessProbe: httpGet: path: / #URI地址 port: 80 #端口号 host: 127.0.0.1 #主机地址 scheme: HTTP #支持的协议,http或者https ……
-
以livenessProbe为例,新建
新建test1.yaml文件:
apiVersion: v1
kind: Pod
metadata:
name: pod-liveness-exec
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
livenessProbe:
exec:
command: ["/bin/cat","/tmp/hello.txt"] # 执行一个查看文件的命令
默认情况下没有这个文件,所以它会重启容器
#创建Pod
[root@master mine]# vim test1.yaml
[root@master mine]# kubectl create -f test1.yaml
pod/pod-liveness-exec created
[root@master mine]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
pod-liveness-exec 1/1 Running 0 19s
#查看详情
[root@master mine]# kubectl describe pods pod-liveness-exec -n dev
.......
Warning Unhealthy 9s (x6 over 59s) kubelet, node2 Liveness probe failed: /bin/cat: /tmp/hello.txt: No such file or directory
Normal Killing 9s (x2 over 39s) kubelet, node2 Container nginx failed liveness probe, will be restarted
#没有这个文件niginx容器重启
[root@master mine]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
pod-liveness-exec 0/1 CrashLoopBackOff 6 4m43s
#RESTARTS重启次数已经变成三次
#删除这个Pod
[root@master mine]# kubectl delete -f test1.yaml
pod "pod-liveness-exec" deleted
#修改yaml文件
[root@master mine]# kubectl create -f test1.yaml
pod/pod-liveness-exec created
[root@master mine]# cat test1.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-liveness-exec
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
livenessProbe:
exec:
command: ["/bin/ls","/tmp/"] # 执行一个查看文件的命令
#这条命令是可以执行的
[root@master mine]# kubectl describe pods pod-liveness-exec -n dev
....
Normal Created 65s kubelet, node2 Created container nginx
Normal Started 65s kubelet, node2 Started container nginx
#发现没有重启
[root@master mine]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
pod-liveness-exec 1/1 Running 0 2m36s
重启策略
Pod 的 spec
中包含一个 restartPolicy
字段,其可能取值包括 Always、OnFailure 和 Never。默认值是 Always。
restartPolicy
适用于 Pod 中的所有容器。restartPolicy
仅针对同一节点上 kubelet
的容器重启动作。当 Pod 中的容器退出时,kubelet
会按指数回退方式计算重启的延迟(10s、20s、40s、…),其最长延迟为 5 分钟。 一旦某容器执行了 10 分钟并且没有出现问题,kubelet
对该容器的重启回退计时器执行重置操作。
- Always:容器失效,自动重启容器
- OnFailure:容器终止运行且退出码不为0时重启
- Never:无论状态如何从不重启
创建pod-restartpolicy.yaml文件:
apiVersion: v1
kind: Pod
metadata:
name: pod-restartpolicy
namespace: dev
spec:
containers:
- name: nginx
image: nginx:1.17.1
ports:
- name: nginx-port
containerPort: 80
livenessProbe:
httpGet:
scheme: HTTP
port: 80
path: /hello #没有这个路径所以无法访问
restartPolicy: Never # 设置重启策略为Never
#创建Pod
[root@master mine]# vim pod-restartpolicy.yaml
[root@master mine]# kubectl create -f pod-restartpolicy.yaml
pod/pod-restartpolicy created
#查看是否重启
[root@master mine]# kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
pod-restartpolicy 0/1 Completed 0 111s
#发现并没有重启
#查看详细信息
[root@master mine]# kubectl describe pod pod-restartpolicy -n dev
....
Warning Unhealthy 3m11s (x3 over 3m31s) kubelet, node2 Liveness probe failed: HTTP probe failed with statuscode: 404
Normal Killing 3m11s kubelet, node2 Stopping container nginx
#返回404未找到但是由于设置了重启策略为Never所以不重启