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

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

새 노드 그룹을 만들어 기존 애플리케이션을 새 그룹으로 정상 마이그레이션하고 클러스터에서 이전 노드 그룹을 제거하는 방법을 설명합니다.

출처: 문서

본문

이 주제는 새 노드 그룹을 만들고, 기존 애플리케이션을 새 그룹으로 정상 마이그레이션하고, 클러스터에서 이전 노드 그룹을 제거하는 방법을 설명합니다. eksctl 또는 AWS Management Console로 새 노드 그룹으로 마이그레이션할 수 있습니다.

eksctl

eksctl을 사용한 마이그레이션에 대한 자세한 내용은 eksctl 문서의 "Unmanaged nodegroups"를 참고하세요.

이 절차는 eksctl 버전 0.215.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
  1. 다음 명령으로 eksctl로 새 노드 그룹을 시작합니다. 명령에서 모든 example value를 자신의 값으로 바꾸세요. 버전 번호는 컨트롤 플레인의 Kubernetes 버전보다 이후일 수 없습니다. 또한 컨트롤 플레인의 Kubernetes 버전보다 두 개의 부 버전보다 더 이전일 수 없습니다. 컨트롤 플레인과 같은 버전을 사용할 것을 권장합니다.

다음 조건이 모두 참이라면 Pod의 IMDS 액세스 차단을 권장합니다.

  • 모든 Kubernetes 서비스 계정에 IAM 역할을 할당하여 Pod가 필요한 최소 권한만 갖도록 계획 중인 경우.
  • 클러스터의 어떤 Pod도 현재 AWS 리전 검색 같은 다른 이유로 IMDS에 액세스할 필요가 없는 경우.

자세한 내용은 "워커 노드에 할당된 인스턴스 프로파일 액세스 제한"을 참고하세요.

Pod의 IMDS 액세스를 차단하려면 다음 명령에 --disable-pod-imds 옵션을 추가하세요.

참고: 더 많은 사용 가능한 플래그와 설명은 https://eksctl.io/를 참고하세요.

eksctl create nodegroup \
  --cluster my-cluster \
  --version 1.36 \
  --name standard-nodes-new \
  --node-type t3.medium \
  --nodes 3 \
  --nodes-min 1 \
  --nodes-max 4 \
  --managed=false
  1. 이전 명령이 완료되면 다음 명령으로 모든 노드가 Ready 상태에 도달했는지 확인합니다.
kubectl get nodes
  1. 다음 명령으로 원래 노드 그룹을 삭제합니다. 명령에서 모든 example value를 클러스터와 노드 그룹 이름으로 바꾸세요.
eksctl delete nodegroup --cluster my-cluster --name standard-nodes-old

AWS Management Console 및 AWS CLI

  1. "자체 관리형 Amazon Linux 노드 생성"에 설명된 단계를 따라 새 노드 그룹을 시작합니다.
  2. 스택 생성이 완료되면 콘솔에서 선택하고 Outputs를 선택합니다.
  3. 생성된 노드 그룹의 NodeInstanceRole을 기록해 둡니다. 새 Amazon EKS 노드를 클러스터에 추가하려면 이 값이 필요합니다.

참고: 이전 노드 그룹 IAM 역할에 추가 IAM 정책을 연결했다면 새 노드 그룹 IAM 역할에도 같은 정책을 연결해 새 그룹에서 해당 기능을 유지하세요. 예를 들어 Kubernetes Cluster Autoscaler에 권한을 추가한 경우에 해당합니다.

  1. 두 노드 그룹이 서로 통신할 수 있도록 둘 다의 보안 그룹을 업데이트합니다. 자세한 내용은 "클러스터용 Amazon EKS 보안 그룹 요구 사항 보기"를 참고하세요.
  2. 두 노드 그룹의 보안 그룹 ID를 기록해 둡니다. 이 값은 AWS CloudFormation 스택 출력의 NodeSecurityGroup 값으로 표시됩니다.

다음 AWS CLI 명령으로 스택 이름에서 보안 그룹 ID를 가져올 수 있습니다. 이 명령에서 oldNodes는 이전 노드 스택의 AWS CloudFormation 스택 이름이고, newNodes는 마이그레이션 대상 스택의 이름입니다. 모든 example value를 자신의 값으로 바꾸세요.

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)
  1. 각 노드 보안 그룹에 서로의 트래픽을 수락하도록 인그레스 규칙을 추가합니다.

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

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
  1. aws-auth configmap을 편집해 RBAC에서 새 노드 인스턴스 역할을 매핑합니다.
