Sidecar 自动注入问题
注入的结果和预期不一致
不一致包括 Sidecar 的非预期注入和预期未注入。
确保您的 Pod 不在
kube-system
或kube-public
名称空间中。 这些命名空间中的 Pod 将忽略 Sidecar 自动注入。确保您的 Pod 在其 Pod 定义中没有
hostNetwork:true
。hostNetwork:true
的 Pod 将忽略 Sidecar 自动注入。Sidecar 模型假定 iptables 会拦截所有 Pod 中的流量给 Envoy,但是
hostNetwork:true
的 Pod 不符合此假设,并且会导致主机级别的路由失败。通过检查 webhook 的
namespaceSelector
以确定目标命名空间是否包含在 webhook 范围内。包含在范围内的
namespaceSelector
如下所示:$ kubectl get mutatingwebhookconfiguration istio-sidecar-injector -o yaml | grep "namespaceSelector:" -A5 namespaceSelector: matchLabels: istio-injection: enabled rules: - apiGroups: - ""
在有
istio-injection=enabled
标签的命名空间中创建 Pod 就会调用注入 webhook。$ kubectl get namespace -L istio-injection NAME STATUS AGE ISTIO-INJECTION default Active 18d enabled istio-system Active 3d kube-public Active 18d kube-system Active 18d
不包含在注入范围的
namespaceSelector
如下所示:$ kubectl get mutatingwebhookconfiguration istio-sidecar-injector -o yaml | grep "namespaceSelector:" -A5 namespaceSelector: matchExpressions: - key: istio-injection operator: NotIn values: - disabled rules: - apiGroups: - ""
在没有标记
istio-injection=disabled
标签的命名空间中创建 Pod,注入 webhook 就会被调用。$ kubectl get namespace -L istio-injection NAME STATUS AGE ISTIO-INJECTION default Active 18d istio-system Active 3d disabled kube-public Active 18d disabled kube-system Active 18d disabled
验证应用程序 Pod 的命名空间是否已相应地被正确(重新)标记,例如:
$ kubectl label namespace istio-system istio-injection=disabled --overwrite
(对所有需要自动注入 webhook 的命名空间都重复上述步骤)
$ kubectl label namespace default istio-injection=enabled --overwrite
检查默认策略
在
istio-sidecar-injector configmap
中检查默认注入策略。$ kubectl -n istio-system get configmap istio-sidecar-injector -o jsonpath='{.data.config}' | grep policy: policy: enabled
策略允许的值为
disabled
或者enabled
。仅当 webhook 的namespaceSelector
与目标命名空间匹配时,默认策略才会生效。无法识别的策略值默认为disabled
。检查每个 Pod 的标签
可以使用 pod template spec metadata 中的标签
sidecar.istio.io/inject
来覆盖默认策略,如果这样的话,Deployment 相应的 metadata 将被忽略。标签值为true
会被强制注入 Sidecar,为false
则会强制不注入 Sidecar。以下标签会覆盖默认策略并强制注入 Sidecar:
$ kubectl get deployment sleep -o yaml | grep "sidecar.istio.io/inject:" -B4 template: metadata: labels: app: sleep sidecar.istio.io/inject: "true"
Pod 不能创建
在失败的 Pod 的 Deployment 上运行 kubectl describe -n namespace deployment name
。通常能在事件中看到调用注入 webhook 失败的原因。
x509 证书相关的错误
Warning FailedCreate 3m (x17 over 8m) replicaset-controller Error creating: Internal error occurred: \
failed calling admission webhook "sidecar-injector.istio.io": Post https://istio-sidecar-injector.istio-system.svc:443/inject: \
x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying \
to verify candidate authority certificate "Kubernetes.cluster.local")
x509: certificate signed by unknown authority
错误通常由 webhook 配置中的空 caBundle
引起。
验证 mutatingwebhookconfiguration
配置中的 caBundle
是否与 istio-sidecar-injector
中 pod 安装的根证书匹配。
$ kubectl get mutatingwebhookconfiguration istio-sidecar-injector -o yaml -o jsonpath='{.webhooks[0].clientConfig.caBundle}' | md5sum
4b95d2ba22ce8971c7c92084da31faf0 -
$ kubectl -n istio-system get configmap istio-ca-root-cert -o jsonpath='{.data.root-cert\.pem}' | base64 -w 0 | md5sum
4b95d2ba22ce8971c7c92084da31faf0 -
CA 证书必须匹配,否则需要重新启动 sidecar-injector pod。
$ kubectl -n istio-system patch deployment istio-sidecar-injector \
-p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}"
deployment.extensions "istio-sidecar-injector" patched
Deployment 状态中出现 no such hosts
或 no endpoints available
注入是失效关闭的(fail-close)。如果 istio-sidecar-injector
Pod 尚未准备就绪,则无法创建 Pod。在这种情况下,则会出现 no endpoints available
。
Internal error occurred: failed calling admission webhook "istio-sidecar-injector.istio.io": \
Post https://istio-sidecar-injector.istio-system.svc:443/admitPilot?timeout=30s: \
no endpoints available for service "istio-sidecar-injector"
$ kubectl -n istio-system get pod -listio=sidecar-injector
NAME READY STATUS RESTARTS AGE
istio-sidecar-injector-5dbbbdb746-d676g 1/1 Running 0 2d
$ kubectl -n istio-system get endpoints istio-sidecar-injector
NAME ENDPOINTS AGE
istio-sidecar-injector 10.48.6.108:15014,10.48.6.108:443 3d
如果 Pod 或 endpoint 尚未准备就绪,可以通过检查 Pod 日志和状态查找有关 Webhook Pod 无法启动的原因。
$ for pod in $(kubectl -n istio-system get pod -listio=sidecar-injector -o jsonpath='{.items[*].metadata.name}'); do \
kubectl -n istio-system logs ${pod} \
done
$ for pod in $(kubectl -n istio-system get pod -listio=sidecar-injector -o name); do \
kubectl -n istio-system describe ${pod} \
done
如果 Kubernetes API server 有代理设置的话,Sidecar 的自动注入功能是不能用的
当 Kubernetes API server 包含诸如以下的代理设置时:
env:
- name: http_proxy
value: http://proxy-wsa.esl.foo.com:80
- name: https_proxy
value: http://proxy-wsa.esl.foo.com:80
- name: no_proxy
value: 127.0.0.1,localhost,dockerhub.foo.com,devhub-docker.foo.com,10.84.100.125,10.84.100.126,10.84.100.127
使用这些设置,Sidecar 自动注入就会失败。相关的报错可以在 kube-apiserver
日志中找到:
W0227 21:51:03.156818 1 admission.go:257] Failed calling webhook, failing open sidecar-injector.istio.io: failed calling admission webhook "sidecar-injector.istio.io": Post https://istio-sidecar-injector.istio-system.svc:443/inject: Service Unavailable
根据 *_proxy
相关的的环境变量设置,确保 Pod 和 service CIDR 是没有被代理的。检查 kube-apiserver
的运行日志验证是否有请求正在被代理。
一种解决方法是在 kube-apiserver
的配置中删除代理设置,另一种解决方法是把 istio-sidecar-injector.istio-system.svc
或者 .svc
加到 no_proxy
的 value
里面。每种解决方法都需要重新启动 kube-apiserver
。
Kubernetes 与此有关的一个 issue 已被 PR #58698 解决。
在 Pod 中使用 tcpdump
的限制
tcpdump
在 Sidecar 中不能工作 - 因为该容器不以 root 身份运行。但是由于同一 Pod 内容器的网络命名空间是共享的,因此 Pod 中的其他容器也能看到所有数据包。iptables
也能查看到 Pod 级别的相关配置。
Envoy 和应用程序之间的通信是通过 127.0.0.1 进行的,这个通讯过程未加密。
集群不会自动缩小
由于 Sidecar 容器安装了本地存储卷,因此节点自动缩放器无法使用注入的 Pod 驱逐节点。这是一个已知的问题。解决方法是向 Pod 添加注解 “cluster-autoscaler.kubernetes.io/safe-to-evict”:“true”
。