최근 k8s 스터디를 진행하면서 이후 프로젝트 진행할 때 블로그에 남기려고 했으나, 내 기억력이 서서히 감퇴되는 것을 보고 믿지 못하기 시작하였다. 그래서 알고리즘, 백엔드 뿐만 아니라 인프라 + 네트워크 관련 스터디 내용도 블로그에 작성하며 공부한 내용을 머리에 각인시키자!
kubernetes 어플리케이션의 자동 배포를 위한 오픈소스 도구로서, k8s 클러스터에 배포된 어플리케이션의 CD 를 담당한다. Git 저장소에서 변경 사항을 감지하여 자동으로 k8s 클러스터 내 어플리케이션에 배포할 수 있도록 한다.
쉽게 풀어서 말하자면, Git 저장소의 default branch (보통 main 또는 master)에 PR 이 머지하고 production 에 배포할 때 안전하고 일관성있게 배포하는 CD 파이프라인을 argocd 가 담당한다는 뜻이다.
보통 무중단 배포를 할 때 rolling, blue/green, canary 방법을 사용한다. 3가지 배포방법에 대해 블로그에서 그림과 함께 설명이 잘 되어있으니 참고하면 좋을 거 같다.
rolling
blue/green
canary
ref: https://onlywis.tistory.com/10
argocd 에서 위와 같은 배포를 하려면 argo 진영 라이브러리인 argo rollout 을 사용해주어야한다.
다음과 같은 상황을 가정해보자
즉, 적은 복제본 개수를 가지고 미세하게 트래픽제어를 하고싶은데 argo rollout 만을 이용해선 이를 가능케 할 수 없다. 이를 해결하려면 트래픽 제어 모듈이 필요한데 이를 위해 argo rollout + istio 가 등장하는 것이다
k8s 에서 트래픽 컨트롤 관련 오픈소스로 유명하다. 이를 통해 라우팅 처리, 트래픽 제어 등을 할 수 있다. argo rollout 에서는 istio 를 이용하여 위와 같은 문제를 해결할 수 있다.
reference: https://argo-rollouts.readthedocs.io/en/stable/features/canary/
If the canary Rollout does not use traffic management, the Rollout makes a best effort attempt to achieve the percentage listed in the last
setWeight
step between the new and old version. For example, if a Rollout has 10 Replicas and 10% for the firstsetWeight
step, the controller will scale the new desired ReplicaSet to 1 replicas and the old stable ReplicaSet to 9. In the case where the setWeight is 15%, the Rollout attempts to get there by rounding up the calculation (i.e. the new ReplicaSet has 2 pods since 15% of 10 rounds up to 2 and the old ReplicaSet has 9 pods since 85% of 10 rounds up to 9). If a user wants to have more fine-grained control of the percentages without a large number of Replicas, that user should use the traffic management functionality.
예를 들어, 2개의 복제본을 가지고 50퍼 비율로 카나리 배포를 할 때 카나리 상태의 1개와 안정 상태의 1개로 유지하면 순차적으로 배포가 진행될 것이다. 만약 20퍼 비율로 카나리 배포를 한다면 어떻게 배포가 될까?
⇒ 적은 복제본에서 미세하고 세밀한 트래픽제어를 하려면 istio 등의 트래픽 제어 모듈이 필요하다!
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollout-example
spec:
replicas: 2
revisionHistoryLimit: 2
selector:
matchLabels:
app: rollout-example
template:
metadata:
labels:
app: rollout-example
spec:
containers:
- name: rollout-example
image: argoproj/rollouts-demo:yellow
imagePullPolicy: Always
ports:
- containerPort: 8080
strategy:
canary:
trafficRouting:
istio:
virtualService:
name: rollout-vsvc # required
routes:
- primary # optional if there is a single route in VirtualService, required otherwise
destinationRule:
name: rollout-destrule # required
canarySubsetName: canary # required
stableSubsetName: stable # required
steps:
- setWeight: 5
- pause:
duration: 1m
apiVersion: v1
kind: Service
metadata:
name: rollout-example
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: rollout-example
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: rollout-vsvc
spec:
gateways:
- istio-rollout-gateway
hosts:
- "lb 주소"
http:
- name: primary # referenced in canary.trafficRouting.istio.virtualService.routes
route:
- destination:
host: rollout-example
subset: stable # referenced in canary.trafficRouting.istio.destinationRule.stableSubsetName
weight: 100
- destination:
host: rollout-example
subset: canary # referenced in canary.trafficRouting.istio.destinationRule.canarySubsetName
weight: 0
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: rollout-destrule
spec:
host: rollout-example
subsets:
- name: canary # referenced in canary.trafficRouting.istio.destinationRule.canarySubsetName
labels: # labels will be injected with canary rollouts-pod-template-hash value
app: rollout-example
- name: stable # referenced in canary.trafficRouting.istio.destinationRule.stableSubsetName
labels: # labels will be injected with stable rollouts-pod-template-hash value
app: rollout-example
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-rollout-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
위 레퍼런스에 나온대로 코드를 작성하고 추가로 다음 작업을 진행하였다
istio-injection=enabled
레이블을 추가하였다argo rollout만 사용하여 배포한 경우 (stable 2개, canary 1개)
argo rollout + istio traffic management (stable 2개, canary 1개)
안녕하세요. 해당 내용 ArgoCD GitOps를 사용하여 동일하게 세팅중입니다. 그러나, 세팅 후에 VirtualService에서 Weight를 변경하면 에러가 발생하는데요, Weight 조절이 가능한걸까요 ? 혹시 부가적인 작업이 더 있나해서 문의드립니다.
기존)
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: rollout-vsvc
spec:
gateways:
hosts:
http:
route:
host: rollout-example
subset: stable # referenced in canary.trafficRouting.istio.destinationRule.stableSubsetName
weight: 100
host: rollout-example
subset: canary # referenced in canary.trafficRouting.istio.destinationRule.canarySubsetName
weight: 0
변경)
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: rollout-vsvc
spec:
gateways:
hosts:
http:
route:
host: rollout-example
subset: stable # referenced in canary.trafficRouting.istio.destinationRule.stableSubsetName
weight: 95
host: rollout-example
subset: canary # referenced in canary.trafficRouting.istio.destinationRule.canarySubsetName
weight: 5