k8s 容器探针

在Kubernetes中,有三种类型的探针(Probes)用于检查容器的健康状况和确定是否应该将请求路由到容器。这些探针可以配置在 Pod 的规范中。

以下是 Kubernetes中 的三种探针类型:

  1. 存活探针(Liveness Probe):存活探针用于确定容器是否处于运行状态。如果存活探针失败(返回失败状态码或超时),Kubernetes会认为容器不健康,并会重启容器。这可以用于检测应用程序内部错误或死锁情况。
  2. 就绪探针(Readiness Probe):就绪探针用于确定容器是否准备好接受流量。如果就绪探针失败,Kubernetes 会将容器从服务的负载均衡中剔除,直到探针成功。这可以用于确保应用程序在启动后完成必要的初始化或数据加载。
  3. 启动探针(Startup Probe):启动探针用于确定容器是否已经启动并且准备好接受流量。与存活探针和就绪探针不同,启动探针在容器的初始启动阶段使用,并且仅会运行一次。启动探针成功后,就绪探针和存活探针才会启动。

对于每种探针类型,可以配置以下参数:

  • 探针类型:选择存活探针、就绪探针或启动探针。
  • 探针动作:通过HTTP GET、TCP套接字或执行命令来检查容器的健康状态。
  • 探针路径:用于HTTP GET探针的URL路径。
  • 探针端口:用于TCP套接字探针的端口号。
  • 探针命令:用于执行命令探针的命令列表。

存活探针(Liveness Probe)

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 15
  periodSeconds: 10

上述示例配置了一个 HTTP GET 请求的存活探针。它将在容器启动后等待 15 秒后开始执行,并且每 10 秒执行一次。探针会发送一个 HTTP GET 请求到容器的 /health 路径,并使用端口号 8080

就绪探针(Readiness Probe)

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 3

上述示例配置了一个 HTTP GET 请求的就绪探针。它将在容器启动后等待 5 秒后开始执行,并且每 3 秒执行一次。探针会发送一个 HTTP GET 请求到容器的 /ready 路径,并使用端口号 8080。

启动探针(Startup Probe)

startupProbe:
  exec:
    command:
    - cat
    - /tmp/initialized
  initialDelaySeconds: 10
  periodSeconds: 5
  failureThreshold: 30

上述示例配置了一个执行命令的启动探针。它将在容器启动后等待 10秒 后开始执行,并且每 5 秒执行一次。探针会执行命令 cat /tmp/initialized,如果命令成功执行,表示容器已经初始化完成

容器探测健康检查配置参数

主机存活性探测和就绪性探测配置参数一模一样,只是定义的命令不一样
[root@k8s-master ~]# kubectl explain pod.spec.containers.livenessProbe

KIND:     Pod
VERSION:  v1
RESOURCE: livenessProbe <Object>
FIELDS:
   exec	<Object>
        command	<[]string>			//执行的命令
        
   httpGet	<Object>					
     host	<string>				//主机地址,默认为pod的ip
     path	<string>				//请求的url路径
     port	<string> 				//端口号
     scheme	<string>				//使用的协议,默认为http

   tcpSocket	<Object>
	 host	<string>					//主机地址,默认为pod的ip
	 port	<string> 					//要探测的端口号
	 
   initialDelaySeconds	<integer>			//容器启动后等待多少秒进行第一次探测
   timeoutSeconds	<integer>				//探测超时时间,默认1秒,最小1秒
   periodSeconds	<integer>				//执行探测的频率,默认10秒,最小1秒
   failureThreshold	<integer>				//连续探测失败多少次才被认定为失败,默认是3,最小值1
   successThreshold	<integer>				//连续探测成功多少次才被认定为成功,默认是1 

	 
