Direkt zum Inhalt

Wie verwende ich Topology Aware Hints in Amazon EKS?

Lesedauer: 5 Minute
0

Ich möchte Topology Aware Hints (TAH) in meinem Amazon Elastic Kubernetes Service (Amazon EKS)-Cluster verwenden.

Behebung

Hinweis: TAH sind möglicherweise nicht für Cluster geeignet, bei denen Amazon Elastic Compute Cloud (Amazon EC2)-Spot-Instances, Horizontales Pod-Autoscaling oder Auto Scaling aktiviert sind. Wenn du diese Cluster-Konfigurationen verwendest, kannst du keine Zuweisung erreichen, die proportional zu den CPU-Kernen ist, die Amazon EKS den Knoten zuweist. Du überschreitest den zulässigen Overhead-Schwellenwert. Wenn es Einschränkungen bei der Pod-Zuweisung gibt, die die Neuverteilung von Endpunkten verbieten, verwendet kube-proxy außerdem kein TAH.

TAH in deinem Cluster einrichten

Voraussetzungen:

  • Stelle sicher, dass die Amazon EKS-Cluster-Version 1.24 oder höher ist.
  • Richte einen Amazon EKS-Cluster und eine verwaltete Knotengruppe mit drei Knoten ein. Jeder Knoten muss die gleiche CPU-Kapazität haben und du musst die Knoten auf drei Availability Zones verteilen.

Gehe wie folgt vor, um TAH in Amazon EKS zu verwenden:

  1. Erstelle einen neuen Namespace:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: "example-namespace"
      labels:
        pod-security.kubernetes.io/audit: restricted
        pod-security.kubernetes.io/enforce: restricted
        pod-security.kubernetes.io/warn: restricted

    Hinweis: Ersetze example-namespace durch deinen Namespace-Namen.

  2. Um eine Beispiel-Bereitstellung zu erstellen, verwende das Image BusyBox:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-deployment-name
      namespace: example-namespace
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: demo
      template:
        metadata:
          labels:
            app: demo
        spec:
          dnsPolicy: Default
          enableServiceLinks: false
          automountServiceAccountToken: false
          securityContext:
            seccompProfile:
              type: RuntimeDefault
            runAsNonRoot: true
            runAsUser: 1000
            runAsGroup: 1000
          containers:
            - name: busybox
              image: public.ecr.aws/docker/library/busybox:latest
              command: ["/bin/sh"]
              args:
                - "-c"
                - |
                  echo "<html><body><h1>PodName: $MY_POD_NAME  NodeName: $MY_NODE_NAME podIP:$MY_POD_IP</h1></body></html>" > /tmp/index.html;
                  while true; do
                    printf 'HTTP/1.1 200 OK\n\n%s\n' $(cat /tmp/index.html) | nc -l -p 8080
                  done
              ports:
                - containerPort: 8080
              env:
              - name: MY_NODE_NAME
                valueFrom:
                 fieldRef:
                  fieldPath: spec.nodeName
              - name: MY_POD_IP
                valueFrom:
                  fieldRef:
                    fieldPath: status.podIP
              - name: MY_POD_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
              resources:
                limits:
                  memory: "128Mi"
                  cpu: "500m"
                requests:
                  memory: "64Mi"
                  cpu: "250m"
              securityContext:
                readOnlyRootFilesystem: true
                allowPrivilegeEscalation: false
                capabilities:
                  drop:
                    - ALL
              volumeMounts:
              - name: tmp
                mountPath: /tmp
          volumes:
            - name: tmp
              emptyDir: {}

    Hinweis: Ersetze example-deployment-name durch den Bereitstellungsnamen und example-namespace durch deinen Namespace-Namen.

  3. Stelle die Bereitstellung als ClusterIP-Servicetyp bereit und füge dann service.kubernetes.io/topology-mode: auto als Annotation hinzu:

    apiVersion: v1
    kind: Service
    metadata:
      name: example-service-name
      namespace: example-namespace
      annotations:
       service.kubernetes.io/topology-mode: auto
    spec:
      selector:
        app: demo
      ports:
        - protocol: TCP
          port: 80
          targetPort: 8080

    Hinweis: Ersetze example-service-name durch den Service-Namen und example-namespace durch den Namespace-Namen. Für Version 1.26 oder früher verwende stattdessen die Annotation service.kubernetes.io/topology-aware-hints: auto.

  4. Um zu überprüfen, ob sich TAHs im Endpunkt befinden, führe den folgenden Befehl aus:

    kubectl get 'endpointslices.discovery.k8s.io' -l kubernetes.io/service-name=example-service-name -n example-namespace -o yaml

    Hinweis: Ersetze example-namespace durch deinen Namespace-Namen und example-service-name durch den Service-Namen.
    Beispielausgabe:

    endpoints:
    - addresses:
      - 10.0.21.125
      conditions:
        ready: true
        serving: true
        terminating: false
      hints:
        forZones:
        - name: eu-west-1b
      nodeName: ip-10-0-17-215.eu-west-1.compute.internal
      targetRef:
        kind: Pod
        name: example-deployment-name-5875bbbb7c-m2j8t
        namespace: example-namespace
        uid: 4e789648-965e-4caa-91db-bd27d240ea59
      zone: eu-west-1b
  5. Um zu überprüfen, ob der Traffic zu einem Pod in derselben Availability Zone geleitet wird, führe den folgenden Befehl aus, um einen Test-Pod bereitzustellen:

    kubectl run tmp-shell --rm -i --tty --image nicolaka/netshoot --overrides='{"spec": { "nodeSelector": {"kubernetes.io/hostname":"example-node-name"}}}'

    Hinweis: Ersetze example-node-name durch den Knotennamen.

  6. Führe den folgenden Befehl aus, um den Pod und den Knoten zu finden, mit denen sich dein Test-Pod verbindet:

    curl example-service-name.example-namespace:80

    Hinweis: Ersetze example-namespace durch deinen Namespace-Namen und example-service-name durch den Service-Namen.
    Beispielausgabe:

    PodName: 7b7b9bf455-c27z9  HTTP/1.1 200 OK
    NodeName: ip-10-0-9-45.eu-west-1.compute.internal
    HTTP/1.1 200 OK
    podIP: example-10.0.11.140
  7. Verwende PodName und NodeName aus der vorherigen Ausgabe, um zu überprüfen, ob der Traffic mit derselben Availability Zone übereinstimmt, in der du deinen Test-Pod bereitgestellt hast.

  8. Skaliere die Bereitstellung auf vier Replikate und führe dann den folgenden Befehl aus, um die EndpointSlices zu prüfen:

    kubectl -n example-namespace scale deployments example-deployment-name --replicas=4

    Hinweis: Ersetze example-namespace durch deinen Namespace-Namen und example-deployment-name durch den Bereitstellungsnamen.

