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
(對所有應為新 Pod 調用注入 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
符合目標命名空間時適用。無法辨識的策略會導致完全停用注入。檢查每個 Pod 的覆寫註解
預設策略可以使用 Pod 範本規格的 Metadata 中的
sidecar.istio.io/inject
標籤覆寫。部署的 Metadata 會被忽略。標籤值為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 伺服器有 Proxy 設定,自動 Sidecar 注入會失敗
當 Kubernetes API 伺服器包含 Proxy 設定時,例如:
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
清單中移除 Proxy 設定,另一種解決方法是在 no_proxy
值中包含 istio-sidecar-injector.istio-system.svc
或 .svc
。請確保在每次解決方法後重新啟動 kube-apiserver
。
與此相關的一個 Issue 已提交給 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 註解 "cluster-autoscaler.kubernetes.io/safe-to-evict": "true"
新增到注入的 Pod。
如果 istio-proxy 未就緒,Pod 或容器啟動時會發生網路問題
許多應用程式會在啟動期間執行需要網路連線的命令或檢查。如果 istio-proxy
Sidecar 容器尚未就緒,可能會導致應用程式容器掛起或重新啟動。
為了避免這種情況,請將 holdApplicationUntilProxyStarts
設定為 true
。這會導致 Sidecar 注入器在 Pod 的容器清單開頭注入 Sidecar,並將其設定為阻止所有其他容器的啟動,直到 Proxy 就緒。
這可以新增為全域配置選項:
values.global.proxy.holdApplicationUntilProxyStarts: true
或作為 Pod 註解:
proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'