CI/CD 파이프라인을 사용하여 Amazon EKS에서 노드 종료 핸들러 배포 자동화 - AWS 권장 가이드

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

CI/CD 파이프라인을 사용하여 Amazon EKS에서 노드 종료 핸들러 배포 자동화

작성자: 샌딥 강가파디야(AWS), 존 바르가스(AWS), 프라티딥 싱(AWS), 샌딥 가완데 (AWS) 및 비요마 사흐데바(AWS)

코드 리포지토리: NTH를 EKS에 배포

환경: 프로덕션

기술: 컨테이너 및 마이크로서비스, DevOps

AWS 서비스: AWS CodePipeline, 아마존 EKS, AWS CodeBuild

요약

Amazon Web Services(AWS) 클라우드에서 오픈 소스 프로젝트인 AWS Node Termination Handler를 사용하여 Kubernetes 내에서 Amazon Elastic Compute Cloud(Amazon EC2) 인스턴스 종료를 적절하게 처리할 수 있습니다. AWS Node Termination Handler는 EC2 인스턴스를 사용할 수 없게 만들 수 있는 이벤트에 Kubernetes 컨트롤 플레인이 적절하게 응답하도록 도와줍니다. 이러한 이벤트에는 다음이 포함됩니다.

이벤트가 처리되지 않으면 애플리케이션 코드가 적절하게 중지되지 않을 수 있습니다. 또한 전체 가용성을 복구하는 데 시간이 더 오래 걸리거나 다운되는 노드에 실수로 작업을 예약할 수도 있습니다. aws-node-termination-handler (NTH)는 인스턴스 메타데이터 서비스(IMDS)또는 대기열 프로세서라는 두 가지 모드로 작동할 수 있습니다. 두 모드에 대한 자세한 내용은 Readme 파일을 참조하세요.

이 패턴은 지속적 통합 및 지속적 전달(CI/CD) 파이프라인을 통해 대기열 프로세서를 사용하여 NTH를 자동으로 배포합니다.

참고: EKS 관리형 노드 그룹 사용하는 경우에는 aws-node-termination-handler이(가) 필요하지 않습니다.

사전 조건 및 제한 사항

사전 조건 

  • 활성 상태의 AWS 계정.

  • AWS Management Console에서 사용할 수 있도록 지원되는 웹 브라우저. 지원되는 브라우저 목록을 참조하세요.

  • AWS Cloud Development Kit(AWS CDK)가 설치됨.

  • kubectl, Kubernetes 명령줄 도구가 설치됨.

  • eksctl, Amazon Elastic Kubernetes Service(Amazon EKS)를 위한 AWS Command Line Interface(AWS CLI)가 설치됨.

  • 버전 1.20 이상으로 실행 중인 EKS 클러스터

  • EKS 클러스터에 연결된 자체 관리형 노드 그룹입니다. 자체 관리형 노드 그룹이 있는 Amazon EKS 클러스터를 생성하려면 다음 명령을 실행합니다.

    eksctl create cluster --managed=false --region <region> --name <cluster_name>

    eksctl에 관한 자세한 내용은 eksctl 설명서를 참조하세요.

  • 클러스터에 대한 AWS Identity and Access Management(IAM) OpenID Connect(OIDC) 공급자입니다. 자세한 내용은 클러스터에 대한 IAM OIDC 공급자 생성을 참조하세요.

제한 사항

  • Amazon EKS 서비스를 지원하는 AWS 리전을 사용해야 합니다.

제품 버전

  • Kubernetes 버전 1.20 이상

  • eksctl 버전 0.107.0 이상

  • AWS CDK 버전 2.27.0 이상

아키텍처

대상 기술 스택  

  • Virtual Private Cloud(VPC)

  • EKS 클러스터

  • Amazon Simple Queue Service(Amazon SQS)

  • IAM

  • Kubernetes

대상 아키텍처 

다음 다이어그램은 노드 종료가 시작되는 시점의 end-to-end 단계를 개괄적으로 보여줍니다.

Auto Scaling 그룹이 있는 VPC, 노드 종료 핸들러가 있는 EKS 클러스터, SQS 대기열.

다이어그램에 표시된 워크플로우는 다음과 같은 개괄적인 단계로 구성되어 있습니다.

  1. 자동 조정 EC2 인스턴스 종료 이벤트는 SQS 대기열로 전송됩니다.

  2. NTH 포드는 SQS 대기열의 새 메시지를 모니터링합니다.

  3. NTH 포드는 새 메시지를 수신하고 다음을 수행합니다.

    • 새 포드가 노드에서 실행되지 않도록 노드를 차단합니다.

    • 노드를 빼서 기존 포드를 비우도록 합니다.

    • 노드를 종료할 수 있도록 Auto Scaling 그룹에 수명 주기 후크 신호를 전송합니다.

