Sidecar 注入问题
Sidecar 注射的结果与我的预期不符
这包括在意外情况下注入的 Sidecar 以及预期情况下缺少注入的 Sidecar。
确保您的 Pod 不在
kube-system
或kube-public
命名空间中。对于这些命名空间中的 Pod,将忽略自动 Sidecar 注射。确保您的 Pod 在其 Pod 规范中没有
hostNetwork: true
。对于位于主机网络上的 Pod,将忽略自动 Sidecar 注射。Sidecar 模型假设 Envoy 拦截流量所需的 iptables 更改位于 Pod 内。对于主机网络上的 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 应该为新 Pod 调用的所有命名空间重复)
$ 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
与目标命名空间匹配时才适用。无法识别的策略会导致完全禁用注入。检查每个 Pod 覆盖注释
默认策略可以通过 Pod 模板规范的元数据中的
sidecar.istio.io/inject
标签覆盖。部署的元数据将被忽略。标签值为true
会强制注入 Sidecar,而值为false
会强制不注入 Sidecar。以下标签将覆盖任何默认的
policy
以强制注入 Sidecar$ kubectl get deployment curl -o yaml | grep "sidecar.istio.io/inject:" -B4 template: metadata: labels: app: curl sidecar.istio.io/inject: "true"
无法创建 Pod
在失败的 Pod 的部署上运行 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://istiod.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
是否与 istiod
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 证书应该匹配。如果不匹配,请重新启动 istiod Pod。
$ kubectl -n istio-system patch deployment istiod \
-p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"`date +'%s'`\"}}}}}"
deployment.extensions "istiod" patched
部署状态错误
当为 Pod 启用自动 Sidecar 注射时,如果注入因任何原因失败,Pod 创建也会失败。在这种情况下,您可以检查 Pod 的部署状态以识别错误。错误也会出现在与部署相关的命名空间的事件中。
例如,如果您尝试部署 Pod 时 istiod
控制平面 Pod 未运行,则事件将显示以下错误
$ kubectl get events -n curl
...
23m Normal SuccessfulCreate replicaset/curl-9454cc476 Created pod: curl-9454cc476-khp45
22m Warning FailedCreate replicaset/curl-9454cc476 Error creating: Internal error occurred: failed calling webhook "namespace.sidecar-injector.istio.io": failed to call webhook: Post "https://istiod.istio-system.svc:443/inject?timeout=10s": dial tcp 10.96.44.51:443: connect: connection refused
$ kubectl -n istio-system get pod -lapp=istiod
NAME READY STATUS RESTARTS AGE
istiod-7d46d8d9db-jz2mh 1/1 Running 0 2d
$ kubectl -n istio-system get endpoints istiod
NAME ENDPOINTS AGE
istiod 10.244.2.8:15012,10.244.2.8:15010,10.244.2.8:15017 + 1 more... 3h18m
如果 istiod Pod 或端点未准备好,请检查 Pod 日志和状态,以了解有关 Webhook Pod 无法启动和提供流量的原因的任何指示。
$ for pod in $(kubectl -n istio-system get pod -lapp=istiod -o jsonpath='{.items[*].metadata.name}'); do \
kubectl -n istio-system logs ${pod} \
done
$ for pod in $(kubectl -n istio-system get pod -l app=istiod -o name); do \
kubectl -n istio-system describe ${pod}; \
done
$
如果 Kubernetes API 服务器具有代理设置,则自动 Sidecar 注射将失败
当 Kubernetes API 服务器包含代理设置时,例如
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
确保 Pod 和服务 CIDR 都不根据 *_proxy
变量进行代理。检查 kube-apiserver
文件和日志以验证配置以及是否正在代理任何请求。
一个解决方法是从 kube-apiserver
清单中删除代理设置,另一个解决方法是在 no_proxy
值中包含 istio-sidecar-injector.istio-system.svc
或 .svc
。确保在每次解决方法后重新启动 kube-apiserver
。
已向 Kubernetes 提交了一个关于此问题的问题,该问题现已关闭。https://github.com/kubernetes/kubernetes/pull/58698#discussion_r163879443
在 Pod 中使用 Tcpdump 的限制
Tcpdump 在 Sidecar Pod 中不起作用 - 容器不以 root 身份运行。但是,同一个 Pod 中的任何其他容器都会看到所有数据包,因为网络命名空间是共享的。iptables
也会看到 Pod 范围的配置。
Envoy 和应用程序之间的通信发生在 127.0.0.1 上,并且未加密。
集群不会自动缩减
由于 Sidecar 容器挂载了本地存储卷,因此节点自动缩放器无法驱逐具有注入 Pod 的节点。这是一个已知问题。解决方法是为注入的 Pod 添加一个 Pod 注释 "cluster-autoscaler.kubernetes.io/safe-to-evict": "true"
。
如果 istio-proxy 未准备好,Pod 或容器将以网络问题启动
许多应用程序在启动期间执行命令或检查,这些命令或检查需要网络连接。如果 istio-proxy
Sidecar 容器未准备好,这会导致应用程序容器挂起或重新启动。
为了避免这种情况,请将 holdApplicationUntilProxyStarts
设置为 true
。这会导致 Sidecar 注射器在 Pod 容器列表的开头注入 Sidecar,并将其配置为阻止所有其他容器启动,直到代理准备就绪。
这可以作为全局配置选项添加
values.global.proxy.holdApplicationUntilProxyStarts: true
或者作为 Pod 注释添加
proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'