Kubernetes学习之路(十八)服务探针
_____egon新书来袭请看:https://egonlin.com/book.html
一 服务探针介绍
什么是服务探针?
对线上业务来说,保证服务的正常稳定是重中之重,对故障服务的及时处理避免影响业务以及快速恢复一直是开发运维的难点。
Kubernetes提供了健康检查服务,对于检测到故障服务会被及时自动下线,以及通过重启服务的方式使服务自动恢复。这就是所谓的服务探针
为何要用服务探针?
1、保证pod中的容器正常启动
2、保证pod中容器能够正常对外提供服务
综合下来就一句话:只有容器启动了并且能够正常对外提供服务了,才能放到负载均衡上供给用户访问
二 存活性探测livenessProbe
先说结论:检测到未存活,则干掉pod,启新的
用于判断容器是否存活,即Pod是否为running状态,如果LivenessProbe探针探测到容器不健康,则kubelet将kill掉容器,并根据容器的重启策略判断按照那种方式重启,如果一个容器不包含LivenessProbe探针,则Kubelet认为容器的LivenessProbe探针的返回值永远成功。存活性探测支持的方法有三种:ExecAction,TCPSocketAction,HTTPGetAction。
pod中所有容器的status=Running时,Pod的状态才会是Running状态。
当存活性检查检测失败的时候,kebulet会删除容器,重新启动一个新的容器。继续检查。
2.1 EXEC
通过执行一条命令,探测服务是否可以正常对外提供服务,例如
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.2 httpGet检查
通过访问某个URL的方式来探测当前的POD是否可以正常对外提供服务,例如
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
2.3 TcpSocket相当于ping
通过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.3 参数详解
例如
apiVersion: apps/v1 kind: Deployment metadata: labels: app: health-test name: health-test spec: replicas: 3 selector: matchLabels: app: health-test strategy: {} template: metadata: labels: app: health-test spec: containers: - image: nginx:1.14 name: nginx # 就绪检查 readinessProbe: exec: command: - cat - /tmp/healthy # 初始化检查延迟时间 initialDelaySeconds: 90 # 隔多少秒检查一次 periodSeconds: 5 # 存活检查 livenessProbe: exec: command: - cat - /tmp/healthy # 初始化检查延迟时间,一般设置比就绪检查的该时间大一点 initialDelaySeconds: 95 # 隔多少秒检查一次 periodSeconds: 5 # 重启策略 restartPolicy: Always status: {}
参数
# 检查失败最少测试,默认: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秒。
三 就绪性探测ReadinessProbe
先说结论:检测到未就绪,不会干掉pod,而是将Pod从Endpoint中剔除
用于判断容器是否正常提供服务,即容器的Ready是否为True,是否可以接收请求,如果ReadinessProbe探测失败,则容器的Ready将设置为False,控制器将此Pod的Endpoint从对应的service的Endpoint列表中移除,从此不再将任何请求调度此Pod上,直到下次探测成功。(剔除此pod,不参与接收请求不会将流量转发给此Pod)
探测失败移出service的Endpoint的健康列表
3.1 HTTPGet
kind: Pod apiVersion: v1 metadata: name: readinessprobe-nginx namespace: default labels: provider: aliyun business: pms environmental: dev spec: containers: - name: readinessprobe-nginx image: nginx imagePullPolicy: Always ports: - containerPort: 80 name: http protocol: TCP - containerPort: 443 name: https protocol: TCP readinessProbe: httpGet: port: 80 path: /demo.html
3.2 EXEC
kind: Pod apiVersion: v1 metadata: name: exec-pod spec: containers: - name: nginx imagePullPolicy: IfNotPresent image: nginx readinessProbe: exec: command: - cat - /usr/share/nginx/html/index.html
3.3 TCPSocket
kind: Pod apiVersion: v1 metadata: name: exec-pod spec: containers: - name: nginx imagePullPolicy: IfNotPresent image: nginx readinessProbe: tcpSocket: port: 80
四 回调钩子HOOK
实际上 Kubernetes 为我们的容器提供了生命周期钩子的,就是我们说的Pod Hook,Pod Hook 是由 kubelet 发起的,当容器中的进程启动前或者容器中的进程终止之前运行,这是包含在容器的生命周期之中。我们可以同时为 Pod 中的所有容器都配置 hook。
如果PostStart或者PreStop钩子失败, 它会杀死容器。所以我们应该让钩子函数尽可能的轻量。当然有些情况下,长时间运行命令是合理的, 比如在停止容器之前预先保存状态。
PostStart:
这个钩子在容器创建后立即执行。但是,并不能保证钩子将在容器ENTRYPOINT之前运行,因为没有参数传递给处理程序。主要用于资源部署、环境准备等。不过需要注意的是如果钩子花费太长时间以至于不能运行或者挂起, 容器将不能达到running状态。
容器启动后执行,注意由于是异步执行,它无法保证一定在ENTRYPOINT之后运行。如果失败,容器会被杀死,并根据RestartPolicy决定是否重启
PreStop:
这个钩子在容器终止之前立即被调用。它是阻塞的,意味着它是同步的, 所以它必须在删除容器的调用发出之前完成。主要用于优雅关闭应用程序、通知其他系统等。如果钩子在执行期间挂起, Pod阶段将停留在running状态并且永不会达到failed状态。
容器停止前执行,常用于资源清理。如果失败,容器同样也会被杀死
案例
kind: Deployment apiVersion: apps/v1 metadata: name: lifecycle spec: selector: matchLabels: app: cycle template: metadata: labels: app: cycle spec: nodeName: k8s-m-01 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