자동화 및 규모 조정

도구

서비스

  • AWS Cloud Development Kit(AWS CDK)는 AWS 클라우드 인프라를 코드로 정의하고 프로비저닝하는 데 도움이 되는 소프트웨어 개발 프레임워크입니다.

  • CodeBuildAWS는 소스 코드를 컴파일하고, 단위 테스트를 실행하고, 배포할 준비가 된 아티팩트를 생성하는 데 도움이 되는 완전관리형 빌드 서비스입니다.

  • CodeCommitAWS는 자체 소스 제어 시스템을 관리할 필요 없이 Git 리포지토리를 비공개로 저장하고 관리할 수 있는 버전 제어 서비스입니다.

  • AWS는 소프트웨어 릴리스의 여러 단계를 신속하게 모델링 및 구성하고 소프트웨어 변경 사항을 지속적으로 릴리스하는 CodePipeline 데 필요한 단계를 자동화하도록 지원합니다.

  • Amazon Elastic Kubernetes Service (Amazon EKS)는 자체 Kubernetes 컨트롤 플레인이나 노드를 설치하거나 유지 관리할 필요 없이 AWS에서 Kubernetes를 실행할 수 있도록 도와줍니다.

  • Amazon EC2 Auto Scaling을 사용하면 애플리케이션 가용성을 유지하고 정의된 조건에 따라 Amazon EC2 인스턴스를 자동으로 추가하거나 제거할 수 있습니다.

  • Amazon Simple Queue Service(Amazon SQS)는 내구력 있고 가용성이 뛰어난 보안 호스팅 대기열을 제공하며 이를 통해 분산 소프트웨어 시스템과 구성 요소를 통합 및 분리할 수 있습니다.

기타 도구

  • kubectl은 Kubernetes 클러스터에 대해 명령을 실행하기 위한 Kubernetes 명령줄 도구입니다. kubectl을 사용하여 애플리케이션을 배포하고, 클러스터 리소스를 검사 및 관리하고, 로그를 볼 수 있습니다.

code

이 패턴의 코드는 GitHub .com의 deploy-nth-to-eks리포지토리에서 확인할 수 있습니다. 코드 리포지토리에는 다음 파일 및 폴더가 포함되어 있습니다.

  • nth folder— 노드 종료 핸들러용 AWS CloudFormation 템플릿을 스캔하고 배포하기 위한 Helm 차트, 값 파일 및 스크립트.

  • config/config.json - 애플리케이션의 구성 파라미터 파일입니다. 이 파일에는 CDK를 배포하는 데 필요한 모든 파라미터가 포함되어 있습니다.

  • cdk - AWS CDK 소스 코드입니다.

  • setup.sh - 필수 CI/CD 파이프라인 및 기타 필수 리소스를 생성하기 위해 AWS CDK 애플리케이션을 배포하는 데 사용되는 스크립트입니다.

  • uninstall.sh - 리소스를 정리하는 데 사용되는 스크립트입니다.

샘플 코드를 사용하려면 에픽 섹션의 지침을 따르십시오.

모범 사례

AWS 노드 종료 핸들러를 자동화하는 모범 사례는 다음을 참조하세요.

에픽

작업설명필요한 기술

리포지토리를 복제합니다.

SSH(보안 셸)를 사용하여 리포지토리를 복제하려면 다음 명령을 실행합니다.

git clone git@github.com:aws-samples/deploy-nth-to-eks.git

HTTPS를 사용하여 리포지토리를 복제하려면 다음 명령을 실행합니다.

git clone https://github.com/aws-samples/deploy-nth-to-eks.git

리포지토리를 복제하면 deploy-nth-to-eks(이)라는 이름의 폴더가 생성됩니다.

해당 디렉터리로 변경합니다.

cd deploy-nth-to-eks
앱 개발자, AWS DevOps, DevOps 엔지니어

kubeconfig 파일을 설정합니다.

터미널에 AWS 보안 인증을 설정하고 클러스터 역할을 맡을 권한이 있는지 확인합니다. 다음 예제 코드를 사용할 수 있습니다.

aws eks update-kubeconfig --name <Cluster_Name> --region <region>--role-arn <Role_ARN>
AWS DevOps, DevOps 엔지니어, 앱 개발자
작업설명필요한 기술

파라미터를 설정합니다.