例子:
apiVersion: v1
kind: Pod
metadata:
  name: pod-livereadiness
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.18
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:					//存活性探测	
      tcpSocket:							//使用TCPSocket探测方式
        port: 80							//探测的端口
    initialDelaySeconds: 30					//容器启动后30s以后开始探测
    timeoutSeconds: 5 					   //探测超时时间
    readinessProbe:					//就绪性探测		
      httpGet:							//使用HTTPGet探测方式
        scheme: HTTP					//协议使用http
        port: 80						//应用端口
        path: /	    					//url路径

Pod资源存活性健康检查实战

使用exec探测方式检测容器的存活性

使用 exec 探测时,如果执行的命令返回的状态码为 1,则表示健康检查失败,k8s 会一直重启当前 pod,只有执行的命令状态码返回的是 0,健康检查才会成功,且 pod 正常运行

1.编写使用exec探测的yaml文件
#exec配置时,执行一个退出状态码为1的命令,观察pod的状态
[root@k8s-master ~]# vim pod-liveness-exec.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-exec
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.18
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:												#定义存活性探测
      exec:														#使用exec命令方式
        command: ["/bin/cat","/tmp/hello.txt"]					#执行具体命令:查看下/tmp/hello.txt文件,这个文件一定是不存在的,返回的状态码一定是1

2.创建pod
[root@k8s-master ~]# kubectl create -f pod-liveness-exec.yaml 
pod/pod-liveness-exec created

3.查看pod的运行状态
#可以看到restarts重启次数已经是3次了
[root@k8s-master ~]# kubectl get pod pod-liveness-exec -n dev
NAME                READY   STATUS    RESTARTS   AGE
pod-liveness-exec   1/1     Running   3          2m47s

4.查看pod的详细输出
[root@k8s-master ~]# kubectl describe pod pod-liveness-exec -n dev
····················
Events:
  Type     Reason     Age                   From               Message
  ----     ------     ----                  ----               -------
  Normal   Scheduled  3m43s                 default-scheduler  Successfully assigned dev/pod-liveness-exec to k8s-node1
  Normal   Pulled     76s (x4 over 2m44s)   kubelet            Container image "nginx:1.15" already present on machine
  Normal   Created    76s (x4 over 2m44s)   kubelet            Created container nginx
  Normal   Killing    76s (x3 over 2m16s)   kubelet            Container nginx failed liveness probe, will be restarted
  Normal   Started    75s (x4 over 2m44s)   kubelet            Started container nginx
  Warning  Unhealthy  66s (x10 over 2m35s)  kubelet            Liveness probe failed: /bin/cat: /tmp/hello.txt: No such file or directory
#在最后的输出里可以看到说找不到/tmp/hello.txt这个文件,命令执行失败  
#根据输出的信息可以看到nginx容器在启动之后就进行了健康检查,健康检查失败之后,容器就会被kill掉,然后尝试重启pod,然而健康检查一直失败,容器就会一直重启

将 exec 执行的命令调整为执行后状态码为0的也就是满足健康检查的要求在查看效果

1.修改yaml文件调整exec执行的命令
[root@k8s-master ~l]# vim pod-liveness-exec.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-exec
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.18
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      exec:
        command: ["/bin/ls","/tmp"]					#健康检查命令调整为查看/tmp下的文件,该命令执行后状态码为0,健康检查也会成功

2.创建pod
[root@k8s-master ~]# kubectl delete -f pod-liveness-exec.yaml
pod "pod-liveness-exec" deleted
[root@k8s-master ~]# kubectl create -f pod-liveness-exec.yaml
pod/pod-liveness-exec created

3.观察pod的状态,多敲几次命令观察
# 一般在容器启动后的30秒左右进行监控检查
[root@k8s-master ~]# kubectl get pod pod-liveness-exec -n dev
NAME                READY   STATUS    RESTARTS   AGE
pod-liveness-exec   1/1     Running   0          46s

4.查看详细信息验证是否报错
[root@k8s-master ~]# kubectl describe pod pod-liveness-exec -n dev
# 已经不报错了,nginx容器正常运行

使用 TCPSocket 方式探测容器的存活性

