ArgoCD를 이용한 무중단 배포하기(Canary 방식, argo-rollout)
운영환경에 어떻게 배포하는지 Continuous Delivery/Deployment에 대해 알아보자.
Deployment는 그냥 바로 배포 때려버리는거고, delivery는 그냥 deploy전에 명시적 승인 절차를 마지막에 한번 두는거라는 차이점이 있다.
신뢰할수 있는 테스트 진행, 무중단 배포가 가능하다는 전제 하에 Deployment 배포가 되어야한다.
배포시 고려해야할 사항
- 애플리케이션 다운타임 최소화
- 사용자에게 미치는 영향 최소화
- 실패한 배포를 안정적으로 롤백하는 방법
무중단 배포의 전략
다운타임 없이 서버를 운영할 수 있다.
그러니까, 서버의 중단 없이 업데이트를 이루는 배포 전략을 말한다.

Rolling 배포
서버를 차례대로 업데이트 시키는 방식.
장점 :
인스턴스를 추가하지 않아 관리가 간편
단점 :
사용중인 인스턴스에 트래픽이 몰릴 수 있음
구버전과 신버전의 공존으로 인한 호환성 문제

Canary 배포
신버전을 소수의 사용자들에게만 배포
문제없는거 확인되면 점진적으로 다른 서버에 신버전을 배포
장점 :
문제 상황을 빠르게 감지 가능
a/b 테스트로 활용 가능
단점 :
모니터링 관리 비용
구버전과 신버전의 공존으로 인한 호환성 문제

Blue / Green 배포
구버전을 Blue, 신버전을 Green으로 지칭
구버전과 동일하게 신버전의 인스턴스를 구성
신버전 배포시 AI 로드 밸런서를 통해 신버전으로만 트래픽을 전송
장점 :
배포 속도가 빠름
신속하게 롤백 가능
기존 버전의 환경을 다음 배포에 재사용
단점 :
시스템 자원이 2배로 필요
기존 k8s의 배포 방식은 Rolling Update로, Pod를 중단시킨 후에 배포한다.
소프트웨어나 애플리케이션의 새로운 버전을 전체적으로 RollOut 하지 않고 일부 사용자 혹은 일부 환경에만 배포
새로운 기능이나 업데이트가 미치는 영향을 확인하고 문제를 식별하는 안전한 방법을 제공
Service에 이용되는 Pod의 수를 조정하거나, ELB Ingress에 연결되는 Service를 조정하는 방법도 있다.
Argo Rollouts를 사용하는 경우
커스텀 리소스 Rollout를 정의해서 Blue-Green, Canary 배포 등을 지원
Argo CD UI에서 활용 가능해서 편하고, Istio Virtual Service를 이용할 수도 있다.
필요 사항 : Argo Rollout Controller 설치와 Custom Resource 정의
Ingress controller integration : NGINX, ALB, Apache APISIX
Service Mesh integration : Istio, SMI 를 지원한다.
Argo Rollout 설치
Github에서 v1.6.2 로 진행했다.
https://argoproj.github.io/rollouts/
Argo Rollouts
Advanced Kubernetes deployment strategies such as Canary and Blue-Green made easy.
argoproj.github.io
kubectl create namespace argo-rollouts
wget https://github.com/argoproj/argo-rollouts/releases/download/v1.6.2/install.yaml -O argo-rollouts-v1.6.2-install.yaml
kubectl apply -n argo-rollouts -f argo-rollouts-v1.6.2-install.yaml
Argo-rollout 리소스에 관한 정의와 환경 설정 생성
k9s에서 확인하면 Argo Rollout에 관한 Pod이 동작중인 것을 확인할 수 있다.

Rollout 리소스로 Helm Chart template 수정
- 우선, Canary Chart를 복제한다.
Deployment.yaml → rollout-canary.yaml로 수정
코드는 지웠습ㄴ다
배포 전략을 Canary로 해서 setWeight를 통해 20%만 배포하겠다.
난 배포하고 pause로 멈추도록 의도했는데 이게 싫으면 duration:600 → 10분 후에 이상없으면 자동으로 배포하도록 할 수 있다.
배포할 프로젝트에 spring-boot-actuator 의존성을 추가해서 health와 info 정보를 check하도록 하자.
https://downfa11.tistory.com/22
Spring Boot Actuator를 이용한 Kubernetes Pod의 Health check
Spring Boot AcutatorHealth Check와 상태 정보(Metrics) 제공 같은 공통 기능들을 마이크로서비스마다 각각 만드는건 비효율적이라, 쉽게 적용할 수 있는 프레임워크Spring Cloud의 Component가 아니라, Spring Bo
downfa11.tistory.com
k8s cluster 내에 Argo 라는 code deploy 라이브러리를 설치
https://github.com/argoproj/argo-cd
GitHub - argoproj/argo-cd: Declarative Continuous Deployment for Kubernetes
Declarative Continuous Deployment for Kubernetes. Contribute to argoproj/argo-cd development by creating an account on GitHub.
github.com
kubectl create namespace argocd
HA를 지원하지 않는 버전으로 실행
그냥 default하게 configMap을 쓸려면 인증서가 필요함 >> 그래서 없이하도록 하겠음
Ingress에 관한 파일과 kustomization 파일을 작성해주자
얘네는 kubectl apply -k로 리소스를 생성해준다.
여기서 삽질을 좀 햇는데.. Ingress의 주소가 안뜨는 오류를 만났음.
결국 내가 Load Balancer Controller를 적용안해서 생긴 문제였고, 해결후 k9s에서 다음과 같이 확인할 수 있었다.

