IstioとKubernetesを使用してカナリアをデプロイする方法
序章
サービスの新しいバージョンを導入する場合、古いバージョンを段階的に廃止する過程で、ユーザートラフィックの制御された割合を新しいバージョンのサービスにシフトすることが望ましい場合がよくあります。 この手法は、カナリア展開と呼ばれます。
Kubernetesクラスターオペレーターは、ラベルとデプロイメントを使用して、カナリアデプロイメントをネイティブにオーケストレーションできます。 ただし、この手法には特定の制限があります。トラフィックの分散とレプリカの数が結合されます。つまり、実際には、トラフィックをカナリアリリースに制限するには、レプリカの比率を手動で制御する必要があります。 つまり、10 % o fトラフィックをカナリア展開に転送するには、10個のポッドのプールが必要です。1個のポッドが10 % o fのユーザートラフィックを受信し、他の9個が残りを受信します。
Istio サービスメッシュを使用してデプロイすると、レプリカ数とトラフィック管理を明確に分離できるため、この問題に対処できます。 Istioメッシュにより、トラフィックの分散と管理をレプリカのスケーリングから切り離す、きめ細かいトラフィック制御が可能になります。 レプリカの比率を手動で制御する代わりに、トラフィックの割合とターゲットを定義でき、残りはIstioが管理します。
このチュートリアルでは、IstioとKubernetesを使用してカナリアデプロイメントを作成します。 デモNode.jsアプリケーションの2つのバージョンをデプロイし、 VirtualServiceおよびDestinationRule リソースを使用して、新しいバージョンと古いバージョンの両方へのトラフィックルーティングを構成します。 これは、Istioを使用して将来のカナリア展開を構築するための良い出発点になります。
前提条件
- ロールベースのアクセス制御(RBAC)が有効になっているKubernetes1.10+クラスター。 このセットアップでは、3つのノードを持つ DigitalOcean Kubernetesクラスターを使用しますが、別の方法を使用してクラスターを自由に作成できます。
<$>[注] ノート: このセットアップには、少なくとも8GBの使用可能なメモリと4vCPUを備えたクラスターを強くお勧めします。 このチュートリアルでは、DigitalOceanの標準の4GB/2vCPUドロップレットのうち3つをノードとして使用します。 <$>
kubectl
コマンドラインツールが開発サーバーにインストールされ、クラスターに接続するように構成されています。kubectl
のインストールの詳細については、公式ドキュメントを参照してください。- Dockerが開発サーバーにインストールされています。 Ubuntu 18.04を使用している場合は、 Ubuntu18.04にDockerをインストールして使用する方法の手順1と2に従ってください。 それ以外の場合は、他のオペレーティングシステムへのインストールについて、公式ドキュメントに従ってください。 リンクされたチュートリアルのステップ2で説明されているように、root以外のユーザーを
docker
グループに必ず追加してください。 - DockerHubアカウント。 これを設定する方法の概要については、DockerHubのこの紹介を参照してください。
- Istioは、KubernetesでIstioをインストールして使用する方法の手順に従ってインストールおよび構成されます。 また、 Grafana テレメトリアドオンを有効にして、外部アクセス用に構成する必要があります。
ステップ1—アプリケーションのパッケージ化
前提条件のチュートリアルIstioをKubernetesでインストールして使用する方法では、ノードデモDockerイメージを作成してサメ情報アプリケーションを実行し、このイメージをDockerHubにプッシュしました。 このステップでは、別のイメージを作成します。カナリアの展開に使用するアプリケーションの新しいバージョンです。
私たちのオリジナルのデモアプリケーションは、サメ情報ページでサメに関するいくつかの友好的な事実を強調しました。
しかし、新しいカナリアバージョンでは、いくつかの恐ろしい事実を強調することにしました。
最初のステップは、この2番目のバージョンのアプリケーションのコードをnode_image
というディレクトリに複製することです。 次のコマンドを使用して、 DigitalOceanCommunityGitHubアカウントからnodejs-canary-appリポジトリのクローンを作成します。 このリポジトリには、アプリケーションの2番目の恐ろしいバージョンのコードが含まれています。
git clone https://github.com/do-community/nodejs-canary-app.git node_image
node_image
ディレクトリに移動します。
cd node_image
このディレクトリには、新しいバージョンのサメ情報アプリケーションのファイルとフォルダが含まれています。このアプリケーションは、元のアプリケーションと同様に、より恐ろしい事実に重点を置いて、サメに関する情報をユーザーに提供します。 アプリケーションファイルに加えて、ディレクトリには、アプリケーションコードを使用してDockerイメージを構築するための手順が記載されたDockerfileが含まれています。 Dockerfileの手順の詳細については、Dockerを使用してNode.jsアプリケーションを構築する方法のステップ3を参照してください。
アプリケーションコードとDockerfileが期待どおりに機能することをテストするには、 docker build コマンドを使用してイメージをビルドおよびタグ付けしてから、イメージを使用してデモコンテナーを実行します。 -t
フラグをdocker build
とともに使用すると、イメージにDocker Hubユーザー名のタグを付けて、テスト後にDockerHubにプッシュできるようになります。
次のコマンドを使用してイメージをビルドします。
docker build -t your_dockerhub_username/node-demo-v2 .
コマンドの.
は、ビルドコンテキストが現在のディレクトリであることを指定します。 KubernetesでIstioをインストールして使用する方法で作成したnode-demo
イメージを参照するために、イメージにnode-demo-v2
という名前を付けました。
ビルドプロセスが完了すると、 dockerimagesを使用してイメージを一覧表示できます。
docker images
イメージビルドを確認する次の出力が表示されます。
OutputREPOSITORY TAG IMAGE ID CREATED SIZE your_dockerhub_username/node-demo-v2 latest 37f1c2939dbf 5 seconds ago 77.6MB node 10-alpine 9dfa73010b19 2 days ago 75.3MB
次に、docker run
を使用して、このイメージに基づいてコンテナーを作成します。 このコマンドには、次の3つのフラグが含まれます。
-p
:これにより、コンテナーのポートが公開され、ホストのポートにマップされます。 ホストではポート80
を使用しますが、そのポートで別のプロセスを実行している場合は、必要に応じてこれを自由に変更してください。 これがどのように機能するかについての詳細は、ポートバインディングに関するDockerドキュメントのこの説明を参照してください。-d
:これはコンテナーをバックグラウンドで実行します。--name
:これにより、コンテナーにカスタマイズされた名前を付けることができます。
次のコマンドを実行して、コンテナーを作成します。
docker run --name node-demo-v2 -p 80:8080 -d your_dockerhub_username/node-demo-v2
dockerpsを使用して実行中のコンテナーを検査します。
docker ps
アプリケーションコンテナが実行されていることを確認する出力が表示されます。
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 49a67bafc325 your_dockerhub_username/node-demo-v2 "docker-entrypoint.s…" 8 seconds ago Up 6 seconds 0.0.0.0:80->8080/tcp node-demo-v2
これで、ブラウザでサーバーIPにアクセスして、セットアップをテストできます:http://your_server_ip
。 アプリケーションは次のランディングページを表示します。
Get Shark Info ボタンをクリックして、より恐ろしいサメ情報を入手してください。
アプリケーションをテストしたので、実行中のコンテナーを停止できます。 docker ps
をもう一度使用して、CONTAINER ID
を取得します。
docker ps
OutputCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 49a67bafc325 your_dockerhub_username/node-demo-v2 "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:80->8080/tcp node-demo-v2
dockerstopでコンテナを停止します。 ここにリストされているCONTAINER ID
は、必ず独自のアプリケーションCONTAINER ID
に置き換えてください。
docker stop 49a67bafc325
イメージをテストしたので、DockerHubにプッシュできます。 まず、前提条件で作成したDockerHubアカウントにログインします。
docker login -u your_dockerhub_username
プロンプトが表示されたら、DockerHubアカウントのパスワードを入力します。 この方法でログインすると、ルート以外のユーザーのホームディレクトリにDockerHubの資格情報を使用して~/.docker/config.json
ファイルが作成されます。
dockerpushコマンドを使用してアプリケーションイメージをDockerHubにプッシュします。 your_dockerhub_username
を独自のDockerHubユーザー名に置き換えることを忘れないでください。
docker push your_dockerhub_username/node-demo-v2
これで、DockerHubに保存された2つのアプリケーションイメージがあります。node-demo
イメージとnode-demo-v2
です。 ここで、前提条件のチュートリアル Istio With Kubernetes をインストールして使用する方法で作成したマニフェストを変更して、トラフィックをアプリケーションのカナリアバージョンに転送します。
ステップ2—アプリケーションデプロイメントの変更
Kubernetes でIstioをインストールして使用する方法では、アプリケーションサービスおよび展開用の仕様を使用してアプリケーションマニフェストを作成しましたオブジェクト。 これらの仕様は、各オブジェクトの望ましい状態を記述します。 このステップでは、アプリケーションの2番目のバージョンのデプロイメントを、Istioがこれらのリソースを管理できるようにするバージョンラベルとともに、このマニフェストに追加します。
前提条件チュートリアルのセットアップ手順に従った場合、istio_project
というディレクトリと2つのyaml
マニフェストを作成しました。node-app.yaml
には、サービスオブジェクトとデプロイメントオブジェクトの仕様が含まれています。およびnode-istio.yaml
には、Istio仮想サービスおよびゲートウェイリソースの仕様が含まれています。
今すぐistio_project
ディレクトリに移動します。
cd cd istio_project
node-app.yaml
をnano
またはお気に入りのエディターで開き、アプリケーションマニフェストに変更を加えます。
nano node-app.yaml
現在、ファイルは次のようになっています。
〜/ istio_project / node-app.yaml
apiVersion: v1 kind: Service metadata: name: nodejs labels: app: nodejs spec: selector: app: nodejs ports: - name: http port: 8080 --- apiVersion: apps/v1 kind: Deployment metadata: name: nodejs labels: version: v1 spec: replicas: 1 selector: matchLabels: app: nodejs template: metadata: labels: app: nodejs version: v1 spec: containers: - name: nodejs image: your_dockerhub_username/node-demo ports: - containerPort: 8080
このファイルの内容の詳細については、KubernetesでIstioをインストールして使用する方法のステップ3を参照してください。
ポッドとサービスに関するIstioの推奨事項に従って、展開metadata
およびtemplate
フィールドにバージョンラベルがすでに含まれています。 これで、アプリケーションの2番目のバージョンを表す2番目のDeploymentオブジェクトの仕様を追加し、最初のDeploymentオブジェクトのname
にすばやく変更を加えることができます。
まず、既存のDeploymentオブジェクトの名前をnodejs-v1
に変更します。
〜/ istio_project / node-app.yaml
... apiVersion: apps/v1 kind: Deployment metadata: name: nodejs-v1 labels: version: v1 ...
次に、このデプロイメントの仕様の下に、2番目のデプロイメントの仕様を追加します。 image
フィールドに自分の画像の名前を追加することを忘れないでください。
〜/ istio_project / node-app.yaml
... --- apiVersion: apps/v1 kind: Deployment metadata: name: nodejs-v2 labels: version: v2 spec: replicas: 1 selector: matchLabels: app: nodejs template: metadata: labels: app: nodejs version: v2 spec: containers: - name: nodejs image: your_dockerhub_username/node-demo-v2 ports: - containerPort: 8080
最初のデプロイメントと同様に、このデプロイメントはversion
ラベルを使用して、このデプロイメントに対応するアプリケーションのバージョンを指定します。 この場合、v2
は、この展開に関連付けられているアプリケーションバージョンを、最初の展開に対応するv1
と区別します。
また、v2
Deploymentによって管理されるPodsが、前の手順で作成したnode-demo-v2
カナリアイメージを実行することを確認しました。
編集が終了したら、ファイルを保存して閉じます。
アプリケーションマニフェストを変更したら、node-istio.yaml
ファイルに変更を加えることができます。
ステップ3—仮想サービスを使用したトラフィックの重み付けと宛先ルールの追加
KubernetesでIstioをインストールして使用する方法では、ゲートウェイオブジェクトと仮想サービスオブジェクトを作成して、外部トラフィックをIstioメッシュに送り、アプリケーションサービスにルーティングできるようにしました。 ここでは、仮想サービス構成を変更して、アプリケーションサービスサブセット(v1
およびv2
)へのルーティングを含めます。 また、宛先ルールを追加して、nodejs
アプリケーションサービスに適用するルーティングルールに追加のバージョンベースのポリシーを定義します。
node-istio.yaml
ファイルを開きます。
nano node-istio.yaml
現在、ファイルは次のようになっています。
〜/ istio_project / node-istio.yaml
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: nodejs-gateway spec: selector: istio: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: nodejs spec: hosts: - "*" gateways: - nodejs-gateway http: - route: - destination: host: nodejs
このマニフェストの仕様の詳細については、KubernetesでIstioをインストールして使用する方法のステップ4を参照してください。
最初の変更は、仮想サービスです。 現在、このリソースは、メッシュに入るトラフィックをnodejs-gateway
を介してnodejs
アプリケーションサービスにルーティングします。 私たちがやりたいのは、トラフィックの80%を元のアプリケーションに送信し、20%を新しいバージョンに送信するルーティングルールを構成することです。 カナリアのパフォーマンスに満足したら、トラフィックルールを再構成して、すべてのトラフィックを新しいアプリケーションバージョンに徐々に送信できます。
元のマニフェストで行ったように、単一のdestination
にルーティングする代わりに、元のバージョン(v1
)と元のバージョンの両方のアプリケーションサブセットにdestination
フィールドを追加します。カナリア(v2
)。
このルーティングルールを作成するには、仮想サービスに次の追加を行います。
〜/ istio_project / node-istio.yaml
... apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: nodejs spec: hosts: - "*" gateways: - nodejs-gateway http: - route: - destination: host: nodejs subset: v1 weight: 80 - destination: host: nodejs subset: v2 weight: 20
追加したポリシーには、アプリケーションの元のバージョンであるv1
を実行しているnodejs
サービスのsubset
とsubset
の2つの宛先が含まれています。 ]カナリアを実行しているv2
。 サブセット1は着信トラフィックの80%を受信し、カナリアは20%を受信します。
次に、トラフィックが適切なサービスにルーティングされた後、着信トラフィックにルールを適用する宛先ルールを追加します。 この例では、適切なバージョンラベルを使用してトラフィックをポッドに送信するようにsubset
フィールドを構成します。
仮想サービス定義の下に次のコードを追加します。
〜/ istio_project / node-istio.yaml
... --- apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: nodejs spec: host: nodejs subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2
ルールにより、サービスサブセットv1
およびv2
へのトラフィックが、適切なラベルversion: v1
およびversion: v2
でポッドに到達することが保証されます。 これらは、アプリケーションのデプロイメント仕様に含めたラベルです。
ただし、必要に応じて、サブセットレベルで特定のトラフィックポリシーを適用して、カナリアの展開をさらに具体化することもできます。 このレベルでのトラフィックポリシーの定義の詳細については、公式のIstioドキュメントを参照してください。
編集が終了したら、ファイルを保存して閉じます。
アプリケーションマニフェストが改訂されたら、構成の変更を適用し、Grafanaテレメトリアドオンを使用してアプリケーショントラフィックデータを調べる準備が整います。
ステップ4—構成変更の適用とトラフィックデータへのアクセス
アプリケーションマニフェストは更新されますが、これらの変更をKubernetesクラスターに適用する必要があります。 kubectl apply コマンドを使用して、既存の構成を完全に上書きせずに変更を適用します。 これを行うと、アプリケーションへのリクエストを生成し、IstioGrafanaダッシュボードで関連データを確認できるようになります。
構成をアプリケーションのServiceオブジェクトとDeploymentオブジェクトに適用します。
kubectl apply -f node-app.yaml
次の出力が表示されます。
Outputservice/nodejs unchanged deployment.apps/nodejs-v1 created deployment.apps/nodejs-v2 created
次に、node-istio.yaml
に行った構成の更新を適用します。これには、仮想サービスと新しい宛先ルールへの変更が含まれます。
kubectl apply -f node-istio.yaml
次の出力が表示されます。
Outputgateway.networking.istio.io/nodejs-gateway unchanged virtualservice.networking.istio.io/nodejs configured destinationrule.networking.istio.io/nodejs created
これで、アプリケーションへのトラフィックを生成する準備が整いました。 ただし、その前に、まずgrafana
サービスが実行されていることを確認してください。
kubectl get svc -n istio-system | grep grafana
Outputgrafana ClusterIP 10.245.233.51 <none> 3000/TCP 4d2h
関連するポッドも確認してください。
kubectl get svc -n istio-system | grep grafana
Outputgrafana-67c69bb567-jpf6h 1/1 Running 0 4d2h
最後に、grafana-gateway
ゲートウェイとgrafana-vs
仮想サービスを確認します。
kubectl get gateway -n istio-system | grep grafana
Outputgrafana-gateway 3d5h
kubectl get virtualservice -n istio-system | grep grafana
Outputgrafana-vs [grafana-gateway] [*] 4d2h
これらのコマンドからの出力が表示されない場合は、KubernetesでIstioをインストールして使用する方法の手順2および5を確認してください。 Istioをインストールする際のGrafanaテレメトリアドオンと、GrafanaサービスへのHTTPアクセスを有効にする方法。
これで、ブラウザでアプリケーションにアクセスできます。 これを行うには、istio-ingressgateway
サービスに関連付けられた外部IPが必要になります。これは、LoadBalancerサービスタイプです。 KubernetesでIstioをインストールして使用する方法でゲートウェイマニフェストを作成するときに、nodejs-gateway
ゲートウェイをこのコントローラーと一致させました。 ゲートウェイマニフェストの詳細については、そのチュートリアルのステップ4を参照してください。
次のコマンドを使用して、istio-ingressgateway
サービスの外部IPを取得します。
kubectl get svc -n istio-system
次のような出力が表示されます。
OutputNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE grafana ClusterIP 10.245.85.162 <none> 3000/TCP 42m istio-citadel ClusterIP 10.245.135.45 <none> 8060/TCP,15014/TCP 42m istio-galley ClusterIP 10.245.46.245 <none> 443/TCP,15014/TCP,9901/TCP 42m istio-ingressgateway LoadBalancer 10.245.171.39 ingressgateway_ip 15020:30707/TCP,80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:30285/TCP,15030:31668/TCP,15031:32297/TCP,15032:30853/TCP,15443:30406/TCP 42m istio-pilot ClusterIP 10.245.56.97 <none> 15010/TCP,15011/TCP,8080/TCP,15014/TCP 42m istio-policy ClusterIP 10.245.206.189 <none> 9091/TCP,15004/TCP,15014/TCP 42m istio-sidecar-injector ClusterIP 10.245.223.99 <none> 443/TCP 42m istio-telemetry ClusterIP 10.245.5.215 <none> 9091/TCP,15004/TCP,15014/TCP,42422/TCP 42m prometheus ClusterIP 10.245.100.132 <none> 9090/TCP 42m
istio-ingressgateway
は、TYPE
LoadBalancer
を備えた唯一のサービスであり、外部IPを備えた唯一のサービスである必要があります。
ブラウザで次の外部IPに移動します:http://ingressgateway_ip
。
次のランディングページが表示されます。
Get SharkInfoボタンをクリックします。 2つのサメ情報ページのいずれかが表示されます。
このページの[更新]を数回クリックします。 恐ろしいバージョンよりも、より親しみやすいサメの情報ページが頻繁に表示されるはずです。
5〜6回更新して負荷を生成したら、Grafanaダッシュボードに移動できます。
ブラウザで、istio-ingressgateway
外部IPとGrafanaGatewayマニフェストで定義されているポートhttp://ingressgateway_ip:15031
を使用して、次のアドレスに移動します。
次のランディングページが表示されます。
ページ上部のホームをクリックすると、istioフォルダーのあるページが表示されます。 ドロップダウンオプションのリストを取得するには、istioフォルダーアイコンをクリックします。
このオプションのリストから、Istioサービスダッシュボードをクリックします。
これにより、別のドロップダウンメニューが表示されたランディングページが表示されます。
利用可能なオプションのリストからnodejs.default.svc.cluster.local
を選択します。
ページのサービスワークロードセクションに移動すると、宛先および応答コード別の受信リクエストを確認できます。
ここでは、200と304のHTTP応答コードの組み合わせが表示され、OK
とNot Modified
の応答が成功したことを示しています。 nodejs-v1
というラベルの付いた応答は、nodejs-v2
というラベルの付いた応答よりも多いはずです。これは、マニフェストで定義したパラメーターに従って、着信トラフィックがアプリケーションサブセットにルーティングされていることを示します。
結論
このチュートリアルでは、IstioとKubernetesを使用してCanaryバージョンのデモNode.jsアプリケーションをデプロイしました。 トラフィックの80%を元のアプリケーションサービスに送信し、20%を新しいバージョンに送信できるようにする仮想サービスと宛先ルールのリソースを作成しました。 新しいバージョンのアプリケーションのパフォーマンスに満足したら、必要に応じて構成設定を更新できます。
Istioでのトラフィック管理の詳細については、ドキュメントの関連する高レベルの概要と、Istioのbookinfoおよびhelloworldサンプルを使用する特定の例を参照してください。アプリケーション。