Passer au contenu

Comment utiliser Topology Aware Hints dans Amazon EKS ?

Lecture de 6 minute(s)
0

Je souhaite utiliser Topology Aware Hints (TAH) dans mon cluster Amazon Elastic Kubernetes Service (Amazon EKS).

Résolution

Remarque : TAH peut ne pas convenir aux clusters sur lesquels les instances Spot Amazon Elastic Compute Cloud (Amazon EC2), l’autoscaling horizontal du pod ou l’autoscaling sont activés. Lorsque vous utilisez ces configurations de cluster, vous ne pouvez pas obtenir une allocation proportionnelle aux cœurs de processeur alloués par Amazon EKS aux nœuds. Vous dépassez le seuil de frais généraux autorisé. De plus, s'il existe des contraintes d'attribution de pods qui interdisent la redistribution des points de terminaison, kube-proxy n'utilise pas TAH.

Configurer TAH dans le cluster

Prérequis :

  • assurez-vous que la version du cluster Amazon EKS est 1.24 ou ultérieure.
  • Configurez un cluster Amazon EKS et un groupe de nœuds géré avec trois nœuds. Chaque nœud doit avoir la même capacité de processeur et vous devez répartir les nœuds dans trois zones de disponibilité.

Pour utiliser TAH dans Amazon EKS, procédez comme suit :

  1. Créez un nouvel espace de noms :

    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

    Remarque : remplacez example-namespace par le nom de l’espace de noms.

  2. Pour créer un exemple de déploiement, utilisez l'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: {}

    Remarque : remplacez example-deployment-name par le nom du déploiement et example-namespace par le nom de l’espace de noms.

  3. Exposez le déploiement en tant que type de service ClusterIP, puis ajoutez service.kubernetes.io/topology-mode: auto en tant qu'annotation :

    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

    Remarque : remplacez example-service-name par le nom de votre service et example-namespace par le nom de votre espace de noms. Pour la version 1.26 ou antérieure, utilisez plutôt l'annotation service.kubernetes.io/topology-aware-hints: auto.

  4. Pour vérifier si les TAH sont renseignés dans le point de terminaison, exécutez la commande suivante :

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

    Remarque : remplacez example-namespace par le nom de votre espace de noms et example-service-name par le nom de votre service.
    Exemple de sortie :

    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. Pour vérifier si le trafic est acheminé vers un espace situé dans la même zone de disponibilité, exécutez la commande suivante pour déployer un pod de test :

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

    Remarque : remplacez example-node-name par le nom de votre nœud.

  6. Exécutez la commande suivante pour rechercher le pod et le nœud auxquels votre pod de test se connecte :

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

    Remarque : remplacez example-namespace par le nom de votre espace de noms et example-service-name par le nom de votre service.
    Exemple de sortie :

    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. utilisez PodName et NodeName de la sortie précédente pour vérifier si le trafic s'aligne sur la même zone de disponibilité que celle dans laquelle vous avez déployé le pod de test.

  8. Mettez à l’échelle le déploiement vers quatre réplicas, puis exécutez la commande suivante pour inspecter les EndpointSlices :

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

    Remarque : remplacez example-namespace par le nom de votre espace de noms et example-deployment-name par le nom de votre déploiement.

Un déploiement mis à l’échelle vers quatre réplicas entraîne la création d'au moins une zone de disponibilité présentant un ratio de points de terminaison de 50 %. De plus, vous dépassez le seuil de surcharge de 20 % et kube-proxy n'utilise pas les TAH.

Résoudre les problèmes de TAH dans le cluster

Lorsque vous utilisez TAH dans Amazon EKS, l'erreur suivante peut s'afficher :

« Skipping topology aware endpoint filtering since node is missing label »

Ce problème peut survenir car des étiquettes sont manquantes dans le nœud ou vous avez utilisé un nom de domaine personnalisé et n'avez pas identifié l'adresse IP du nœud.

Afin de résoudre ce problème, procédez comme suit :

  1. Pour vérifier que les étiquettes sont présentes sur les nœuds, exécutez la commande suivante :

    kubectl get nodes --show-labels |grep "topology.kubernetes.io/zone"
  2. Si Amazon EKS a libellé les nœuds, consultez les journaux de kube-proxy pour vous assurer qu'Amazon EKS a correctement identifié l'adresse IP du nœud :

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

    Remarque : remplacez kube-proxy-pod-name par le nom du pod kube-proxy.

Si vous utilisez un nom de domaine personnalisé, il se peut qu’Amazon EKS n’identifie pas correctement l'adresse IP du nœud et l'erreur suivante s'affiche :

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

Le --hostname-override doit être égal au PrivateDnsName renvoyé par un appel DescribeInstances.

Pour modifier les options DNS et DHCP (Dynamic Host Configuration Protocol) d'un cloud privé virtuel (VPC), utilisez un domaine personnalisé. L'exemple suivant utilise un nom d'hôte modifié :

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

Pour plus d'informations, consultez la page bootstrap.sh sur le site Web de GitHub.

Informations connexes

Routage tenant compte de la topologie sur le site Web de Kubernetes

Exploration de l'effet des conseils tenant compte de la topologie sur le trafic réseau dans Amazon Elastic Kubernetes Service

AWS OFFICIELA mis à jour il y a 6 mois