由于Sidecar对网格内应用接收请求的拦截机制,如果您为加入服务网格ASM(即注入了Sidecar)中的应用配置了HTTP请求或TCP请求形式的健康检查,则健康检查可能出现不符合预期的行为,例如健康检查一直失败。本文介绍如何为网格内应用开启健康检查重定向。
背景信息
为网格内应用启用HTTP和TCP请求的健康检查存在以下问题。因此,您需要基于Annotation方式为网格内应用开启健康检查重定向,让健康检查恢复正常。
类型 | 说明 |
使用HTTP请求的健康检查 | Kubernetes集群由Kubelet服务统一发送Pod的健康检查请求,而在开启了双向TLS模式后,网格内应用被强制要求使用TLS方式进行通信。由于Kubelet服务并非网格的一部分,该服务没有服务网格为应用颁发的证书,导致使用HTTP方式的健康检查请求会被拒绝,健康检查一直失败。 说明 如果您未在ASM中开启双向TLS模式,无需配置健康检查重定向,就可以使用HTTP请求对应用Pod进行健康检查。 |
使用TCP请求的健康检查 | 由于Sidecar拦截请求的需要,网格内应用Pod的所有端口都会被监听。在使用TCP请求方式的健康检查时,Kubelet服务会检查应用Pod所配置的端口是否有应用正在进行监听,判断应用的健康状态。 由于上述原因,只要应用注入了Sidecar,且Sidecar正在运行,无论应用本身处于何种状态,健康检查都始终会成功。例如,您为应用配置了错误端口,Pod的健康检查理应始终失败,Pod应该处于未就绪状态,但实际上健康检查成功。 |
默认情况下,网格拓扑图中会显示应用服务的健康检查的请求调用,但在很多场景下可能会混淆流量统计的结果。如果您需要移除这些内部的健康检查调用统计,可以为网格内应用开启健康检查重定向。
启用HTTP请求的健康检查重定向
本文以Nginx应用为例,在开启双向TLS模式后,为Nginx应用配置HTTP请求的健康检查,但是健康检查一直失败,然后为Nginx应用开启健康检查重定向,查看Pod事件时无健康检查失败事件,且Pod处于就绪状态,说明为应用启用HTTP请求的健康检查重定向成功。
步骤一:开启网格全局双向TLS模式
登录ASM控制台。
在左侧导航栏,选择 。
在网格管理页面,找到待配置的实例,单击实例的名称或在操作列中单击管理。
在网格详情页面左侧导航栏,选择 。
在对等身份认证页面顶部,选择命名空间,然后单击设置全局双向TLS模式。
在设置全局双向TLS模式页面,设置mTLS模式(命名空间级)为STRICT - 严格遵循双向TLS认证,单击创建。
步骤二:部署Nginx应用
部署Nginx应用。
使用以下内容,创建http-liveness.yaml。
在readinessProbe参数下设置httpGet,表示为该应用启用HTTP请求的健康检查。
执行以下命令,部署Nginx应用。
kubectl apply -f http-liveness.yaml
查看应用的健康检查状态。
执行以下命令,查看Nginx应用的Pod名称。
kubectl get pod| grep nginx
执行以下命令,查看Pod事件。
kubectl describe pod <Pod名称>
预期输出:
Warning Unhealthy 45s kubelet Readiness probe failed: Get "http://172.23.64.22:80/index.html": read tcp 172.23.64.1:54130->172.23.64.22:80: read: connection reset by peer
可以看到,针对Pod的HTTP健康检查失败,使得Pod一直处于未就绪的状态。
步骤三:为Nginx应用开启健康检查重定向
执行以下命令,编辑http-liveness.yaml。
vim http-liveness.yaml
在
template
参数下添加以下内容:annotations: sidecar.istio.io/rewriteAppHTTPProbers: "true"
以下为添加Annotation注解后的http-liveness.yaml文件:
执行以下命令,部署Nginx应用。
kubectl apply -f http-liveness.yaml
步骤四:验证健康检查结果是否符合预期
查看Pod的健康检查状态。
执行以下命令,查看Nginx应用的Pod名称。
kubectl get pod| grep nginx
执行以下命令,查看Pod事件。
kubectl describe pod <Pod名称>
返回结果中不包含任务健康检查失败的事件,Pod处于就绪状态,启用健康检查成功,符合预期。
执行以下命令,查看经过健康检查重定向后的Pod YAML文件。
kubectl get pod nginx-deployment-676f85f66b-7vxct -o yaml
启用了健康检查重定向后,原先配置的健康检查端口由80改为15020,健康检查的路径也由/index.html改为/app-health/nginx/readyz。同时,Pod中的Sidecar容器新增一个名为
ISTIO_KUBE_APP_PROBERS
的环境变量,其值为改写健康检查之前的健康检查配置经过JSON序列化后的内容。对于网格内应用来说,15020是一个用于网格可观测性的特殊端口,发送到该端口的流量不会被Sidecar拦截,因此不需要遵循TLS模式的要求。 在启用健康检查重定向后,运行于Sidecar容器中的pilot-agent服务会开启监听15020端口,接收来自Kubelet服务的健康检查,并根据
ISTIO_KUBE_APP_PROBERS
环境变量中配置的健康检查内容将健康检查请求转发至业务容器,从而使HTTP请求方式的健康检查正常运行。
启用TCP请求的健康检查重定向
本文以Nginx应用为例,为Nginx应用配置了错误端口,但是使用TCP的方式对应用的Pod健康检查仍然成功,不符合预期。然后为Nginx应用开启健康检查重定向,使用TCP的方式对应用的Pod健康检查失败,符合预期,从而为应用成功启用TCP请求的健康检查重定向。
步骤一:部署Nginx应用
部署Nginx应用。
使用以下内容,创建tcp-liveness.yaml。
以下内容中配置了一个错误的健康检查端口2940,由于Nginx应用不在2940端口开启监听,因此部署应用后健康检查应始终失败,导致Pod一直处于未就绪状态。
在readinessProbe参数下设置tcpSocket,表示为该应用启用TCP请求的健康检查。
执行以下命令,部署Nginx应用。
kubectl apply -f tcp-liveness.yaml
查看应用的健康检查状态。
执行以下命令,查看Nginx应用的Pod名称。
kubectl get pod| grep nginx
执行以下命令,查看Pod事件。
kubectl describe pod <Pod名称>
返回结果中不包含任何健康检查失败事件,Pod处于就绪状态,不符合预期结果。
步骤二:为Nginx应用开启健康检查重定向
执行以下命令,编辑tcp-liveness.yaml文件。
vim tcp-liveness.yaml
在tcp-liveness.yaml文件中
template
参数下添加以下内容:annotations: sidecar.istio.io/rewriteAppHTTPProbers: "true"
以下为添加Annotation注解后的tcp-liveness.yaml文件:
执行以下命令,部署Nginx应用。
kubectl apply -f tcp-liveness.yaml
步骤三:验证健康检查结果是否符合预期
查看应用的健康检查状态。
执行以下命令,查看Nginx应用的Pod名称。
kubectl get pod| grep nginx
执行以下命令,查看Pod事件。
kubectl describe pod <Pod名称>
预期输出:
Warning Unhealthy 45s kubelet Readiness probe failed: HTTP probe failed with statuscode: 500
可以看到返回结果中提示健康检查失败,符合预期。
执行以下命令,查看经过健康检查重定向的应用Pod YAML内容。
kubectl get pod nginx-deployment-746458cdc9-m9t9q -o yaml
启用了健康检查重定向后,可以发现原先的TCP请求健康检查被改写为HTTP请求健康检查,健康检查端口由80改为15020,并配置了HTTP健康检查的路径为/app-health/nginx/readyz。同时,Pod中的Sidecar容器也会新增一个名为
ISTIO_KUBE_APP_PROBERS
的环境变量,其值为改写健康检查之前的TCP健康检查配置经过JSON序列化后的内容。对于TCP请求的健康检查,服务网格的健康检查重定向实际做了与HTTP请求的健康检查相同的处理,将其改写为一个15020端口的HTTP健康检查。同时在Pod内部,运行于Sidecar容器中的pilot-agent服务会开启监听15020端口,接收来自Kubelet服务的健康检查,并根据
ISTIO_KUBE_APP_PROBERS
环境变量中配置的TCP健康检查内容,对业务容器配置的TCP健康检查端口进行实际的探测。如果实际的TCP健康检查失败,pilot-agent服务会返回500状态码,以标识健康检查失败。