Proxyprobleme in Cloud Service Mesh beheben

In diesem Dokument werden häufige Cloud Service Mesh-Probleme und deren Behebung erläutert. Weitere Informationen finden Sie unter Support.

Beim Erreichen eines Endpunkts mit Istio wurde die Verbindung abgelehnt

Gelegentlich treten bei der Kommunikation von Ihren Clustern zu Ihren Endpunkten Fehler vom Typ „Verbindung abgelehnt“ (ECONNREFUSED) auf, z. B. bei Memorystore Redis, CloudSQL oder einem externen Dienst, den Ihre Anwendungslast erreichen muss.

Dies kann auftreten, wenn Ihre Anwendungsarbeitslast schneller gestartet wird als istio-proxy (Envoy) und versucht, einen externen Endpunkt zu erreichen. Weil istio-init (initContainer) bereits ausgeführt, sind iptables-Regeln eingerichtet haben, die den gesamten ausgehenden Traffic an Envoy weiterleiten. Da der Istio-Proxy noch nicht bereit ist, wird der Traffic von den Iptables-Regeln an einen Sidecar-Proxy weitergeleitet, der noch nicht gestartet wurde. Daher erhält die Anwendung den Fehler ECONNREFUSED.

So prüfen Sie, ob dieser Fehler vorliegt:

  1. Prüfen Sie die Stackdriver-Protokolle mit dem folgenden Filter, um zu ermitteln, bei welchen Pods das Problem aufgetreten ist.

    Das folgende Beispiel zeigt eine typische Fehlermeldung:

    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
    
  2. Suchen Sie nach einem Auftreten des Problems. Wenn Sie Legacy-Stackdriver verwenden, Verwenden Sie dann resource.type="container".

    resource.type="k8s_container"
    textPayload:"$ERROR_MESSAGE$"
    
  3. Maximieren Sie das letzte Vorkommen, um den Namen des Pods zu erhalten, und notieren Sie sich der pod_name unter resource.labels.

  4. Ermitteln, wann das Problem zum ersten Mal für diesen Pod aufgetreten ist:

    resource.type="k8s_container"
    resource.labels.pod_name="$POD_NAME$"
    

    Beispielausgabe:

    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
    
  5. Notieren Sie sich den Zeitstempel des ersten Fehlers für diesen Pod.

  6. Mit dem folgenden Filter können Sie die Pod-Startereignisse sehen.

    resource.type="k8s_container"
    resource.labels.pod_name="$POD_NAME$"
    

    Beispielausgabe:

    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}
    
  7. Anhand der Zeitstempel der Fehler und der Istio-Proxy-Startereignisse können Sie prüfen, ob die Fehler auftreten, wenn Envoy nicht bereit ist.

    Wenn die Fehler auftreten, während der Istio-Proxy-Container noch nicht bereit ist, ist es normal, dass Fehlermeldungen zur Verbindungsverweigerung angezeigt werden. Im vorherigen Beispiel hat der Pod bereits ab 2020-03-31T10:41:15.552128897Z versucht, eine Verbindung zu Redis herzustellen. Bis zum 2020-03-31T10:41:58Z hat der Istio-Proxy jedoch weiterhin keine Bereitschaftstests bestanden.

    Obwohl der istio-proxy-Container zuerst gestartet wurde, ist es möglich, dass er war nicht schnell genug bereit, bevor die App bereits versuchte, eine Verbindung herzustellen an den externen Endpunkt.

    Wenn das bei dir der Fall ist, fahre mit den folgenden Schritten zur Fehlerbehebung fort.

  8. Annotieren Sie die Konfiguration auf Pod-Ebene. Dies ist nur im Pod verfügbar und nicht auf globaler Ebene.

    annotations:
    proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
    
  9. Ändern Sie den Anwendungscode so, dass geprüft wird, ob Envoy bereit ist, bevor weitere Anfragen an externe Dienste gesendet werden. Sie können beispielsweise beim Starten der Anwendung eine Schleife starten, die Anfragen an den Istio-Proxy-Systemdiagnoseendpunkt sendet und erst fortgesetzt wird, wenn der Statuscode 200 zurückgegeben wird. Der Endpunkt „health“ des Istio-Proxys lautet:

    http://localhost:15020/healthz/ready
    

Race-Bedingung während der Sidecar-Einschleusung zwischen Vault und Istio

Bei Verwendung von vault für die Verwaltung von Secrets wird manchmal durch vault eine Sidecar-Datei eingeschleust vor istio, wodurch Pods im Status Init hängen bleiben. In diesem Fall Die erstellten Pods bleiben nach dem Neustart einer Bereitstellung oder die Bereitstellung einer neuen. Beispiel:

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

Dieses Problem wird durch eine Race-Bedingung verursacht. Sowohl Istio als auch vault fügen den Sidecar ein und Istio muss dies als Letztes tun. Der istio-Proxy wird während der Initialisierung von Containern nicht ausgeführt. Der Init-Container istio richtet iptables-Regeln ein, um den gesamten Traffic an den Proxy weiterleiten. Da sie noch nicht ausgeführt wird, und alle Zugriffe werden blockiert. Deshalb muss der Init-Container als letzter ausgeführt werden, damit der Proxy sofort nach der Einrichtung der iptables-Regeln einsatzbereit ist. Leider ist die Reihenfolge nicht deterministisch. Wenn also Istio injiziert wird, aber zuerst geht es kaputt.

Um dieses Problem zu beheben, erlauben Sie die IP-Adresse von vault, damit der Traffic, der an die Vault-IP-Adresse gesendet wird, nicht an den Envoy-Proxy weitergeleitet wird, der noch nicht bereit ist und daher die Kommunikation blockiert. Um dies zu erreichen, wird eine neue Anmerkung namens excludeOutboundIPRanges hinzugefügt werden.

Beim verwalteten Cloud Service Mesh ist dies nur auf Bereitstellungs- oder Pod-Ebene möglich unter spec.template.metadata.annotations, zum Beispiel:

apiVersion: apps/v1
kind: Deployment
...
...
...
spec:
  template:
    metadata:
      annotations:
        traffic.sidecar.istio.io/excludeOutboundIPRanges:

Für clusterinternes Cloud Service Mesh gibt es eine Option, um es als globales Service Mesh festzulegen mit Einen IstioOperator unter spec.values.global.proxy.excludeIPRanges. Beispiel:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  values:
    global:
      proxy:
        excludeIPRanges: ""

Starten Sie Ihre Arbeitslasten nach dem Hinzufügen der Annotation neu.