Eine Bereitstellung, die du auf vier Replikate skaliert hast, führt dazu, dass mindestens eine Availability Zone ein Verhältnis von 50 % an Endpunkten hat. Außerdem überschreitest du den Overhead-Schwellenwert von 20 %, und kube-proxy verwendet keine TAHs.

TAH-Probleme in deinem Cluster beheben

Wenn du TAH in Amazon EKS verwendest, wird möglicherweise der folgende Fehler angezeigt:

„Skipping topology aware endpoint filtering since node is missing label“

Dieses Problem kann auftreten, weil deinem Knoten Bezeichnungen fehlen oder du einen benutzerdefinierten Domain-Namen verwendet hast und die Knoten-IP-Adresse nicht identifiziert wurde.

Gehe wie folgt vor, um dieses Problem zu beheben:

  1. Um zu überprüfen, ob die Bezeichnungen auf den Knoten vorhanden sind, führe den folgenden Befehl aus:

    kubectl get nodes --show-labels |grep "topology.kubernetes.io/zone"
  2. Wenn Amazon EKS die Knoten beschriftet hat, überprüfe die kube-proxy-Protokolle, um sicherzustellen, dass Amazon EKS die Knoten-IP-Adresse korrekt identifiziert hat:

    kubectl logs -n kube-system kube-proxy-pod-name | grep -i retrieved

    Hinweis: Ersetze kube-proxy-pod-name durch den Namen deines kube-proxy-Pods.

Wenn du einen benutzerdefinierten Domain-Namen verwendest, kann Amazon EKS deine Knoten-IP-Adresse möglicherweise nicht korrekt identifizieren und du erhältst den folgenden Fehler:

„I1215 12:24:22.082120 1 server_others.go:138] "Detected node IP" address="127.0.0.1"“

Der Parameter --hostname-override muss dem PrivateDnsName entsprechen, den ein DescribeInstances-Aufruf für EC2 zurückgibt.

Um die Virtual Private Cloud (VPC)-DNS- und Dynamic Host Configuration Protocol (DHCP)-Optionen zu ändern, verwende eine benutzerdefinierte Domain. Das folgende Beispiel verwendet einen geänderten Host-Namen:

kubectl edit ds -n kube-system kube-proxy

spec:
  template:
    spec:
      containers:
        - name: kube-proxy
          command:
            - kube-proxy
            - --hostname-override=$(NODE_NAME)
            - --v=6
            - --config=/var/lib/kube-proxy-config/config
          env:
            - name: NODE_NAME
              valueFrom:
                fieldRef:
                  apiVersion: v1
                  fieldPath: spec.nodeName

Weitere Informationen findest du unter bootstrap.sh auf der GitHub-Website.

Ähnliche Informationen

Topology Aware Routing auf der Kubernetes-Website

Untersuchung der Auswirkungen von Topology Aware Hints auf den Netzwerkverkehr in Amazon Elastic Kubernetes Service

AWS OFFICIALAktualisiert vor 9 Monaten