1.什么是Pod
2.Pod的使用
3.Pod的生命周期
4.Probe 探针机制(健康检查机制)
1.什么是Pod
虽然我们要介绍pod,但是我们一般不直接创建pod,而是创建一些(deployment等)来题我们创建Pod,通过其它途径创建出来的pod拥有自恢复能力。
Pod是一组(一个或者多个)的容器(docker)集合,如同豌豆存在于豌豆荚中,这些容器共享存储,网络,以及如何运行这些容器等申明。
pod的形式
- pod对容器有自恢复的能力(Pod自动重启启动失败的容器)
- Pod自己没有自恢复的能力,删除了就真的没了。(deployment部署下的Pod有自恢复的能力。)
- Pod 天生地为其成员容器提供了两种共享资源:网络和存储。
- 单一容器的pod
- 多容器的pod,我们把另外的容器成为SideCar(为应用赋能)。
- 一个Pod由一个Pause容器设置好整个Pod里面所有容器的网络、名称空间等信息
- kubelet启动一个Pod,准备两个容器,一个是Pod声明的应用容器(nginx),另外一个是
Pause。Pause给当前应用容器设置好网络空间各种的。
2.Pod的使用
我们可以打开Lens,连上们的K8s集群,使用如图功能,再选择pod模板,就可以直接创建pod了。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
接着再点击右边的 Create&Close 就可以创建了.
3.Pod的生命周期
在讲解pod的生命周期之前,我们要先理解一个概念:initContainers(初始化容器)。初始化容器是K8s官网为我们提供的一个可以用来判断环境是否已经满足运行Pod应用前提的所需条件。
比如我们部署一个应用,必须要拥有一个前置环境,比如线上服务运行时得先启动Tomcat。我们需要检查Tomcat是否准备好,InitContainer就可以来帮助我们做这个事情。(一般在生产上会初始化一个容器监控服务,比如skeywalking的初始化,就会放在initContainers)。
- Pod启动,会先依次执行所有初始化容器,有一个失败,则Pod不能启动。
- 接下来启动所有的应用容器(每一个应用容器都必须能够一直运行),Pod开始正式工作,一个启动失败就会尝试重启Pod内的这个容器,Pod只要是NotReady,Pod就不对外提供服务了。
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
initContainers: # 支持配置多个初始化容器,当前面的初始化容器运行成功后,便会进行退出操作,紧接着启动下一个容器。
- name: my-init-container
image: busybox:1.28
# 打印666,睡眠60秒后启动程序。
command: [ 'sh', '-c', 'echo 666 ;sleep 60' ]
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
4.Probe 探针机制(健康检查机制)
探针是一种协助容器是否正常启动的辅助工具,通过配置各种探针来监控服务是否正常启动和运行,如果异常该pod就会自动重启或者不启动。
每个容器都有三种探针(Probe)
启动探针
- 使用启动探针,来检测应用是否正常启动,如果启动就可以进行后续的探测检查。
- 启动探针成功以后就不用了,剩下存活探针和就绪探针持续运行。
存活探针
- 使用存活探针,来检测容器是否正常存活。有些容器可能因为某些原因cpu飙升或者死锁,此时存活探针就会检测失败,导致重启这个pod。
就绪探针
- 使用就绪探针,来检测容器是否准备好了可以接收流量。当一个Pod内所有容器都准备好了,才能把这个pod看作就绪。用途就是:Service后端负载均衡多个Pod,如果某个Pod还没就绪,就会从service负载均衡里面剔除。
容器探针的yml写法:
apiVersion: v1
kind: Pod
metadata:
name: "nginx-start-probe02"
namespace: default
labels:
app: "nginx-start-probe02"
spec:
containers:
- name: nginx-start-probe02
image: "nginx"
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
ports:
- containerPort: 80
startupProbe: #启动探针
exec:
command: ["/bin/sh","-c","cat /app/abc"] #必须有这个文件才能启动
initialDelaySeconds: 20 ## 指定的这个秒以后才执行探测
periodSeconds: 5 ## 每隔几秒来运行这个
timeoutSeconds: 5 ##探测超时,到了超时时间探测还没返回结果说明失败
successThreshold: 1 ## 成功阈值,连续几次成才算成功
failureThreshold: 3 ## 失败阈值,连续几次失败才算真失败
livenessProbe: #存活探针
exec:
command: ["/bin/sh","-c","cat /usr/share/nginx/html/abc.html"] #必须有这个文件才算存活
initialDelaySeconds: 20 ## 指定的这个秒以后才执行探测
periodSeconds: 5 ## 每隔几秒来运行这个
timeoutSeconds: 5 ##探测超时,到了超时时间探测还没返回结果说明失败
successThreshold: 1 ## 成功阈值,连续几次成才算成功
failureThreshold: 3 ## 失败阈值,连续几次失败才算真失败
readinessProbe: #就绪探针
httpGet:
path: /abc.html
port: 80
scheme: HTTP
initialDelaySeconds: 20 ## 指定的这个秒以后才执行探测
periodSeconds: 5 ## 每隔几秒来运行这个
timeoutSeconds: 5 ##探测超时,到了超时时间探测还没返回结果说明失败
successThreshold: 1 ## 成功阈值,连续几次成才算成功
failureThreshold: 3 ## 失败阈值,连续几次失败才算真失败
volumeMounts:
- name: nginx-vol
mountPath: /app
- name: nginx-html
mountPath: /usr/share/nginx/html
volumes:
- name: nginx-vol
hostPath:
path: /app
- name: nginx-html
hostPath:
path: /html
restartPolicy: Always
以上只是demo写法,生产中我们部署springBoot应用,可以引入如下依赖,然后访问服务的/actuator/health接口就可以实现容器的健康检查。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
livenessProbe:
httpGet:
path: /actuator/health
port: 80
scheme: HTTP
initialDelaySeconds: 220
timeoutSeconds: 5
periodSeconds: 5
successThreshold: 1
failureThreshold: 1
readinessProbe:
httpGet:
path: /actuator/health
port: 80
scheme: HTTP
initialDelaySeconds: 120
timeoutSeconds: 10
periodSeconds: 10
successThreshold: 1
failureThreshold: 1
startupProbe:
httpGet:
path: /actuator/health
port: 80
scheme: HTTP
initialDelaySeconds: 200
timeoutSeconds: 10
periodSeconds: 10
successThreshold: 1
failureThreshold: 1
startupProbe:
httpGet:
path: /actuator/health
port: 80
scheme: HTTP
initialDelaySeconds: 180
timeoutSeconds: 10
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
同时我们还可以接入服务的优雅停机,这样我们就可以实现健康检查+优雅停机=0宕机的做法,来无缝衔接发布一个服务。
springBoot的yaml:
server:
# 设置关闭方式为优雅关闭 默认立即
shutdown: graceful
spring:
lifecycle:
# 优雅关闭超时时间, 默认30s
timeout-per-shutdown-phase: 300s
或者也可以在K8s的yaml中配置优雅停机:
# 和containers同一级别 因为这是操作整个pod的
spec.terminationGracePeriodSeconds:100
配合k8s的探针,当ctl 发起 kubeclt delete pod 时。k8s发起一个kill -2 命令,服务会立即不接受流量,k8sReadiness探针失败,不再分配流量。
springboot项目若配置了优雅停止,在超时时间内等待所有的controller,即tomcat的线程池的任务全部完成后。k8s持续探测的Liveness探针会在服务完全关闭的时候失败,之后k8s就算成功杀死pod了。
注意controller fork 出来的子线程的任务不会收到web的优雅停机的影响。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。