config/config.json 파일에서 다음과 같은 필수 파라미터를 설정합니다.

  • pipelineName: AWS CDK에서 생성할 CI/CD 파이프라인의 이름(예제: deploy-nth-to-eks-pipeline)입니다. AWS는 이 이름을 가진 파이프라인을 생성할 CodePipeline 것입니다.

  • repositoryName: 생성할 AWS CodeCommit 리포지토리 (예:deploy-nth-to-eks-repo) AWS CDK는 이 리포지토리를 생성하고 이를 CI/CD 파이프라인의 소스로 설정합니다.

    참고: 이 솔루션은 이 CodeCommit 리포지토리와 브랜치를 생성합니다 (다음 브랜치 파라미터에 제공됨).

  • branch: 리포지토리의 브랜치 이름(예제: main)입니다. 이 브랜치를 커밋하면 CI/CD 파이프라인이 시작됩니다.

  • cfn_scan_script: AWS CloudFormation 템플릿에서 NTH (scan.sh) 를 스캔하는 데 사용할 스크립트의 경로입니다. 이 스크립트는 AWS CodeCommit 리포지토리의 일부가 될 nth 폴더에 있습니다.

  • cfn_deploy_script: NTH용 AWS CloudFormation 템플릿을 배포하는 데 사용할 스크립트 경로 (installApp.sh).

  • stackName: 배포할 CloudFormation 스택의 이름.

  • eksClusterName: 기존 EKS 클러스터 이름입니다.

  • eksClusterRole: 모든 Kubernetes API 호출을 위해 EKS 클러스터에 액세스하는 데 사용되는 IAM 역할입니다(예제: clusteradmin). 일반적으로 aws-auth ConfigMap에 이 역할이 추가됩니다.

  • create_cluster_role: eksClusterRole IAM 역할을 생성하려면 yes를 입력합니다. eksClusterRole 파라미터에 기존 클러스터 역할을 제공하려면 no를 입력합니다.

  • create_iam_oidc_provider: 클러스터에 대한 IAM OIDC 공급자를 생성하려면 yes를 입력합니다. IAM OIDC 공급자가 이미 존재하면 no를 입력합니다. 자세한 내용은 클러스터에 대한 IAM OIDC 공급자 생성을 참조하세요.

  • AsgGroupName: EKS 클러스터에 속하는 Auto Scaling 그룹 이름을 쉼표로 구분한 목록입니다(예제: ASG_Group_1,ASG_Group_2).

  • region: 클러스터가 위치한 AWS 리전의 이름(예제: us-east-2)입니다.

  • install_cdk: AWS CDK가 현재 머신에 설치되어 있지 않은 경우 yes를 입력합니다. cdk --version 명령을 실행하여 설치된 AWS CDK 버전이 2.27.0 이상인지 확인합니다. 이 경우 no를 입력합니다.

    yes를 입력하면 setup.sh 스크립트가 sudo npm install -g cdk@2.27.0 명령을 실행하여 AWS CDK를 시스템에 설치합니다. 스크립트에는 sudo 권한이 필요하므로 메시지가 표시되면 계정 암호를 제공하세요.

앱 개발자, AWS DevOps, DevOps 엔지니어

CI/CD 파이프라인을 생성하여 NTH를 배포합니다.

setup.sh 스크립트를 실행합니다.

./setup.sh

스크립트는 파일의 사용자 입력 파라미터를 기반으로 예제 코드, 파이프라인, CodeBuild 프로젝트가 포함된 CodeCommit 리포지토리를 생성하는 AWS CDK 애플리케이션을 배포합니다. config/config.json

이 스크립트는 sudo 명령으로 npm 패키지를 설치할 때 암호를 묻습니다.

앱 개발자, AWS DevOps, DevOps 엔지니어

CI/CD 파이프라인을 검토합니다.

AWS Management Console을 열고 스택에 생성된 다음 리소스를 검토하세요.

  • CodeCommit 폴더 내용이 포함된 nth 리포지토리

  • CloudFormation 템플릿의 취약점을 스캔하는 AWS CodeBuild 프로젝트cfn-scan.

  • CodeBuild 이 프로젝트는 Nth-Deploy AWS CloudFormation 템플릿과 해당 NTH Helm 차트를 AWS 파이프라인을 통해 배포합니다. CodePipeline

  • NTH를 배포하기 위한 CodePipeline 파이프라인.

파이프라인이 성공적으로 실행되면 EKS 클러스터에 Helm 릴리스 aws-node-termination-handler(이)가 설치됩니다. 또한 클러스터의 kube-system 네임스페이스에서 aws-node-termination-handler 이름의 포드가 실행 중입니다.

앱 개발자, AWS DevOps, DevOps 엔지니어
작업설명필요한 기술

Auto Scaling 그룹 스케일 인 이벤트를 시뮬레이션합니다.

자동 조정 스케일 인 이벤트를 시뮬레이션하려면 다음을 수행합니다.

  1. AWS console EC2 콘솔을 열고 Auto Scaling 그룹을 선택합니다.

  2. config/config.json에서 제공한 것과 이름이 같은 Auto Scaling 그룹을 선택하고 편집을 선택합니다.

  3. 원하는 용량과 최소 용량을 1씩 줄입니다.

  4. 업데이트를 선택합니다.

