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

Bei der Kommunikation zwischen Ihren Clustern und Ihren Endpunkten können zeitweise Fehler aufgrund abgelehnter Verbindung (ECONNREFUSED) auftreten, z. B. Memorystore Redis, CloudSQL oder ein externer Dienst, den Ihre Anwendungsarbeitslast erreichen muss.

Dies kann vorkommen, wenn Ihre Anwendungsarbeitslast schneller als der Container "istio-proxy (Envoy)" initiiert wird und versucht, einen externen Endpunkt zu erreichen. Da istio-init (initContainer) in dieser Phase bereits ausgeführt wurde, gibt es iptables-Regeln, die den gesamten ausgehenden Traffic an Envoy weiterleiten. Da istio-proxy noch nicht bereit ist, leiten die iptables-Regeln den Traffic an einen Sidecar-Proxy um, der noch nicht gestartet wurde. Daher erhält die Anwendung den Fehler ECONNREFUSED.

In den folgenden Schritten wird beschrieben, wie Sie prüfen können, ob dieser Fehler auftritt:

  1. Prüfen Sie die Stackdriver-Logs 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 Fall, in dem das Problem aufgetreten ist. Wenn Sie Legacy-Stackdriver verwenden, verwenden Sie resource.type="container".

    resource.type="k8s_container"
    textPayload:"$ERROR_MESSAGE$"
    
  3. Maximieren Sie das letzte Vorkommen, um den Namen des Pods abzurufen, und notieren Sie sich dann 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. Verwenden Sie den folgenden Filter, um die Pod-Startereignisse zu 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. Verwenden Sie die Zeitstempel der Fehler und die istio-proxy-Startereignisse, um zu bestätigen, dass 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, Fehler aufgrund abgelehnter Verbindung abzurufen. Im vorherigen Beispiel hat der Pod versucht, sofort nach 2020-03-31T10:41:15.552128897Z eine Verbindung zu Redis herzustellen, aber istio-proxy 2020-03-31T10:41:58Z scheitert immer noch bei Bereitschaftsprüfungen.

    Obwohl der istio-proxy-Container zuerst gestartet wurde, war er möglicherweise nicht schnell genug bereit, bevor die Anwendung bereits versucht hat, eine Verbindung zum externen Endpunkt herzustellen.

    Wenn dies Ihr Problem ist, fahren Sie mit den folgenden Schritten zur Fehlerbehebung fort.

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

    annotations:
    proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
    
  9. Ändern Sie den Anwendungscode so, dass Envoy überprüft wird, bevor weitere Anfragen an externe Dienste gesendet werden. Initiieren Sie beispielsweise beim Start der Anwendung eine Schleife, die Anfragen an den Health-Endpunkt von istio-proxy stellt und erst dann fortgesetzt wird, wenn 200 empfangen wird. Der Health-Endpunkt istio-proxy:

    http://localhost:15020/healthz/ready
    

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

Wenn Sie vault für die Verwaltung von Secrets verwenden, wird mit vault manchmal Sidecar vor istio eingeschleust, wodurch Pods im Status Init hängen bleiben. In diesem Fall bleiben die erstellten Pods nach dem Neustart einer Bereitstellung oder Bereitstellung einer neuen im Init-Status hängen. 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 zuletzt tun. Der istio-Proxy wird während der Init-Container nicht ausgeführt. Der Init-Container istio richtet iptables-Regeln ein, um den gesamten Traffic an den Proxy weiterzuleiten. Da sie noch nicht ausgeführt wird, leiten diese Regeln in nichts weiter und blockieren den gesamten Traffic. Aus diesem Grund muss der Init-Container zuletzt sein, sodass der Proxy sofort nach Einrichtung der iptables-Regeln aktiv ist. Leider ist die Reihenfolge nicht deterministisch. Wenn Istio also zuerst injiziert wird, funktioniert es nicht mehr.

Erlauben Sie zur Fehlerbehebung die IP-Adresse von vault, damit der an die Vault-IP-Adresse gerichtete Traffic nicht an den noch nicht bereitstehenden Envoy-Proxy weitergeleitet wird und dadurch die Kommunikation blockiert wird. Dazu sollte eine neue Annotation mit dem Namen excludeOutboundIPRanges hinzugefügt werden.

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

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

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

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

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