スピードが求められる今のソフトウェア開発において、革新性と信頼性は両立してこそ価値があります。プログレッシブデリバリーを使えば、新機能を安全に、段階的に、そしてコントロールしながらリリースできます。Kubernetesのような変化の激しい環境では、サービスの安定性を保ちつつイノベーションを継続するうえで、プログレッシブデリバリーが大きな役割を果たします。
Argo Rolloutsを使ったことがある方なら、こうした段階的デプロイをいかにスマートに管理できるかをご存じでしょう。Argo Rolloutsでは、オプションとしてトラフィックプロバイダーを組み合わせ、Pod間のトラフィックを完全に制御しながら段階的に振り分けることができます。
これまで、新しいトラフィックプロバイダーをArgo Rolloutsに統合するには、その都度個別のコード対応が必要でした。しかし、最近の2つの動きにより、こうした手間は過去のものとなりました。
- 1つ目は、バージョン1.5以降で利用可能になったArgo Rolloutsのトラフィックプラグインです。
- 2つ目は、新しいKubernetesのGateway APIです。トラフィックルーティングをきめ細かく制御でき、サービスメッシュやIngressをはじめとする幅広い領域で新たな可能性が広がります。
Argo RolloutsでGateway APIを採用すれば、統合は格段にシンプルになります。Gateway APIに対応したトラフィックプロバイダーであれば、自動的にArgo Rolloutsでサポートされるためです。既知の実装はGateway APIの公式サイトにまとめられています。
本記事では、Google Kubernetes EngineでGateway APIとArgo Rolloutsを組み合わせ、プログレッシブデリバリーを実現する方法をご紹介します。
前提条件
- Gateway APIを有効化したGKEクラスター
- クラスターにインストール済みのArgo Rollouts
- コマンドラインからロールアウトを管理・可視化するためのkubectlプラグイン
制限事項
- Argo RolloutsのGateway APIプラグインは、Blue/Greenデプロイ戦略には対応していません。
- 本機能はGCPのEnvoyベースのアプリケーションロードバランサーでのみ利用可能です。Classic Application Load BalancerやNetwork Load Balancerでは直接サポートされません。
Argo Rollouts Gateway APIプラグインのデプロイ
- 以下のマニフェストをクラスターに適用し、ConfigMapを作成します。利用可能なバージョンはReleasesページを参照し、必要に応じてアーキテクチャを変更してください。
cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: ConfigMap
metadata:
name: argo-rollouts-config # must be so name
namespace: argo-rollouts # must be in this namespace
data:
trafficRouterPlugins: |-
- name: "argoproj-labs/gatewayAPI"
location: "https://github.com/argoproj-labs/rollouts-plugin-trafficrouter-gatewayapi/releases/download/v0.3.0/gateway-api-plugin-linux-amd64"
EOF
- Argo RolloutsのPodを再起動すると、起動時にプラグインがダウンロードされます。

プラグインのインストールが確認できるサンプルPodログ
Gatewayリソースのデプロイ
- Gatewayリソースは、Kubernetesでトラフィックをルーティングするデータプレーンを表現するものです。利用するGatewayClassに応じて、さまざまな種類のロードバランシングやルーティングを表現できます。
- 以下のマニフェストを適用し、グローバル外部アプリケーションロードバランサーを作成します。
cat <<EOF | kubectl apply -f -
---
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: argo-rollouts-demo-external-http
spec:
gatewayClassName: gke-l7-global-external-managed
listeners:
- name: http
protocol: HTTP
port: 80
EOF

Gateway APIリソースのサンプル
Argo RolloutsにHTTPRouteの編集権限を付与
- 以下のマニフェストを適用し、Argo RolloutsにHTTPRouteリソースの編集権限を付与します。
cat <<EOF | kubectl apply -f -
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: gateway-controller-role
namespace: argo-rollouts
rules:
- apiGroups:
- gateway.networking.k8s.io
resources:
- httproutes
verbs:
- get
- patch
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: gateway-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: gateway-controller-role
subjects:
- namespace: argo-rollouts
kind: ServiceAccount
name: argo-rollouts
EOF
HTTPRouteとKubernetes Serviceの作成
- サンプルのHTTPRouteを作成し、先ほど作成したGatewayリソースに接続します。
cat <<EOF | kubectl apply -f -
---
kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: argo-rollouts-demo-http-route
spec:
parentRefs:
- kind: Gateway
name: argo-rollouts-demo-external-http
hostnames:
- "argo-rollouts-demo.example.com"
rules:
- backendRefs:
- name: argo-rollouts-demo-stable-service
port: 80
- name: argo-rollouts-demo-canary-service
port: 80
EOF
- Canary用のServiceを作成します。
cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: Service
metadata:
name: argo-rollouts-demo-canary-service
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: argo-rollouts-demo
EOF
- Stable用のServiceを作成します。
cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: Service
metadata:
name: argo-rollouts-demo-stable-service
spec:
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app: argo-rollouts-demo
EOF

