Overview
GitOps Bridge 패턴을 활용하여 EKS 클러스터 간의 Blue/Green 워크로드 마이그레이션 전략을 소개합니다. 해당 글은 Amazon EKS Blueprints for Terraform 의 예제(blue-green-upgrade) 를 참고하여 작성하였습니다.
EKS 멀티 클러스터 버전 업그레이드
해당 전략은 EKS 버전 업그레이드를 위해 구성되었습니다. EKS 버전은 기간이 지남에 따라 지원이 종료되며 추가 지원 종료일 이후에는 버전이 자동으로 업그레이드 됩니다. 자동으로 업그레이드되면 되는거 아니야 라고 할 수 있지만, 버전간의 호환성 및 워크로드의 순단이 발생함으로 사전에 대비가 필요합니다.
- 표준 지원 종료일 이후에는 추가 지원 종료일까지 비용이 약 5배 정도 더 부과됩니다.
EKS 버전 업그레이드 방법은 크게 두가지로 분류됩니다.
구분
|
단일 클러스터 업그레이드
|
멀티클러스터 업그레이드
|
정의
|
기존 클러스터의 Kubernetes 버전을 직접 업그레이드
|
새로운 클러스터를 구성하고 기존 워크로드를 새 클러스터로 마이그레이션
|
장점
|
간단하고 직관적인 프로세스 적은 리소스로 관리 가능
|
기존 클러스터의 운영 중단 최소화(무중단 가능) 업그레이드 중 발생할 수 있는 리스크 감소 복수의 버전 업그레이드를 건너뛰고 직접 이행 가능
|
단점
|
업그레이드 실패 시 서비스 중단 가능성 한 번에 하나의 버전만 업그레이드 가능 롤백 불가능
|
초기 설정과 마이그레이션으로 인한 복잡성 및 비용 증가
|
적용 시나리오
|
클러스터 규모가 작거나 중간일 때 리스크 관리가 용이한 환경
|
대규모 또는 미션 크리티컬 애플리케이션 운영 시 지속적인 서비스 가용성이 필수적인 경우
|
멀티클러스터 업그레이드가 복잡하지만 롤백이 가능한 점 그리고 무중단으로 업그레이드가 가능하다는 점에서 많이 고려됩니다.
다만, 초기 클러스터 구성과 워크로드 마이그레이션 방법이 복잡한 편인데요. 이를 Gitops Bridge 패턴을 통해 EKS 구성을 하고 워크로드 마이그레이션을 손 쉽게 구성하겠습니다.
Gitops Bridge 패턴은 워크로드 부분은 Git Repo(addon, Workload) 에서 정의하고 인프라 부분과 git repo를 호출하는 부분은 테라폼으로 감싸 관리하는 패턴입니다.
해당 패턴의 핵심은 워크로드 구성을 각 메타데이터로 관리한다는 점입니다. 워크로드 배포(ArgoCD) 시크릿을 통해 배포된 메타데이터를 확인할 수 있습니다.
이러한 메타데이터를 추출하여 다른 클러스터에 그대로 배포할 수 있습니다.
필자의 지난 글에서는 이러한 특징을 소개하여 멀티클러스터 구성을 자동화하였는데요.
이번 글에서는 gitops bridge 모듈에 Route53 가중치 기반 설정 기능을 추가하여 클러스터간 마이그레이션을 진행하겠습니다.
구성 변수 확인
업그레이드 테스트 전 구성 변수를 확인하겠습니다.
git clone https://github.com/aws-ia/terraform-aws-eks-blueprints.git
cd patterns/blue-green-upgrade/
vi terraform.tfvars.example
---
# You should update the below variables
aws_region = "ap-northeast-2"
environment_name = "eks-blueprint"
hosted_zone_name = "horang.link" # your Existing Hosted Zone
eks_admin_role_name = "Admin" # Additional role admin in the cluster (usually the role I use in the AWS console)
#gitops_addons_org = "git@github.com:aws-samples"
#gitops_addons_repo = "eks-blueprints-add-ons"
#gitops_addons_path = "argocd/bootstrap/control-plane/addons"
#gitops_addons_basepath = "argocd/"
# EKS Blueprint Workloads ArgoCD App of App repository
gitops_workloads_org = "git@github.com:aws-samples"
gitops_workloads_repo = "eks-blueprints-workloads"
gitops_workloads_revision = "main"
gitops_workloads_path = "envs/dev"
#Secret manager secret for github ssk jey
aws_secret_manager_git_private_ssh_key_name = "github-blueprint-ssh-key"
- hosted_zone_name 의 경우 필자의 도메인으로 등록하였습니다. 각자 도메인으로 입력해야합니다.
- gitops_addons 블록은 주석처리 되어있지만, 다음 테라폼 변수 우선순위(각 배포 폴더 variables.tf)에서 설정됩니다.
- gitops_workloads 은 워크로드 구성 Git Repo 입니다. 링크와 브랜치를 따라가면 다음과 같은 워크로드가 클러스터에 배포됩니다.
- aws_secret_manager_git_private_ssh_key_name 는 git 에 액세스하기 위한 SSH 키입니다.
ssh-keygen -t rsa -C “본인 GitHub 계정”
# 비밀번호 등록 엔터
# 공개 키 등록
cat ~/.ssh/id_rsa.pub
# <https://github.com/settings/keys> 에서 SSH KEY 등록
# 비밀 키 등록
cat ~/.ssh/id_rsa
# AWS Secret manager > 다른 유형의 암호 생성
# > 일반 텍스트에 비밀 키 입력, 이름은 github-blueprint-ssh-key
변수 설정 후 각 배포 모듈에 변수를 복사합니다.
cp terraform.tfvars.example terraform.tfvars
ln -s ../terraform.tfvars environment/terraform.tfvars
ln -s ../terraform.tfvars eks-blue/terraform.tfvars
ln -s ../terraform.tfvars eks-green/terraform.tfvars
배포
테라폼으로 배포하는 구성은 3개입니다. 왼쪽, 오른쪽 파란색 네모로 표시된 부분입니다.
- environment : VPC 와 Route53, ACM(git repo SSH 키 저장용) 생성 모듈입니다.
- eks-blue : EKS Blue 모듈입니다.
- eks-green : EKS Green 모듈입니다.
모듈을 확인하면 eks-blue, eks-green 은 eks_cluster 모듈을 통해 구성됩니다.
eks-blue, eks-green 간의 차이점은 service_name(환경 변수)와 route53 가중치 입니다.
테라폼 코드를 확인하면 차이점을 확인할 수 있습니다.
- service_name : 클러스터 구분을 위한 변수입니다. suffix로 처리되며 각 ingress 설정에 레코드 설정으로 들어갑니다.
- Route53 가중치 : 가중치 기반 정책의 비율을 설정하는 부분입니다. 100, 0으로 설정되어 blue 클러스터로만 트래픽이 가도록 설정되어 있습니다.
다음의 명령어를 통해 클러스터를 배포합니다.
cd environment
terraform init
terraform apply
cd eks-blue
terraform init
terraform apply
cd eks-green
terraform init
terraform apply
- 클러스터 배포시 corddns 배포에서 20분정도 딜레이가 발생됩니다. EKS 생성시 이미 구성되어 coredns 생성이 충돌되는 부분이며 아래 화면이 지속된다면 취소(command + C) 후 다시 배포(terraform apply) 해주세요.
배포를 완료하고 클러스터(blue)로 접근하면 배포 워크로드를 확인할 수 있습니다.
aws eks update-kubeconfig --name eks-blueprint-blue --region ap-northeast-2
# 구성 워크로드 확인
kubectl get deployment -n team-burnham -l app=burnham
ArgoCD applicationset를 통해 배포한 메타데이터를 확인할 수 있습니다. 위 핵심 원리에서 다뤘던 메타데이터 부분이며 해당 메타데이터를 통해 클러스터 별 마이그레이션 가능한 것을 확인할 수 있습니다.
# ArgoCD 메타데이터 확인
kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster -o json | jq '.items[0].metadata.labels' | grep -v false | jq .
kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=cluster -o json | jq '.items[0].metadata.annotations'
Blue / Green 클러스터간 트래픽 마이그레이션
워크로드 서비스의 도메인를 호출하면 blue 클러스터의 워크로드가 호출이 되는 것을 확인할 수 있을텐데요.
URL=$(echo -n "https://" ; kubectl get ing -n team-burnham burnham-ingress -o json | jq ".spec.rules[0].host" -r)
echo $URL
curl -s $URL | grep CLUSTER_NAME | awk -F "<span>|</span>" '{print $4}'
이는 위에서 설정한 route53의 가중치 기반 설정때문입니다. Route53 도메인을 확인하면 클러스터별 설정한 가중치 값과 서비스 이름이 들어간 것을 확인할 수 있습니다.
그린 클러스터의 가중치 값을 100으로 변경하여 클러스터간 트래픽 마이그레이션 확인하겠습니다.
eks-green/main.tf 에서 가중치값을 0 에서 100으로 수정하여 apply 합시다.
Apply 후 Route53 가중치와 도메인 호출을 통해 트래픽 경로를 확인하겠습니다.
URL=$(echo -n "https://" ; kubectl get ing -n team-burnham burnham-ingress -o json | jq ".spec.rules[0].host" -r)
repeat 10 curl -s $URL | grep CLUSTER_NAME | awk -F "<span>|</span>" '{print $4}' && sleep 60
- 기본 TTL이 300초로 설정되어 있어 5번의 호출은 blue로 호출되며, DNS TTL이 최신 상태가 되면 트래픽이 eks-green 클러스터로도 유입되는 것을 확인 할 수 있습니다.
테라폼 코드로 가중치를 변경하였지만, 내부 동작은 addons인 external-dns 에서 관리하게 됩니다.
예제 워크로드인 burnham-ingress 를 확인하면 annotations 값을 통해 route53 를 제어하는 것을 확인할 수 있습니다.
간단한 변수 값 설정으로 클러스터간 마이그레이션을 테스트하였는데요. 실제 클러스터별 트래픽 마이그레이션을 진행한다면 TTL 값을 최솟값으로 설정하여 TTL이 최신 상태가 되도록 하는 것을 추천드립니다.
클러스터 삭제
구성한 배포 폴더에서 다음의 명령어로 삭제를 진행해주세요.
cd eks-blue, eks-green
terraform destroy -target="module.eks_cluster.module.kubernetes_addons" -auto-approve || (echo "error deleting module.eks_cluster.module.kubernetes_addons" && exit -1)
terraform destroy -target="module.eks_cluster.module.eks_blueprints_platform_teams" -auto-approve || (echo "error deleting module.eks_cluster.module.eks_blueprints_platform_teams" && exit -1)
terraform destroy -target="module.eks_cluster.module.eks_blueprints_dev_teams" -auto-approve || (echo "error deleting module.eks_cluster.module.eks_blueprints_dev_teams" && exit -1)
terraform destroy -target="module.eks_cluster.module.eks_blueprints_ecsdemo_teams" -auto-approve || (echo "error deleting module.eks_cluster.module.eks_blueprints_ecsdemo_teams" && exit -1)
terraform destroy -target="module.eks_cluster.module.gitops_bridge_bootstrap" -auto-approve || (echo "error deleting module.eks_cluster.module.gitops_bridge_bootstrap" && exit -1)
terraform destroy -target="module.eks_cluster.module.gitops_bridge_metadata" -auto-approve || (echo "error deleting module.eks_cluster.module.gitops_bridge_metadata" && exit -1)
terraform destroy -target="module.eks_cluster.module.eks_blueprints_addons" -auto-approve || (echo "error deleting module.eks_cluster.module.eks" && exit -1)
terraform destroy -target="module.eks_cluster.module.ebs_csi_driver_irsa" --auto-approve
terraform destroy -target="module.eks_cluster.module.vpc_cni_irsa" --auto-approve
terraform destroy -target="module.eks_cluster.module.eks" -auto-approve || (echo "error deleting module.eks_cluster.module.eks" && exit -1)
cd enviroment
terraform destroy -auto-approve || (echo "error deleting terraform" && exit -1)
- helm 이식 문제로 addon 삭제 과정에서 시간이 너무 오래 걸리거나, 모듈 삭제 순서가 꼬이는 경우가 있습니다. 이러한 경우 콘솔에서 리소스를 전부 삭제해주세요.