Rollout 에서 Istio 를 왜 사용할까?

uchan·2023년 11월 13일
0

배경

최근 k8s 스터디를 진행하면서 이후 프로젝트 진행할 때 블로그에 남기려고 했으나, 내 기억력이 서서히 감퇴되는 것을 보고 믿지 못하기 시작하였다. 그래서 알고리즘, 백엔드 뿐만 아니라 인프라 + 네트워크 관련 스터디 내용도 블로그에 작성하며 공부한 내용을 머리에 각인시키자!

argocd 란?

kubernetes 어플리케이션의 자동 배포를 위한 오픈소스 도구로서, k8s 클러스터에 배포된 어플리케이션의 CD 를 담당한다. Git 저장소에서 변경 사항을 감지하여 자동으로 k8s 클러스터 내 어플리케이션에 배포할 수 있도록 한다.
쉽게 풀어서 말하자면, Git 저장소의 default branch (보통 main 또는 master)에 PR 이 머지하고 production 에 배포할 때 안전하고 일관성있게 배포하는 CD 파이프라인을 argocd 가 담당한다는 뜻이다.

그럼 argo rollout 은 뭔데?

보통 무중단 배포를 할 때 rolling, blue/green, canary 방법을 사용한다. 3가지 배포방법에 대해 블로그에서 그림과 함께 설명이 잘 되어있으니 참고하면 좋을 거 같다.

  • rolling

  • blue/green

  • canary

ref: https://onlywis.tistory.com/10

argocd 에서 위와 같은 배포를 하려면 argo 진영 라이브러리인 argo rollout 을 사용해주어야한다.

카나리 배포에 대해 조금 더 살펴보자

다음과 같은 상황을 가정해보자

  • pod 가 2개인 서비스를 배포할 때
    • stable 2개 -> stable 2개 + canary 1개 -> stable 2개 + canary 2개 -> stable(canary 였던거) 2개 순서대로 배포된다.
    • 이때 두번째 단계 stable 2개 + canary 1개 에서 66:33 으로 트래픽 제어를 가능하다.
    • 그러나 이를 95:5 으로 트래픽 제어가 가능할까?

즉, 적은 복제본 개수를 가지고 미세하게 트래픽제어를 하고싶은데 argo rollout 만을 이용해선 이를 가능케 할 수 없다. 이를 해결하려면 트래픽 제어 모듈이 필요한데 이를 위해 argo rollout + istio 가 등장하는 것이다

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 first setWeight 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 등의 트래픽 제어 모듈이 필요하다!

실험

ref: https://argoproj.github.io/argo-rollouts/features/traffic-management/istio/#subset-level-traffic-splitting

source codes
  • Rollout
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
  • Service
apiVersion: v1
kind: Service
metadata:
  name: rollout-example
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: rollout-example
  • VirtualService
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
  • DestinationRule
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
  • Gateway (레퍼런스에는 없어서 직접 코드 작성)
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:
    - "*"

위 레퍼런스에 나온대로 코드를 작성하고 추가로 다음 작업을 진행하였다

  • 앱 서비스 파드에 envoy sidecar container 가 존재하지 않아 해당 파드가 존재하는 네임스페이스에 istio-injection=enabled 레이블을 추가하였다
  • istio 를 거쳐서 트래픽이 전달되도록 앱 서비스의 virtual service 앞 단에 gateway 를 추가하였다.

result

  • argo rollout만 사용하여 배포한 경우 (stable 2개, canary 1개)

    • setWeight 을 5% 로 지정했지만 파드 개수에 의해서 트래픽이 제어되다 보니 적은 복제본 수에서 미세하게 트래픽 컨트롤 불가하다
  • argo rollout + istio traffic management (stable 2개, canary 1개)

    • setWeight 을 5% 로 지정하였더니 적은 복제본 수에서도 미세하게 트래픽 컨트롤 가능하다

7개의 댓글

comment-user-thumbnail
2024년 3월 15일

안녕하세요. 해당 내용 ArgoCD GitOps를 사용하여 동일하게 세팅중입니다. 그러나, 세팅 후에 VirtualService에서 Weight를 변경하면 에러가 발생하는데요, Weight 조절이 가능한걸까요 ? 혹시 부가적인 작업이 더 있나해서 문의드립니다.

기존)
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: 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: 95
    • destination:
      host: rollout-example
      subset: canary # referenced in canary.trafficRouting.istio.destinationRule.canarySubsetName
      weight: 5
2개의 답글