Probleme beim Starten von Arbeitslasten in Cloud Service Mesh beheben

In diesem Dokument werden häufig auftretende Probleme bei Cloud Service Mesh und deren Behebung beschrieben. Weitere Informationen finden Sie unter Support.

Gateway kann mit einem Distroless-Proxy nicht gestartet werden, wenn ein privilegierter Port verfügbar gemacht wird

Standardmäßig wird der Distroless-Proxy mit Nicht-Root-Berechtigungen gestartet, was in einigen Fällen zu Bindefehlern an privilegierten Ports führen kann. Wenn beim Starten des Proxys Fehler wie die folgenden auftreten, muss für die Gateway-Bereitstellung ein zusätzliches `securityContext` angewendet werden.

  Error adding/updating listener(s) 0.0.0.0_80: cannot bind '0.0.0.0:80': Permission denied

Das folgende Beispiel zeigt das YAML für eine Egress-Gateway-Bereitstellung:

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 

Verbindung abgelehnt beim Erreichen eines Cloud Service Mesh-Endpunkts

Es kann vorkommen, dass bei der Kommunikation von Ihren Clustern zu Ihren Endpunkten zeitweise Fehler vom Typ „Verbindung abgelehnt“ (ECONNREFUSED) auftreten, z. B. bei Memorystore Redis, Cloud SQL oder einem externen Dienst, den Ihre Anwendungslast erreichen muss.

Dies kann passieren, wenn Ihre Anwendungslast schneller als der istio-proxy (Envoy)-Container gestartet wird und versucht, einen externen Endpunkt zu erreichen. Da istio-init (initContainer) in dieser Phase bereits ausgeführt wurde, sind iptables-Regeln vorhanden, 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 weiter, der noch nicht gestartet wurde. Daher erhält die Anwendung den Fehler ECONNREFUSED.

In den folgenden Schritten wird beschrieben, wie Sie prüfen, ob dies der Fehler ist, der bei Ihnen auftritt:

  1. Prüfen Sie die Stackdriver-Logs mit dem folgenden Filter, um herauszufinden, 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 Vorkommen des Problems. 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 zu erhalten, und notieren Sie sich dann pod_name unter resource.labels.

  4. Rufen Sie das erste Vorkommen des Problems für diesen Pod ab:

    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-Start-Ereignisse aufzurufen.

    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 istio-proxy-Start-Ereignisse, 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, dass Fehler vom Typ „Verbindung abgelehnt“ auftreten. Im vorherigen Beispiel hat der Pod versucht, eine Verbindung zu Redis herzustellen, sobald 2020-03-31T10:41:15.552128897Z erreicht wurde. Bis 2020-03-31T10:41:58Z sind die Bereitschaftstests für istio-proxy jedoch weiterhin fehlgeschlagen.

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

    Wenn dies das Problem ist, das bei Ihnen auftritt, fahren Sie mit den folgenden Schritten zur Fehlerbehebung fort.

  8. Annotieren Sie die Konfiguration auf Pod-Ebene. Dies ist nur auf Pod-Ebene und nicht auf globaler Ebene möglich.

    annotations:
    proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
    
  9. Ändern Sie den Anwendungscode so, dass geprüft wird, ob Envoy bereit ist, bevor andere Anfragen an externe Dienste gesendet werden. Starten Sie beispielsweise beim Start der Anwendung eine Schleife, die Anfragen an den Systemdiagnoseendpunkt von istio-proxy sendet und erst fortgesetzt wird, wenn der Code 200 zurückgegeben wird. Der Systemdiagnoseendpunkt von istio-proxy ist:

    http://localhost:15020/healthz/ready
    

Race-Bedingung bei der Sidecar-Einfügung zwischen Vault und Cloud Service Mesh

Wenn Sie vault für die Verwaltung von Secrets verwenden, fügt vault manchmal den Sidecar vor istio ein, wodurch Pods im Status Init hängen bleiben. In diesem Fall bleiben die erstellten Pods nach dem Neustart einer Bereitstellung oder der Bereitstellung einer neuen Bereitstellung im Status „Init“ 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. Istio muss dies als Letztes tun. Der istio-Proxy wird während der Init-Container nicht ausgeführt. Der istio-Init-Container richtet iptables-Regeln ein, um den gesamten Traffic an den Proxy weiterzuleiten. Da er noch nicht ausgeführt wird, leiten diese Regeln den Traffic an nichts weiter und blockieren so den gesamten Traffic. Aus diesem Grund muss der Init-Container als Letztes ausgeführt werden, damit der Proxy sofort nach dem Einrichten der iptables-Regeln ausgeführt wird. Leider ist die Reihenfolge nicht deterministisch. Wenn Istio zuerst eingefügt wird, funktioniert es nicht.

Um dieses Problem zu beheben, lassen Sie die IP-Adresse von vault zu, damit der Traffic zur Vault-IP nicht an den Envoy-Proxy weitergeleitet wird, der noch nicht bereit ist und daher die Kommunikation blockiert. Dazu muss eine neue Annotation mit dem Namen excludeOutboundIPRanges hinzugefügt werden.

Bei verwaltetem Cloud Service Mesh ist dies nur auf Bereitstellungs- oder Pod-Ebene unter spec.template.metadata.annotations möglich, z. B.:

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

Bei clusterinternem Cloud Service Mesh besteht die Möglichkeit, es mit einem IstioOperator unter spec.values.global.proxy.excludeIPRanges als global festzulegen, z. B.:

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

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

Proxy-Image-Typ im Cluster ermitteln

Um zu ermitteln, welchen Proxy-Image-Typ (default oder distroless) ein bestimmter Pod verwendet, können Sie die Pod-Spezifikation prüfen.

Führen Sie den folgenden Befehl aus, um das vom istio-proxy-Container verwendete Image zu prüfen:

kubectl get pod POD_NAME -n NAMESPACE -o jsonpath='{.spec.containers[?(@.name=="istio-proxy")].image}'
  • Wenn der Image-Pfad im Tag oder Suffix nicht -distroless enthält, wird das default -Image verwendet.
  • Wenn der Image-Pfad im Tag oder Suffix -distroless enthält, wird das distroless -Image verwendet.

Konfigurationsabsicht prüfen

Der Image-Typ kann auf zwei Arten konfiguriert werden (die Annotation hat Vorrang vor MeshConfig):

  1. Pod-Annotation: Prüfen Sie, ob der Pod die sidecar.istio.io/proxyImageType Annotation hat.

    kubectl get pod POD_NAME -n NAMESPACE -o jsonpath='{.metadata.annotations["sidecar.istio.io/proxyImageType"]}'
    
  2. MeshConfig: Prüfen Sie die Einstellung defaultConfig.image.imageType in der istio-RELEASE_CHANNEL-ConfigMap im Namespace istio-system.

Hinweis: Für Cluster mit der verwalteten TRAFFIC_DIRECTOR Steuerungsebene:

  • Für Cluster, die direkt mit einer verwalteten TRAFFIC_DIRECTOR-Steuerungsebene bereitgestellt wurden, werden nur distroless-Images unterstützt. Überschreibungen anderer Image-Typen werden ignoriert.
  • Für Cluster, die zur TRAFFIC_DIRECTOR-Steuerungsebene migriert wurden (z. B. Cluster, die von CSM-ISTIOD migriert wurden), ist der Image-Typ standardmäßig das default-Image. Sie können jedoch distroless mit MeshConfig oder einer Pod-Annotation aktivieren. Überschreibungen anderer Image-Typen (z. B. debug) werden nicht unterstützt.