k8s-故障转移学习总结
大纲
- 概念
- K8S中Pod健康检查
- livenessProbe & readinessProbe
- livenessProbe 存活探测实例
- readinessProbe 就绪探测实例
概念
故障转移有哪些情况
- 物理机故障
- 程序故障
在计算机术语中,故障转移(英语:failover),即当活动的服务或应用意外终止时,快速启用冗余或备用的服务器、系统、硬件或者网络接替它们工作。
K8S中Pod健康检查
默认情况下,kubelet根据容器运行状态作为健康依据,不能监控容器中应用程序状态!
例如程序假死。这就会导致无法提供服务,丢失流量。因此引入健康检查机制确保容器健康存活。
Pod通过两类探针来检查容器的健康状态
- LivenessProbe(存活探测)
- ReadinessProbe(就绪探测)
启动(Startup)探针是另外的一个探测
官方资料: https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
livenessProbe(存活探测)
kubelet 使用livenessProbe(存活探测)来确定什么时候要重启容器。 例如,存活探针可以探测到应用死锁(应用程序在运行,但是无法继续执行后面的步骤)情况。 重启这种状态下的容器有助于提高应用的可用性,即使其中存在缺陷。
存活探测将通过http、shell命令或者tcp等方式去检测容器中的应用是否健康,然后将检查结果返回给kubelet,
如果检查容器中应用为不健康状态提交给kubelet后,kubelet将根据Pod配置清单中定义的重启策略restartPolicy来对Pod进行重启。
readinessProbe(就绪探测)
kubelet 使用就绪探针可以知道容器何时准备好接受请求流量,当一个 Pod 内的所有容器都就绪时,才能认为该 Pod 就绪。 这种信号的一个用途就是控制哪个 Pod 作为 Service 的后端。 若 Pod 尚未就绪,会被从 Service 的负载均衡器中剔除。
如果容器或则Pod状态为(NoReady)状态,Kubernetes则会把该Pod从Service的后端endpoints Pod中去剔除。
livenessProbe(存活探测),readinessProbe(就绪探测),这两种探测都支持以下方式对容器进行健康检查
- Exec(执行脚本):在容器中执行命令,命令执行后返回的状态为0则成功,表示我们探测结果正常
- HTTP:根据容器IP、端口以及路径发送HTTP请求,返回码如果是200-400之间表示成功
- TCPSocketAction:根据容器IP地址及特定的端口进行TCP检查,端口开放表示成功
以上每种检查动作都可能有以下三种返回状态
- Success,表示通过了健康检查
- Failure,表示没有通过健康检查
- Unknown,表示检查动作失败
livenessProbe(存活探测)
livenessProbe(存活探测) 控制Pod的重启
livenessProbe:
# 会访问localhost:5555/health 这个http请求
httpGet:
path: /health
port: 5555
initialDelaySeconds: 10 #延迟探测时间
timeoutSeconds: 1
periodSeconds: 10 #访问频率单位秒
failureThreshold: 3
配置说明
-
periodSeconds 字段指定了 kubelet 应该每几秒执行一次存活探测
-
initialDelaySeconds 字段告诉 kubelet 在执行第一次探测前应该等待 5 秒
-
failureThreshold 针对 HTTP 或 TCP 检测,可以通过将 failureThreshold * periodSeconds 参数设置为足够长的时间来应对启动时间过慢的情况
例如
failureThreshold: 3
periodSeconds:10
应用程序将会有最多 半分钟(3 * 10 = 30s)的时间来完成其启动过程
注意:使用livenessProbe(存活探测)时要注意程序的启动时间如果启动时间过长会导致健康检查失败 一直重启
可以使用startupProbe(启动探针)保护慢启动容器
startupProbe:
httpGet:
path: /health
port: 5555
failureThreshold: 30
periodSeconds: 10
readinessProbe(就绪探测)
readinessProbe(就绪探测) 控制Service是否可以使用Pod
readinessProbe:
# 会访问localhost:5555/health 这个http请求
httpGet:
path: /startok
port: 5555
# 可以自定义请求头
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 5 #延迟探测时间
timeoutSeconds: 1
periodSeconds: 5 #访问频率
failureThreshold: 3
livenessProbe 存活探测实例
step1 镜像与配合的代码
调整docker容器JVM堆内存大小,让java.lang.OutOfMemoryError来得快点
对应的controller代码
//定义一个列表保存数据
private List<Object> list = new ArrayList<>();
@RequestMapping("/oop")
public boolean oop(){
System.out.println(list.size());
new Thread(()->{
while(true){
//循环创建一个1M的数组 没有释放 让其触发OutOfMemoryError
list.add(new String[1024][1024]);
list.add(new String[1024][1024]);
list.add(new String[1024][1024]);
list.add(new String[1024][1024]);
System.out.println("加数据");
}
}).start();
return true;
}
//健康检查接口 无法继续创建对象
@RequestMapping("/health")
public String health() {
Health h = createHealth();
return h.getStatus();
}
private Health createHealth(){
Health h = new Health();
h.setArry(new String[1024][1024]);
h.setStatus("ok");
return h;
}
step2 启动pod
http-health-check.yaml 关键配置如下:
livenessProbe:
# 会访问localhost:5555/health 这个http请求
httpGet:
path: /health
port: 5555
initialDelaySeconds: 10 #延迟探测时间
timeoutSeconds: 1
periodSeconds: 10 #访问频率
failureThreshold: 3
详情见《/yaml/http-health-check.yaml》
kubectl apply -f http-health-check.yaml 创建Pod
可以看到 RESTARTS是0 表示还没重启过
step3 测试故障转移
触发OOM异常
此时 springboot已经无法正常使用了
step4 k8s故障转移
k8s会自动的重启 Pod 让服务重新可用
可以看到Pod RESTARTS是1 表示已经重启过一次
注意: livenessProbe 存活探测只无法处理节点宕机的情况
readinessProbe就绪探测实例
就绪探测可以测试pod是否可以开始对外提供服务了,Service可以开始使用pod了
step1 代码改造
step2 启动pod
http-health-check.yaml 关键配置如下:
readinessProbe:
# 会访问localhost:5555/health 这个http请求
httpGet:
path: /startok
port: 5555
# 可以自定义请求头
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 5 #延迟探测时间
timeoutSeconds: 1
periodSeconds: 5 #访问频率
failureThreshold: 3
详情见《/yaml/http-health-check.yaml》
kubectl apply -f http-health-check.yaml 创建Pod
step3 测试就绪探测
Pod成功创建 ,使用Pod ip可以访问程序,但使用service ip 则无法访问
等待90s后
成功访问