Saltar al contenido

¿Cómo utilizo Topology Aware Hints en Amazon EKS?

6 minutos de lectura
0

Quiero usar Topology Aware Hints (TAH) en mi clúster de Amazon Elastic Kubernetes Service (Amazon EKS).

Solución

Nota: Es posible que el TAH no sea adecuado para clústeres que tienen activadas instancias puntuales de Amazon Elastic Compute Cloud (Amazon EC2), el escalamiento automático de pods horizontales o el escalamiento automático. Cuando usa estas configuraciones de clúster, no puedes obtener una asignación que sea proporcional a los núcleos de CPU que Amazon EKS asigna a los nodos. Superas el umbral de sobrecarga permitido. Además, si hay restricciones de asignación de pods que prohíben la redistribución de puntos de enlace, kube-proxy no usa TAH.

Configuración de TAH en tu clúster

Requisitos previos:

Para usar TAH en Amazon EKS, sigue estos pasos:

  1. Crea un nuevo espacio de nombres:

    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: Sustituye example-namespace por el nombre del espacio de nombres.

  2. Usa la imagen de BusyBox para crear un despliegue de muestra:

    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: Sustituye example-deployment-name por el nombre de tu implementación y example-namespace por el nombre de tu espacio de nombres.

  3. Expón el despliegue como un tipo de servicio ClusterIP y, a continuación, agrega service.kubernetes.io/topology-mode: auto como anotación:

    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: Sustituye example-service-name por el nombre de tu servicio y example-namespace por el nombre de tu espacio de nombres. Para la versión 1.26 o anterior, usa la anotación automática service.kubernetes.io/topology-aware-hints: auto en su lugar.

  4. Para comprobar si los TAH se rellenan en el punto final, ejecuta el siguiente comando:

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

    Nota: Sustituye example-namespace por el nombre de tu espacio de nombres y example-service-name por el nombre de tu servicio.
    Resultado de ejemplo:

    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. Para comprobar si el tráfico se dirige a un pod en la misma zona de disponibilidad, ejecuta el siguiente comando para desplegar un pod de prueba:

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

    Nota: Sustituye example-node-name por el nombre de tu nodo.

  6. Ejecuta el siguiente comando para buscar el pod y el nodo al que se conecta el pod de prueba:

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

    Nota: Sustituye example-namespace por el nombre de tu espacio de nombres y example-service-name por el nombre de tu servicio.
    Resultado de ejemplo:

    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. Usa PodName y NodeName del resultado anterior para comprobar si el tráfico se alinea con la misma zona de disponibilidad en la que desplegaste el pod de prueba.

  8. Escala el despliegue a cuatro réplicas y, a continuación, ejecuta el siguiente comando para inspeccionar los valores EndpointSlices:

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

    Nota: Sustituye example-namespace por el nombre de tu espacio de nombres y example-deployment-name por el nombre de tu despliegue.

Un despliegue que se escala a cuatro réplicas da como resultado al menos una zona de disponibilidad con una proporción del 50 % de puntos de enlace. Además, superas el umbral de gastos generales del 20 % y kube-proxy no usa TAH.

Solución de problemas de TAH en el clúster

Al usar TAH en Amazon EKS, es posible que aparezca el siguiente error:

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

Es posible que experimentes este problema porque a tu nodo le faltan etiquetas o porque usaste un nombre de dominio personalizado y no identificaste la dirección IP del nodo.

Para resolver este problema, sigue estos pasos:

  1. Para comprobar que las etiquetas están presentes en los nodos, ejecuta el siguiente comando:

    kubectl get nodes --show-labels |grep "topology.kubernetes.io/zone"
  2. Si Amazon EKS etiquetó los nodos, comprueba los registros de kube-proxy para confirmar que Amazon EKS identificó correctamente la dirección IP del nodo:

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

    Nota: Sustituye kube-proxy-pod-name por el nombre de tu pod kube-proxy.

Si utilizas un nombre de dominio personalizado, es posible que Amazon EKS no identifique correctamente la dirección IP de tu nodo y veas el siguiente error:

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

El valor **--hostname-override ** debe ser igual al de PrivateDnsName que devuelve una llamada DescribeInstances de EC2.

Para modificar las opciones de DNS y el protocolo de configuración dinámica de host (DHCP) de una nube virtual privada (VPC), usa un dominio personalizado. El siguiente ejemplo usa un nombre de host modificado:

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

Para obtener más información, consulta bootstrap.sh en el sitio web de GitHub.

Información relacionada

Topology Aware Routing (Enrutamiento con reconocimiento de topología) en el sitio web de Kubernetes

Exploring the effect of Topology Aware Hints on network traffic in Amazon Elastic Kubernetes Service (Análisis del efecto de Topology Aware Hints en el tráfico de red en Amazon Elastic Kubernetes Service)

OFICIAL DE AWSActualizada hace 6 meses