17
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Argo Rollouts + Istio を連携してトラフィックシェーピングによるカナリアリリース

Last updated at Posted at 2020-07-27

Istioは Kubernetesクラスタ外部からのリクエストトラフィックを受ける Ingress コントローラーに代わって利用することができる。それもグラフィカルに状態を表示する視覚化、そして、トラフィック・シェーピング機能を持つ優れたものである。それに加えて、Argoプロジェクトファミリーの一つである Argo Rollout は コンテナ化アプリケーションのバージョンアップやリリースに対して、予め定めた段階的なリリースを推進してくれる。 この二つを組み合わせる事で、CICDの運用に有用なインフラとして活用する事できる。

スクリーンショット 2020-07-28 13.49.00.png

本記事では、IBMクラウドのマネージドIstioとArgo Rollout を利用して、機能の検証を実施した。

Argo Rollouts とは

Argoロールアウトは、KubernetesコントローラとCRDのセットであり、ブルー・グリーン・デプロイ、カナリアリリース、カナリア分析、実験的配信など、Kubernetesへの段階的な配信などの高度なデプロイ機能を提供する。Argoロールアウトは、Istio サービスメッシュと統合し、ロールアウト中にシェーピング機能を利用してトラフィックを新しいバージョンに徐々にシフトする。さらに、ロールアウトは、さまざまなプロバイダーからのメトリックを参照および解釈して、主なKPIを検証し、ロールアウト時に、自動昇格またはロールバックを進める。

参考資料

KuberneteクラスタへのArgo Rolloutのインストール

本記事では、Kubenetesクラスタがデプロイされ、kubectl コマンドで操作可能な状態から始める。ここで利用したKubernetesのバージョンは、1.17である。

参考資料のクイックスタートでは、GitHubから直接デプロイしていたが、それでは内容の把握が十分にできないので、一度、ローカルにクローンしてから利用する。

$ git clone -b stable https://github.com/argoproj/argo-rollouts

Argoロールアウトのカスタムコントローラーを動かす名前空間 argo-rollouts を作成してから、インストールする。

export ANS=argo-rollouts
$ kubectl create namespace $ANSa

kustomzie の 構成ファイルが、以下のパスに置かれているので、これを利用する。

$ cd argo-rollouts/manifests/cluster-install
$ kubectl create -k ./ -n $ANS

しばらくすると、Argo Rollout の カスタムコントローラーが立ち上がってくるので、この状態になれば準備完了である。

$ kubectl get pod -n $ANS
NAME                             READY   STATUS    RESTARTS   AGE
argo-rollouts-6bcb4945db-dp58j   1/1     Running   0          13s

Kubectl Argo-rollouts プラグインのインストール

Argoロールアウトには、kubectlコマンドのプラグインが提供されている。これを利用する事で見やすい表示を得ることができる。 参考資料にはダウンロードする方法もあるが、ここでは、macOSのパッケージマネージャー brew を使ってインストールした。

$ brew install argoproj/tap/kubectl-argo-rollouts

一応、バージョンも確認しておく。

$ kubectl argo rollouts version
kubectl-argo-rollouts: v0.8.3+a0dfe6d
  BuildDate: 2020-06-04T00:59:12Z
  GitCommit: a0dfe6d61bf303ff3ab4669dfb756468d4c54d17
  GitTreeState: clean
  GoVersion: go1.13.1
  Compiler: gc
  Platform: darwin/amd64

マネージド Istio セットアップ

次に Istio のセットアップに進む。アップストリームの Kubernetes を使用する場合には、手作業でインストールしても良いが、クラウドの便利な機能を利用する。

IBM Cloud のマネージド Istio は、クラウドのウェブコンソールからクリックして起動しておく。起動を確認するには、ic ks cluster addon ls -c <k8sクラスタ名> を実行する。以下の例では、ワーカーノード x 2のクラスタで、Istioを実行したが、リソース不足のメッセージが出たので、ワーカーノード x3 体制で実施した。

2ノード時の表示では、リソースが足りないことを表示している。このまま実行してもリソース不足で正常に動かない可能性があるので、ノードを追加することにした。

$ ic ks cluster addon ls -c tok05-b3c.4x16
OK
名前    バージョン   正常性の状態   正常性の状況
istio   1.6        warning      Cluster resources low, not enough workers in Ready state. 

クラウドのウェブコンソールから、3ノードに増強した結果、警告が消え、正常を表す表示に変わったので、次の作業へ進む。

$ ic ks cluster addon ls -c tok05-b3c.4x16
OK
名前    バージョン   正常性の状態   正常性の状況
istio   1.6        normal       Addon Ready  

Istio モニタリング機能の有効化

マネージド Istio では 視覚化のためのツールを簡単に起動できるように設定されている。最初から起動するとリソースを大量に消費するので、ユーザーへの配慮がされている様だ。 Kialiなどを有効化するために、次のコマンドで実行中の設定を編集する。

