Istioは Kubernetesクラスタ外部からのリクエストトラフィックを受ける Ingress コントローラーに代わって利用することができる。それもグラフィカルに状態を表示する視覚化、そして、トラフィック・シェーピング機能を持つ優れたものである。それに加えて、Argoプロジェクトファミリーの一つである Argo Rollout は コンテナ化アプリケーションのバージョンアップやリリースに対して、予め定めた段階的なリリースを推進してくれる。 この二つを組み合わせる事で、CICDの運用に有用なインフラとして活用する事できる。
本記事では、IBMクラウドのマネージドIstioとArgo Rollout を利用して、機能の検証を実施した。
Argo Rollouts とは
Argoロールアウトは、KubernetesコントローラとCRDのセットであり、ブルー・グリーン・デプロイ、カナリアリリース、カナリア分析、実験的配信など、Kubernetesへの段階的な配信などの高度なデプロイ機能を提供する。Argoロールアウトは、Istio サービスメッシュと統合し、ロールアウト中にシェーピング機能を利用してトラフィックを新しいバージョンに徐々にシフトする。さらに、ロールアウトは、さまざまなプロバイダーからのメトリックを参照および解釈して、主なKPIを検証し、ロールアウト時に、自動昇格またはロールバックを進める。
参考資料
- Argo Rollouts - Kubernetes Progressive Delivery Controller, https://argoproj.github.io/argo-rollouts/
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 をみる事で、全体の適用順番を知ることができる。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- rollout.yaml
- services.yaml
- gateway.yaml
- virtualsvc.yaml
次は、ArgoロールアウトのCRDに対する構成指示である。
trafficRouting
に Istio
を指定する。そして、steps
で最初のカナリアリリースの段階で setWeight: 5
を指定する。そして、pasue: {}
を入れる事で、kubectl argo
コマンドからの指示を待つ。
ポッドテンプレートのスペックが記述されているが、デプロイメントコントローラーなどポッドのコントローラーが指定が無いことに注目して欲しい。Argoコントローラーが、ReplicaSetsコントローラーに指示を与え、ポッドの起動をおこなっている。
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種類設定する。
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ゲートウェイを繋げるための設定
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から自動変更されるので、このファイルを手動で変更して再適用する必要は無い。
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のタグの付いたコンテナから応答を受けていることを表している。
モニタリング
kubectl argo
プラグインを利用した表示で、Stableバージョンが動作しているのが判る。
Isito に組み込まれている Kiali から視覚化した様子。Isitoイングレスゲートウェイ - サービス - ポッド のリクエストの流れを直感的にみることができる。これは便利だ。
カナリアリリース
次にカナリアリリースを開始する。 コマンドラインから、次にリリースするイメージ 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プラグインの画面で確認する。黄色文字がカナリアリリースしたコンテナイメージだ。
Argoアプリケーションの表示では、5%に相当するトラフィック量の黄色の水玉が表示された。
Kialiの画面を確認すると、Istioによって二つのサービスへトラフィックが分流されていることが把握できる。
カナリアリリース プロモーション
カナリアリリースの評価結果が良好なので、手動で本番サービスに昇格させることにする。
$ kubectl argo rollouts promote rollouts-demo
以下はコマンド実行直後の状態である。revision: 2
のINFOが stable に変わって、本番リリースされたことが確認できる。
水玉は黄色一色に変わった。
Kiali の表示では、Stable 側のサービスにトラフィックが流れる、後からデプロイした Yellowタグのポッドが、Stableとして扱われいるのが見て判る。
まとめ
Istioを利用しないでArgoロールアウトを使用した場合、トラフィックシェーピングが出来ない代わりに、ポッドの存在数で割り当て量をコントロールする。つまり、カナリアリリースで10%を指定すると、ステーブルのポッドを9個起動して、その中に1個のカナリアポッドを起動する。しかし、これでは無駄なリソースを使用することになり、サービスのランダムな割り振りに依存した制御となりエレガントでは無い。それに対して、Istioを組み合わせる事で、正確なトラフィック制御、グラフィカルで直感的なビュー、そして、サービスメッシュとしての拡張性を与えることができる。
Istioはサービスメッシュの側面が強調されるが、実際、Ingress ゲートウェイとして利用すると、従来のイングレスコントローラーを使用するよりも、多くの利点を受けることができる。もっと、Isitoを使わなけえれば勿体ない。
Argoロールアウトは、デプロイメントコントローラーにとって代わり、ポッドのレプリカ数をコントロールする。Istioと統合して利用できる点でデプロイメントコントローラーを駆使して、ロールアウトするよりも、運用は楽になるのではないかと期待される。