一、健康检查
- 怎样保证pod中的容器正常启动?
- 怎样保证pod中容器能够正常对外提供服务?
- 只有容器启动了并且能够正常对外提供服务了,才能放到负载均衡上供给用户访问
- Kubernetes提供了健康检查服务,对于检测到故障服务会被及时自动下线,以及通过重启服务的方式使服务自动恢复。
1.存活性检查 (LivenessProbe)
- pod中所有容器的
status=Running
时,Pod的状态才会是Running
状态。 - 判断容器是否存活,即Pod是否为running状态,如果
LivenessProbe
探针探测到容器不健康,则kubelet将kill
掉容器,并根据容器的重启策略判断按照那种方式重启,如果一个容器不包含LivenessProbe探针,则Kubelet认为容器的LivenessProbe探针的返回值永远成功
。 - 当存活性检查
检测失败
的时候,kebulet会删除容器,重新启动一个新的容器
。继续检查。 - 存活性探测支持的方法有三种:
ExecAction
,TCPSocketAction
,HTTPGetAction
参考语法:kubectl explain deployment.spec.template.spec.containers.livenessProbe.httpGet
#1.ExecAction检测
kind: Service
apiVersion: v1
metadata:
name: name-mysql
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: name-mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: alvinos/django:v1
livenessProbe: #存活性检查
exec:
command:
- cat
- /root/test/manage.py
#2.HTTPGetAction检测
kind: Service
apiVersion: v1
metadata:
name: name-mysql
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: name-mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: alvinos/django:v1
livenessProbe: #存活性检查
httpGet:
port: 80
path: /index
host: #不能跟上127.0.0.1 可以跟上service name ,一般跟上pod IP
注意:host必须为集群内部的host,探测的时候是在自己的容器中,但是网络空间在主容器中。一般情况下探测自己的时候就不写host。
#3.TcpSocket 相当于 ping
kind: Service
apiVersion: v1
metadata:
name: name-mysql
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: mysql
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: name-mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: alvinos/django:v1
livenessProbe: #存活性检查
tcpSocket:
port: 80
2.健康检查参数
参考语法: kubectl explain deployment.spec.template.spec.containers.livenessProbe
#1.检查失败最少次数,默认:3次
delay=10s : 探测延时时间initialDelaySeconds
timeout=1s :探测的超时时间
period=10s :探测的频率
success=1 :成功多少次才算成功
failure=1 :失败多少次才算失败
以下的参数都是公用的,在存活性和就绪性都可以使用,一般情况下这几个参数不设置
`failureThreshold`:最少连续几次探测失败的次数,满足该次数则认为fail
`initialDelaySeconds`:容器启动之后开始进行存活性探测的秒数。不填立即进行
`periodSeconds`:执行探测的频率(秒)。默认为10秒。最小值为1。
`successThreshold`:探测失败后,最少连续探测成功多少次才被认定为成功,满足该次数则认为success。(但是如果是liveness则必须是 1。最小值是 1。)
`timeoutSeconds`:每次执行探测的超时时间,默认1秒,最小1秒。
#2.实例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: name-mysql
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: alvinos/django:v1
livenessProbe:
exec:
command:
- cat
- /root/test/manage.py
failureThreshold:1
initialDelaySeconds:1
periodSeconds:1
3.就绪性探测
- 就绪性探测的特点是
探测失败,立即移出负载均衡(endpoints —> NotReadyAddresses), NotReadyAddresses可以在kubectl describe endpoints readinessprobe 命令里面查看
- 如果
ReadinessProbe
探测失败,则容器的Ready将设置为False,控制器将此Pod的Endpoint从对应的service的Endpoint列表中移除,从此不再将任何请求调度此Pod上,直到下次探测成功。
参考语法:kubectl explain deployment.spec.template.spec.containers.readinessProbe
#实例:
kind: Service
apiVersion: v1
metadata:
name: readinessprobe
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: readinessprobe
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: readinessprobe
spec:
selector:
matchLabels:
app: readinessprobe
template:
metadata:
labels:
app: readinessprobe
spec:
containers:
- name: readinessprobe
image: alvinos/django:v1
readinessProbe:
exec:
command:
- cat
- /root/test/manage.py
一般要求尽量副本设置3个
效果:
查看pod
[root@k8s-master-01 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
readinessprobe-6fdd7db9db-ml4rf 1/1 Running 0 10s
查看endpoints
[root@k8s-master-01 ~]# kubectl get endpoints
NAME ENDPOINTS AGE
readinessprobe 10.244.2.76:80 27s
查看svc
[root@k8s-master-01 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S
readinessprobe ClusterIP 10.103.0.196 <none> 80/TCP
进入容器
[root@k8s-master-01 ~]# kubectl exec -it readinessprobe-6fdd7db9db-ml4rf -- bash
[root@readinessprobe-6fdd7db9db-ml4rf test]# ls
db.sqlite3 docker file manage.py
移除manage.py文件
[root@readinessprobe-6fdd7db9db-ml4rf test]# mv manage.py manage.py.bak
[root@readinessprobe-6fdd7db9db-ml4rf test]# exit
exit
查看endpoints的详情
[root@k8s-master-01 ~]# kubectl describe endpoints readinessprobe
Name: readinessprobe
Namespace: default
Labels: <none>
Annotations: endpoints.kubernetes.io/last-change-trigger-time: 2021-08-26T10:53:25Z
Subsets:
Addresses: <none>
NotReadyAddresses: 10.244.2.76 #发现IP为不健康ip
Name Port Protocol
---- ---- --------
http 80 TCP
Events: <none>
刚开始探测健康没有问题,当我们移除文件的时候,就拒绝连接了。探测失败
[root@k8s-master-01 wordpress]# while true;do curl 10.103.0.196/index;echo;sleep 1;done
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
curl: (7) Failed connect to 10.103.0.196:80; 拒绝连接
curl: (7) Failed connect to 10.103.0.196:80; 拒绝连接
curl: (7) Failed connect to 10.103.0.196:80; 拒绝连接
curl: (7) Failed connect to 10.103.0.196:80; 拒绝连接
curl: (7) Failed connect to 10.103.0.196:80; 拒绝连接
curl: (7) Failed connect to 10.103.0.196:80; 拒绝连接
curl: (7) Failed connect to 10.103.0.196:80; 拒绝连接
curl: (7) Failed connect to 10.103.0.196:80; 拒绝连接
还原文件即可正常加入负载均衡
[root@k8s-master-01 ~]# kubectl exec -it readinessprobe-6fdd7db9db-ml4rf -- bash
[root@readinessprobe-6fdd7db9db-ml4rf test]# ls
db.sqlite3 docker file manage.py.bak
[root@readinessprobe-6fdd7db9db-ml4rf test]# mv manage.py.bak manage.py
[root@readinessprobe-6fdd7db9db-ml4rf test]# exit
[root@k8s-master-01 wordpress]# while true;do curl 10.103.0.196/index;echo;sleep 1;done
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
因为监控的时候没有准备好,为了避免报错,所以修改配置文件。
一般建议设置3个副本,只要不是0就不会报错
kind: Service
apiVersion: v1
metadata:
name: readinessprobe
spec:
ports:
- name: http
port: 80
targetPort: 80
selector:
app: readinessprobe
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: readinessprobe
spec:
selector:
matchLabels:
app: readinessprobe
template:
metadata:
labels:
app: readinessprobe
spec:
containers:
- name: readinessprobe
image: alvinos/django:v1
readinessProbe:
httpGet:
port: 80
path: /index
这就是简单的灰度发布:
打包镜像
[root@k8s-master-01 ~]# kubectl set image deployment/readinessprobe readinessprobe=alvinos/django:v2
deployment.apps/readinessprobe image updated
[root@k8s-master-01 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-849b69b448-wqlct 1/1 Running 0 3h42m
readinessprobe-5b8dff4dc7-6p4wq 0/1 ContainerCreating 0 7s
readinessprobe-6fdd7db9db-84kmc 1/1 Running 0 62m
readinessprobe-6fdd7db9db-h64ns 1/1 Running 0 62m
readinessprobe-6fdd7db9db-ml4rf 1/1 Running 0 83m
test--ginx-b97c459f7-qckwp 1/1 Running 1 27h
test-6799fc88d8-mqb72 1/1 Running 2 45h
test-deployment-5849786498-5xlmg 1/1 Running 2 2d1h
wordpress-0 2/2 Running 0 4h
[root@k8s-master-01 ~]# kubectl get pods -w
NAME READY STATUS RESTARTS AGE
mysql-849b69b448-wqlct 1/1 Running 0 3h43m
readinessprobe-5b8dff4dc7-5c4l2 0/1 Running 0 25s
readinessprobe-5b8dff4dc7-6p4wq 1/1 Running 0 46s
readinessprobe-6fdd7db9db-84kmc 1/1 Running 0 63m
readinessprobe-6fdd7db9db-h64ns 1/1 Terminating 0 63m
readinessprobe-6fdd7db9db-ml4rf 1/1 Running 0 83m
test--ginx-b97c459f7-qckwp 1/1 Running 1 27h
test-6799fc88d8-mqb72 1/1 Running 2 45h
test-deployment-5849786498-5xlmg 1/1 Running 2 2d1h
wordpress-0 2/2 Running 0 4h
readinessprobe-5b8dff4dc7-5c4l2 1/1 Running 0 28s
readinessprobe-6fdd7db9db-84kmc 1/1 Terminating 0 63m
readinessprobe-5b8dff4dc7-j7s2m 0/1 Pending 0 0s
readinessprobe-5b8dff4dc7-j7s2m 0/1 Pending 0 0s
readinessprobe-5b8dff4dc7-j7s2m 0/1 ContainerCreating 0 0s
readinessprobe-6fdd7db9db-h64ns 0/1 Terminating 0 63m
readinessprobe-5b8dff4dc7-j7s2m 0/1 Running 0 2s
readinessprobe-5b8dff4dc7-j7s2m 1/1 Running 0 3s
readinessprobe-6fdd7db9db-ml4rf 1/1 Terminating 0 83m
readinessprobe-6fdd7db9db-h64ns 0/1 Terminating 0 63m
readinessprobe-6fdd7db9db-h64ns 0/1 Terminating 0 63m
^C[root@k8s-master-01 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
mysql-849b69b448-wqlct 1/1 Running 0 3h44m
readinessprobe-5b8dff4dc7-5c4l2 1/1 Running 0 59s
readinessprobe-5b8dff4dc7-6p4wq 1/1 Running 0 80s
readinessprobe-5b8dff4dc7-j7s2m 1/1 Running 0 30s
readinessprobe-6fdd7db9db-84kmc 0/1 Terminating 0 64m
readinessprobe-6fdd7db9db-ml4rf 1/1 Terminating 0 84m
test--ginx-b97c459f7-qckwp 1/1 Running 1 27h
test-6799fc88d8-mqb72 1/1 Running 2 45h
test-deployment-5849786498-5xlmg 1/1 Running 2 2d1h
wordpress-0 2/2 Running 0 4h1m
监控会从v1----v2
[root@k8s-master-01 ~]# while true;do curl 10.103.0.196/index;echo;sleep 1;done
主机名:readinessprobe-5b8dff4dc7-6p4wq,版本:v2
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-84kmc,版本:v1
主机名:readinessprobe-6fdd7db9db-84kmc,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-6fdd7db9db-84kmc,版本:v1
主机名:readinessprobe-6fdd7db9db-84kmc,版本:v1
主机名:readinessprobe-5b8dff4dc7-6p4wq,版本:v2
主机名:readinessprobe-6fdd7db9db-ml4rf,版本:v1
主机名:readinessprobe-5b8dff4dc7-6p4wq,版本:v2
主机名:readinessprobe-5b8dff4dc7-5c4l2,版本:v2
主机名:readinessprobe-5b8dff4dc7-5c4l2,版本:v2
主机名:readinessprobe-5b8dff4dc7-j7s2m,版本:v2
主机名:readinessprobe-5b8dff4dc7-5c4l2,版本:v2
主机名:readinessprobe-5b8dff4dc7-5c4l2,版本:v2
主机名:readinessprobe-5b8dff4dc7-6p4wq,版本:v2
主机名:readinessprobe-5b8dff4dc7-6p4wq,版本:v2
主机名:readinessprobe-5b8dff4dc7-6p4wq,版本:v2
主机名:readinessprobe-5b8dff4dc7-j7s2m,版本:v2
就绪、探测性结合案例
# 1、编写配置清单
[root@k8s-m-01 k8s]# vim livenessProbe.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: test-deployment
spec:
replicas: 1
selector:
matchLabels:
app: deployment
template:
metadata:
labels:
app: deployment
spec:
containers:
- name: nginx
image: alvinos/django:v1
livenessProbe:
exec:
command:
- "/bin/sh" #前台运行
- "-c" #前台运行
- "cat /root/test/manage.py"
initialDelaySeconds: 0
periodSeconds: 3 #可能网络原因,不起来,所以要探测三次
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
readinessProbe: #就绪性探测
tcpSocket:
port: 80 #修改访问不存在的端口,即探测失败
initialDelaySeconds: 30 # jave大项目60s
periodSeconds: 1 # 如果失败,立即踢出负载均衡,为了怕影响的用户体验,所以必须设置成1s
timeoutSeconds: 1
successThreshold: 3
failureThreshold: 1
# 2、查看pod
[root@k8s-m-01 k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
test-deployment-5d765fb67d-xksgc 1/1 Running 0 48s
# 3、具体查看健康检查的信息
[root@k8s-m-01 k8s]# kubectl describe pod test-deployment-5d765fb67d-xksgc
...
Restart Count: 0
Liveness: exec [/bin/sh -c cat /root/test/manage.py] delay=0s timeout=1s period=3s #success=1 #failure=3
Readiness: tcp-socket :80 delay=30s timeout=1s period=1s #success=3 #failure=1
# 4、查看负载均衡
[root@k8s-m-01 k8s]# while true;do curl 10.97.199.150/index;sleep 1;echo;done
主机名:test-deployment-5d765fb67d-xksgc,版本:v1
主机名:test-deployment-5d765fb67d-48slj,版本:v1
主机名:test-deployment-5d765fb67d-729r9,版本:v1
主机名:test-deployment-5d765fb67d-xksgc,版本:v1
主机名:test-deployment-5d765fb67d-48slj,版本:v1
主机名:test-deployment-5d765fb67d-729r9,版本:v1
# 5、修改版本与sevice类型
[root@k8s-m-01 k8s]# kubectl edit deployments.apps test-deployment
- image: alvinos/django:v2
replicas: 1
[root@k8s-m-01 k8s]# kubectl edit svc test-svc
type: NodePort
# 6、重新查看结果与svc
[root@k8s-m-01 k8s]# while true;do curl 10.97.199.150/index;sleep 1;echo;done
主机名:test-deployment-5d765fb67d-729r9,版本:v1
主机名:test-deployment-d75444fb5-gpwk4,版本:v2
主机名:test-deployment-d75444fb5-gpwk4,版本:v2
[root@k8s-m-01 k8s]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
test-svc NodePort 10.97.199.150 <none> 80:31881/TCP 54m
# 7、IP访问
192.168.15.111:31881
# 注 虽然版本和副本数改变了,但是没有报错
4.总结
- 存活性探测:探测失败,立即删除容器
- 就绪性探测:探测失败,立即移除负载均衡
service:是一个命名空间资源,需要指定名称空间。
namespace:是一个集群资源,不需要指定名称空间。
ingress:是一个命名空间资源,需要指定名称空间。
二、回调HOOK
Pod Hook
是由 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。
PostStart
:这个钩子在容器创建后立即执行。但是,并不能保证钩子将在容器ENTRYPOINT
之前运行,因为没有参数传递给处理程序。主要用于资源部署、环境准备等。不过需要注意的是如果钩子花费太长时间以至于不能运行或者挂起, 容器将不能达到running状态。
-PreStop
:这个钩子在容器终止之前立即被调用。它是阻塞的,意味着它是同步的, 所以它必须在删除容器的调用发出之前完成。主要用于优雅关闭应用程序、通知其他系统等。如果钩子在执行期间挂起, Pod阶段将停留在running状态并且永不会达到failed状态。
如果PostStart或者PreStop钩子失败, 它会杀死容器。所以我们应该让钩子函数尽可能的轻量。当然有些情况下,长时间运行命令是合理的, 比如在停止容器之前预先保存状态 。
参考语法:kubectl explain deployment.spec.template.spec.containers.lifecycle
1.回调钩子
案例一:数据卷 存储挂载
#1.poststart:启动回调钩子,是在容器启动之后立即执行
apiVersion: apps/v1
kind: Deployment
metadata:
name: lifecycle
spec:
selector:
matchLabels:
app: cycle
template:
metadata:
labels:
app: cycle
spec:
nodeName: gdx2
containers:
- name: nginx
image: nginx
volumeMounts: #定义存储卷
- mountPath: /usr/share/nginx/html #容器内挂载路径
name: lifecycle-data
lifecycle: #生命周期
postStart: #启动回调钩子
exec:
command: #执行命令
- "/bin/bash"
- "-c"
- "echo 'This is Lifecycle' > /usr/share/nginx/html/index.html"
preStop: #结束回调钩子
exec:
command: #执行命令
- "/bin/bash"
- "-c"
- "echo 'This is Lifecycle preStop' > /usr/share/nginx/html/index.html"
volumes: #定义宿主机存储卷
- name: lifecycle-data
hostPath: #存储卷方式
path: /opt/discuz/data #宿主机挂载路径
#2.验证启动回调钩子
[root@k8s-master1 ~]# kubectl get pods -w -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
lifecycle-94b467df6-2grpm 1/1 Running 0 10m 10.244.1.35 gdx2 <none> <none>
[root@k8s-master1 ~]# curl 10.244.1.35
This is Lifecycle
#3.验证结束回调钩子
[root@k8s-master1 ~]# kubectl delete deployments.apps lifecycle
deployment.apps "lifecycle" deleted
[root@k8s-node1 discuz]# cat data/index.html
This is Lifecycle preStop
案例二
# 1、编写yaml文件
[root@k8s-m-01 k8s]# vim livenessProbe.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: test-deployment
spec:
replicas: 1
selector:
matchLabels:
app: deployment
template:
metadata:
labels:
app: deployment
spec:
containers:
- name: nginx
image: alvinos/django:v1
lifecycle:
postStart:
exec:
command:
- "/bin/sh"
- "-c"
- "touch /root/1.txt"
preStop:
exec:
command:
- "/bin/sh"
- "-c"
- "echo '123' > /root/1.txt"
livenessProbe:
exec:
command:
- "/bin/sh"
- "-c"
- "cat /root/test/manage.py"
initialDelaySeconds: 0
periodSeconds: 3 #可能网络原因,不起来,所以要探测三次
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
readinessProbe: #就绪性探测
tcpSocket:
port: 80 #修改访问不存在的端口,即探测失败
initialDelaySeconds: 30 # jave大项目60s
periodSeconds: 1 # 如果失败,立即踢出负载均衡,为了怕影响的用户体验,所以必须设置成1s
timeoutSeconds: 1
successThreshold: 3
failureThreshold: 1
# 2、查看pod
[root@k8s-m-01 k8s]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
test-deployment-9db95f48d-p7c5d 1/1 Running 0 40s 10.244.2.70 k8s-n-02 <none> <none>
# 3、进入容器查看
[root@k8s-m-01 k8s]# kubectl exec -it test-deployment-9db95f48d-p7c5d -- bash
[root@test-deployment-9db95f48d-p7c5d test]# cd /root/
[root@test-deployment-9db95f48d-p7c5d ~]# ls
1.txt anaconda-ks.cfg test #默认创建1.txt
# 4、退出
[root@k8s-m-01 k8s]# kubectl delete -f livenessProbe.yaml
deployment.apps "test-deployment" deleted
[root@test-deployment-9db95f48d-p7c5d ~]# ls
1.txt anaconda-ks.cfg test # 默认在1.txt打印123
总结
1、PostStart
: 启动回调钩子,是在容器启动之后立即执行
2、PreStop
: 结束回调钩子,是在容器结束之前立即执行
回调钩子不仅支持exec,还支持httpGet等等