$ kubectl edit cm managed-istio-custom -n ibm-operators

上記のコマンドで起動したエディタで istio-monitoring: "true" を追加する。これで保存すれば、自動的にKialiなどモニタリングのポッドが起動する。

apiVersion: v1
data:
  _example: ""
  istio-ingressgateway-zone-1: tok05
  istio-monitoring: "true"
kind: ConfigMap
metadata:
  annotations:
    armada-service: addon-istio
<以下省略>

istioctl コマンドのセットアップ

GitHub https://github.com/istio/istio の master をクリックして tag から最新リリースのバージョンを確認する。その値をISTIO_VERSIONの値としてセットする。以下の操作で、istioctlコマンドが利用できるようになる。

curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.5 sh -
cd istio-1.6.5
export PATH=$PWD/bin:$PATH

動作確認のために istioctl version を実行しておく。

アプリケーションの名前空間作成とIstio管理対象に設定

Argo Rollouts が対象とする名前空間を作成して、Istioの管理対象とするために、名前空間にラベルを設定する。

export AN=argo-apl
kubectl create ns $AN
kubectl label namespace $AN istio-injection=enabled

Argo ロールアウト アプリケーションの構成ファイル作成

アプリケーションを動かすためのマニフェストを準備する。 ここで動作させるコンテナは https://hub.docker.com/r/argoproj/rollouts-demo/tags にあるイメージで、tag に色が設定されている。起動すると何色に対してリクエストされたか判る様にWeb画面が表示される。

.
├── gateway.yaml         Istio の Ingress gateway と連携するための設定
├── kustomization.yaml   マニフェストの実行順番を書いておき、このファイルを使ってデプロイする
├── rollout.yaml         Argoロールアウトのマニフェストで、ロールアウトの仕様を記述、カナリアリリース時の割合もここに定義する
├── services.yaml        カナリアリリース対象のポッドへのサービスの定義と、元のバージョンへのサービスと2種類
└── virtualsvc.yaml      Istio の 仮想サービスの定義でシェイプの初期値をセット

続いて各構成ファイルの内容を確認する。

最初に Kustomization をみる事で、全体の適用順番を知ることができる。

kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- rollout.yaml
- services.yaml
- gateway.yaml
- virtualsvc.yaml

次は、ArgoロールアウトのCRDに対する構成指示である。
trafficRoutingIstio を指定する。そして、steps で最初のカナリアリリースの段階で setWeight: 5を指定する。そして、pasue: {}を入れる事で、kubectl argo コマンドからの指示を待つ。

ポッドテンプレートのスペックが記述されているが、デプロイメントコントローラーなどポッドのコントローラーが指定が無いことに注目して欲しい。Argoコントローラーが、ReplicaSetsコントローラーに指示を与え、ポッドの起動をおこなっている。

rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: rollouts-demo
spec:
  replicas: 1
  strategy:
    canary:
      canaryService: rollouts-demo-canary
      stableService: rollouts-demo-stable
      trafficRouting:
        istio:
          virtualService:
            name: rollouts-demo-vsvc
            routes:
            - primary # At least one route is required
      steps:
      - setWeight: 5
      - pause: {}
  revisionHistoryLimit: 2
  selector:
    matchLabels:
      app: rollouts-demo
  template:
    metadata:
      labels:
        app: rollouts-demo
        istio-injection: enabled
    spec:
      containers:
      - name: rollouts-demo
        image: argoproj/rollouts-demo:blue
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP
        resources:
          requests:
            memory: 32Mi
            cpu: 5m

サービスは 名前を変えて2種類設定する。

services.yaml
apiVersion: v1
kind: Service
metadata:
  name: rollouts-demo-canary
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: rollouts-demo
    # This selector will be updated with the pod-template-hash of the canary ReplicaSet. e.g.:
    # rollouts-pod-template-hash: 7bf84f9696
---
apiVersion: v1
kind: Service
metadata:
  name: rollouts-demo-stable
spec:
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app: rollouts-demo
    # This selector will be updated with the pod-template-hash of the stable ReplicaSet. e.g.:
    # rollouts-pod-template-hash: 789746c88d

Istio Ingressゲートウェイを繋げるための設定

gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: rollouts-demo-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"

Istio Ingressゲートウェイから、転送先のサービスを記述する。 weight に初期値を設定しておく。これはArgoロールアウトのCRDから自動変更されるので、このファイルを手動で変更して再適用する必要は無い。

virtualsvc.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: rollouts-demo-vsvc
spec:
  gateways:
  - rollouts-demo-gateway
  hosts:
  - "*"
  http:
  - name: primary
    route:
    - destination:
        host: rollouts-demo-stable
      weight: 100
    - destination:
        host: rollouts-demo-canary
      weight: 0

