一、Pod简介
Pod的退出流程
1、什么是Pod
2、定义一个Pod
二、探针、零宕机发布
1、Pod探针
2、Pod探针的检测方式
3、探针检查参数配置
4、startupProbe
5、liveness
6、readiness
7、Pod 优雅关闭
管理员 执行的删除操作
Pod 的状态为 terminating
EndPoint 会删除 对应的 Pod-IP
执行Prestop的指令
Pod是Kubernetes中最小的单元,它由一组、一个或多个容器组成,每个Pod还包含了一个Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理,通过Pause容器可以使同一个Pod里面的多个容器共享存储、网络、PID、IPC等。
通过Pod的概念能够方便 管理容器,因为容器不只一种,有多种容器
副本的概念,便捷的扩容与伸缩,资源的管理,Pod使容器之间的通信更为密切(通过Pause镜像),减少端口的资源浪费
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据
name: nginx # 必选,符合RFC 1035规范的Pod名称
# namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace
labels: # 可选,标签选择器,一般用于过滤和区分Pod,根据业务自定义
app: nginx
role: frontend # 可以写多个
annotations: # 可选,注释列表,可以写多个
app: nginx1.21 #可以注释一些 Nginx版本
spec: # 必选,用于定义容器的详细信息
# initContainers: # 初始化容器,在容器启动之前执行的一些初始化操作
# - command:
# - sh
# - -c
# - echo "I am InitContainer for init some configuration"
# image: busybox
# imagePullPolicy: IfNotPresent
# name: init-container
containers: # 必选,容器列表
- name: nginx # 必选,符合RFC 1035规范的容器名称
image: nginx:1.15.2 # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent # 可选,镜像拉取策略, IfNotPresent: 如果宿主机有这个镜像,那就不需要拉取了. Always: 总是拉取, Never: 不管是否存储都不拉去
command: # 可选,容器启动执行的命令 ENTRYPOINT, arg --> cmd
- nginx
- -g
- "daemon off;"
workingDir: /usr/share/nginx/html # 可选,容器的工作目录
# volumeMounts: # 可选,存储卷配置,可以配置多个
# - name: webroot # 存储卷名称
# mountPath: /usr/share/nginx/html # 挂载目录
# readOnly: true # 只读
ports: # 可选,容器需要暴露的端口号列表
- name: http # 端口名称
containerPort: 80 # 端口号
protocol: TCP # 端口协议,默认TCP
env: # 可选,环境变量配置列表
- name: TZ # 变量名
value: Asia/Shanghai # 变量的值
- name: LANG
value: en_US.utf8
# resources: # 可选,资源限制和资源请求限制
# limits: # 最大限制设置
# cpu: 1000m
# memory: 1024Mi
# requests: # 启动所需的资源
# cpu: 100m
# memory: 512Mi
# startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
# path: /api/successStart # 检查路径
# port: 80
# readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
# path: / # 检查路径
# port: 80 # 监控端口
# livenessProbe: # 可选,健康检查
#exec: # 执行容器命令检测方式
#command:
#- cat
#- /health
#httpGet: # httpGet检测方式
# path: /_health # 检查路径
# port: 8080
# httpHeaders: # 检查的请求头
# - name: end-user
# value: Jason
# tcpSocket: # 端口检测方式
# port: 80
# initialDelaySeconds: 60 # 初始化时间
# timeoutSeconds: 2 # 超时时间
# periodSeconds: 5 # 检测间隔
# successThreshold: 1 # 检查成功为2次表示就绪
# failureThreshold: 2 # 检测失败1次表示未就绪
# lifecycle:
# postStart: # 容器创建完成后执行的指令, 可以是exec httpGet TCPSocket
# exec:
# command:
# - sh
# - -c
# - 'mkdir /data/ '
# preStop:
# httpGet:
# path: /
# port: 80
# exec:
# command:
# - sh
# - -c
# - sleep 9
restartPolicy: Always # 可选,默认为Always,容器故障或者没有启动成功,那就自动该容器,Onfailure: 容器以不为0的状态终止,自动重启该容器, Never:无论何种状态,都不会重启
#nodeSelector: # 可选,指定Node节点
# region: subnet7
# imagePullSecrets: # 可选,拉取镜像使用的secret,可以配置多个
# - name: default-dockercfg-86258
# hostNetwork: false # 可选,是否为主机模式,如是,会占用主机端口
# volumes: # 共享存储卷列表
# - name: webroot # 名称,与上述对应
# emptyDir: {} # 挂载目录
# #hostPath: # 挂载本机目录
# # path: /etc/hosts
实现 零宕机 上线应用
StartupProbe:k8s1.16版本后新加的探测方式,用于判断容器内应用程序是否已经启动。如果配置了startupProbe,就会先禁止其他的探测,直到它成功为止,成功后将不在进行探测。
LivenessProbe:用于探测容器是否运行,如果探测失败,kubelet会根据配置的重启策略进行相应的处理。若没有配置该探针,默认就是success。
ReadinessProbe:一般用于探测容器内的程序是否健康,它的返回值如果为success,那么久代表这个容器已经完成启动,并且程序已经是可以接受流量的状态。
ExecAction:在容器内执行一个命令,如果返回值为0,则认为容器健康。
livenessProbe:
exec:
command:
- pgrep
- nginx
TCPSocketAction:通过TCP连接检查容器内的端口是否是通的,如果是通的就认为容器健康。
livenessProbe:
tcpSocket:
port: 80
HTTPGetAction:通过应用程序暴露的API地址来检查程序是否是正常的,如果状态码为200~400之间,则认为容器健康。
linvenessProbe:
httpGet:
path: /index.html
port: 80
在公司,开发人员需要暴露该服务的两个健康检查API接口,如果测试两个API接口通,代表容器正常运行,不会去误停容器。
探针的参数
initialDelaySeconds: 3
容器的初始化时长,用于容器中的服务初始化时间较长的场景
合理使用初始化时长,避免容器中的应用应初始化时长被探针检测失败
timeoutSeconds: 2
超时时长,检测一个容器中的服务,超时2秒,认定检测失败
periodSeconds: 2
当检测失败后,每隔 2 秒检测一次
successThreshold: 1
检测成功的次数,检测1次成功认定该容器ready
failureThreshold: 2
检测失败的次数,有两次检测失败,认定该容器 NotReady
检测失败的重启时长
容器初始化检测失败的时长,唯一的区别就是加上容器初始化时长
{ ( timeoutSecounds + periodSeconds ) * failureThreshold } + initialDelaySeconds
{ (2+2) * 2} + 3 = 11s
容器启动之后检测的方式
( timeoutSecounds + periodSeconds ) * failureThreshold
{(2+2) * 2 = 8s
初始化时间,不建议设置太长,滚动发布受影响 # initialDelaySecond: 60 超时时间,命令去GET页面的超时时间 # timeoutSeconds: 2 检测间隔,每5秒检测一次 # periodSeconds: 5 检查成功为1次表示就绪,检测失败2次表示未就绪 # successThreshold: 1 # failureThreshold: 2 检测失败的重启时间:(2+5)* 2 = 14 s 所以检测失败次数不建议设置太大
Prestop:先去请求eureka接口,把自己的IP地址和端口号,进行下线,eureka从注册表中删除该应用的IP地址。然后容器进行sleep 90;kill pgrep java
注意:
在生产环境中,一定要合理设置探针检查的参数
假如一个Java程序的初始化时间为90s,我们没有合理设置探测参数,这样会造成,初始化时间没有给到,后面的检查又失败,失败后Pod又被kubelet干掉,又重启,重启之后又初始化,无限循环,这样对业务造成的影响非常大
所以就有新的一种探针模式的增加 --> startupProbe
原理:在1.16+版本后,为了防止程序的初始化时间的过长,导致的Pod被检测失败与无限次的重启,设置startupProbe后,程序会在初始化时,先进行startupProbe的检测,检测期间会将其他的两种检测方式进行禁用。只执行一次,自动退出。
4.1、进行测试
[root@k8s-master01 k8s-day01]# vim pod-Probe.yaml
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据
name: nginx # 必选,符合RFC 1035规范的Pod名称
# namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace
labels: # 可选,标签选择器,一般用于过滤和区分Pod,根据业务自定义
app: nginx
role: frontend # 可以写多个
annotations: # 可选,注释列表,可以写多个
app: nginx1.19 #可以注释一些 Nginx版本
spec: # 必选,用于定义容器的详细信息
nodeSelector:
kubernetes.io/hostname: k8s-node01
containers: # 必选,容器列表
- name: nginx # 必选,符合RFC 1035规范的容器名称
image: daocloud.io/library/nginx:latest # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent # 可选,镜像拉取策略, IfNotPresent: 如果宿主机有这个镜像,那就不需要拉取了. Always: 总是拉取, Never: 不管是否存储都不拉去
command: # 可选,容器启动执行的命令 ENTRYPOINT, arg --> cmd
- nginx
- -g
- "daemon off;"
workingDir: /usr/share/nginx/html # 可选,容器的工作目录
ports: # 可选,容器需要暴露的端口号列表
- name: http # 端口名称
containerPort: 80 # 端口号
protocol: TCP # 端口协议,默认TCP
env: # 可选,环境变量配置列表
- name: TZ # 变量名
value: Asia/Shanghai # 变量的值
- name: LANG
value: en_US.utf8
startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
path: /api/successStart # 检查路径
port: 80
restartPolicy: Always # 可选,默认为Always,容器故障或者没有启动成功,那就自动该容器,Onfailure: 容器以不为0的状态终止,自动重启该容器, Never:无论何种状态,都不会重启
[root@k8s-master01 k8s-day01]# kubectl apply -f pod-Probe.yaml
pod/nginx created
[root@k8s-master01 k8s-day01]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 0/1 Running 0 9s
[root@k8s-master01 k8s-day01]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 0/1 Running 2 3m
# 重启2次了
#可以看,nginx的Pod并未ready,一直在重启
4.2、解析报错信息
[root@k8s-master01 k8s-day01]# kubectl describe pod nginx | grep -A10 "Events"
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 7m38s default-scheduler Successfully assigned default/nginx to k8s-node01
Normal Pulled 3m56s (x4 over 7m38s) kubelet Container image "daocloud.io/library/nginx:latest" already present on machine
Normal Created 3m56s (x4 over 7m38s) kubelet Created container nginx
Normal Started 3m55s (x4 over 7m38s) kubelet Started container nginx
Warning Unhealthy 3m55s (x10 over 7m35s) kubelet Startup probe failed: HTTP probe failed with statuscode: 404 # 注意看这里,探针检测失败
Normal Killing 2m35s (x4 over 6m32s) kubelet Container nginx failed startup probe, will be restarted
注意:从报错的信息看,HTTP probe 检测失败,主要是因为 "path: /api/successStart",nginx网站并没有/api/successStart该路径, 我们可以加入 TcpSocker 对nginx进行Tcp方面的探测
4.3、进行优化,添加 TcpSocker
[root@k8s-master01 k8s-day01]# vim pod-Probe.yaml
#进行注释与添加
startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
# path: /api/successStart # 检查路径
# port: 80
tcpSocket:
port: 80
[root@k8s-master01 k8s-day01]# kubectl apply -f pod-Probe.yaml
pod/nginx created
[root@k8s-master01 k8s-day01]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 2m14s
[root@k8s-master01 k8s-day01]# kubectl describe pod nginx | grep -A10 "^Event"
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m24s default-scheduler Successfully assigned default/nginx to k8s-node01
Normal Pulled 3m24s kubelet Container image "daocloud.io/library/nginx:latest" already present on machine
Normal Created 3m24s kubelet Created container nginx
Normal Started 3m24s kubelet Started container nginx
:可以看到,Pod已经重新恢复,主要是 tcpSocket 检测 80端口 成功,nginx默认80端口
注意:一定要使用接口级的健康检查 /path /index.html.........,尽量少使用命令去检查 pgrep nginx
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据
name: nginx # 必选,符合RFC 1035规范的Pod名称
# namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace
labels: # 可选,标签选择器,一般用于过滤和区分Pod,根据业务自定义
app: nginx
role: frontend # 可以写多个
annotations: # 可选,注释列表,可以写多个
app: nginx1.21 #可以注释一些 Nginx版本
spec: # 必选,用于定义容器的详细信息
nodeSelector:
kubernetes.io/hostname: k8s-node01
containers: # 必选,容器列表
- name: nginx # 必选,符合RFC 1035规范的容器名称
image: daocloud.io/library/nginx:latest # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent # 可选,镜像拉取策略, IfNotPresent: 如果宿主机有这个镜像,那就不需要拉取了. Always: 总是拉取, Never: 不管是否存储都不拉去
command: # 可选,容器启动执行的命令 ENTRYPOINT, arg --> cmd
- nginx
- -g
- "daemon off;"
ports: # 可选,容器需要暴露的端口号列表
- name: http # 端口名称
containerPort: 80 # 端口号
protocol: TCP # 端口协议,默认TCP
env: # 可选,环境变量配置列表
- name: TZ # 变量名
value: Asia/Shanghai # 变量的值
- name: LANG
value: en_US.utf8
startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
# httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
# path: /api/successStart # 检查路径
# port: 80
tcpSocket:
port: 80
readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
path: / # 检查路径
port: 80 # 监控端口
#-------------------------------------------------
livenessProbe: # 可选,健康检查
#exec: # 执行容器命令检测方式
#command:
#- cat
#- /health
httpGet: # httpGet检测方式
path: /index.html # 检查路径
port: 80
# httpHeaders: # 检查的请求头
# - name: end-user
# value: Jason
#-------------------------------------------------
initialDelaySeconds: 3 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 2 # 检测间隔
successThreshold: 1 # 检查成功为2次表示就绪
failureThreshold: 2 # 检测失败1次表示未就绪
restartPolicy: Always
readiness 美 /'rɛdɪnəs/ 英 /'redɪnəs/ n. 敏捷,迅速;准备就绪;愿意
解析:自定义 监控项对容器启动时的监控,如果监测失败,不会去重启容器,不会停止容器
只会 限制 服务的 进出流量,用户只能通过 Pod-IP进行访问,无法从Cluster-IP、NodePort-IP进行访问。
1、报错演示
[root@k8s-master01 k8s-day01]# vim pod-Probe.yaml
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据
name: nginx # 必选,符合RFC 1035规范的Pod名称
# namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace
labels: # 可选,标签选择器,一般用于过滤和区分Pod,根据业务自定义
app: nginx
role: frontend # 可以写多个
annotations: # 可选,注释列表,可以写多个
app: nginx1.21 #可以注释一些 Nginx版本
spec: # 必选,用于定义容器的详细信息
nodeSelector:
kubernetes.io/hostname: k8s-node01
containers: # 必选,容器列表
- name: nginx # 必选,符合RFC 1035规范的容器名称
image: daocloud.io/library/nginx:latest # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent # 可选,镜像拉取策略, IfNotPresent: 如果宿主机有这个镜像,那就不需要拉取了. Always: 总是拉取, Never: 不管是否存储都不拉去
command: # 可选,容器启动执行的命令 ENTRYPOINT, arg --> cmd
- nginx
- -g
- "daemon off;"
workingDir: /usr/share/nginx/html # 可选,容器的工作目录
ports: # 可选,容器需要暴露的端口号列表
- name: http # 端口名称
containerPort: 80 # 端口号
protocol: TCP # 端口协议,默认TCP
env: # 可选,环境变量配置列表
- name: TZ # 变量名
value: Asia/Shanghai # 变量的值
- name: LANG
value: en_US.utf8
#"---------------------------------------------------------------------------"
readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
path: /a.html # 检查路径,该路径不存在
port: 80 # 监控端口
#"---------------------------------------------------------------------------"
initialDelaySeconds: 3 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 2 # 检测间隔
successThreshold: 1 # 检查成功为2次表示就绪
failureThreshold: 2 # 检测失败1次表示未就绪
preStop: #容器关闭之前执行的命令
restartPolicy: Always
[root@k8s-master01 k8s-day01]# vim nginx-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80 # 映射端口,nginx服务为80端口,如果mysql就3306
nodePort: 30080 # 映射到外部的端口,可以在外部浏览器访问 Node-IP:30080
- name: https # SSL
port: 443
targetPort: 443
nodePort: 30443
selector: # 上方的Nginx设置的 Labels
app: nginx
[root@k8s-master01 k8s-day01]# kubectl apply -f pod-Probe.yaml
pod/nginx created
[root@k8s-master01 k8s-day01]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 0/1 Running 0 5m7s 172.17.125.11 k8s-node01
[root@k8s-master01 k8s-day01]# kubectl apply -f nginx-svc.yaml
service/nginx-svc configured
[root@k8s-master01 k8s-day01]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 3d20h
nginx-svc NodePort 10.106.106.114 80:30080/TCP,443:30443/TCP 3d15h
# 10.106.106.114:80 -> 192.168.178.54:30080
(部署Pod的Node-IP)
查看报错日志信息:
[root@k8s-master01 k8s-day01]# kubectl describe pod nginx | grep -A10 "Event"
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m24s default-scheduler Successfully assigned default/nginx to k8s-node01
Normal Pulled 3m24s kubelet Container image "daocloud.io/library/nginx:latest" already present on machine
Normal Created 3m24s kubelet Created container nginx
Normal Started 3m24s kubelet Started container nginx
Warning Unhealthy 2m39s (x22 over 3m21s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 404
2、使用容器内部进行访问,可以看到访问成功:
[root@k8s-master01 k8s-day01]# kubectl exec -it nginx -- sh
# curl -I localhost:80
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Thu, 11 Nov 2021 06:07:30 GMT
# curl -I 172.17.125.11:80
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Thu, 11 Nov 2021 06:15:05 GMT
3、使用外部、集群IP进行访问进行访问,访问失败,进出流量限制:
[root@k8s-master01 k8s-day01]# curl -I 10.106.106.114:80
curl: (7) Failed connect to 10.106.106.114:80; Connection refused
[root@k8s-master01 k8s-day01]# curl -I 192.168.178.54:30080
curl: (7) Failed connect to 192.168.178.54:30080; Connection refused
2、正确演示
#找到并修改
readinessProbe:
httpGet:
path: /index.html # 修改此处即可
port: 80
[root@k8s-master01 k8s-day01]# kubectl describe pod nginx | grep -A10 "Event"
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 3m24s default-scheduler Successfully assigned default/nginx to k8s-node01
Normal Pulled 3m24s kubelet Container image "daocloud.io/library/nginx:latest" already present on machine
Normal Created 3m24s kubelet Created container nginx
Normal Started 3m24s kubelet Started container nginx
Warning Unhealthy 2m39s (x22 over 3m21s) kubelet Readiness probe failed: HTTP probe failed with statuscode: 404
2、使用容器内部进行访问,可以看到访问成功:
[root@k8s-master01 k8s-day01]# kubectl exec -it nginx -- sh
# curl -I localhost:80
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Thu, 11 Nov 2021 06:07:30 GMT
# curl -I 172.17.125.11:80
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Thu, 11 Nov 2021 06:15:05 GMT
3、使用外部、集群IP进行访问进行访问,访问失败,进出流量限制:
[root@k8s-master01 k8s-day01]# curl -I 10.106.106.114:80
curl: (7) Failed connect to 10.106.106.114:80; Connection refused
[root@k8s-master01 k8s-day01]# curl -I 192.168.178.54:80
curl: (7) Failed connect to 192.168.178.54:80; Connection refused
[root@k8s-master01 k8s-day01]# kubectl apply -f pod-Probe.yaml
pod/nginx created
[root@k8s-master01 k8s-day01]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 18s 172.17.125.12 k8s-node01
1、使用容器内部访问,访问成功:
[root@k8s-master01 k8s-day01]# kubectl exec -it nginx -- sh
# curl -I 172.17.125.12:80
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Thu, 11 Nov 2021 06:40:58 GMT
2、使用容器Cluster-IP、NodePort访问,成功:
[root@k8s-master01 k8s-day01]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 443/TCP 3d20h
nginx-svc NodePort 10.106.106.114 80:30080/TCP,443:30443/TCP 3d15h
[root@k8s-master01 k8s-day01]# curl -I 10.106.106.114:80
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Thu, 11 Nov 2021 06:42:17 GMT
[root@k8s-master01 k8s-day01]# curl -I 192.168.178.54:30080
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Thu, 11 Nov 2021 06:42:37 GMT
:零宕机下线应用
合理使用 proStop,进行容器退出时执行的命令
1、Pod优雅关闭
模式:
postStart
容器在启动之前做的一系列指定操作,比如 提前创建 目录、文件、执行脚本等。
preStop
容器关闭之后,执行的命令
通常我们会使用该参数进行 Pod 的优雅关闭,实现 零宕机 下线服务
spec:
terminationGracePeriods: 90s
containers:
lifecycle:
preStop: #容器关闭之前执行的命令
exec:
command:
- sh
- -c
- sleep 90;kill `pgrep nginx`
可以看到下方的 yaml 配置 ,nginx 在退出时,执行了睡眠操作,保证容器中的服务 有足够的时间进行下线操作(处理服务关闭之前,接收的服务未进行处理,等待处理完成后,关闭服务,保证数据的完整性)
注意:
我们往往会忽视一个参数,terminationGracePeriodSeconds (容器优雅的关闭的时间间隔)
这参数默认为30秒,就算你不设置, terminationGracePeriodSeconds: 30
⛔再次注意:
如果你想使 容器 进行 90s 的优雅关闭时长,那你的参数应该为 terminationGracePeriodSeconds: 90
加入你设置的 sleep 时长为 90s ,你的参数为 terminationGracePeriodSeconds: 30,那肯定容器只等待30s左右就会关闭,你应该设置参数为 50s,才能保证 sleep 50 运行成功
所以我们在进行容器优雅下线时,要合理使用 preStop 与 该参数
2、效果演示
1️⃣默认情况:terminationGracePeriodSeconds: 30
apiVersion: v1 # 必选,API的版本号
kind: Pod # 必选,类型Pod
metadata: # 必选,元数据
name: nginx # 必选,符合RFC 1035规范的Pod名称
# namespace: default # 可选,Pod所在的命名空间,不指定默认为default,可以使用-n 指定namespace
labels: # 可选,标签选择器,一般用于过滤和区分Pod,根据业务自定义
app: nginx
role: frontend # 可以写多个
annotations: # 可选,注释列表,可以写多个
app: nginx1.21 #可以注释一些 Nginx版本
spec: # 必选,用于定义容器的详细信息
nodeSelector:
kubernetes.io/hostname: k8s-node01
containers: # 必选,容器列表
- name: nginx # 必选,符合RFC 1035规范的容器名称
image: daocloud.io/library/nginx:latest # 必选,容器所用的镜像的地址
imagePullPolicy: IfNotPresent # 可选,镜像拉取策略, IfNotPresent: 如果宿主机有这个镜像,那就不需要拉取了. Always: 总是拉取, Never: 不管是否存储都不拉去
command: # 可选,容器启动执行的命令 ENTRYPOINT, arg --> cmd
- nginx
- -g
- "daemon off;"
workingDir: /usr/share/nginx/html # 可选,容器的工作目录
ports: # 可选,容器需要暴露的端口号列表
- name: http # 端口名称
containerPort: 80 # 端口号
protocol: TCP # 端口协议,默认TCP
env: # 可选,环境变量配置列表
- name: TZ # 变量名
value: Asia/Shanghai # 变量的值
- name: LANG
value: en_US.utf8
startupProbe: # 可选,检测容器内进程是否完成启动。注意三种检查方式同时只能使用一种。
tcpSocket:
port: 80
readinessProbe: # 可选,健康检查。注意三种检查方式同时只能使用一种。
httpGet: # httpGet检测方式,生产环境建议使用httpGet实现接口级健康检查,健康检查由应用程序提供。
path: / # 检查路径
port: 80 # 监控端口
livenessProbe: # 可选,健康检查
httpGet: # httpGet检测方式
path: /index.html # 检查路径
port: 80
initialDelaySeconds: 3 # 初始化时间
timeoutSeconds: 2 # 超时时间
periodSeconds: 2 # 检测间隔
successThreshold: 1 # 检查成功为2次表示就绪
failureThreshold: 2 # 检测失败1次表示未就绪
lifecycle:
preStop: #容器关闭之前执行的命令
exec:
command:
- sh
- -c
#"----------------------------------------------------------------------"
- sleep 90;kill `pgrep nginx` #设置 90 秒关闭 容器
#"----------------------------------------------------------------------"
restartPolicy: Always
[root@k8s-master01 k8s-day01]# kubectl apply -f pod-Probe.yaml
pod/nginx created
[root@k8s-master01 k8s-day01]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 15s
[root@k8s-master01 k8s-day01]# time kubectl delete -f pod-Probe.yaml
pod "nginx" deleted
real 0m36.076s
user 0m0.051s
sys 0m0.031s
#这里可以看到,容器并没有 90 秒退出,默认的 terminationGracePeriodSeconds 为30s
2️⃣修改:terminationGracePeriodSeconds: 90s
spec: # 必选,用于定义容器的详细信 息
nodeSelector:
kubernetes.io/hostname: k8s-node01
# "----------------------------------------------------------------------"
terminationGracePeriodSeconds: 90 #添加此行,为 90s 进行优雅关闭容器
# "-----------------------------------------------------------------------"
[root@k8s-master01 k8s-day01]# kubectl apply -f pod-Probe.yaml
pod/nginx created
[root@k8s-master01 k8s-day01]# time kubectl delete -f pod-Probe.yaml
pod "nginx" deleted
real 1m32.343s #可以看到 关闭时长为 90s
user 0m0.057s
sys 0m0.022s