본문 바로가기

리눅스 인프라/Docker, Jenkins, Kubernates

Rolling update와 Blue/Green 배포 패턴에 대한 이해, Argocd(Rollouts)을 사용한 Blue/Green 배포 방법

개요 목적

이전 과제를 통해 Argocd와 git허브에 저장되어 있는 helm-chart를 연동하여 kubernetes 배포 자동화 방법에 대해서 알아보았다. 이번 시간에는 지속적 배포 방식 중 다운 타임(중간 타임)을 최소화 하는 가장 많이 사용하는 배포 패턴 두 가지에 대해서 알아본다.(Rolling update - Blue/Green) - 두 배포 패턴의 과정 상 차이와 장 단점에 대해서 알아본다.

그리고 Argo CD에서 Argo Rollouts 라이브러리를 사용하여 Blue/Green 배포를 하는 방법에 대해서 알아본다. (Rollingupdate 배포 방식은 기본적으로 쿠버네티스 배포 전략으로 지원한다.)

Rollingupdate 배포 방식

두 가지 배포 패턴의 가장 큰 차이는 Blue/Green 배포는 두 개의 환경을 사용하는 반면, Rolling 배포는 하나의 환경을 사용한다. Rolling 배포는 기존 환경의 인스턴스를 업데이트된 버전으로 점진적으로 대체하는 방식을 사용한다.

예를 들어, 쿠버네티스에서 Blue를 기존 작동하는 Pod이고, Green은 새롭게 배포 해야 할 pod이라고 가정할 때, Rolling 배포 방식의 과정은

  1. Blue 2개 / Green 0개
  2. Blue 1개 / Green 1개 ← 해당 시점에서 service에 2개 버전의 Pod가 존재함.
  3. Blue 0개 / Green 2개(Green을 새로운 Blue로 등극)

이런 식으로 Blue Pod을 하나씩 Green Pod으로 업데이트하면서 배포를 진행한다.

장점

  • 모니터링 및 롤백

롤링 패턴의 이점은 점진적으로 배포 업데이트를 진행하기 때문에 업데이트 되는 동안 새 환경을 모니터링 할 수 있다. 따라서 문제가 발생하면 롤아웃을 중지하고 이전 버전으로 롤백할 수 있다.

  • 낮은 서비스 사용

새로운 배포가 완전히 작동하는 독립된 공간을 사용하는 Blue/Green보다 롤링 패턴은 적은 리소스 서비스를 사용한다.

단점

  • 속도

롤링 패턴은 업데이트를 구현하는데 많은 시간이 필요한 알고리즘에 의존하여서 업데이트 배포 속도가 Blue/Green 패턴보다 느리다.

  • 하위 호환성

업데이트 시기에 이전 코드와 업데이트 코드가 동일한 환경에 노출되는 시간이 존재한다. 그래서 각 사용자마다 다른 버전을 액세스하는 경우가 발생한다.

Blue/Green 배포 방식

Blue/Green 배포는 현재 인스턴스를 새 환경으로 완전히 전환하기 전에 엄격하게 테스트된 두 번째 환경을 만드는 작업이 수행된다. 독립된 환경에서 새로운 Pod이 실행되면 한번에 기존 Pod과 교체하여 배포를 완료한다.

예를 들면,

  1. Blue 2개 / Green 0개
  2. Blue 2개 / Green 2개 ← 해당 시점에서 service Green 2개로 바로 교체된다.
  3. Blue 0개 / Green 2개

기존 Blue Pod은 active service 리소스에서 실행되고 있고, 업데이트할 Green Pod은 preview service 리소스에서 실행 준비를 맞힌다. Preview에서 실행 준비가 끝나면 기존 active service 리소스를 preview resource로 교체하면서 배포가 완료된다.

장점

  • 유지 관리 기간 없음

유지 관리 기간과 다운 타임을 걱정할 필요 없이 한번에 업데이트 된 버전으로 배포가 완료된다.

  • 안전

업데이트된 인스턴스가 현재 실행 중인 인스턴스와 접촉하지 않기 때문에 훨씬 안전한 경향이 있다. 이전 버전과 호환성을 고려할 필요가 없다.

단점

  • 높은 인프라 비용

업데이트 배포를 위해 두 개의 환경을 사용해야 하기 때문에 Rolling 배포보다 인프라 비용이 높다.

ArgoCD rollout라이브러리 사용하여 Blue-Green 배포하기

목표

window local에서 aws에 eks kubernetes와 argocd에 명령을 보내서 새로운 Blue/Green 배포를 하는 방법을 알아본다.

 

EKS에 Argocd와 Rollouts 라이브러리 설치

  • 먼저 AWS CLI를 사용하여 window local과 eks를 연결한다.