kubectl edit configmap -n kube-system aws-auth

새 노드 그룹의 mapRoles 항목을 추가합니다.

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을 적용합니다.

  1. 노드 상태를 관찰하고 새 노드가 클러스터에 가입해 Ready 상태에 도달할 때까지 기다립니다.
kubectl get nodes --watch
  1. (선택 사항) Kubernetes Cluster Autoscaler를 사용한다면 충돌하는 스케일링 작업을 피하기 위해 배포를 0(0)개 레플리카로 축소합니다.
kubectl scale deployments/cluster-autoscaler --replicas=0 -n kube-system
  1. 다음 명령으로 제거하려는 각 노드를 NoSchedule로 taint 합니다. 이는 교체 중인 노드에 새 Pod가 스케줄되거나 재스케줄되지 않도록 하기 위함입니다. 자세한 내용은 Kubernetes 문서의 "Taints and Tolerations"를 참고하세요.
kubectl taint nodes node_name key=value:NoSchedule

노드를 새 Kubernetes 버전으로 업그레이드한다면 다음 코드 조각으로 특정 Kubernetes 버전(이 경우 1.34)의 모든 노드를 식별하고 taint 할 수 있습니다. 버전 번호는 컨트롤 플레인의 Kubernetes 버전보다 이후일 수 없습니다. 또한 컨트롤 플레인의 Kubernetes 버전보다 두 개의 부 버전보다 더 이전일 수 없습니다. 컨트롤 플레인과 같은 버전을 사용할 것을 권장합니다.

K8S_VERSION=1.34
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
  1. 클러스터의 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

현재 배포가 2개 미만의 레플리카를 실행 중이면 두 레플리카로 확장합니다. 이전 명령 출력에서 kubedns가 반환되었다면 coredns를 kubedns로 바꾸세요.

kubectl scale deployments/coredns --replicas=2 -n kube-system
  1. 다음 명령으로 클러스터에서 제거하려는 각 노드를 드레인합니다.
kubectl drain node_name --ignore-daemonsets --delete-emptydir-data

노드를 새 Kubernetes 버전으로 업그레이드한다면 다음 코드 조각으로 특정 Kubernetes 버전(이 경우 1.34)의 모든 노드를 식별하고 드레인합니다.

K8S_VERSION=1.34
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-emptydir-data
done
  1. 이전 노드 드레인이 끝난 후 앞서 승인한 보안 그룹 인바운드 규칙을 취소합니다. 그런 다음 AWS CloudFormation 스택을 삭제해 인스턴스를 종료합니다.

참고: 이전 노드 그룹 IAM 역할에 Kubernetes Cluster Autoscaler 권한 추가 같은 추가 IAM 정책을 연결했다면, AWS CloudFormation 스택을 삭제하기 전에 역할에서 해당 추가 정책을 분리하세요.

앞서 노드 보안 그룹용으로 만든 인바운드 규칙을 취소합니다. 이 명령에서 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
  1. AWS CloudFormation 콘솔을 엽니다.
  2. 이전 노드 스택을 선택합니다.
  3. Delete를 선택합니다.
  4. Delete stack 확인 대화 상자에서 Delete stack을 선택합니다.
  5. aws-auth configmap을 편집해 RBAC에서 이전 노드 인스턴스 역할을 제거합니다.
kubectl edit configmap -n kube-system aws-auth

이전 노드 그룹의 mapRoles 항목을 삭제합니다.

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을 적용합니다.

  1. (선택 사항) Kubernetes Cluster Autoscaler를 사용한다면 배포를 한 레플리카로 다시 확장합니다.

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

kubectl scale deployments/cluster-autoscaler --replicas=1 -n kube-system
  1. (선택 사항) 최신 버전의 Amazon VPC CNI plugin for Kubernetes를 사용하고 있는지 확인합니다. 최신 지원 인스턴스 유형을 사용하려면 CNI 버전을 업데이트해야 할 수 있습니다. 자세한 내용은 "Amazon VPC CNI로 Pod에 IP 할당"을 참고하세요.
  2. 클러스터가 DNS 확인에 kube-dns를 사용한다면 kube-dns 배포를 한 레플리카로 축소합니다.
kubectl scale deployments/kube-dns --replicas=1 -n kube-system

더 알아보기 (Learn more)