アプリケーションのでデプロイ

kubectl の Kustomzieの機能を利用して、アプリケーションをデプロイする。

$ kubectl apply -k . -n $AN
service/rollouts-demo-canary created
service/rollouts-demo-stable created
rollout.argoproj.io/rollouts-demo created
gateway.networking.istio.io/rollouts-demo-gateway created
virtualservice.networking.istio.io/rollouts-demo-vsvc created

Argoロールアウト カスタムリソースが起動する。その管理下でポッドが起動しているのが判る。そして、READY の値が 2/2 となっているので Istio のインジェクトションが働いて Istio Proxy のサイドカーが注入されていることが判る。

$ kubectl get ro  -n $AN
NAME            DESIRED   CURRENT   UP-TO-DATE   AVAILABLE
rollouts-demo   1         1         1            1

$ kubectl get pod  -n $AN
NAME                             READY   STATUS    RESTARTS   AGE
rollouts-demo-594bbbb9bf-r89tn   2/2     Running   0          6m26s

Istio のオブジェクト gateway も起動が確認できる。

$ kubectl get gateway -n $AN
NAME                    AGE
rollouts-demo-gateway   7m27s

アプリケーションへのアクセス

インターネットからアクセスのため Istio イングレスゲートウェイの外部IPアドレスを確認する。

$ kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                                      AGE
istio-ingressgateway   LoadBalancer   172.21.166.163   165.192.86.82   15021:30016/TCP,80:31811/TCP,443:30768/TCP,15443:32152/TCP   3d1h

このIPアドレスにブラウザからアクセすると、宇宙人の画面が表示される。水玉とバーグラフはブラウザからのトラフィックの結果を示しており、blueのタグの付いたコンテナから応答を受けていることを表している。

ss-argo-1.png

モニタリング

kubectl argo プラグインを利用した表示で、Stableバージョンが動作しているのが判る。

ss-argo-plugin-1.png

Isito に組み込まれている Kiali から視覚化した様子。Isitoイングレスゲートウェイ - サービス - ポッド のリクエストの流れを直感的にみることができる。これは便利だ。

ss-kiali-1.png

カナリアリリース

次にカナリアリリースを開始する。 コマンドラインから、次にリリースするイメージ rollouts-demo=argoproj/rollouts-demo:yellow を指定する。これにより予め設定したカナリアリリースのサービスへトラフィックが回される様になる。その比率は、rolloutes.yamlで指定した 5%となる。

$ kubectl argo rollouts set image rollouts-demo rollouts-demo=argoproj/rollouts-demo:yellow
$ kubectl argo rollouts get rollout rollouts-demo

まずは、Argoプラグインの画面で確認する。黄色文字がカナリアリリースしたコンテナイメージだ。

ss-argo-plugin-2.png

Argoアプリケーションの表示では、5%に相当するトラフィック量の黄色の水玉が表示された。

ss-argo-2.png

Kialiの画面を確認すると、Istioによって二つのサービスへトラフィックが分流されていることが把握できる。

ss-kiali-2.png

カナリアリリース プロモーション

カナリアリリースの評価結果が良好なので、手動で本番サービスに昇格させることにする。

$ kubectl argo rollouts promote rollouts-demo

以下はコマンド実行直後の状態である。revision: 2のINFOが stable に変わって、本番リリースされたことが確認できる。

ss-argo-plugin-3.png

水玉は黄色一色に変わった。

ss-argo-3.png

Kiali の表示では、Stable 側のサービスにトラフィックが流れる、後からデプロイした Yellowタグのポッドが、Stableとして扱われいるのが見て判る。

ss-argo-plugin-3.png

まとめ

Istioを利用しないでArgoロールアウトを使用した場合、トラフィックシェーピングが出来ない代わりに、ポッドの存在数で割り当て量をコントロールする。つまり、カナリアリリースで10%を指定すると、ステーブルのポッドを9個起動して、その中に1個のカナリアポッドを起動する。しかし、これでは無駄なリソースを使用することになり、サービスのランダムな割り振りに依存した制御となりエレガントでは無い。それに対して、Istioを組み合わせる事で、正確なトラフィック制御、グラフィカルで直感的なビュー、そして、サービスメッシュとしての拡張性を与えることができる。

Istioはサービスメッシュの側面が強調されるが、実際、Ingress ゲートウェイとして利用すると、従来のイングレスコントローラーを使用するよりも、多くの利点を受けることができる。もっと、Isitoを使わなけえれば勿体ない。

Argoロールアウトは、デプロイメントコントローラーにとって代わり、ポッドのレプリカ数をコントロールする。Istioと統合して利用できる点でデプロイメントコントローラーを駆使して、ロールアウトするよりも、運用は楽になるのではないかと期待される。

参考資料

17
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?