반응형
이번엔 트래픽을 조절하면서 Canary 배포를 해보겠습니다.
왜 Canary 배포 + 헤더 기반 트래픽 분기를 도입했는가?
- 기존 방식 (RollingUpdate)의 한계
- 기존 배포 방식(RollingUpdate)은 새 버전의 파드를 조금씩 올리면서 기존 파드를 내림
- 이 과정에서 사용자가 기존 파드에 연결되어 작업 중이면, 세션 끊김/진행 중인 요청 실패/예상치 못한 오류가 발생할 수 있음
- Canary 배포 전략 도입
- 이러한 문제를 최소화하기 위해, 새 버전의 파드를 일부 트래픽에만 점진적으로 적용
- 초기에 적은 비율만 새 버전으로 넘기고, 문제가 없는지 충분히 관찰
→ 장애/버그가 발생해도 전체 서비스에는 영향이 최소화
- 헤더 기반 트래픽 분기 활용
- 추가로, 트래픽에 특정 조건(예: 헤더)을 걸어
- 내부 테스트, 운영자, 베타 사용자 등 일부 그룹에게만 먼저 새 버전을 제공
- 일반 사용자는 안정적인 기존 버전을 계속 이용 가능
- 이 방식 덕분에
- 신규 유저/특정 유저는 바로 새로운 버전 체험 가능
- 기존 작업 중인 유저의 서비스 연속성 보장
- 전체 배포로 전환하기 전까지 버그 및 문제를 사전 검증할 수 있음
4.결과적으로
- 사용자 경험의 연속성을 지키면서
- 운영 리스크를 줄이고
- 배포/릴리즈의 유연성과 품질을 동시에 확보할 수 있음
이제 실습을 통해 좀 더 자세히 알아보겠습니다.
- 사전 준비
먼저 nginx 를 사용해서 index.html 에서 Blue, Green이 표시 되도록 이미지 두 개를 생성해주도록 하겠습니다.
Blue_index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Blue</title> </head> <body> <h1>Blue</h1> </body> </html>
Blue_Dockerfile
# 기본 이미지를 nginx:latest 로 사용 FROM nginx:latest # 현재 디렉터리에 있는 index.html 파일을 컨테이너 내 /usr/share/nginx/index.html 위치에 복사 COPY index.html /usr/share/nginx/html/index.html # 80 포트를 사용하겠다는 선언 EXPOSE 80 # nginx 서비스를 forground에서 실행 CMD ["nginx", "-g", "daemon off;"]
Green_index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Green</title> </head> <body> <h1>Green</h1> </body> </html>
Green_Dockerfile
# 기본 이미지를 nginx:latest 로 사용 FROM nginx:latest # 현재 디렉터리에 있는 index.html 파일을 컨테이너 내 /usr/share/nginx/index.html 위치에 복사 COPY index.html /usr/share/nginx/html/index.html # 80 포트를 사용하겠다는 선언 EXPOSE 80 # nginx 서비스를 forground에서 실행 CMD ["nginx", "-g", "daemon off;"]
이제 각 Dockerfile을 빌드하여 Public 레포지토리에 넣어주면 됩니다. (저는 제 Dockerhub에 넣었습니다)
그리고 Istio 설치 및 Istio-ingressgateway 작업은 아래 링크를 보고 따라 하시면 됩니다.
이제 실습 사전 준비가 되었으니까 rollout 부터 설치해보도록 하겠습니다.
Argo Rollout 설치
helm repo add argo https://argoproj.github.io/argo-helm helm install my-argo-rollouts argo/argo-rollouts
Rollout.yaml 작성
apiVersion: argoproj.io/v1alpha1 kind: Rollout metadata: name: kingsuhan namespace: default spec: replicas: 3 revisionHistoryLimit: 2 # 배포 기간 동안 이전 버전의 파드의 개수 selector: matchLabels: app: kingsuhan template: metadata: labels: app: kingsuhan version: blue spec: containers: - name: kingsuhan image: kingsuhan/nginx:blue ports: - containerPort: 80 strategy: canary: canaryService: kingsuhan-canary # 신규 배포된 애플리케이션과 연결될 서비스 stableService: kingsuhan-stable # 기존 배포되었던 애플리케이션과 연결된 서비스 trafficRouting: # 여기서 트래픽 라우팅은 istio로 정의 istio: virtualService: name: kingsuhan # 생성할 VirtualService의 이름 routes: - primary # VirtualService에서 조정할 라우팅 이름 steps: # 배포 비율 정의 - setWeight: 10 - pause: { duration: 2m } - setWeight: 50 - pause: { duration: 3m } - setWeight: 100
이제 Rollout과 연결될 서비스 생성
apiVersion: v1 kind: Service metadata: name: kingsuhan-stable namespace: default spec: selector: app: kingsuhan ports: - port: 80 targetPort: 80
apiVersion: v1 kind: Service metadata: name: kingsuhan-canary namespace: default spec: selector: app: kingsuhan ports: - port: 80 targetPort: 80
Istio Gateway 리소스 정의
apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: kingsuhan-gateway namespace: default spec: selector: istio: gateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "kingsuhan.outcode.ai" # ALB Ingress에서 정의한 hosts 명 넣으면 됩니다.
VirtualService 정의
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: kingsuhan namespace: default spec: hosts: - kingsuhan.outcode.ai gateways: - kingsuhan-gateway http: - name: primary # 배포 될 때 rollout이 관리하는 라우팅 규칙 route: - destination: host: kingsuhan-stable.default.svc.cluster.local port: number: 80 weight: 100 - destination: host: kingsuhan-canary.default.svc.cluster.local port: number: 80 weight: 0 - match: # 헤더 값에 "x-version: new" 가 존재하는 사용자들의 트래픽 조절 - headers: x-version: exact: "new" route: - destination: host: kingsuhan-canary.default.svc.cluster.local port: number: 80 weight: 100 # 새롭게 배포되는 서비스로만 트래픽이 가도록 설정 - destination: host: kingsuhan-stable.default.svc.cluster.local port: number: 80 weight: 0
결과 확인
curl -H "x-version: new" https://kingsuhan.outcode.ai
헤더에 “x-version: new” 값을 넣고 호출을 하면,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Green</title>
</head>
<body>
<h1>Green</h1>
</body>
</html>
이렇게 새롭게 배포된 내용만 보이게 됩니다.
감사합니다.
반응형
'Monitoring' 카테고리의 다른 글
Istio ingressgateway 와 ALB 연결 (0) | 2025.07.24 |
---|---|
Istio, Kiali 설치 및 Prometheus, Grafana 연결 (Using Helm) (3) | 2025.07.24 |
telegraf <-> Prometheus <-> Grafana 연결하여 모니터링 해보기 (1) | 2024.11.21 |
Prometheus - Grafana 설치 (Helm 차트) (0) | 2024.11.15 |
ELK 연결 구성 (filebeat 포함) (4) | 2024.09.24 |