AWS 기술 블로그

LG U+의 GitOps를 이용한 Amazon EKS 클러스터 무중단 버전 업데이트 사례

배경

오늘날 소비자는 공중파, IPTV, OTT 등 여러 채널과 휴대폰, 셋톱박스, 스마트TV 등 여러 장치에서 미디어를 시청할 수 있습니다. 국내 주요 통신사업자인 LG U+의 IPTV 사업부문은 500만 대 이상의 셋탑을 통해 공중파, IPTV, VOD 등의 서비스를 제공하고 있습니다. 가정내 셋탑 숫자 기준이므로, 2인 가족을 가정한다면 천만명 이상, 모바일앱을 추가한다면 이보다도 더 많은 고객에게 서비스를 제공하고 있습니다.

많은 OTT 플랫폼들이 경쟁을 하는 가운데 시장과 고객이 요구하는 빠른 변화에 발맞추기 위해 LG U+ IPTV 사업부문 DevOps 팀(이하 DevOps 팀)은 마이크로서비스 아키텍처를 채택하고, 미디어 서비스의 특징인 순간적인 트래픽 급증에 대응할 수 있도록 워크로드를 Amazon EKS로 이관하기로 결정했습니다. 이후 Amazon EKS로 이관작업을 AWS Professional Services 조직과 함께 수행하여 지난 2023년 3월 성공적으로 마무리지었습니다. 이 글은 LG U+가 워크로드를 Amazon EKS로 이관한 이후, 클러스터 버전 업데이트 문제를 GitOps를 활용해 무중단으로 해결한 사례를 소개합니다.

GitOps는 인프라 및 애플리케이션 배포를 위한 신뢰할 수 있는 단일 소스로 Git을 사용하는 DevOps 방법론입니다. 배포와 관련된 모든 내용이 선언적 코드로 작성되어 Git을 통해서만 이루어지므로 신뢰성있게 인프라 및 애플리케이션을 프로비저닝, 구성 및 관리할 수 있습니다. 일반적으로 인프라의 경우에는 AWS CloudFormationAWS CDK 그리고 Hashicorp의 Terraform 같은 도구를 사용하며, Kubernetes 환경에서 어플리케이션을 배포할 때는 ArgoCD, Weaveworks Flux 와 같은 도구를 사용합니다. DevOps팀은 인프라는 Terraform, 어플리케이션은 ArgoCD를 사용하여 GitOps 배포 파이프라인을 구축하였습니다.

Amazon EKS 버전 업데이트의 어려움

Amazon EKS 클러스터 버전 업데이트 문제는 국내외의 많은 고객께서 공통적으로 어려움을 호소하고 있는 문제입니다. Amazon EKS는 Kubernetes의 컨트롤 플레인을 고객이 직접 관리하지 않아도 된다는 장점을 제공하지만, 반대로 Kubernetes 최신 버전과의 호환성을 유지하기 위해 유지 관리 기간이 지나면 컨트롤 플레인의 버전을 자동으로 업데이트합니다. 이때 고객이 데이터 플레인의 버전을 업데이트 해주지 않으면 버전 불일치의 문제로 클러스터가 정상 작동하지 않을 수 있고, 충분한 준비 없이 버전 업데이트를 진행하다가 서비스 중단이나 장애가 발생할 수 있습니다.

일반적으로 업데이트 방식에는 싱글 클러스터 방식과 멀티 클러스터 방식이 있습니다. 싱글 클러스터 방식은 하나의 클러스터를 사용하면서 먼저 컨트롤 플레인의 버전을 한 단계 업데이트 한 다음, 데이터 플레인인 노드 그룹을 업데이트하고, kube-proxy, coredns와 같은 애드온의 버전을 업데이트하는 순서로 진행하게 됩니다. 서비스를 제공 중인 클러스터를 업데이트 할 때는 한번에 하나의 마이너버전만 업데이트 할 수 있으며, 업데이트 후에는 롤백이 되지 않는 점 때문에 문제 발생 시 장애로 이어질 가능성이 있습니다.

