在未开启双向tls认证时,kubelet发出健康检查请求,虽然经过了envoy,但是能够正常的转发到我们的应用服务。
但是在启用双向TLS时,对liveness-http服务的运行状况检查请求是由Kubelet发送的,而Kubelet没有Istio颁发的证书。因此,启用双向TLS后,运行状况检查请求将失败。
为了能够正常的响应健康检查,Istio通过重写应用程序PodSpec 就绪/活跃性探针的方式解决了此问题,从而将探针请求发送到Sidecar代理。然后,sidecar代理将请求重定向到应用程序,剥离响应主体,仅返回响应代码。
默认情况下,所有内置Istio配置文件中都启用了此功能
默认情况下,Istio使用探针重写来实现HTTP探针。您可以为特定的pod或全局禁用此功能。
您可以使用注释注释pod,sidecar.istio.io/rewriteAppHTTPProbers: "false"
以禁用探针重写选项。确保将注释添加到pod资源,因为注释 将在其他任何地方(例如,在封闭的部署资源上)被忽略。
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: liveness-http
spec:
selector:
matchLabels:
app: liveness-http
version: v1
template:
metadata:
labels:
app: liveness-http
version: v1
annotations:
sidecar.istio.io/rewriteAppHTTPProbers: "false"
spec:
containers:
- name: liveness-http
image: docker.io/istio/health:example
ports:
- containerPort: 8001
livenessProbe:
httpGet:
path: /foo
port: 8001
initialDelaySeconds: 5
periodSeconds: 5
EOF
这种方法在单个deployment上禁用运行状况检查探针重写,而无需重新安装Istio。
当开启rewriteAppHTTPProbers时将在注入时对容器进行改写
添加路径到istio-proxy的环境变量
if rewrite && sidecar != nil {
if prober := DumpAppProbers(&pod.Spec); prober != "" {
sidecar.Env = append(sidecar.Env, corev1.EnvVar{Name: status.KubeAppProberEnvName, Value: prober})
}
}
对于上面的示例服务我们可以看到添加了以下环境变量
- name: ISTIO_KUBE_APP_PROBERS
value: '{"/app-health/liveness-http/livez":{"httpGet":{"path":"/foo","port":8001,"scheme":"HTTP"},"timeoutSeconds":1}}'
生成path,用于修改pod的配置
patch = append(patch, createProbeRewritePatch(pod.Annotations, &pod.Spec, sic, mesh.GetDefaultConfig().GetStatusPort())...)
分别对readyness,liveness,startup 三种probe进行重写,根据容器名称生成健康检查路径
func FormatProberURL(container string) (string, string, string) {
return fmt.Sprintf("/app-health/%v/readyz", container),
fmt.Sprintf("/app-health/%v/livez", container),
fmt.Sprintf("/app-health/%v/startupz", container)
}
将原有的probe转换为新的probe配置
func convertAppProber(probe *corev1.Probe, newURL string, statusPort int) *corev1.Probe {
if probe == nil || probe.HTTPGet == nil {
return nil
}
p := probe.DeepCopy()
// 修改容器的probe配置
p.HTTPGet.Port = intstr.FromInt(statusPort)
p.HTTPGet.Path = newURL
// Kubelet -> HTTP -> Pilot Agent -> HTTPS -> Application
if p.HTTPGet.Scheme == corev1.URISchemeHTTPS {
p.HTTPGet.Scheme = corev1.URISchemeHTTP
}
return p
}
通过handleAppProbe对健康检查进行响应
mux.HandleFunc("/app-health/", s.handleAppProbe)
handleAppProbe根据对应的请求路径构建httpclient,请求本地的应用服务,因为在iptables的劫持策略中同用户的lo网卡的流量直接转发不经过envoy,从而达成请求真实应用服务的目的
istio 通过mutatingwebhook 对原有pod的配置进行修改,生成由pilot-agent响应健康检查的配置,优雅的兼容在开启双向 tls情况下,kubelet无法请求成功的问题,同时由pilot-agent发出的请求直达应用服务,也避免了envoy产生大量健康检查日志的问题。