내용으로 건너뛰기

Amazon EKS에서 Topology Aware Hints를 사용하려면 어떻게 해야 합니까?

4분 분량
0

Amazon Elastic Kubernetes Service(Amazon EKS) 클러스터에서 Topology Aware Hints(TAH)를 사용하고 싶습니다.

해결 방법

참고: TAH는 Amazon Elastic Compute Cloud(Amazon EC2) 스팟 인스턴스, 수평적 포드 오토 스케일링 또는 오토 스케일링이 활성화된 클러스터에 적합하지 않을 수 있습니다. 이러한 클러스터 구성을 사용하는 경우 Amazon EKS가 노드에 할당하는 CPU 코어에 비례하는 할당을 달성할 수 없습니다. 허용된 오버헤드 임계값을 초과했습니다. 또한 엔드포인트 재분배를 금지하는 포드 할당 제약 조건이 있는 경우 kube-proxy는 TAH를 사용하지 않습니다.

클러스터에 TAH 설정

사전 요구 사항:

  • Amazon EKS 클러스터 버전이 1.24 이상인지 확인합니다.
  • Amazon EKS 클러스터 및 노드 3개가 있는 관리형 노드 그룹을 설정합니다. 각 노드의 CPU 용량은 동일해야 하며 세 개의 가용 영역에 노드를 분산해야 합니다.

Amazon EKS에서 TAH를 사용하려면 다음 단계를 완료하십시오.

  1. 새 네임스페이스를 만듭니다.

    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

    참고: example-namespace를 사용자의 네임스페이스로 바꾸십시오.

  2. 샘플 배포를 만들려면 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: {}

    참고: example-deployment-name을 사용자의 배포 이름으로 바꾸고 example-namespace를 사용자의 네임스페이스 이름으로 바꾸십시오.

  3. 배포를 ClusterIP 서비스 유형으로 노출한 다음 service.kubernetes.io/topology-mode: auto를 주석으로 추가합니다.

    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

    참고: example-service-name을 사용자의 서비스 이름으로 바꾸고 example-namespace를 사용자의 네임스페이스 이름으로 바꾸십시오. 1.26 이하 버전에서는 service.kubernetes.io/topology-aware-hints: auto 주석을 대신 사용하십시오.

  4. 엔드포인트에 TAH가 채워지는지 확인하려면 다음 명령을 실행합니다.

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

    참고: example-namespace를 네임스페이스 이름으로 바꾸고 example-service-name을 서비스 이름으로 바꾸십시오.
    출력 예시:

    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. 트래픽이 동일한 가용 영역의 포드로 라우팅되는지 확인하려면 다음 명령을 실행하여 테스트 포드를 배포하십시오.

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

    참고: example-node-name을 사용자의 노드 이름으로 바꾸십시오.

  6. 다음 명령을 실행하여 테스트 포드가 연결되는 포드와 노드를 찾습니다.

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

    참고: example-namespace를 네임스페이스 이름으로 바꾸고 example-service-name을 서비스 이름으로 바꾸십시오.
    출력 예시:

    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. 위 출력의 PodNameNodeName을 사용하여 테스트 포드를 배포한 가용 영역과 트래픽이 일치하는지 확인합니다.

  8. 배포 규모를 복제본 4개로 조정한 후 다음 명령을 실행하여 EndpointSlices를 조사합니다.

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

    참고: example-namespace를 사용자의 네임스페이스 이름으로 바꾸고 example-deployment-name을 사용자의 배포 이름으로 바꾸십시오.

4개의 복제본으로 규모가 조정된 배포에서는 엔드포인트 비율이 50%인 가용 영역이 하나 이상 생성됩니다. 또한 오버헤드 임계값 20%가 초과되고 kube-proxy가 TAH를 사용하지 않습니다.

클러스터의 TAH 문제 해결

Amazon EKS에서 TAH를 사용할 때는 다음과 같은 오류가 나타날 수 있습니다.

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

이 문제가 발생한 이유는 노드에 레이블이 없거나 사용자 지정 도메인 이름을 사용하고 노드 IP 주소를 식별하지 않았기 때문일 수 있습니다.

이 문제를 해결하려면 다음 단계를 완료하십시오.

  1. 노드에 레이블이 있는지 확인하려면 다음 명령을 실행합니다.

    kubectl get nodes --show-labels |grep "topology.kubernetes.io/zone"
  2. Amazon EKS가 노드에 레이블을 지정한 경우 kube-proxy 로그를 확인하여 Amazon EKS가 노드 IP 주소를 올바르게 식별했는지 확인하십시오.

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

    참고: kube-proxy-pod-name을 kube-proxy 포드 이름으로 바꾸십시오.

사용자 지정 도메인 이름을 사용하는 경우 Amazon EKS가 노드 IP 주소를 올바르게 식별하지 못해 다음과 같은 오류가 발생할 수 있습니다.

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

--hostname-override는 EC2 DescribeInstances 호출이 반환하는 PrivateDnsName과 같아야 합니다.

가상 프라이빗 클라우드(VPC) DNS 및 DHCP(Dynamic Host Configuration Protocol) 옵션을 수정하려면 사용자 지정 도메인을 사용합니다. 다음 예에서는 수정된 호스트 이름을 사용합니다.

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

자세한 내용은 GitHub 웹 사이트의 bootstrap.sh를 참조하십시오.

관련 정보

Kubernetes 웹 사이트의 Topology Aware Routing

Topology Aware Hints가 Amazon Elastic Kubernetes Service의 네트워크 트래픽에 미치는 영향 살펴보기

AWS 공식업데이트됨 9달 전