애플리케이션을 새 노드 그룹으로 마이그레이션 - Amazon EKS

애플리케이션을 새 노드 그룹으로 마이그레이션

이 주제에서는 새로운 노드 그룹을 생성하고, 기존 애플리케이션을 새 그룹으로 안정적으로 마이그레이션한 다음, 이전 노드 그룹을 클러스터에서 제거하는 방법을 설명합니다. eksctl 또는 AWS Management Console을 사용하여 새 노드 그룹으로 마이그레이션할 수 있습니다.

eksctl

eksctl을 사용하여 애플리케이션을 새 노드 그룹으로 마이그레이션하려면

마이그레이션에 eksctl을 사용하는 방법에 대한 자세한 내용은 eksctl 설명서의 비관리형 노드 그룹을 참조하세요.

이 절차에는 eksctl 버전 0.194.0 이상이 필요합니다. 버전은 다음 명령을 통해 확인할 수 있습니다.

eksctl version

eksctl 설치 또는 업데이트에 대한 지침은 eksctl 설명서에서 Installation을 참조하세요.

참고

이 절차는 eksctl을 사용하여 생성한 클러스터 및 노드 그룹에 대해서만 사용할 수 있습니다.

  1. my-cluster를 클러스터 이름으로 바꿔서 기존 노드 그룹의 이름을 검색합니다.

    eksctl get nodegroups --cluster=my-cluster

    예제 출력은 다음과 같습니다.

    CLUSTER NODEGROUP CREATED MIN SIZE MAX SIZE DESIRED CAPACITY INSTANCE TYPE IMAGE ID default standard-nodes 2019-05-01T22:26:58Z 1 4 3 t3.medium ami-05a71d034119ffc12
  2. 다음 명령어로 eksctl을 사용하여 새 노드 그룹을 시작합니다. 명령에서 모든 예제 값을 고유한 값으로 바꿉니다. 버전 번호는 컨트롤 플레인의 Kubernetes 버전보다 이후일 수 없습니다. 또한 컨트롤 플레인의 Kubernetes 버전보다 이전인 마이너 버전이 2개를 초과할 수 없습니다. 컨트롤 플레인과 동일한 버전을 사용하는 것이 좋습니다.

    다음과 같은 조건에 해당하면 IMDS에 대한 Pod 액세스를 차단하는 것이 좋습니다.

    • Pods에 필요한 최소 권한만 있도록 모든 Kubernetes 서비스 계정에 IAM 역할을 할당할 계획입니다.

    • 클러스터의 어떤 Pods도 현재 AWS 리전 검색과 같은 다른 이유로 Amazon EC2 인스턴스 메타데이터 서비스(IMDS)에 액세스할 필요가 없습니다.

      자세한 내용은 작업자 노드에 할당된 인스턴스 프로파일에 대한 액세스 제한 부분을 참조하세요.

      Pod가 IMDS에 액세스하지 못하게 차단하려면 --disable-pod-imds 옵션을 다음 명령에 추가합니다.

      참고

      사용 가능한 플래그 및 설명에 대한 자세한 내용은 https://eksctl.io/를 참조하세요.

    eksctl create nodegroup \ --cluster my-cluster \ --version 1.30 \ --name standard-nodes-new \ --node-type t3.medium \ --nodes 3 \ --nodes-min 1 \ --nodes-max 4 \ --managed=false
  3. 이전 명령이 완료되면 다음 명령으로 모든 노드가 Ready 상태가 되었는지 확인합니다.

    kubectl get nodes
  4. 다음 명령을 사용하여 원래 노드 그룹을 삭제합니다. 명령에서 모든 예제 값을 클러스터 이름과 노드 그룹 이름으로 바꿉니다.

    eksctl delete nodegroup --cluster my-cluster --name standard-nodes-old

AWS Management Console 및 AWS CLI