한편, 멀티 클러스터 방식은 버전만 다르고 그 외 모든 것이 동일한 새로운 클러스터(Green)를 준비해서 워크로드를 이관하고, 준비된 테스트 시나리오로 새 버전의 클러스터를 충분히 검증한 뒤, 이전 클러스터(Blue)에서 새로운 클러스터(Green)으로 트래픽을 전환하는 방식입니다. 서비스를 제공중인 클러스터 위에서 업데이트 작업이 일어나지 않고, 한번 작업할 때 여러 버전을 건너뛰고 한번에 업데이트를 할 수 있으며, 작업 도중에 문제가 발생할 경우 정상 동작중인 Blue 클러스터로 트래픽을 절체해주는 것만으로 쉽게 롤백을 할 수 있습니다. DevOps 팀은 이 두 방식의 장단점을 고려하여 장애 가능성이 더 낮은 멀티 클러스터를 이용한 Blue/Green 방식의 클러스터 버전 업데이트 방식을 채택하였습니다.

멀티 클러스터를 이용한 Blue/Green 방식의 클러스터 버전 업데이트

다음 다이어그램은 서로 다른 버전의 Amazon EKS 클러스터 2개를 이용하여 Blue/Green 방식으로 클러스터를 업데이트하는 아키텍처를 보여줍니다. Terraform으로 새로운 버전의 Amazon EKS를 생성하고, ArgoCDApp of apps 패턴으로 기존의 어플리케이션과 애드온을 모두 동일하게 옮겨온 뒤, 정해진 내부 검증 절차로 Green 클러스터의 정상 동작 여부를 확인합니다. Green 클러스터의 정상 동작을 확인한 뒤에는 Route 53의 Weighted Routing 기능을 사용하여 Reverse Proxy에서 트래픽을 점진적으로 새로 생성된 Green 클러스터로 보내줍니다. 이때 Green 클러스터에서 이상 동작이 감지되면, 즉시 기존의 Blue 클러스터로 롤백을 실시하고, 이상이 없으면 트래픽을 100% Green 클러스터로 보내고 업데이트 작업을 완료합니다.

DevOps팀은 이 방식을 기반으로 내부적으로 많은 검증을 거친 뒤 지난 2023년 3월 Amazon EKS 클러스터 버전 1.21에서 1.24로 마이너 버전 3개를 한번에 무중단으로 업데이트하는 것에 성공하였습니다. 많은 수의 어플리케이션과 애드온을 신규 클러스터에 동일하게 배포하는 데에는 ArgoCD의 App of apps 패턴이 큰 도움이 되었습니다. ArgoCD는 오픈 소스 GitOps 배포 도구로써 Kubernetes 상에서 동작하며 어플리케이션 및 애드온의 배포를 수행합니다. ArgoCD는 신뢰할 수 있는 단일 소스로 Git을 사용하며, 현재 클러스터의 애플리케이션의 상태를 Git에 정의된 상태와 비교하여 지속적으로 모니터링해서 차이가 있는 경우, 필요한 변경 사항을 수동 또는 자동으로 동기화하여 Git에 정의된 상태와 현재 클러스터의 어플리케이션 상태를 일치시켜줍니다.

ArgoCD는 Application 이라는 사용자 정의 자원 (Custom Resource)을 이용하여 관리중인 어플리케이션의 정보를 담는데, 다음과 같은 YAML Manifest의 형태를 가지고 있습니다.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: order-service
  namespace: argocd
spec:
  destination:
    namespace: demo
    server: https://<my-cluster-endpoint>.eks.amazonaws.com
  project: default
  source:
    path: apps/order-service
    repoURL: https://<my-git-repository>/order-service
    targetRevision: HEAD

