Ir para o conteúdo

Como faço para usar Topology Aware Hints no Amazon EKS?

6 minuto de leitura
0

Quero usar Topology Aware Hints (TAH) no meu cluster do Amazon Elastic Kubernetes Service (Amazon EKS).

Resolução

Observação: o TAH pode não ser adequado para clusters que têm instâncias spot, ajuste de escala automático de pods horizontais ou ajuste de escala automático do Amazon Elastic Compute Cloud (Amazon EC2) ativados. Ao usar essas configurações de cluster, não é possível obter uma alocação proporcional aos núcleos de CPU que o Amazon EKS aloca a nós. Você excede o limite de sobrecarga permitido. Além disso, se houver restrições de atribuição de pod que proíbam a redistribuição de endpoints, o kube-proxy não usará o TAH.

Configurar o TAH no cluster

Pré-requisitos:

  • Certifique-se de que sua versão do cluster do Amazon EKS seja 1.24 ou posterior.
  • Configure um cluster do Amazon EKS e um grupo de nós gerenciados com três nós. Cada nó deve ter a mesma capacidade de CPU e você deve distribuir os nós em três zonas de disponibilidade.

Para usar o TAH no Amazon EKS, conclua as seguintes etapas:

  1. Crie um novo 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

    Observação: substitua example-namespace pelo seu nome do namespace.

  2. Use a imagem do BusyBox para criar uma implantação de amostra:

    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: {}

    Observação: substitua example-deployment-name pelo nome da implantação e example-namespace pelo nome do namespace.

  3. Exponha a implantação como um tipo de serviço ClusterIP e, em seguida, adicione service.kubernetes.io/topology-mode: auto como uma anotação:

    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

    Observação: substitua example-service-name pelo nome do seu serviço e example-namespace pelo nome do namespace. Para a versão 1.26 ou anterior, use a anotação service.kubernetes.io/topology-aware-hints: auto.

  4. Para verificar se os TAHs são preenchidos no endpoint, execute o seguinte comando:

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

    Observação: substitua example-namespace pelo seu nome do namespace e example-service-name pelo seu nome do serviço.
    Exemplo de saída:

    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 verificar se o tráfego é direcionado para um pod na mesma zona de disponibilidade, execute o seguinte comando para implantar um pod de teste:

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

    Observação: substitua example-node-name pelo nome do seu nó.

  6. Execute o comando a seguir para encontrar o pod e o nó aos quais seu pod de teste se conecta:

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

    Observação: substitua example-namespace pelo seu nome do namespace e example-service-name pelo seu nome do serviço.
    Exemplo de saída:

    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. Use PodName e NodeName da saída anterior para verificar se o tráfego está alinhado com a mesma zona de disponibilidade em que você implantou seu pod de teste.

  8. Escale a implantação para quatro réplicas e, em seguida, execute o seguinte comando para inspecionar os EndpointSlices:

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

    Observação: substitua example-namespace pelo nome do namespace e example-deployment-name pelo nome da implantação.

Uma implantação escalada para quatro réplicas resulta em pelo menos uma Zona de disponibilidade com uma proporção de 50% de endpoints. Além disso, você excede o limite de sobrecarga de 20% e o kube-proxy não usa TAHs.

Solucionar problemas de TAH no cluster

Ao usar o TAH no Amazon EKS, você pode ver o seguinte erro:

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

Você pode enfrentar esse problema porque seu nó não tem rótulos ou você usou um nome de domínio personalizado e não identificou o endereço IP do nó.

Para solucionar esse problema, conclua as etapas a seguir:

  1. Para verificar se os rótulos estão presentes nos nós, execute o seguinte comando:

    kubectl get nodes --show-labels |grep "topology.kubernetes.io/zone"
  2. Se o Amazon EKS tiver rotulado os nós, verifique os logs do kube-proxy para confirmar se o Amazon EKS identificou corretamente o endereço IP do nó:

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

    Observação: substitua kube-proxy-pod-name pelo nome do pod kube-proxy.

Se você usar um nome de domínio personalizado, o Amazon EKS pode não identificar corretamente o endereço IP do seu nó e você receberá o seguinte erro:

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

O --hostname-override deve ser igual a PrivateDnsName que uma chamada EC2 DescribeInstances retorna.

Para modificar as opções de DNS e DHCP (Protocolo de Configuração Dinâmica de Host) de uma nuvem privada virtual (VPC), use um domínio personalizado. O exemplo a seguir usa um nome 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 mais informações, consulte bootstrap.sh no site do GitHub.

Informações relacionadas

Topology Aware Routing no site do Kubernetes

Exploring the effect of Topology Aware Hints on network traffic in Amazon Elastic Kubernetes Service (Explorando o efeito do Topology Aware Hints no tráfego de rede no Amazon Elastic Kubernetes Service)

AWS OFICIALAtualizada há 7 meses