地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【k8s】ArgoRolloutsでカナリアリリースを試す

概要

github.com

ArgoRolloutsを使ってさくっとカナリアリリースを試す記事です

ArgoRolloutsとは

KubernetesのCRDで標準ではできないブルーグリーンデプロイやカナリアリリースなどの高度なデプロイ機能を提供するOSSです。ArgoCDと組み合わせることでGitOpsのさらなる広がりを感じることのできるツールです。

Progressive Deliveryとは

Progressive DeliveryはCD++みたいな感じで言われていてCDで解決できなかった問題を解決する手段を兼ね備えたCDのような考え方。全てのユーザー向けに新しい機能を公開する前に、デプロイしたアプリケーションに対する評価を行うフェーズを設けて評価の結果次第で進めるかロールバックを行うかを決める。従来のデリバリーに「分析」という観点を加えることでこれまでのデプロイで行っていた動作確認なんかをカナリアリリース中に自動で行うというもの。ArgoRolloutsではこの分析なんかまで設定を行うことができて分析結果次第でロールバックなんかの判断を自動で行うことができる。

準備

① ArgoRolloutsのインストール

$ kubectl create namespace argo-rollouts
$ kubectl apply -n argo-rollouts -f https://raw.githubusercontent.com/argoproj/argo-rollouts/stable/manifests/install.yaml

$ kubectl get crd rollouts.argoproj.io
NAME                   CREATED AT
rollouts.argoproj.io   2021-01-11T13:02:10Z

② ArgoRolloutsのプラグインのインストール

$ curl -LO https://github.com/argoproj/argo-rollouts/releases/latest/download/kubectl-argo-rollouts-linux-amd64
$ chmod +x ./kubectl-argo-rollouts-linux-amd64
$ sudo mv ./kubectl-argo-rollouts-linux-amd64 /usr/local/bin/kubectl-argo-rollouts

$ kubectl argo rollouts version
kubectl-argo-rollouts: v0.10.2+54343d8
  BuildDate: 2020-12-17T20:46:09Z
  GitCommit: 54343d8c9eb1e4b9f7e87b3da533530199916733
  GitTreeState: clean
  GoVersion: go1.13.1
  Compiler: gc
  Platform: linux/amd64

マニフェストの全容から

ざっくり以下のようにyamlを書くことでカナリアリリースを行うことができます。基本的には.spec.strategy.canary.stps以外は実はDeploymentと共通の項目をかけるので標準機能のローリングアップデートを使っているなら特に困ることなく導入できてしまいます。

apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-demo
spec:
  replicas: 5
  strategy:
    canary:
      steps:
      - setWeight: 20
      - pause: {}
      - setWeight: 60
      - pause: {duration: 10}
      - setWeight: 80
      - pause: {duration: 10}
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: rollouts-demo
  template:
    metadata:
      labels:
        app: rollouts-demo
    spec:
      containers:
      - name: rollouts-demo
        image: ryuichi1208/color:blue
        ports:
        - name: http
          containerPort: 5000
          protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: rollout
spec:
  type: NodePort
  ports:
  - name: node-port
    protocol: TCP
    port: 5001
    targetPort: 5000
  selector:
    app: rollouts-demo

カナリアリリースをやっている箇所は具体的には以下です。

      - setWeight: 20
      - pause: {}
      - setWeight: 60
      - pause: {duration: 10}
      - setWeight: 80
      - pause: {duration: 10}

setWeightは、送信する必要のあるトラフィックの割合を示します。割合なので今回のサンプルだと20%で1つのpodとなり第一フェーズでは1つのpodのみが新規のpodとなります。

pause構造体はロールアウトに一時停止するように指示します。durationを指定することでそのフェーズの時間を指定することができます。何も指定しない場合は外部からアクションを行わない限りは次フェーズへも行かないしロールバックも起きません。ログなどから人間が判断して先に進めるかを決断します。

# 先に進める場合
$ kubectl argo rollouts promote rollouts-demo

# 異常があってロールバックする場合
$ kubectl argo rollouts abort rollouts-demo