로드밸런서의 프로비져닝을 마치는대로 해당 주소를 통해 Argo로 접속할 수 있다.

짠. 다음과 같이 대시보드를 열 수 있다.
Argo에 Repository와 애플리케이션을 등록하면 k8s Manifest를 통해 Helm chart를 배포할 수 있다.
다시 Argo CD 접속하는데 원래 ELB 키는데 좀 걸리니 진정해 김남석!
결과 :

테스트
20%를 배포해보고 오류가 없고 괜찮다? 전체 다 배포해야한다.


Blue-Green 방식은 Canary와 크게 다르지 않은데 이정도만 소개하겠음
성격상.. CD도 deployment보다 delivery가 더 취향이고
Blue Green 방식보다 Canary가 취향이다… mbti 느낌
둘다 실습은 해봤는데, 취향안타서 그런지 정이 안간다. 근데 방법 자체는 Canary와 크게 다르지 않은 것만 알아두자.
rollout-blueGreen.yaml 코드
blueGreen:
autoPromotionEnabled: false
activeService: {{ include "membership-service-chart.fullname" }}
previewService" {{ include "membership-service-chart.fullname" }}-preview
... Canary와 동일
activeService와 previewService가 blue와 green 구분하는 셈이다.
실습을 위해 autoPromotionEnabled는 false 체크했다.
트러블 슈팅 - 무중단 배포시 504 gateway time-out 오류
무중단 배포 과정에서 504 Gateway Time-out이 벌어지는데, 수정해보자

- pod이 생성하는데 트래픽 받을 준비되기 전에 요청이 들어오는 상황
- pod이 종료됐는데 계속 요청이 가는 상황
- 로드밸런서가 k8s로부터 해당 pod 종료 소식을 듣기 전에 요청을 보낸거
1번 상황 - Readiness Probe와 Initial delay를 넉넉하게 줬기에 Pod가 준비되기 전에 요청을 받지 않을거다.
2번 상황 - Pod가 종료되면서 종료하는데 준비 시간이 필요하다.
3번 상황 - ALB는 k8s API로부터 Pod의 상태 변화를 실시간으로 받아야 하는데, Pod의 종료 소식을 듣기 전에 먼저 요청을 보내게 되는 경우가 자주 생긴다.
> health check 주기를 줄여서 Pod의 상태 변화를 빠르게 반영하도록 해주면 된다.
사실 2번과 3번이 유사한데, k8s cluster가 아직 Pod의 종료를 인식 못한건지 로드밸런서가 인식을 못한건지의 차이이다.
2번 상황의 업데이트 지연을 해결해보자
ALB에서 Target Group이 삭제 된 후에 Pod 이 종료되도록 처리하면 된다.
→ preStop Hook으로 인위적인 Delay 시간을 추가한다.
그냥 리눅스 명령어로 잠깐 sleep해서 처리한다.
엥 이거 말고 어떤 방법이 있을까..??? 이건 더 공부해보겠음
우아한 연결종료(Graceful shutdown)이나 로드밸런서 설정 최적화도 나온다
ALB 504 gateway error - https://hoohoo.top/blog/20221005104324-aws-elb-return-5xxs-error-504-gateway-timeout/
요즘 자료 찾으면 중국애들꺼가 자주 나온다.
(해결) Unable to create application: application spec for .. is invalid 오류
Unable to create application: application spec for *-canary is invalid: InvalidSpecError: repository not accessible: repositories not accessible: &Repository{Repo: "git@github.com:*.git", Type: "", Name: "", Project: ""}: repo client error while testing repository: rpc error: code = Unknown desc = error testing repository connectivity: error creating SSH agent: "SSH agent requested but SSH_AUTH_SOCK not-specified"
> Setting에 Repository SSH 연결 먼저 해야 앱 등록이 된다.
(해결) Resource not found in cluster 오류
Resource not found in cluster: argoproj.io/v1alpha1/Rollout:dev-*
Resource not found in cluster: v1/Service:dev-*
처음에 앱 생성할때 AUTO-INCREMENT NAMESPACE 안해서 apps가 없는 오류