ArgoCD의 App of apps 패턴은 이렇게 하나의 어플리케이션 또는 애드온의 정보를 위와 같은 YAML Manifest로 선언적으로 관리할 수 있다는 점에 착안하여, 현재 사용중인 클러스터의 모든 어플리케이션과 애드온의 정보를 하나의 App of apps Manifest에 담아, 마치 Terraform과 같은 Infrastructure as Code 도구가 많은 수의 자원을 선언적으로 한번에 생성하는 것처럼, 많은 수의 어플리케이션과 애드온들을 신규 클러스터에 신속하게 배포할 수 있게 해줍니다.

DevOps 팀은 100개가 넘는 어플리케이션과 애드온을 사용하고 있는데, 처음에 잘 정의된 App of apps Manifest를 만드는데 까지는 시간이 다소 소요되었으나, Manifest가 준비되고 나서부터는 신규 클러스터에 App of apps 패턴으로 기존과 동일한 어플리케이션과 애드온을 배포하는 데에 5분도 걸리지 않았습니다.

App of apps 도입 시 고려 사항

DevOps 팀에서는 이미 모든 어플리케이션과 Istio, Karpenter, AWS Load Balancer Controller 와 같은 애드온들을 Helm Chart를 통한 GitOps로 관리하고 있었기 때문에, App of apps 패턴을 도입하는 것에 크게 어려움을 겪지 않을 것이라고 예상하였습니다. 하지만 실제로 작업을 진행하다보니 다음과 같은 이슈들을 만나게 되었습니다.

첫번째 이슈는 어플리케이션과 애드온들을 합쳐 100개가 넘어가는 App들을 환경별로 다른 클러스터에 배포되도록 App of apps Manifest를 만드는 일이었습니다. 동일한 Manifest 파일을 환경별로 만들려면 많은 공수가 들어가지만 Helm의 변수 기능과 ArgoCD Application의 destination 설정을 활용하여 아래와 같이 destination.server 를 변수화하는 것으로 해결할 수 있었습니다.

# destination.server를 Helm Chart의 value로 전달하여 환경별로 다른 클러스터에 배포되게 하였습니다.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  destination:
    namespace: argocd
    server: {{ .Values.spec.destination.server }}
  project: default
  source:
	  helm:
      valueFiles:
      - {{ .Values.valuesfile }} #App of Apps의 values에 환경별 values 파일을 참조하도록 선언
    path: guestbook
    repoURL: <https://github.com/argoproj/argocd-example-apps>
    targetRevision: HEAD

두번째 이슈는 App과 Addon 사이의 의존성 이슈였습니다. DevOps팀은 Amazon EKS 상에 Service Mesh로 Istio를 설치해서 사용하고 있었고, App이 Istio보다 먼저 설치되면 App이 트래픽을 받지 못하는 일들이 벌어졌습니다. 마찬가지로 Istio가 설치될 때에도 istio-base, istiod, istio-gateway Chart 별로 설치 순서가 지켜져야 합니다. 이 문제를 해결하기 위해 DevOps팀은 어플리케이션을 위한 App of Apps Manifest와 애드온을 위한 App of Apps Manifest를 구분하였고, ArgoCD Sync Waves를 이용하여 하나의 Manifest 안에서의 순서 보장 문제를 해결하였습니다. ArgoCD의 Sync Wave 기능은 App of apps Manifest 내에서 각 Application 마다 argocd.argoproj.io/sync-wave 라는 annotation 설정을 통해 설치 순서를 제어할 수 있는 기능으로, 기본값은 0으로 설정되어 있으나, 이 값을 조절하여 원하는대로 설치 순서를 조절할 수 있게 해줍니다.

가령, 아래와 같은 App of apps Manifest가 있다고 하면, istio-base의 경우엔 wave값이 기본값인 0이고, istiod의 경우에는 wave값이 1이므로, istio-base가 istiod보다 먼저 설치되게 합니다.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: istio-base
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: istiod
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
  annotations:
    argocd.argoproj.io/sync-wave: "1"

App of apps를 통한 배포 후 검증