로그를 검토합니다.

스케일 인 이벤트 중에 NTH Pod는 해당 워커 노드(스케일 인 이벤트의 일부로 종료될 EC2 인스턴스)를 차단하고 드레이닝합니다. 로그를 확인하려면 추가 정보 섹션의 코드를 사용합니다.

앱 개발자, AWS DevOps, DevOps 엔지니어
작업설명필요한 기술

모든 AWS 리소스를 정리합니다.

이 패턴으로 생성된 리소스를 정리하려면 다음 명령을 실행합니다.

./uninstall.sh

그러면 CloudFormation 스택이 삭제되어 이 패턴으로 생성된 모든 리소스가 정리됩니다.

DevOps 엔지니어

문제 해결

문제Solution

npm 레지스트리가 올바르게 설정되지 않았습니다.

이 솔루션을 설치하는 동안 스크립트는 npm install을 설치하여 필수 패키지를 모두 다운로드합니다. 설치 중에 “모듈을 찾을 수 없습니다”라는 메시지가 표시되면 npm 레지스트리가 올바르게 설정되지 않은 것일 수 있습니다. 현재 레지스트리 설정을 확인하려면 다음 명령을 실행합니다.

npm config get registry

https://registry.npmjs.org/(으)로 레지스트리를 설정하려면 다음 명령을 실행합니다.

npm config set registry https://registry.npmjs.org

SQS 메시지 전송을 지연합니다.

문제 해결의 일환으로, NTH 포드로 SQS 메시지 전송을 지연하려는 경우 SQS 전송 지연 파라미터를 조정할 수 있습니다. 자세한 내용은 Amazon SQS 지연 대기열을 참조하세요.

관련 리소스

추가 정보

1. NTH 포드 이름을 찾습니다.

kubectl get pods -n kube-system |grep aws-node-termination-handler aws-node-termination-handler-65445555-kbqc7 1/1 Running 0 26m kubectl get pods -n kube-system |grep aws-node-termination-handler aws-node-termination-handler-65445555-kbqc7 1/1 Running 0 26m

2. 로그를 확인합니다. 예제 로그는 다음과 같습니다. Auto Scaling 그룹 수명 주기 후크 완료 신호를 보내기 전에 노드가 차단되고 드레이닝되었음을 보여줍니다.

kubectl -n kube-system logs aws-node-termination-handler-65445555-kbqc7 022/07/17 20:20:43 INF Adding new event to the event store event={"AutoScalingGroupName":"eksctl-my-cluster-target-nodegroup-ng-10d99c89-NodeGroup-ZME36IGAP7O1","Description":"ASG Lifecycle Termination event received. Instance will be interrupted at 2022-07-17 20:20:42.702 +0000 UTC \n","EndTime":"0001-01-01T00:00:00Z","EventID":"asg-lifecycle-term-33383831316538382d353564362d343332362d613931352d383430666165636334333564","InProgress":false,"InstanceID":"i-0409f2a9d3085b80e","IsManaged":true,"Kind":"SQS_TERMINATE","NodeLabels":null,"NodeName":"ip-192-168-75-60.us-east-2.compute.internal","NodeProcessed":false,"Pods":null,"ProviderID":"aws:///us-east-2c/i-0409f2a9d3085b80e","StartTime":"2022-07-17T20:20:42.702Z","State":""} 2022/07/17 20:20:44 INF Requesting instance drain event-id=asg-lifecycle-term-33383831316538382d353564362d343332362d613931352d383430666165636334333564 instance-id=i-0409f2a9d3085b80e kind=SQS_TERMINATE node-name=ip-192-168-75-60.us-east-2.compute.internal provider-id=aws:///us-east-2c/i-0409f2a9d3085b80e 2022/07/17 20:20:44 INF Pods on node node_name=ip-192-168-75-60.us-east-2.compute.internal pod_names=["aws-node-qchsw","aws-node-termination-handler-65445555-kbqc7","kube-proxy-mz5x5"] 2022/07/17 20:20:44 INF Draining the node 2022/07/17 20:20:44 ??? WARNING: ignoring DaemonSet-managed Pods: kube-system/aws-node-qchsw, kube-system/kube-proxy-mz5x5 2022/07/17 20:20:44 INF Node successfully cordoned and drained node_name=ip-192-168-75-60.us-east-2.compute.internal reason="ASG Lifecycle Termination event received. Instance will be interrupted at 2022-07-17 20:20:42.702 +0000 UTC \n" 2022/07/17 20:20:44 INF Completed ASG Lifecycle Hook (NTH-K8S-TERM-HOOK) for instance i-0409f2a9d3085b80e