Kubernetes之Pod生命周期
- Pod生命周期官方文档
- Pod的状态
- 初始化容器
- 案例
- 钩子函数
- Exec命令
- TCPSocket
- HTTPGet
- 案例
- 容器探测
- Exec命令
- TCPSocket
- HTTPGet
- 探测时间
- 重启策略
Pod生命周期官方文档
Pod生命周期官方文档
Pod的状态
- pending:挂起,apiserver创建了pod资源对象已存入etcd中,但它尚未被调度完成,或者仍处于从仓库下载镜像的过程中;
- running:运行中,pod已经被调度到某节点,并且所有容器都已经被kubelet创建完成;
- complet:成功,pod中所有容器都已经成功终止并且不会重启;
- failed:失败,pod中所有容器都已经终止了,并且至少有一个容器是因为失败终止的,即容器以非0状态退出或者被系统禁止;
- unknown:未知,apiserver无法正常获取到pod对象的状态信息,通常是由于无法与所在工作节点的kubelet通信所致;
初始化容器
- k8s的初始化容器(initContainer)优先级都是高于主容器(container)的。无论容器写在初始化容器前还是写在初始化容器后,会最先执行的都是初始化容器。只有初始化容器执行成功后才可以启动主容器。
- 初始化容器的应用场景应该是多pod。比如:mysql和业务分开两个pod。此时,业务pod添加初始化容器,初始化容器执行telnet,检查mysql是否启动了。若mysql启动,则业务pod启动;否则业务pod等待mysql启动。
初始化容器是在pod主容器启动之前要运行的容器,主要是做一些主容器的前置工作,它具有两大特征:
- 初始化容器必须运行完成直至结束,若某初始化容器运行失败,那么kubernetes需要重启它直到成功完成;
- 初始化容器必须按照定义的顺序执行,当且仅当前一个成功之后,后面的一个才能运行;
案例
apiVersion: v1
kind: Pod
metadata:
name: pod-initcontainer
namespace: bubble-dev
spec:
containers:
- name: main-container
image: nginx:1.17.9
ports:
- name: nginx-port
containerPort: 80
initContainers:
- name: mysql
image: busybox:1.30
command: [ "/bin/sh","-c","sleep 40;"]
- name: redis
image: busybox:1.30
busybox:1.30启动成功之后,会立即停止,通过使用command命令,40S之后这个容器才会停止;
启动主容器(main-container)必须等待初始化容器(mysql和redis)启动并运行成功之后,才可以启动;
vi pod-initcontainer.yaml
cat pod-initcontainer.yaml
kubectl create ns bubble-dev
kubectl create -f pod-initcontainer.yaml
[root@master ~]# kubectl describe pods -n bubble-dev
Name: pod-initcontainer
Namespace: bubble-dev
Priority: 0
Node: node1/192.168.102.160
Start Time: Thu, 12 Jan 2023 10:44:14 -0500
Labels: <none>
Annotations: <none>
Status: Running
IP: 172.17.0.2
IPs:
IP: 172.17.0.2
Init Containers:
mysql:
Container ID: docker://6c41381ade3cb74d93b4b449920a89ce1b534860da4a3803d886389b7873f5c4
Image: busybox:1.30
Image ID: docker-pullable://busybox@sha256:4b6ad3a68d34da29bf7c8ccb5d355ba8b4babcad1f99798204e7abb43e54ee3d
Port: <none>
Host Port: <none>
Command:
/bin/sh
-c
sleep 40;
State: Terminated
Reason: Completed
Exit Code: 0
Started: Thu, 12 Jan 2023 10:44:16 -0500
Finished: Thu, 12 Jan 2023 10:44:56 -0500
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-9bq4c (ro)
redis:
Container ID: docker://8a504efac19030ab4a266599795e7ad1368f351f48eae8eb45101100aec0dec1
Image: busybox:1.30
Image ID: docker-pullable://busybox@sha256:4b6ad3a68d34da29bf7c8ccb5d355ba8b4babcad1f99798204e7abb43e54ee3d
Port: <none>
Host Port: <none>
State: Terminated
Reason: Completed
Exit Code: 0
Started: Thu, 12 Jan 2023 10:44:57 -0500
Finished: Thu, 12 Jan 2023 10:44:57 -0500
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-9bq4c (ro)
Containers:
main-container:
Container ID: docker://920298ed4e9f76c825249290078a9a408476df66175e6fc8b9dcdaf25346f324
Image: nginx:1.17.9
Image ID: docker-pullable://nginx@sha256:88ea86df324b03b3205cbf4ca0d999143656d0a3394675630e55e49044d38b50
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Thu, 12 Jan 2023 10:44:58 -0500
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-9bq4c (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-9bq4c:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-9bq4c
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 4m47s default-scheduler Successfully assigned bubble-dev/pod-initcontainer to node1
Normal Pulled 4m46s kubelet, node1 Container image "busybox:1.30" already present on machine
Normal Created 4m46s kubelet, node1 Created container mysql
Normal Started 4m45s kubelet, node1 Started container mysql
Normal Pulled 4m4s kubelet, node1 Container image "busybox:1.30" already present on machine
Normal Created 4m4s kubelet, node1 Created container redis
Normal Started 4m4s kubelet, node1 Started container redis
Normal Pulled 4m3s kubelet, node1 Container image "nginx:1.17.9" already present on machine
Normal Created 4m3s kubelet, node1 Created container main-container
Normal Started 4m3s kubelet, node1 Started container main-container
我们可以分析出Pod中首先启动并运行的是mysql容器,mysql容器运行成功后,redis容器开始启动并运行,完成运行后主容器才开始启动。
钩子函数
k8s在主容器启动之后和停止之前提供了两个钩子函数
- post-start:容器创建之后执行(相关命令),如果失败了则会自动重启容器,容器创建后立即执行,注意由于是异步执行,它无法保证一定在ENTRYPOINT之前运行。如果失败,容器会被杀死,并根据RestartPolicy决定是否重启;
- pre-stop:容器终止之前执行(相关命令) ,例如杀死进程等,容器终止前执行,常用于资源清理。执行完成之后容器将成功终止,如果失败,容器同样也会被杀死。在其完成之前,会阻塞删除容器的操作;
钩子的回调函数支持三种方式:Exec命令、TCPSocket、HTTPGet
Exec命令
spec:
containers:
- name: main-container
image: nginx:1.17.1
lifecycle:
postStart:
exec: # 容器创建之后执行(相关命令)修改nginx页面
command: ["/bin/sh","-c","echo honey > /usr/share/nginx/html/index.html"]
preStop:
exec: # 容器停止之后执行停止nginx服务
command: ["/usr/sbin/nginx","-s","quit" ]
TCPSocket
spec:
containers:
- name: main-container
image: nginx:1.17.1
lifecycle:
postStart:
tcpSocket:
port: 8080
HTTPGet
spec:
containers:
- name: main-container
image: nginx:1.17.1
lifecycle:
postStart:
httpGet:
path: /init # URI地址
port: 80 # 端口号
host: 192.168.110.1 # 主机地址
scheme: HTTP # 支持的协议,http或https
案例
apiVersion: v1
kind: Pod
metadata:
name: pod-hook
namespace: bubble-dev
spec:
containers:
- name: main-container
image: nginx:1.17.9
lifecycle:
postStart:
exec: # 容器创建之后执行(相关命令)修改nginx页面
command: ["/bin/sh","-c","echo honey > /usr/share/nginx/html/index.html"]
preStop:
exec: # 容器停止之后执行停止nginx服务
command: ["/usr/sbin/nginx","-s","quit" ]
容器探测
k8s提供了livenessProbe(可用性探针)和readinessProbe(就绪性探针)对容器的健康性进行检测,类似心跳机制。
判断我们的应用实例是否存活,如果为宕机状态,则自动重启,同时如果发现该pod无法接受请求,则service不会转发到该pod上执行。
- 存活探针(可用性探针):用于检测容器实例当前是否处于正常运行的状态,如果不是正常运行的状态,k8s则会重启容器;
- 就绪探针(就绪性探针):用于检测应用实例当前是否可以接收请求,如果不能接收请求,k8s不会将请求转发到该实例;
其实非常好理解,livenessProbe 判断容器是否重启、readinessProbe 判断是否路由转发
支持三种探测方式:
- Exec命令:在容器内执行一次命令,如果命令执行的退出码为0,则认为程序正常,否则不正常;
- TCPSocket:会尝试访问一个用户指定的容器端口,如果能够成功建立连接则认为正常,否则认为不正常;
- HTTPGet:调用容器内Web系统的url,如果http状态码是在200和399之间,则认为程序正常,否则不正常;
Exec命令
apiVersion: v1
kind: Pod
metadata:
name: pod-exec
namespace: bubble-dev
spec:
containers:
- name: nginx
image: nginx:1.17.9
ports:
- name: nginx-port
containerPort: 80
livenessProbe: # 存活探针(可用性探针)
exec: # 执行一个查看文件的命令
command: ["/bin/cat" ,"/tmp/honey.txt"]
我们可以看到,由于没有/tmp/honey.txt这个文件,执行的查看命令是失败的,所以容器一直在进行重新启动操作
如果将命令修改成pwd则不会有问题
apiVersion: v1
kind: Pod
metadata:
name: pod-exec
namespace: bubble-dev
spec:
containers:
- name: nginx
image: nginx:1.17.9
ports:
- name: nginx-port
containerPort: 80
livenessProbe: # 存活探针(可用性探针)
exec: # 执行一个pwd的命令
command: ["/bin/pwd" ,"/"]
TCPSocket
apiVersion: v1
kind: Pod
metadata:
name: pod-tcp
namespace: bubble-dev
spec:
containers:
- name: nginx
image: nginx:1.17.9
ports:
- name: nginx-port
containerPort: 80
livenessProbe: # 存活探针(可用性探针)
tcpSocket: # 底层会尝试访问容器ip:8080
port: 8080
将端口号修改成80则不会有问题
apiVersion: v1
kind: Pod
metadata:
name: pod-tcp
namespace: bubble-dev
spec:
containers:
- name: nginx
image: nginx:1.17.9
ports:
- name: nginx-port
containerPort: 80
livenessProbe: # 存活探针(可用性探针)
tcpSocket: # 底层会尝试访问容器ip:80
port: 80
HTTPGet
apiVersion: v1
kind: Pod
metadata:
name: pod-http
namespace: bubble-dev
spec:
containers:
- name: nginx
image: nginx:1.17.9
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
livenessProbe:
httpGet: # 访问指定的scheme://host:port/path
scheme: HTTP # 支持的协议,http或者https
port: 80 # 端口号
path: /honey # URI地址 该地址不存在会报错404
将URI地址修改成 / 则不会有问题
apiVersion: v1
kind: Pod
metadata:
name: pod-http
namespace: bubble-dev
spec:
containers:
- name: nginx
image: nginx:1.17.9
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
livenessProbe:
httpGet: # 访问指定的scheme://host:port/path
scheme: HTTP # 支持的协议,http或者https
port: 80 # 端口号
path: / # URI地址
探测时间
容器探测的原理本身就是心跳策略
initialDelaySeconds <integer> # 容器启动后 等待多少秒 开始执行第一次探测
timeoutSeconds <integer> # 探测超时时间 默认1秒,最小1秒
periodSeconds <integer> # 执行探测的频率,默认是10秒,最小1秒
failureThreshold <integer> # 连续探测失败多少次才被认定为失败,默认是3,最小值是1
successThreshold <integer> # 连续探测成功多少次才被认定为成功,默认是1
apiVersion: v1
kind: Pod
metadata:
name: pod-seconds
namespace: bubble-dev
spec:
containers:
- name: nginx
image: nginx:1.17.9
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
livenessProbe:
httpGet: # 访问指定的scheme://host:port/path
scheme: HTTP # 支持的协议,http或者https
port: 80 # 端口号
path: /honey # URI地址 该地址不存在会报错404
initialDelaySeconds: 10 # 容器启动后10s开始探测
failureThreshold: 2 # 探测2次认为是失败
restartPolicy: Never # 设置重启策略为Never 无论状态如何都不会重启
重启策略
重启策略有三种:
- Always:出现问题时自动重启该容器,默认方式
- OnFailure:容器终止运行且退出码不为0时重启
- Never:不论状态为何,都不重启该容器
apiVersion: v1
kind: Pod
metadata:
name: pod-restart
namespace: bubble-dev
spec:
containers:
- name: nginx
image: nginx:1.17.9
ports:
- name: nginx-port
containerPort: 80
protocol: TCP
livenessProbe:
httpGet: # 访问指定的scheme://host:port/path
scheme: HTTP # 支持的协议,http或者https
port: 80 # 端口号
path: /honey # URI地址 该地址不存在会报错404
restartPolicy: Never # 设置重启策略为Never 无论状态如何都不会重启