Sidecar 注入問題

Sidecar 注入的結果不如預期

這包括在不預期時注入了 Sidecar,以及在預期時缺少注入 Sidecar。

  1. 請確保您的 Pod 不在 kube-systemkube-public 命名空間中。在這些命名空間中的 Pod 將會忽略自動 Sidecar 注入。

  2. 請確保您的 Pod 的 Pod 規格中沒有 hostNetwork: true。在主機網路上的 Pod 將會忽略自動 Sidecar 注入。

    Sidecar 模型假設 Envoy 攔截流量所需的 iptables 變更是在 Pod 內部。對於主機網路上的 Pod,此假設被違反,可能會導致主機層級的路由失敗。

  3. 檢查 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
    
  4. 檢查預設策略

    檢查 istio-sidecar-injector configmap 中的預設注入策略。

    $ kubectl -n istio-system get configmap istio-sidecar-injector -o jsonpath='{.data.config}' | grep policy:
    policy: enabled
    

    允許的策略值為 disabledenabled。預設策略僅在 Webhook 的 namespaceSelector 符合目標命名空間時適用。無法辨識的策略會導致完全停用注入。

  5. 檢查每個 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 失敗通常會記錄在事件日誌中。

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 }'
此資訊是否對您有幫助?
您有任何改進建議嗎?

感謝您的回饋!