App of apps를 통해 새로 만들어진 클러스터에 동일한 어플리케이션과 애드온들이 순서에 맞게 배포되는 것을 확인하고 난 뒤에 DevOps팀은 500만대 이상의 셋탑을 사용하는 고객들에게 아무런 영향없이 클러스터를 교체할 수 있는지 여부를 확인해야 했습니다. 이를 위해 다양한 환경에서 기존의 클러스터인 Blue로부터 새로 만들어진 클러스터인 Green으로 무중단 트래픽 전환 테스트를 진행하였습니다.

DevOps팀은 Reverse Proxy를 구성하여 사용중이었기 때문에 실제 트래픽 전환은 Reverse Proxy가 바라보는 Private NLB의 DNS Name을 Route 53의 Weighted Routing 기능을 이용하여 Reverse Proxy가 Route 53을 통해 DNS를 Resolve할 때 정해진 비율로 Weight를 조절함으로써 점진적으로 Green 클러스터를 바라보는 Private NLB로 DNS가 Resolve되는 방식으로 진행하였습니다.

우선 개발 환경에 Green 클러스터를 생성하고, ArgoCD App of apps 패턴으로 모든 어플리케이션과 애드온을 설치한 뒤, 개발 테스트 케이스를 수행하는 수준에서 Green 클러스터에 올라온 중요 API를 개발자 및 DevOps 팀원이 호출해가며 정상 호출 및 에러 유무를 테스트하였습니다.

개발 환경에서의 검증이 통과되면, 그 다음으로는 검증 환경에서 동일한 방식으로 Green 클러스터를 생성하고, 모든 어플리케이션과 애드온을 설치한 뒤, 검증팀의 성능 및 부하 테스트를 통하여 Green 클러스터와 Blue 클러스터를 비교합니다. 그 다음, 성능 및 부하 테스트 결과를 통해 두 클러스터가 동일하거나 Green이 Blue보다 더 나은 성능을 보여주는지 여부를 테스트 하였습니다.

또한, 검증 환경에서는 Apache JMeterPostman을 활용한 API 응답 검증테스트도 수행하여 다양한 테스트 케이스에 해당하는 API를 Blue와 Green 클러스터에 각각 호출하여 각각의 클러스터에서 응답하는 응답값이 실제값과 동일한지 여부를 확인하였습니다.

검증 환경에서의 검증이 통과되면, 셋탑 검증 환경에서 동일한 방식으로 Green 클러스터를 생성하고, 모든 어플리케이션과 애드온을 설치한 뒤, 셋탑 박스를 상용 환경이 아닌, 셋탑 검증 환경의 Green 클러스터 API를 호출하도록 구성한 뒤 셋탑을 통한 서버 호출 및 사용자 시나리오별 테스트를 수행하였습니다.

여러 환경에서 다양한 테스트를 준비하고 수행하는 데에는 많은 시간이 소요되었지만, GitOps를 활용하여 각 환경별로 동일 조건의 클러스터를 만들 수 있었던 것이 많은 도움을 주었고 이 과정에서 수집된 데이터와 학습된 경험은 실제 상용 환경에 이 방식으로 무중단 클러스터 업데이트를 진행할 수 있겠다는 자신감을 갖게 해주었습니다.

실제로 시간을 측정해보았을 때, Terraform으로 새로운 클러스터를 생성하는 시점부터 App of apps 방식으로 모든 어플리케이션과 애드온을 설치한 뒤, 트래픽을 무중단으로 전환하는 데에 걸리는 시간은 테스트와 모니터링 시간을 제외하고 1시간이 채 걸리지 않았습니다. 전환에 걸리는 시간이 짧았던 것은 여러 환경에서 여러 차례 클러스터를 생성하고 어플리케이션과 애드온을 설치하는 과정을 반복하며 DevOps 팀원들이 멀티 클러스터를 이용한 Blue/Green 방식으로 Amazon EKS 클러스터의 버전을 업데이트하는 과정에서 만나는 다양한 문제 상황들을 해결해나가며 전체 전환 과정을 최적화할 수 있었기 때문입니다.

상용 환경 적용과 그 이후