#aws access 토큰으로 로그인하기
aws configure

자신의 acess key ID와 secrete key region 정보를 입력하여 접속한다.

#해당 region에 생성한 eks name 입력하여 eks 연결하기
#aws eks --region (리전입력) update-kubeconfig --name (생성한eks이름)
aws eks --region ap-northeast-2 update-kubeconfig --name eks

그러면 .kube config 파일이 생성된다.

이 이후로 kubectl을 통해서 eks 조작이 가능하다.

  • argo cd 다운로드
#namespace 생성
kubectl create namespace argocd
#다운로드
kubectl apply -n argocd -f <https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml>
#외부 접속을 하기 위해 service를 loadbalance type으로 변경
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'
#argocd에 입장할 비밀번호 확인 아이디는 "admin"이다.
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
  • argo Rollouts 라이브러리 설치
#네임스페이스 생성
kubectl create namespace argo-rollouts 
#다운로드
kubectl apply -n argo-rollouts -f <https://raw.githubusercontent.com/argoproj/argo-rollouts/stable/manifests/install.yaml> 

Blue/Green 배포를 위한 manifest 설정 적용

기존 인스턴스 Blue는 image:hawangdy/api:35를 사용한다. 기존 인스턴스 get /helm 요청을 하게 되면 first라는 Stirng 값을 전달한다. 업데이트할 인스턴스 Green은 image:hwangdy/api:1을 사용한다. GET /helm 요청을 하게 되면 change라는 String 값을 전달한다.

argocd에서 변경을 감지하고 배포를 하게 되면 preview service에서 Green Pod이 실행될 준비를 하고 준비가 완료되면 active service에서 실행되고 있는 Blue Pod을 대체하는 manifest를 알아보자.

# apps/v1 대신 argoproj.io/v1alpha1를 사용한다.
apiVersion: argoproj.io/v1alpha1 
# Deployment 대신 Rollout을 사용한다.
kind: Rollout 
# ==== 이 아래의 내용은 기존 Deployment와 동일하게 작성 ====
metadata:
  name: "api-server"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: "api-server"
  template:
    metadata:
      labels:
        app: "api-server"
    spec:
      containers:
        - name: "api-server"
          image: hwangdy/api:35
          imagePullPolicy: Always
          ports:
            - protocol: TCP
              containerPort: 5511
  # ==== 이 위의 내용은 기존 Deployment와 동일하게 작성 ====
  strategy:
    blueGreen:
      # activeService는 Green이 Blue로 승격 시 새 템플릿 해시로 업데이트 할 Service를 지정
      activeService: "api-server-active"

      # previewService는 Green이 Blue로 승격 되기 전에 새 템플릿 해시로 업데이트 할 Service를 지정
      # 이를 통해 프로덕션 트래픽을 제공하지 않고 미리보기 스택을 통해 테스트 해볼 수 있다.

      previewService: "api-server-preview"

      # autoPromotionEnabled는 승격 직전에 롤아웃을 일시 중지하여 새 스택의 승격을 자동으로 비활성화한다.
      # 이 옵션을 생략하면(또는 true) 기본 동작은 ReplicaSet이 완전히 준비/사용 가능한 즉시 새 스택을 승격시킨다.
      # 이 옵션을 false로 설정 한다면, 다음 명령어를 사용하여 롤아웃을 재개 할 수 있다.
      # `kubectl argo rollouts resume ROLLOUT`
      autoPromotionEnabled: true

---
#active service 설정
kind: Service
apiVersion: v1
metadata:
  name: "api-server-active"
spec:
  selector:
    app: "api-server"
  type: LoadBalancer
  ports:
    - name: http
      port: 5511
      targetPort: 5511
      protocol: TCP

---
#preview service 설정
kind: Service
apiVersion: v1
metadata:
  name: "api-server-preview"
spec:
  selector:
    app: "api-server"
  type: LoadBalancer
  ports:
    - name: http
      port: 5511
      targetPort: 5511
      protocol: TCP

적용 결과 image: hwangdy/api:35→image: hwangdy/api:1 로 바꾸게 되면

preview service에서 api:1의 이미지를 준비하면서 아래 그림처럼 두개의 Pod 실행되는 것을 확인할 수 있다.

preview service에서 api:1의 이미지 준비가 완료되면 기존 Blue Pod은 사라지고 active service자리를 api:1의 이미지의 Green Pod실행되게 된다.


Reference

https://launchdarkly.com/blog/blue-green-deployments-versus-rolling-deployments/

https://medium.com/finda-tech/argo-cd를-이용한-다양한-배포-방식을-지원하는-라이브러리-argo-rollouts-3a205abf7261