Salta al contenuto

Come posso utilizzare Topology Aware Hints in Amazon EKS?

5 minuti di lettura
0

Desidero utilizzare Topology Aware Hints (TAH) nel mio cluster Amazon Elastic Kubernetes Service (Amazon EKS).

Risoluzione

Nota: TAH potrebbe non essere adatto per i cluster con istanze spot Amazon Elastic Compute Cloud (Amazon EC2), il dimensionamento automatico orizzontale dei pod o il dimensionamento automatico attivati. Quando utilizzi queste configurazioni del cluster, non puoi ottenere un'allocazione proporzionale ai core della CPU che Amazon EKS alloca ai nodi. Superi la soglia massima consentita. Inoltre, se sono presenti vincoli di assegnazione dei pod che vietano la ridistribuzione degli endpoint, kube-proxy non utilizza TAH.

Configura TAH nel cluster

Prerequisiti:

  • Assicurati che la versione del cluster Amazon EKS sia 1.24 o successiva.
  • Configura un cluster Amazon EKS e un gruppo di nodi gestiti con tre nodi. Ogni nodo deve avere la stessa capacità in termini di CPU ed devi distribuire i nodi su tre zone di disponibilità.

Per utilizzare TAH in Amazon EKS, completa i seguenti passaggi:

  1. Crea un nuovo 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

    Nota: sostituisci example-namespace con il nome del tuo namespace.

  2. Per creare un esempio di distribuzione, utilizza l'immagine 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: {}

    Nota: sostituisci example-deployment-name con il nome della tua distribuzione e example-namespace xon il nome del tuo namespace.

  3. Esponi la distribuzione come tipo di servizio ClusterIP, quindi aggiungi service.kubernetes.io/topology-mode: auto come annotazione:

    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

    Nota: sostituisci example-service-name con il nome del tuo servizio e example-namespace con il nome del tuo namespace. Per la versione 1.26 o precedente, utilizza l'annotazione service.kubernetes.io/topology-aware-hints: auto.

  4. Per verificare se i TAH sono presenti nell'endpoint, esegui questo comando:

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

    Nota: sostituisci example-namespace con il nome del tuo namespace e example-service-name con il tuo nome del servizio.
    Esempio di output:

    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. Per verificare se il traffico viene indirizzato a un pod nella stessa zona di disponibilità, esegui questo comando per distribuire un pod di prova:

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

    Nota: sostituisci example-node-name con il nome del tuo nodo.

  6. Esegui questo comando per trovare il pod e il nodo a cui si connette il pod di prova:

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

    Nota: sostituisci example-namespace con il nome del tuo namespace e example-service-name con il tuo nome del servizio.
    Esempio di output:

    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. Utilizza PodName e NodeName dell'output precedente per verificare se il traffico è in linea con la stessa zona di disponibilità in cui hai distribuito il pod di prova.

  8. Scala la distribuzione a quattro repliche, quindi esegui questo comando per ispezionare gli EndpointSlices:

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

    Nota: sostituisci example-namespace con il nome del tuo namespace e example-deployment-name con il nome della tua distribuzione.

Una distribuzione scalata a quattro repliche produce almeno una zona di disponibilità con un rapporto di endpoint del 50%. Inoltre, superi la soglia di sovraccarico del 20% e kube-proxy non utilizza i TAH.

Risolvi i problemi relativi ai TAH nel cluster

Quando utilizzi TAH in Amazon EKS, potresti visualizzare il seguente errore:

"Skipping topology aware endpoint filtering since node is missing label"

Potresti riscontrare questo problema perché al nodo mancano le etichette o hai utilizzato un nome di dominio personalizzato e non hai identificato l'indirizzo IP del nodo.

Per risolverlo, completa i seguenti passaggi:

  1. Per verificare che nei nodi siano presenti le etichette, esegui questo comando:

    kubectl get nodes --show-labels |grep "topology.kubernetes.io/zone"
  2. Se Amazon EKS ha etichettato i nodi, controlla i log di kube-proxy per verificare che Amazon EKS abbia identificato correttamente l'indirizzo IP del nodo:

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

    Nota: sostituisci kube-proxy-pod-name con il nome del tuo pod kube-proxy.

Se utilizzi un nome di dominio personalizzato, Amazon EKS potrebbe non identificare correttamente l'indirizzo IP del nodo e ricevi il seguente errore:

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

Il valore --hostname-override deve essere uguale al valore PrivateDnsName restituito da una chiamata EC2 DescribeInstances.

Per modificare le opzioni DNS e DHCP (Dynamic Host Configuration Protocol) di un cloud privato virtuale (VPC), utilizza un dominio personalizzato. L'esempio seguente utilizza un nome host modificato:

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

Per ulteriori informazioni, consulta bootstrap.sh sul sito web GitHub.

Informazioni correlate

Topology Aware Routing sul sito web Kubernetes

Exploring the effect of Topology Aware Hints on network traffic in Amazon Elastic Kubernetes Service (Esplorazione dell'effetto dei Topology Aware Hints sul traffico di rete in Amazon Elastic Kubernetes Service)

AWS UFFICIALEAggiornata 5 mesi fa