2023년 3월, DevOps 팀은 Amazon EKS 클러스터의 버전을 1.21에서 1.24로 무중단 업데이트하는 것에 성공하였습니다. 모든 검증 및 테스트를 완전히 통과할 때까지 많은 시간을 투자하여 철저하고 다양하게 테스트를 수행했기 때문에 업데이트 과정 중 단 1건의 에러도 발생하지 않았습니다.

이 과정을 통해 DevOps팀은 멀티 클러스터를 이용한 Blue/Green 방식의 클러스터 버전 업데이트가 충분히 상용에 적용가능한 전략이라는 결론을 얻었습니다. 버전별로 달라지는 점에 대해 충분한 조사가 필요하긴 했습니다만, 1.21에서 1.24같이 마이너버전을 한번에 여러 단계 건너뛰고 업데이트할 수 있다는 점도 매력적이었습니다. Amazon EKS의 버전별 중요 업데이트 사항에 대한 가이드는 Amazon EKS Kubernetes 버전 문서를 참조해주시기 바랍니다.

한편, 지난 2023년 5월 24일, Amazon EKS 1.27이 공식 출시되었고, Amazon EKS 1.24의 지원 종료 시점도 2024년 1월로 예정되어 있어 DevOps팀은 가까운 미래에 한차례 더 클러스터 업데이트를 수행해야 합니다. Amazon EKS는 평균 3개월마다 마이너 버전이 릴리즈되고, 릴리즈 된 버전은 최대 14개월까지 지원됩니다. 이러한 짧은 릴리즈 주기는 엔터프라이즈 규모의 서비스를 운영하는 입장에서는 매우 부담스러운 것이 사실입니다.

하지만 DevOps팀은 위의 과정을 통해 클러스터 버전 업데이트 작업이 충분히 준비만 되어 있다면 어렵지 않게 할 수 있다는 것을 알게 되었습니다. 여러 환경에서 반복적으로 테스트를 수행하다보니 Terraform 모듈의 구조를 최적화하거나 aws 이외의 kubernetes, helm 과 같은 다양한 Terraform Provider를 활용하는 경험들도 얻을 수 있었습니다. 이런 경험들이 누적되면서 전체적으로 DevOps 팀원들의 역량이 강화되었고, 이번에 진행했던 부분들 중 부족한 부분을 보완하고 자동화하여 다음 업데이트는 더욱 빠르고 안전하게 수행할 수 있을 거라는 확신도 얻었습니다.

결론

본 게시물에서는 LG U+ IPTV 사업부문 DevOps 팀에서 GitOps를 이용해서 상용 Amazon EKS 클러스터의 버전을 무중단으로 업데이트한 실전 사례에 대해 살펴봤습니다. 이 과정을 통해 DevOps 팀은 향후 클러스터 버전 업데이트에 사용가능한 App of apps 템플릿과 그 운영 노하우를 얻을 수 있었습니다.

멀티 클러스터를 이용한 Blue/Green 방식의 클러스터 버전 업데이트를 이번 기회에 직접 체험해보고자 하시는 분들께서는 AWS 기술 블로그의 Blue/Green, Canary 방법을 활용한 stateless 워크로드의 Amazon EKS 클러스터 마이그레이션 전략 게시글을 참고해주시기 바랍니다.

이름

Taehoon So

소태훈 책임은 LG U+ IPTV 서비스에서 제공하는 모든 서비스의 Amazon EKS 클러스터를 운영하고 있습니다. U+ IPTV 시청 고객들께 더 좋은 고객경험을 드리기 위해 쿠버네티스, 서비스메시, GitOps 등 다양한 컨테이너 운영환경 고도화 기법에 관심이 많습니다.

Sean Lee

Sean Lee

Sean Lee 어플리케이션 아키텍트는 컨테이너와 서버리스 그리고 DevOps를 중심으로, AWS 기반으로 서비스를 구성하고자 하는 고객들께 클라우드 환경에 최적화된 아키텍처 구성을 컨설팅하고 지원하는 역할을 수행하고 있습니다.