TCPSocket 方式就是与指定的容最端口进行建立连接,如果能够成功建立连接,则表示健康检查成功,否则将会一直重启容器

1.编写TCPSocket方式的yaml文件
[root@k8s-master ~]# vim pod-liveness-tcpsocket.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-tcpsocket
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.18
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:					#定义存活性探测
      tcpSocket:					#类型为TCPSocket
        port: 8080					#探测的端口号为8080,8080在nginx容器里是不存在的,因此会健康检查失败,观察容器状态
        
2.创建pod
[root@k8s-master ~]# kubectl create -f pod-liveness-tcpsocket.yaml
pod/pod-liveness-tcpsocket created

3.查看容器状态
#可以看到已经重启2次了
[root@k8s-master ~]# kubectl get pod pod-liveness-tcpsocket -n dev
NAME                     READY   STATUS    RESTARTS   AGE
pod-liveness-tcpsocket   1/1     Running   2          108s

4.查看详细输出
[root@k8s-master ~]# kubectl describe pod pod-liveness-tcpsocket -n dev
····················
Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  2m30s                default-scheduler  Successfully assigned dev/pod-liveness-tcpsocket to k8s-node1
  Normal   Pulled     30s (x4 over 119s)   kubelet            Container image "nginx:1.15" already present on machine
  Normal   Created    30s (x4 over 119s)   kubelet            Created container nginx
  Normal   Started    30s (x4 over 119s)   kubelet            Started container nginx
  Normal   Killing    30s (x3 over 90s)    kubelet            Container nginx failed liveness probe, will be restarted
  Warning  Unhealthy  20s (x10 over 110s)  kubelet            Liveness probe failed: dial tcp 10.244.1.35:8080: connect: connection refused
# 可以在最后看到提示 808 0端口连接失败
# 根据输出的信息可以看到 nginx 容器在启动之后就进行了健康检查,健康检查失败之后,容器就会被 kill 掉,然后尝试重启 pod,然而健康检查一直失败,容器就会一直重启

将 TCPSocket 检测的端口调整为正确端口,在观察 pod 的状态

1.修改yaml文件中探测端口为80
[root@k8s-master ~]# vim pod-liveness-tcpsocket.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-tcpsocket
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.18
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:	
      tcpSocket:
        port: 80						#80是nginx的端口,调整为80,健康检查就会成功

2.创建pod
[root@k8s-master ~]# kubectl delete -f pod-liveness-tcpsocket.yaml
pod "pod-liveness-tcpsocket" deleted
[root@k8s-master ~]# kubectl create -f pod-liveness-tcpsocket.yaml
pod/pod-liveness-tcpsocket created

3.观察pod状态
[root@k8s-master ~]# kubectl get pod pod-liveness-tcpsocket -n dev
NAME                     READY   STATUS    RESTARTS   AGE
pod-liveness-tcpsocket   1/1     Running   0          35s
# pod 运行成功,已经不会重启了

使用 HTTPGet 方式探测容器的存活性

HTTPGet 方式就是访问指定的 url 链接,如果能访问成功表示健康检查成功,访问失败则会一直重启容器

1.编写yaml
[root@k8s-master ~]# vim pod-liveness-httpget.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-httpget
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.18
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:						#定义存活性探测
      httpGet:							#定义httpGet探测方式,如果下面不知道host参数,默认是pod的ip,地址连起来就是:scheme://podip:port/path
        scheme: HTTP					#使用的应用协议,默认是http,可以是http、https
        port: 80						#应用端口号
        path: /hello					#访问的url地址,地址连起来就是:http://127.0.0.1/hello,默认的nginx,hello页面一定不存在,健康检查也会失败
        
2.创建pod
[root@k8s-master ~]# kubectl create -f pod-liveness-httpget.yaml
pod/pod-liveness-httpget created

