解決 Cloud Service Mesh 中的工作負載啟動問題
本文說明常見的 Cloud Service Mesh 問題,以及解決方法。如需其他協助,請參閱取得支援。
公開特權通訊埠時,閘道無法透過無發行版 Proxy 啟動
根據預設,無發行版 Proxy 會以非 Root 權限啟動,在某些情況下可能會導致特殊權限通訊埠繫結失敗。如果您在 Proxy 啟動期間看到類似以下的錯誤,就需要為網關部署套用額外的 securityContext。
Error adding/updating listener(s) 0.0.0.0_80: cannot bind '0.0.0.0:80': Permission denied
以下是外送閘道部署作業的 yaml 範例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-egressgateway
spec:
selector:
matchLabels:
app: istio-egressgateway
istio: egressgateway
template:
metadata:
annotations:
# This is required to tell Anthos Service Mesh to inject the gateway with the
# required configuration.
inject.istio.io/templates: gateway
labels:
app: istio-egressgateway
istio: egressgateway
spec:
containers:
- name: istio-proxy
image: auto # The image will automatically update each time the pod starts.
resources:
limits:
cpu: 2000m
memory: 1024Mi
requests:
cpu: 100m
memory: 128Mi
# Allow binding to all ports (such as 80 and 443)
securityContext:
sysctls:
- name: net.ipv4.ip_unprivileged_port_start
value: "0"
serviceAccountName: istio-egressgateway
連線至 Cloud Service Mesh 端點時遭拒
您可能會間歇性地發生連線遭拒 (ECONNREFUSED
) 錯誤,導致叢集與端點 (例如 Memorystore Redis、Cloud SQL 或應用程式工作負載需要存取的任何外部服務) 之間的通訊中斷。
當應用程式工作負載的啟動速度比 istio-proxy (Envoy
) 容器快,並嘗試存取外部端點時,就可能發生這種情況。由於在這個階段 istio-init (initContainer
) 已執行,因此有 iptables 規則將所有外送流量重新導向至 Envoy
。由於 istio-proxy 尚未就緒,iptables 規則會將流量重新導向至尚未啟動的側邊代理程式,因此應用程式會收到 ECONNREFUSED
錯誤。
請按照下列步驟檢查是否為您遇到的錯誤:
使用下列篩選器檢查 Stackdriver 記錄,找出有問題的 Pod。
以下是常見的錯誤訊息示例:
Error: failed to create connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect: connection refused [ioredis] Unhandled error event: Error: connect ECONNREFUSED
搜尋問題發生的時間點。如果您使用的是舊版 Stackdriver,請使用
resource.type="container"
。resource.type="k8s_container" textPayload:"$ERROR_MESSAGE$"
展開最新的事件,取得 Pod 名稱,然後記下
resource.labels
底下的pod_name
。取得該 pod 中問題首次發生的時間:
resource.type="k8s_container" resource.labels.pod_name="$POD_NAME$"
輸出內容範例:
E 2020-03-31T10:41:15.552128897Z post-feature-service post-feature-service-v1-67d56cdd-g7fvb failed to create connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect: connection refused post-feature-service post-feature-service-v1-67d56cdd-g7fvb
請記下這個 Pod 第一次發生錯誤的時間戳記。
使用下列篩選器查看 Pod 啟動事件。
resource.type="k8s_container" resource.labels.pod_name="$POD_NAME$"
輸出內容範例:
I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Container image "docker.io/istio/proxyv2:1.3.3" already present on machine spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Created container spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Started container spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{APP-CONTAINER-NAME} Created container spec.containers{APP-CONTAINER-NAME} W 2020-03-31T10:41:17Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:26Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:28Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:31Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:58Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy}
請使用錯誤和 Istio-Proxy 啟動事件的時間戳記,確認錯誤是在
Envoy
未就緒時發生。如果錯誤發生在 istio-proxy 容器尚未就緒時,則會正常收到連線遭拒的錯誤。在上述範例中,Pod 會在
2020-03-31T10:41:15.552128897Z
一啟動就嘗試連線至 Redis,但在2020-03-31T10:41:58Z
時,istio-proxy 仍會失敗執行就緒性探查。即使 istio-proxy 容器先啟動,但在應用程式嘗試連線至外部端點之前,該容器可能無法及時就緒。
如果您遇到這個問題,請繼續執行下列疑難排解步驟。
在 Pod 層級加上註解。這項功能僅可在 Pod 層級使用,無法在全球層級使用。
annotations: proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
修改應用程式程式碼,讓程式碼在嘗試向外部服務提出任何其他要求前,先檢查
Envoy
是否已就緒。舉例來說,在應用程式啟動時,請啟動一個迴圈,向 istio-proxy 健康情況端點提出要求,並在取得 200 時才繼續執行。istio-proxy 健康狀態端點如下:http://localhost:15020/healthz/ready
Vault 和 Cloud Service Mesh 之間的 sidecar 注入作業發生競爭條件
使用 vault
管理密鑰時,vault
有時會在 istio
之前注入 sidecar,導致 Pod 卡在 Init
狀態。發生這種情況時,重新啟動任何部署作業或部署新部署作業後,建立的 Pod 就會卡在初始狀態。例如:
E 2020-03-31T10:41:15.552128897Z
post-feature-service post-feature-service-v1-67d56cdd-g7fvb failed to create
connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect:
connection refused post-feature-service post-feature-service-v1-67d56cdd-g7fvb
這個問題是由於競爭狀態造成,Istio 和 vault
都會注入 sidecar,而 Istio 必須是最後一個執行此操作的程式,istio
代理在初始化容器期間不會執行。istio
初始化容器會設定 iptables 規則,將所有流量重新導向至 Proxy。由於尚未執行,這些規則會重新導向至空白,進而封鎖所有流量。因此,初始化容器必須是最後一個,這樣 Proxy 才能在設定 iptables 規則後立即啟動及執行。很抱歉,順序並非確定性的,因此如果先注入 Istio,就會發生錯誤。
如要排解這個問題,請允許 vault
的 IP 位址,這樣傳送至 Vault IP 的流量就不會重新導向至尚未就緒的 Envoy Proxy,進而封鎖通訊。為此,您應新增名為 excludeOutboundIPRanges
的新註解。
對於代管的 Cloud Service Mesh,這項操作只能在 spec.template.metadata.annotations
下的部署或 Pod 層級執行,例如:
apiVersion: apps/v1
kind: Deployment
...
...
...
spec:
template:
metadata:
annotations:
traffic.sidecar.istio.io/excludeOutboundIPRanges:
針對叢集內的 Cloud Service Mesh,您可以選擇將其設為全域服務網格,並在 spec.values.global.proxy.excludeIPRanges
下使用 IstioOperator,例如:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
proxy:
excludeIPRanges: ""
新增註解後,請重新啟動工作負載。