EKS/Jenkins & ArgoCD

EKS CICD Automation - 4. ArgoCD Blue/Green Deployment

Camouflage129 2020. 9. 7. 11:54

공식 다큐는 아래와 같습니다.

argoproj.github.io/argo-rollouts/features/bluegreen/

 

BlueGreen - Argo Rollouts - Kubernetes Progressive Delivery Controller

BlueGreen Deployment Strategy A Blue Green Deployment allows users to reduce the amount of time multiple versions running at the same time. Overview In addition to managing ReplicaSets, the rollout controller will modify a Service resource during the BlueG

argoproj.github.io

https://hub.helm.sh/charts/argo/argo-rollouts

 

https://hub.helm.sh/charts/argo/argo-rollouts

 

hub.helm.sh

 

먼저, 블루그린 배포를 할때, ArgoCD Project에서 만든 Rollout Object를 사용해야 합니다.

이 Object를 인식시켜주기 위해서 아래와 같이 helm으로 설치하도록 하겠습니다.

 

rollout.yaml

 

controller:
  nodeSelector: 
    nodegroup-type: MANAGE

 

rollout 설치 명령어

 

helm install -f rollout.yaml -n argocd argo-rollouts argo/argo-rollouts

 

자, 이제 준비는 끝났으니 Blue Green 배포가 되는 방식을 알아보도록 하겠습니다.

 

기존 포스터들을 다 읽으셨다면, 혹은 ECS를 사용해보셨다면 ECS의 블루그린 배포방식과 유사하다고 생각하시면 됩니다.

 

Target 그룹이 두개가 있어 하나의 남는 타겟그룹에 서비스를 띄우고 트래픽을 이전하는 것과 유사합니다.

 

Preview Service와 Active Service 두개로 나뉘어 Active Service는 기존 서비스에 대해 트래픽을 전달하다가,

 

 

새로운 배포가 생기면 Preview Service에 새 파드들을 띄우고 (개수를 지정할 수 있습니다.)

 

 

이상이 없으면 전체 파드 수 만큼 띄운 후 Active Service가 해당 파드들로 트래픽을 이전하게 되는 방식입니다.

 

 

따라서 Service는 아래와 같이 두개를 띄워주도록 하겠습니다.

 

Active Service

apiVersion: v1
kind: Service
metadata:
  labels:
    app: phh-fo
    service: phh-fo
  name: phh-fo
  namespace: phh-test-fo
spec:
  ports:
    - port: 9000
      name: http
      protocol: TCP
  selector:
    app: phh-fo

 

Preview Service

apiVersion: v1
kind: Service
metadata:
  labels:
    app: phh-fo-prv
    service: phh-fo-prv
  name: phh-fo-prv
  namespace: phh-test-fo
spec:
  ports:
    - port: 9090
      name: http
      protocol: TCP
  selector:
    app: phh-fo

 

그리고 해당 Deployment에 대해서는 Deployment가 아닌, Rollout으로 오브젝트를 만들어 배포해주셔야 합니다.

 

apiVersion: argoproj.io/v1alpha1 # Changed from apps/v1
kind: Rollout # Changed from Deployment
# ----- Everything below this comment is the same as a deployment -----
metadata:
  name: phh-fo
  namespace: phh-test-fo
spec:
  selector:
    matchLabels:
      app: phh-fo
  replicas: 2
  template:
    metadata:
      labels:
        app: phh-fo
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: nodegroup-type
                operator: In
                values:
                - FRONTEND
      terminationGracePeriodSeconds: 30
      containers:
      - image: {{ ECR Repo }}
        imagePullPolicy: Always
        name: phh-fo
        ports:
        - containerPort: 9000
        lifecycle:
          preStop:
            exec:
              command:
              - sh
              - -c
              - curl --silent http://localhost:9000/change/readiness/refuse
        livenessProbe:
          exec:
            command:
            - sh
            - -c
            - curl --silent http://localhost:9000/sys/healthz/liveness | grep -q '^{\"status\"\:\"UP\".*}$'
            - echo $?
          initialDelaySeconds: 15
          periodSeconds: 30
          failureThreshold: 3
          timeoutSeconds: 1
        readinessProbe:
          exec:
            command:
            - sh
            - -c
            - curl --silent http://localhost:9000/sys/healthz/readiness | grep -q '^{\"status\"\:\"UP\".*}$'
            - echo $?
          initialDelaySeconds: 15
          periodSeconds: 10
          failureThreshold: 3
          timeoutSeconds: 1
        env:
        - name: LOG_TYPE
          valueFrom:
            configMapKeyRef: 
              name: spring-info
              key: log-type
        - name: PROJECT
          valueFrom:
            configMapKeyRef: 
              name: spring-info
              key: project
        - name: BO_CORE_DNS
          valueFrom:
            configMapKeyRef: 
              name: spring-info
              key: bo-core-dns
        - name: FULENTD_SERVER_IP
          valueFrom:
            configMapKeyRef: 
              name: spring-info
              key: fluentd-sever-ip
  minReadySeconds: 30
  revisionHistoryLimit: 3
  strategy:
  # ----- Everything above this comment are the same as a deployment -----
    blueGreen: # A new field for the Blue Green strategy options
      previewService: phh-fo-prv # Reference to a service
      activeService: phh-fo # Reference to a service
      autoPromotionEnabled: true
      previewReplicaCount: 1
      scaleDownDelaySeconds: 60  #전환후 이전 active pod 삭제 대기 시간

 

# 사이에 있는 부분이 기존 Deployment와 동일한 부분이라고 보시면 됩니다.

 

간단하게 꼭 필요한 부분만 설명해드리도록 하겠습니다.

 

previewService는 위의 배포 방식 설명 처럼, 새 버전의 파드를 띄우고 테스트해보기 위한 부분이며,

activeService는 실제 배포된 파드들이 서비스 되는 부분입니다.

 

previewReplicaCount는 blue green 배포를 할때, 파드를 먼저 몇개를 띄워 테스트를 해볼 것인지 정하는 개수이며,

리소스를 절약하기 위해 저는 1개를 띄우고 하나의 파드가 이상이 없으면 전체 기존 파드 개수만큼 띄우게 하였습니다.

 

scaleDownDelaySeconds는 새 파드들로 트래픽이 이전된 후 몇초 후 기존 파드들을 종료시킬 것인지 정하는 대기시간입니다.

저는 1분으로 이 시간을 정해두었습니다.

 

마지막으로 Jenkins Pipeline Code는 사실 이전 롤링과 다를게 없습니다.

Deployment.yaml을 수정하던 부분에서 Rollout.yaml에 있는 컨테이너 버전만 바꿔주시면 됩니다.

 

ArgoCD를 통한 EKS Blue Green 배포에 대해서 알아봤습니다.