ルート設定が反映された外部ロードバランサー
Canary Rolloutの作成
- RolloutはKubernetesのDeploymentオブジェクトに相当するカスタムリソースで、より高度なデプロイ機能やプログレッシブデリバリーが必要な場面でDeploymentの代わりに利用します。
- 新規にRolloutを作成することも、既存のDeploymentをRolloutリソースに紐付けることもできます。Argo RolloutsのGateway APIプラグインが対応するのはCanaryデプロイのみです。利用可能なオプションはRollout Specificationを参照してください。
- 以下のマニフェストをクラスターに適用し、アプリケーションが起動するのを待ってから、ブラウザでGatewayのIPアドレスにアクセスします。
cat <<EOF | kubectl apply -f -
---
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: argo-rollouts-demo
namespace: default
spec:
replicas: 5
strategy:
canary:
canaryService: argo-rollouts-demo-canary-service # canary service
stableService: argo-rollouts-demo-stable-service # stable service
trafficRouting:
plugins:
argoproj-labs/gatewayAPI:
httpRoute: argo-rollouts-demo-http-route # httproute
namespace: default
steps:
- setWeight: 50
- pause: {}
- setWeight: 100
- pause: {}
revisionHistoryLimit: 2
selector:
matchLabels:
app: argo-rollouts-demo
template:
metadata:
labels:
app: argo-rollouts-demo
spec:
containers:
- name: argo-rollouts-demo
image: argoproj/rollouts-demo:blue
ports:
- name: http
containerPort: 8080
protocol: TCP
resources:
requests:
memory: 32Mi
cpu: 5m
EOF
- HTTPRouteリソースの状態を確認し、Argo RolloutsのPodログでロールアウトが正常にデプロイされたかをチェックします。Argo RolloutsはHTTPRoute内のweight値を書き換え、その内容がロードバランサーに同期されます。

初期状態のロードバランサールーティング設定

サンプルアプリケーションのレスポンス。カスタムHostヘッダーの付与にはChrome拡張のModHeaderを使用
Canaryデプロイの実行
- 以下のコマンドを実行してイメージを変更すると、新しいロールアウトが開始されます。
kubectl argo rollouts set image argo-rollouts-demo argo-rollouts-demo=argoproj/rollouts-demo:yellow
- Argo Rolloutsはトラフィックの割合に合わせて必要な数のPodを作成します。今回のケースでは、新バージョンへ50%のトラフィックを流すため、新たに3つのPodが作成されます。
- 以下のコマンドでロールアウトの進捗を確認できます。Argo Rolloutsのkubectlプラグインには、ロールアウトを可視化できるローカルUIダッシュボードも用意されています。
kubectl argo rollouts get rollout rollouts-demo

初期のロールアウトステータスの例
- HTTPRouteを確認し、Argo Rolloutsによってバックエンドサービスのweightが書き換えられていることを確認します。

HTTPRouteのサンプル

ロードバランサーのルーティングルール
- この時点では、各バージョンが50%ずつリクエストを受け取る状態になります。ブラウザでも動作を確認できます。

Canaryロールアウトの初期状態
- 以下のコマンドでロールアウトをpromoteし、新バージョンへのトラフィック比率を増やします。HTTPRouteとロードバランサーのルーティング設定もあわせて確認してください。
kubectl argo rollouts promote rollouts-demo
- もう一度promoteコマンドを実行するとロールアウトが完了します。旧バージョンのPodが破棄されるまで待ちましょう。Rolloutのイメージを再度変更すれば、プロセスは最初からやり直しになります。

完了後のロールアウトステータス

更新後のロードバランサールーティングルール

完了したCanaryロールアウト
Gateway APIとArgo Rolloutsを組み合わせることで、Kubernetesにおけるプログレッシブデリバリーは大きく前進します。トラフィックルーティングがシンプルになり、Canaryデプロイの実行や、バージョン間のトラフィックを精緻にコントロールしながら切り替える運用がぐっと容易になります。
本記事が皆様のお役に立てば幸いです。さらに詳しい情報や当社サービスにご関心をお持ちの方は、お気軽にこちらからお問い合わせください。