3.观察 pod 状态
#可以看到使用 httpGet 方式的健康检查,如果健康检查失败状态会变为 CrashLoopBackOff,且容器一直会重启
[root@k8s-master ~]# kubectl get pod pod-liveness-httpget -n dev
NAME                   READY   STATUS             RESTARTS   AGE
pod-liveness-httpget   0/1     CrashLoopBackOff   5          3m56s

4.查看详细输出信息
[root@k8s-master ~]# kubectl describe pod pod-liveness-httpget -n dev
·····················
Events:
  Type     Reason     Age                    From               Message
  ----     ------     ----                   ----               -------
  Normal   Scheduled  6m6s                   default-scheduler  Successfully assigned dev/pod-liveness-httpget to k8s-node1
  Normal   Pulled     4m39s (x4 over 6m3s)   kubelet            Container image "nginx:1.15" already present on machine
  Normal   Created    4m39s (x4 over 6m3s)   kubelet            Created container nginx
  Normal   Started    4m39s (x4 over 6m2s)   kubelet            Started container nginx
  Normal   Killing    4m39s (x3 over 5m39s)  kubelet            Container nginx failed liveness probe, will be restarted
  Warning  Unhealthy  59s (x19 over 5m59s)   kubelet            Liveness probe failed: HTTP probe failed with statuscode: 404
# 可以看到提示,健康检查的页面访问 404,健康检查失败  
# 根据输出的信息可以看到 nginx 容器在启动之后就进行了健康检查,健康检查失败之后,容器就会被kill掉,然后尝试重启pod,然而健康检查一直失败,容器就会一直重启

调整 HTTPGet 健康检查的页面为可访问的页面,继续观察 pod 的状态

1.修改httpGet请求的页面为真实存在的
[root@k8s-master ~]# vim pod-liveness-httpget.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-liveness-httpget
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.18
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:
      httpGet:
        scheme: HTTP
        port: 80
        path: /						#调整url路径为可以访问的,这样一来健康检查就是成功的

2.创建pod
[root@k8s-master ~]# kubectl delete -f pod-liveness-httpget.yaml
pod "pod-liveness-httpget" deleted
[root@k8s-master ~]# kubectl create -f pod-liveness-httpget.yaml
pod/pod-liveness-httpget created

3.观察pod状态
[root@k8s-master ~]# kubectl get pod pod-liveness-httpget -n dev
NAME                   READY   STATUS    RESTARTS   AGE
pod-liveness-httpget   1/1     Running   0          52s
# 发现 pod 已经不会重启了,pod 运行成功

Pod资源就绪性健康检查实战

  1. 设置一个容器存活性探测和就绪性探测共存的健康检查
  2. 存活探测使用tcpSocket方式,检查端口是否可用
  3. 就绪性探测使用httpGet方式,检查是否可用提供服务
1.编写yaml
[root@k8s-master ~]# vim pod-livereadiness.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-livereadiness
  namespace: dev
spec:
  containers:
  - name: nginx
    image: nginx:1.18
    ports:
    - name: nginx-port
      containerPort: 80
    livenessProbe:						#定义存活性探测
      tcpSocket:						#使用tcpSocket方式
        port: 80						#探测的端口
    readinessProbe:						#定义就绪性探测
      httpGet:							#使用httpGet方式
        scheme: HTTP					#使用的协议
        port: 80						#服务端口
        path: /							#url路径

2.创建pod
[root@k8s-master ~]# kubectl create -f pod-livereadiness.yaml
pod/pod-livereadiness created

3.查看pod的运行状态
[root@k8s-master ~]# kubectl get pod pod-livereadiness -n dev
NAME                READY   STATUS    RESTARTS   AGE
pod-livereadiness   1/1     Running   0          2m5s

4.查看健康检查是否生效
[root@k8s-master ~]# kubectl  describe pod  pod-livereadiness -n dev | grep -A 2 -B2 'Liveness'
    Ready:          True
    Restart Count:  0
    Liveness:       tcp-socket :80 delay=0s timeout=1s period=10s #success=1 #failure=3
    Readiness:      http-get http://:80/ delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:    <none>