AWS Management Console 및 AWS CLI에서 애플리케이션을 새 노드 그룹으로 마이그레이션하려면

  1. 자체 관리 Amazon Linux 노드 생성에 설명된 단계에 따라 새 노드 그룹을 시작합니다.

  2. 스택이 생성된 후 콘솔에서 이를 선택하고 출력(Outputs)을 선택합니다.

  3. 생성된 노드 그룹에 대해 NodeInstanceRole을 기록합니다. 새 Amazon EKS 노드를 클러스터에 추가하려면 이 정보가 필요합니다.

    참고

    추가 IAM 정책을 이전 노드 그룹의 IAM 역할에 연결한 경우 새 그룹에서 해당 기능을 유지하려면 동일한 정책을 새 노드 그룹의 IAM 역할에 연결해야 합니다. 이는 예를 들어 Kubernetes Cluster Autoscaler에 대한 권한을 추가한 경우에 적용됩니다.

  4. 두 노드 그룹이 서로 통신할 수 있도록 두 노드 그룹의 보안 그룹을 업데이트합니다. 자세한 내용은 클러스터에 대한 Amazon EKS 보안 그룹 요구 사항 보기 단원을 참조하십시오.

    1. 두 노드 그룹에 대한 보안 그룹 ID를 모두 기록합니다. 이는 AWS CloudFormation 스택 출력에 NodeSecurityGroup 값으로 표시됩니다.

      다음 AWS CLI 명령을 사용하여 스택 이름에서 보안 그룹 ID를 가져옵니다. 이러한 명령에서 oldNodes는 이전 노드 스택의 AWS CloudFormation 스택 이름이고 newNodes는 마이그레이션하는 대상 스택의 이름입니다. 모든 예제 값을 자신의 값으로 바꾸세요.

      oldNodes="old_node_CFN_stack_name" newNodes="new_node_CFN_stack_name" oldSecGroup=$(aws cloudformation describe-stack-resources --stack-name $oldNodes \ --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \ --output text) newSecGroup=$(aws cloudformation describe-stack-resources --stack-name $newNodes \ --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \ --output text)
    2. 각 노드 보안 그룹이 서로의 트래픽을 수락하도록 노드 보안 그룹에 인그레스 규칙을 추가합니다.

      다음 AWS CLI 명령은 상대 보안 그룹의 모든 프로토콜에서 모든 트래픽을 허용하는 인바운드 규칙을 각 보안 그룹에 추가합니다. 이렇게 구성하면 워크로드를 새 그룹으로 마이그레이션하는 동안 각 노드 그룹의 Pods가 서로 통신할 수 있습니다.

      aws ec2 authorize-security-group-ingress --group-id $oldSecGroup \ --source-group $newSecGroup --protocol -1 aws ec2 authorize-security-group-ingress --group-id $newSecGroup \ --source-group $oldSecGroup --protocol -1
  5. aws-auth configmap을 편집하여 RBAC에서 새 노드 인스턴스 역할을 매핑합니다.

    kubectl edit configmap -n kube-system aws-auth

    새 노드 그룹에 대한 새 mapRoles 항목을 추가합니다. 클러스터가 AWS GovCloud(미국 동부) 또는 AWS GovCloud(미국 서부) AWS 리전에 있는 경우, arn:aws: arn:aws-us-gov:로 대체합니다.

    apiVersion: v1 data: mapRoles: | - rolearn: ARN of instance role (not instance profile) username: system:node:{{EC2PrivateDNSName}} groups: - system:bootstrappers - system:nodes> - rolearn: arn:aws:iam::111122223333:role/nodes-1-16-NodeInstanceRole-U11V27W93CX5 username: system:node:{{EC2PrivateDNSName}} groups: - system:bootstrappers - system:nodes

    ARN of instance role (not instance profile) 조각을 이전 절차에서 기록한 NodeInstanceRole 값으로 교체하고 파일을 저장합니다. 그런 다음 파일을 저장하고 닫아서 업데이트된 configmap을 적용합니다.

  6. 노드의 상태를 보면서 새 노드가 클러스터에 조인하고 Ready 상태에 도달할 때까지 기다립니다.

    kubectl get nodes --watch
  7. (선택 사항) Kubernetes Cluster Autoscaler를 사용하는 경우 배포를 복제본 0개로 축소하여 조정 작업의 충돌을 방지합니다.

    kubectl scale deployments/cluster-autoscaler --replicas=0 -n kube-system
  8. 다음 명령을 사용하여 NoSchedule로 제거하려는 각 노드를 테인트합니다. 이는 바꾸고 있는 노드에서 새 Pods가 예약되거나 다시 예약되지 않도록 하기 위한 것입니다. 테인트와 허용 오차에 대한 자세한 내용을 알아보려면 Kubernetes설명서를 참조하세요.

    kubectl taint nodes node_name key=value:NoSchedule

    노드를 새 Kubernetes 버전으로 업그레이드하는 경우 다음 코드 조각을 사용하여 특정 Kubernetes 버전(이 경우 1.28)의 모든 노드를 식별하고 테인트할 수 있습니다. 버전 번호는 컨트롤 플레인의 Kubernetes 버전보다 이후일 수 없습니다. 또한 컨트롤 플레인의 Kubernetes 버전보다 이전인 마이너 버전이 2개를 초과할 수 없습니다. 컨트롤 플레인과 동일한 버전을 사용하는 것이 좋습니다.

    K8S_VERSION=1.28 nodes=$(kubectl get nodes -o jsonpath="{.items[?(@.status.nodeInfo.kubeletVersion==\"v$K8S_VERSION\")].metadata.name}") for node in ${nodes[@]} do echo "Tainting $node" kubectl taint nodes $node key=value:NoSchedule done
  9. 클러스터의 DNS 공급자를 결정합니다.

    kubectl get deployments -l k8s-app=kube-dns -n kube-system

    예제 출력은 다음과 같습니다. 이 클러스터는 DNS 확인에 CoreDNS를 사용하고 있지만, 클러스터는 그 대신 kube-dns를 반환할 수 있습니다.

    NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE coredns 1 1 1 1 31m
  10. 현재 배포가 두 개 미만의 복제본을 실행하고 있는 경우, 배포를 복제본 두 개로 확장합니다. 이전 명령 출력에서 해당 값이 대신 반환된 경우 corednskubedns로 교체합니다.

    kubectl scale deployments/coredns --replicas=2 -n kube-system
  11. 다음 명령을 사용하여 클러스터에서 제거할 각 노드를 드레이닝합니다.

    kubectl drain node_name --ignore-daemonsets --delete-local-data

    노드를 새 Kubernetes 버전으로 업그레이드하는 경우 다음 코드 조각을 사용하여 특정 Kubernetes 버전(이 경우 1.28)의 모든 노드를 식별하고 테인트할 수 있습니다.

    K8S_VERSION=1.28 nodes=$(kubectl get nodes -o jsonpath="{.items[?(@.status.nodeInfo.kubeletVersion==\"v$K8S_VERSION\")].metadata.name}") for node in ${nodes[@]} do echo "Draining $node" kubectl drain $node --ignore-daemonsets --delete-local-data done
  12. 이전 노드가 드레이닝을 완료한 후 앞서 권한을 부여한 보안 그룹 인바운드 규칙을 취소합니다. 그런 다음 AWS CloudFormation 스택을 삭제하여 인스턴스를 종료합니다.

    참고

    Kubernetes 클러스터 오토스케일러에 대한 사용 권한 추가와 같이 이전 노드 그룹 IAM 역할에 추가 IAM 정책을 첨부한 경우, AWS CloudFormation 스택을 삭제하기 전에 해당 추가 정책을 역할에서 분리해야 한다.

    1. 위에서 노드 보안 그룹에 대해 생성한 인바운드 규칙을 취소합니다. 이러한 명령에서 oldNodes는 이전 노드 스택의 AWS CloudFormation 스택 이름이고 newNodes는 마이그레이션하는 대상 스택의 이름입니다.

      oldNodes="old_node_CFN_stack_name" newNodes="new_node_CFN_stack_name" oldSecGroup=$(aws cloudformation describe-stack-resources --stack-name $oldNodes \ --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \ --output text) newSecGroup=$(aws cloudformation describe-stack-resources --stack-name $newNodes \ --query 'StackResources[?ResourceType==`AWS::EC2::SecurityGroup`].PhysicalResourceId' \ --output text) aws ec2 revoke-security-group-ingress --group-id $oldSecGroup \ --source-group $newSecGroup --protocol -1 aws ec2 revoke-security-group-ingress --group-id $newSecGroup \ --source-group $oldSecGroup --protocol -1
    2. AWS CloudFormation 콘솔을 엽니다.

    3. 이전 노드 스택을 선택합니다.

    4. Delete(삭제)를 선택합니다.

    5. 스택 삭제(Delete stack) 확인 대화 상자에서 스택 삭제(Delete stack)를 선택합니다.

  13. aws-auth configmap을 편집하여 RBAC에서 이전 노드 인스턴스 역할을 제거합니다.

    kubectl edit configmap -n kube-system aws-auth

    이전 노드 그룹에 대한 mapRoles 항목을 삭제합니다. 클러스터가 AWS GovCloud(미국 동부) 또는 AWS GovCloud(미국 서부) AWS 리전에 있는 경우, arn:aws: arn:aws-us-gov:로 대체합니다.

    apiVersion: v1 data: mapRoles: | - rolearn: arn:aws:iam::111122223333:role/nodes-1-16-NodeInstanceRole-W70725MZQFF8 username: system:node:{{EC2PrivateDNSName}} groups: - system:bootstrappers - system:nodes - rolearn: arn:aws:iam::111122223333:role/nodes-1-15-NodeInstanceRole-U11V27W93CX5 username: system:node:{{EC2PrivateDNSName}} groups: - system:bootstrappers - system:nodes>

    파일을 저장하고 닫아서 업데이트된 configmap을 적용합니다.

  14. (선택 사항) Kubernetes Cluster Autoscaler를 사용하는 경우 배포를 다시 복제본 한 개로 축소합니다.

    참고

    또한 새 Auto Scaling 그룹에 적절한 태그를 지정하고(예: k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/my-cluster) 태그가 새로 지정된 Auto Scaling 그룹을 가리키도록 Cluster Autoscaler 배포에 대한 명령을 업데이트해야 합니다. 자세한 내용은 AWS의 Cluster Autoscaler를 참조하십시오.

    kubectl scale deployments/cluster-autoscaler --replicas=1 -n kube-system
  15. (선택 사항) 최신 버전의 Kubernetes용 Amazon VPC CNI 플러그인을 사용하고 있는지 확인합니다. 지원되는 최신 인스턴스 유형을 사용하려면 CNI 버전을 업데이트해야 할 수 있습니다. 자세한 내용은 Amazon VPC CNI 단원을 참조하십시오.

  16. 클러스터가 DNS 확인에 kube-dns를 사용하는 경우([migrate-determine-dns-step] 단계 참조) kube-dns 배포를 복제본 한 개로 축소합니다.

    kubectl scale deployments/kube-dns --replicas=1 -n kube-system