Anthos Service Mesh ワークショップ: ラボガイド

1. アルファ版ワークショップ

ワークショップ Codelab へのリンク: bit.ly/asm-workshop

2. 概要

アーキテクチャ図

9a033157f44308f3.png

このワークショップは、GCP で本番環境のグローバルに分散されたサービスを設定する方法を学ぶ実践的な没入型エクスペリエンスです。使用される主なテクノロジーは、コンピューティング用の Google Kubernetes Engine(GKE)と、安全な接続、オブザーバビリティ、高度なトラフィック シェーピングを作成するための Istio サービス メッシュです。このワークショップで使用するプラクティスとツールは、本番環境で使用するものと同じです。

アジェンダ

  • モジュール 0 - 概要とプラットフォームのセットアップ
  • 概要とアーキテクチャ
  • サービス メッシュと Istio/ASM の概要
  • ラボ: インフラストラクチャの設定: ユーザー ワークフロー
  • 休憩
  • QnA
  • モジュール 1 - ASM を使用してアプリケーションをインストール、保護、モニタリングする
  • リポジトリ モデル: インフラストラクチャ リポジトリと Kubernetes リポジトリの説明
  • ラボ: サンプル アプリケーションをデプロイする
  • 分散サービスとオブザーバビリティ
  • 昼食
  • ラボ: Stackdriver を使用したオブザーバビリティ
  • QNA
  • モジュール 2 - DevOps - カナリア ロールアウト、ポリシー/RBAC
  • マルチクラスタ サービス ディスカバリとセキュリティ/ポリシー
  • ラボ: 相互 TLS
  • カナリア デプロイ
  • ラボ: カナリア デプロイ
  • マルチクラスタのグローバル ロード バランシングを保護する
  • 休憩
  • ラボ: 認可ポリシー
  • QNA
  • モジュール 3 - インフラストラクチャ運用 - プラットフォームのアップグレード
  • 分散型サービスの構成要素
  • ラボ: インフラストラクチャのスケーリング
  • 次のステップ

スライド

このワークショップのスライドは、次のリンクでご覧いただけます。

ASM ワークショップのスライド

前提条件

このワークショップに進む前に、次のものが必要です。

  1. GCP 組織ノード
  2. 請求先アカウント ID(この請求先アカウントの請求管理者である必要があります)
  3. ユーザーの組織レベルの Organization Administrator IAM ロール

3. インフラストラクチャの設定 - 管理者のワークフロー

ブートストラップ ワークショップ スクリプトの説明

bootstrap_workshop.sh というスクリプトを使用して、ワークショップの初期環境を設定します。このスクリプトを使用すると、自分用に単一の環境を設定することも、複数のユーザーにこのワークショップをトレーニングとして提供する場合に複数のユーザー用に複数の環境を設定することもできます。

ブートストラップ ワークショップ スクリプトには、次の入力が必要です。

  • 組織名(例: yourcompany.com) - ワークショップの環境を作成する組織です。
  • 請求先 ID(例: 12345-12345-12345) - この請求先 ID は、ワークショップで使用されるすべてのリソースの請求に使用されます。
  • ワークショップ番号(例: 01) - 2 桁の数字。これは、1 日に複数のワークショップを実施し、それぞれを個別に追跡する場合に使用します。ワークショップ番号は、プロジェクト ID の導出にも使用されます。ワークショップ番号を分けることで、毎回一意のプロジェクト ID を取得しやすくなります。ワークショップ番号に加えて、現在の日付(YYMMDD 形式)もプロジェクト ID に使用されます。日付とワークショップ番号の組み合わせにより、一意のプロジェクト ID が提供されます。
  • 開始ユーザー番号(例: 1) - この番号は、ワークショップの最初のユーザーを示します。たとえば、10 人のユーザー向けのワークショップを作成する場合は、開始ユーザー番号を 1、終了ユーザー番号を 10 に設定します。
  • エンドユーザー番号(例: 10) - この番号は、ワークショップの最後のユーザーを示します。たとえば、10 人のユーザー向けのワークショップを作成する場合は、開始ユーザー番号を 1、終了ユーザー番号を 10 に設定します。単一の環境(自分用など)を設定する場合は、開始ユーザー数と終了ユーザー数を同じにします。これにより、単一の環境が作成されます。
  • 管理者の GCS バケットmy-gcs-bucket-name など) - GCS バケットは、ワークショップ関連の情報を保存するために使用されます。この情報は、cleanup_workshop.sh スクリプトによって、ブートストラップ ワークショップ スクリプトで作成されたすべてのリソースを正常に削除するために使用されます。ワークショップを作成する管理者は、このバケットに対する読み取り/書き込み権限を持っている必要があります。

ブートストラップ ワークショップ スクリプトは、上記の値を使用し、setup-terraform-admin-project.sh スクリプトを呼び出すラッパー スクリプトとして機能します。setup-terraform-admin-project.sh スクリプトは、単一ユーザーのワークショップ環境を作成します。

ワークショップのブートストラップに必要な管理者権限

このワークショップには 2 種類のユーザーがいます。このワークショップのリソースを作成および削除する ADMIN_USER。2 つ目は MY_USER です。ワークショップで手順を実行します。MY_USER は、自身のリソースにのみアクセスできます。ADMIN_USER はすべてのユーザー設定にアクセスできます。この設定を自分用に作成する場合は、ADMIN_USERMY_USER は同じです。複数の生徒向けにこのワークショップを作成する講師の場合、ADMIN_USERMY_USER は異なります。

ADMIN_USER には、次の組織レベルの権限が必要です。

  • オーナー - 組織内のすべてのプロジェクトに対するプロジェクト オーナー権限。
  • フォルダ管理者 - 組織内のフォルダを作成および削除する権限。各ユーザーには、プロジェクト内のすべてのリソースを含む単一のフォルダが割り当てられます。
  • 組織管理者
  • プロジェクト作成者 - 組織でプロジェクトを作成する権限。
  • プロジェクトの削除者 - 組織内のプロジェクトを削除する権限。
  • プロジェクト IAM 管理者 - 組織内のすべてのプロジェクトで IAM ルールを作成する権限。

これらに加えて、ADMIN_USER はワークショップで使用される請求先 ID の請求先管理者である必要もあります。

ワークショップを実行するユーザーのスキーマと権限

組織内のユーザー(自分以外)向けにこのワークショップを作成する場合は、MY_USERs のユーザー命名スキームに沿う必要があります。bootstrap_workshop.sh スクリプトの実行中に、開始ユーザー番号と終了ユーザー番号を指定します。これらの番号は、次のユーザー名の作成に使用されます。

  • user<3 digit user number>@<organization_name>

たとえば、開始ユーザー番号が 1、終了ユーザー番号が 3 のブートストラップ ワークショップ スクリプトを実行すると、yourcompany.com という組織で、次のユーザーのワークショップ環境が作成されます。

  • user001@yourcompany.com
  • user002@yourcompany.com
  • user003@yourcompany.com

これらのユーザー名には、setup_terraform_admin_project.sh スクリプトの実行中に作成された特定のプロジェクトのプロジェクト オーナー ロールが割り当てられます。ブートストラップ スクリプトを使用する場合は、このユーザー命名スキーマに準拠する必要があります。G Suite で複数のユーザーをまとめて追加する方法を参照してください。

ワークショップに必要なツール

このワークショップは、Cloud Shell からブートストラップすることを想定しています。このワークショップでは、次のツールが必要です。

  • gcloud(バージョン 270 以降)
  • kubectl
  • sed(Cloud Shell/Linux の sed で動作し、Mac OS では動作しません)
  • git(最新の状態であることを確認してください)
  • sudo apt update
  • sudo apt install git
  • jq
  • envsubst
  • kustomize

ワークショップを自分で設定する(シングル ユーザー設定)

  1. Cloud Shell を開き、次の操作をすべて Cloud Shell で行います。下のリンクをクリックしてください。

CLOUD SHELL

  1. 目的の管理者ユーザーで gcloud にログインしていることを確認します。
gcloud config list
 
  1. WORKDIR を作成し、ワークショップ リポジトリのクローンを作成します。
mkdir asm-workshop
cd asm-workshop
export WORKDIR=`pwd`
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git asm
 
  1. 組織名、請求先 ID、ワークショップ番号、ワークショップで使用する管理者 GCS バケットを定義します。ワークショップの設定に必要な権限については、上記のセクションをご覧ください。
gcloud organizations list
export ORGANIZATION_NAME=<ORGANIZATION NAME>

gcloud beta billing accounts list
export ADMIN_BILLING_ID=<ADMIN_BILLING ID>

export WORKSHOP_NUMBER=<two digit number for example 01>

export ADMIN_STORAGE_BUCKET=<ADMIN CLOUD STORAGE BUCKET>
 
  1. bootstrap_workshop.sh スクリプトを実行します。このスクリプトが完了するまで数分かかることがあります。
cd asm
./scripts/bootstrap_workshop.sh --org-name ${ORGANIZATION_NAME} --billing-id ${ADMIN_BILLING_ID} --workshop-num ${WORKSHOP_NUMBER} --admin-gcs-bucket ${ADMIN_STORAGE_BUCKET} --set-up-for-admin 
 

bootstrap_workshop.sh スクリプトが完了すると、組織内のユーザーごとに GCP フォルダが作成されます。フォルダ内に Terraform 管理プロジェクトが作成されます。Terraform 管理プロジェクトは、このワークショップに必要な残りの GCP リソースを作成するために使用されます。必要な API は、Terraform 管理プロジェクトで有効にします。Cloud Build を使用して Terraform プランを適用します。Cloud Build サービス アカウントに適切な IAM ロールを付与して、GCP でリソースを作成できるようにします。最後に、Google Cloud Storage(GCS)バケットにリモート バックエンドを構成して、すべての GCP リソースの Terraform 状態を保存します。

Terraform 管理プロジェクトで Cloud Build タスクを表示するには、Terraform 管理プロジェクト ID が必要です。これは、asm ディレクトリの vars/vars.sh ファイルに保存されます。このディレクトリは、管理者としてワークショップを自分で設定する場合にのみ永続化されます。

  1. 変数ファイルをソースして環境変数を設定する
echo "export WORKDIR=$WORKDIR" >> $WORKDIR/asm/vars/vars.sh
source $WORKDIR/asm/vars/vars.sh 
 

複数のユーザー向けにワークショップを設定する(マルチユーザー設定)

  1. Cloud Shell を開き、次の操作をすべて Cloud Shell で行います。下のリンクをクリックしてください。

CLOUD SHELL

  1. 目的の管理者ユーザーで gcloud にログインしていることを確認します。
gcloud config list
 
  1. WORKDIR を作成し、ワークショップ リポジトリのクローンを作成します。
mkdir asm-workshop
cd asm-workshop
export WORKDIR=`pwd`
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git asm
 
  1. 組織名、請求 ID、ワークショップ番号、開始ユーザー番号と終了ユーザー番号、ワークショップで使用する管理 GCS バケットを定義します。ワークショップの設定に必要な権限については、上記のセクションをご覧ください。
gcloud organizations list
export ORGANIZATION_NAME=<ORGANIZATION NAME>

gcloud beta billing accounts list
export ADMIN_BILLING_ID=<BILLING ID>

export WORKSHOP_NUMBER=<two digit number for example 01>

export START_USER_NUMBER=<number for example 1>

export END_USER_NUMBER=<number greater or equal to START_USER_NUM>

export ADMIN_STORAGE_BUCKET=<ADMIN CLOUD STORAGE BUCKET>
 
  1. bootstrap_workshop.sh スクリプトを実行します。このスクリプトが完了するまで数分かかることがあります。
cd asm
./scripts/bootstrap_workshop.sh --org-name ${ORGANIZATION_NAME} --billing-id ${ADMIN_BILLING_ID} --workshop-num ${WORKSHOP_NUMBER} --start-user-num ${START_USER_NUMBER} --end-user-num ${END_USER_NUMBER} --admin-gcs-bucket ${ADMIN_STORAGE_BUCKET}
 
  1. 管理 GCS バケットから workshop.txt ファイルを取得して、Terraform プロジェクト ID を取得します。
export WORKSHOP_ID="$(date '+%y%m%d')-${WORKSHOP_NUMBER}"
gsutil cp gs://${ADMIN_STORAGE_BUCKET}/${ORGANIZATION_NAME}/${WORKSHOP_ID}/workshop.txt .
 

4. ラボのセットアップと準備

ラボのパスを選択する

このワークショップのラボは、次のいずれかの方法で実行できます。

  • easy fast track interactive scripts」の方法
  • 各手順を手動でコピーして貼り付ける」方法

高速トラック スクリプト メソッドを使用すると、ラボごとに 1 つのインタラクティブ スクリプトを実行できます。このスクリプトは、ラボのコマンドを自動的に実行してラボの手順を説明します。コマンドはバッチで実行され、各ステップとその目的が簡潔に説明されます。各バッチの後に、次のコマンド バッチに進むよう求められます。これにより、自分のペースでラボを実行できます。ファスト トラック スクリプトはべき等です。つまり、これらのスクリプトを複数回実行しても、同じ結果が得られます。

ファスト トラック スクリプトは、次の図に示すように、各ラボの上部に緑色のボックスで表示されます。

コピー&ペースト方式は、コマンドの説明を含む個々のコマンドブロックをコピー&ペーストする従来の方法です。このメソッドは 1 回だけ実行することを想定しています。この方法でコマンドを再実行しても、同じ結果が得られる保証はありません。

ラボを実施する際は、2 つの方法のいずれかを選択してください。

Fast Track Script Setup

ユーザー情報を取得する

このワークショップは、ワークショップの管理者が作成した一時的なユーザー アカウント(またはラボ アカウント)を使用して行います。ラボアカウントは、ワークショップ内のすべてのプロジェクトを所有しています。ワークショップの管理者は、ワークショップを実施するユーザーにラボ アカウントの認証情報(ユーザー名とパスワード)を提供します。ユーザーのすべてのプロジェクトには、ラボ アカウントのユーザー名が接頭辞として付加されます。たとえば、ラボ アカウント user001@yourcompany.com の場合、Terraform 管理プロジェクト ID は user001-200131-01-tf-abcde になります。他のプロジェクトも同様です。各ユーザーは、ワークショップの管理者から提供されたラボアカウントでログインし、ラボアカウントを使用してワークショップを実施する必要があります。

  1. 下のリンクをクリックして Cloud Shell を開きます。

CLOUD SHELL

  1. ラボ アカウントの認証情報でログインします(企業アカウントや個人アカウントでログインしないでください)。ラボアカウントは userXYZ@<workshop_domain>.com のようになります。3101eca1fd3722bf.png
  2. 新しいアカウントであるため、Google 利用規約に同意するよう求められます。[同意する] をクリックします。

fb0219a89ece5168.png 4. 次の画面で、Google 利用規約に同意するチェックボックスをオンにして、Start Cloud Shell をクリックします。

7b198cf2e32cb457.png

このステップでは、GCP リソースへのアクセスに使用する小規模な Linux Debian VM をプロビジョニングします。各アカウントには Cloud Shell VM が割り当てられます。ラボアカウントでログインすると、ラボアカウントの認証情報を使用してプロビジョニングとログインが行われます。Cloud Shell に加えて、コードエディタもプロビジョニングされるため、構成ファイル(Terraform、YAML など)の編集が容易になります。デフォルトでは、Cloud Shell 画面は Cloud Shell シェル環境(下部)と Cloud Code エディタ(上部)に分割されます。5643bb4ebeafd00a.png 右上の鉛筆アイコン 8bca25ef1421c17e.png とシェル プロンプト アイコン eaeb4ac333783ba8.png を使用すると、2 つ(シェルとコードエディタ)を切り替えることができます。中央の区切りバーを上下にドラッグして、各ウィンドウのサイズを手動で変更することもできます。5. このワークショップの WORKDIR を作成します。WORKDIR は、このワークショップのすべてのラボを実行するフォルダです。Cloud Shell で次のコマンドを実行して、WORKDIR を作成します。

mkdir -p ${HOME}/asm-workshop
cd ${HOME}/asm-workshop
export WORKDIR=`pwd` 
 
  1. このワークショップで使用する変数としてラボ アカウント ユーザーをエクスポートします。これは、Cloud Shell にログインしたアカウントと同じです。
export MY_USER=<LAB ACCOUNT EMAIL PROVIDED BY THE WORKSHOP ADMIN>
# For example export MY_USER=user001@gcpworkshops.com 
 
  1. 次のコマンドを実行して、WORKDIR 変数と MY_USER 変数をエコーし、両方が正しく設定されていることを確認します。
echo "WORKDIR set to ${WORKDIR}" && echo "MY_USER set to ${MY_USER}"
 
  1. ワークショップ リポジトリのクローンを作成します。
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git ${WORKDIR}/asm
 

5. インフラストラクチャ設定 - ユーザー ワークフロー

目的: インフラストラクチャと Istio のインストールを検証する

  • ワークショップ ツールをインストールする
  • ワークショップ リポジトリのクローンを作成する
  • Infrastructure のインストールを確認する
  • k8s-repo のインストールを確認する
  • Istio のインストールを確認する

コピー&ペースト方式のラボの手順

ユーザー情報を取得する

ワークショップを設定する管理者は、ユーザーにユーザー名とパスワードの情報を提供する必要があります。ユーザーのすべてのプロジェクトには、ユーザー名の接頭辞が付きます。たとえば、ユーザー user001@yourcompany.com の場合、Terraform 管理プロジェクト ID は user001-200131-01-tf-abcde になります。他のプロジェクトも同様です。各ユーザーは、自分のワークショップ環境にのみアクセスできます。

ワークショップに必要なツール

このワークショップは、Cloud Shell からブートストラップすることを想定しています。このワークショップでは、次のツールが必要です。

  • gcloud(バージョン 270 以降)
  • kubectl
  • sed(Cloud Shell/Linux の sed で動作し、Mac OS では動作しません)
  • git(最新の状態であることを確認してください)
  • sudo apt update
  • sudo apt install git
  • jq
  • envsubst
  • kustomize
  • pv

terraform 管理プロジェクトにアクセスする

bootstrap_workshop.sh スクリプトが完了すると、組織内のユーザーごとに GCP フォルダが作成されます。フォルダ内に Terraform 管理プロジェクトが作成されます。Terraform 管理プロジェクトは、このワークショップに必要な残りの GCP リソースを作成するために使用されます。setup-terraform-admin-project.sh スクリプトは、Terraform 管理プロジェクトで必要な API を有効にします。Cloud Build は Terraform プランの適用に使用されます。スクリプトを使用して、Cloud Build サービス アカウントに適切な IAM ロールを付与し、GCP でリソースを作成できるようにします。最後に、すべての GCP リソースの Terraform 状態を保存するために、Google Cloud Storage(GCS)バケットにリモート バックエンドが構成されます。

Terraform 管理プロジェクトで Cloud Build タスクを表示するには、Terraform 管理プロジェクト ID が必要です。これは、ブートストラップ スクリプトで指定された管理 GCS バケットに保存されます。複数のユーザーに対してブートストラップ スクリプトを実行すると、すべての Terraform 管理プロジェクト ID が GCS バケットに格納されます。

  1. 下のリンクをクリックして Cloud Shell を開きます(ラボの設定と準備のセクションでまだ開いていない場合)。

CLOUD SHELL

  1. $HOME/bin フォルダに kustomize をインストールし(まだインストールされていない場合)、$HOME/bin フォルダを $PATH に追加します。
mkdir -p $HOME/bin
cd $HOME/bin
curl -s "https://raw.githubusercontent.com/\
kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"  | bash
cd $HOME
export PATH=$PATH:${HOME}/bin
echo "export PATH=$PATH:$HOME/bin" >> $HOME/.bashrc
 
  1. pv をインストールして、$HOME/bin/pv に移動します。
sudo apt-get update && sudo apt-get -y install pv
sudo mv /usr/bin/pv ${HOME}/bin/pv
 
  1. bash プロンプトを更新します。
cp $WORKDIR/asm/scripts/krompt.bash $HOME/.krompt.bash
echo "export PATH=\$PATH:\$HOME/bin" >> $HOME/.asm-workshop.bash
echo "source $HOME/.krompt.bash" >> $HOME/.asm-workshop.bash

alias asm-init='source $HOME/.asm-workshop.bash' >> $HOME/.bashrc
echo "source $HOME/.asm-workshop.bash" >> $HOME/.bashrc
source $HOME/.bashrc
 
  1. 目的のユーザー アカウントで gcloud にログインしていることを確認します。
echo "Check logged in user output from the next command is $MY_USER"
gcloud config list account --format=json | jq -r .core.account
 
  1. 次のコマンドを実行して、Terraform 管理プロジェクト ID を取得します。
export TF_ADMIN=$(gcloud projects list | grep tf- | awk '{ print $1 }')
echo $TF_ADMIN
 
  1. ワークショップに関連付けられているすべてのリソースは、Terraform 管理プロジェクトの GCS バケットに保存されている vars.sh ファイルの変数として保存されます。Terraform 管理プロジェクトの vars.sh ファイルを取得します。
mkdir $WORKDIR/asm/vars
gsutil cp gs://$TF_ADMIN/vars/vars.sh $WORKDIR/asm/vars/vars.sh
echo "export WORKDIR=$WORKDIR" >> $WORKDIR/asm/vars/vars.sh
 
  1. 表示されたリンクをクリックして、Terraform 管理プロジェクトの Cloud Build ページを開き、ビルドが正常に完了したことを確認します。
source $WORKDIR/asm/vars/vars.sh
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_ADMIN}"
 

Cloud コンソールに初めてアクセスする場合は、Google の利用規約に同意します。

  1. Cloud Build ページが表示されたら、左側のナビゲーションから History リンクをクリックし、最新のビルドをクリックして、最初の Terraform 適用に関する詳細を表示します。次のリソースは、Terraform スクリプトの一部として作成されます。上記のアーキテクチャ図も参照してください。
  • 組織内の 4 つの GCP プロジェクト。指定された請求先アカウントは各プロジェクトに関連付けられています。
  • 1 つのプロジェクトは、共有 VPC の network host project です。このプロジェクトでは他のリソースは作成されません。
  • 1 つのプロジェクトは、Istio コントロール プレーンの GKE クラスタに使用される ops project です。
  • 2 つのプロジェクトは、それぞれのサービスに取り組む 2 つの異なる開発チームを表しています。
  • 3 つの opsdev1dev2 プロジェクトそれぞれに 2 つの GKE クラスタが作成されます。
  • k8s-repo という名前の CSR リポジトリが作成されます。このリポジトリには、Kubernetes マニフェスト ファイル用の 6 つのフォルダが含まれています。GKE クラスタごとに 1 つのフォルダ。このリポジトリは、GitOps 方式で Kubernetes マニフェストをクラスタにデプロイするために使用されます。
  • k8s-repo の master ブランチに commit があるたびに、それぞれのフォルダから Kubernetes マニフェストを GKE クラスタにデプロイするように、Cloud Build トリガーが作成されます。
  1. terraform admin project でビルドが完了すると、ops プロジェクトで別のビルドが開始されます。表示されたリンクをクリックして ops project の Cloud Build ページを開き、k8s-repo Cloud Build が正常に完了したことを確認します。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
 

インストールを確認する

  1. すべてのクラスタの kubeconfig ファイルを作成します。次のスクリプトを実行します。
$WORKDIR/asm/scripts/setup-gke-vars-kubeconfig.sh
 

このスクリプトは、gke フォルダに kubemesh という新しい kubeconfig ファイルを作成します。

  1. 新しい kubeconfig ファイルを指すように KUBECONFIG 変数を変更します。
source $WORKDIR/asm/vars/vars.sh
export KUBECONFIG=$WORKDIR/asm/gke/kubemesh
 
  1. Cloud Shell が再起動するたびに vars.sh と KUBECONFIG 変数が読み込まれるように、Cloud Shell の .bashrc に追加します。
echo "source ${WORKDIR}/asm/vars/vars.sh" >> $HOME/.bashrc
echo "export KUBECONFIG=${WORKDIR}/asm/gke/kubemesh" >> $HOME/.bashrc
 
  1. クラスタ コンテキストを一覧表示します。6 つのクラスタが表示されます。
kubectl config view -ojson | jq -r '.clusters[].name'
 
    `Output (do not copy)`
gke_tf05-01-ops_us-central1_gke-asm-2-r2-prod
gke_tf05-01-ops_us-west1_gke-asm-1-r1-prod
gke_tf05-02-dev1_us-west1-a_gke-1-apps-r1a-prod
gke_tf05-02-dev1_us-west1-b_gke-2-apps-r1b-prod
gke_tf05-03-dev2_us-central1-a_gke-3-apps-r2a-prod
gke_tf05-03-dev2_us-central1-b_gke-4-apps-r2b-prod

Istio のインストールを確認する

  1. すべての Pod が実行され、ジョブが完了していることを確認して、Istio が両方のクラスタにインストールされていることを確認します。
kubectl --context ${OPS_GKE_1} get pods -n istio-system
kubectl --context ${OPS_GKE_2} get pods -n istio-system
 
    `Output (do not copy)`
NAME                                      READY   STATUS    RESTARTS   AGE
grafana-5f798469fd-z9f98                  1/1     Running   0          6m21s
istio-citadel-568747d88-qdw64             1/1     Running   0          6m26s
istio-egressgateway-8f454cf58-ckw7n       1/1     Running   0          6m25s
istio-galley-6b9495645d-m996v             2/2     Running   0          6m25s
istio-ingressgateway-5df799fdbd-8nqhj     1/1     Running   0          2m57s
istio-pilot-67fd786f65-nwmcb              2/2     Running   0          6m24s
istio-policy-74cf89cb66-4wrpl             2/2     Running   1          6m25s
istio-sidecar-injector-759bf6b4bc-mw4vf   1/1     Running   0          6m25s
istio-telemetry-77b6dfb4ff-zqxzz          2/2     Running   1          6m24s
istio-tracing-cd67ddf8-n4d7k              1/1     Running   0          6m25s
istiocoredns-5f7546c6f4-g7b5c             2/2     Running   0          6m39s
kiali-7964898d8c-5twln                    1/1     Running   0          6m23s
prometheus-586d4445c7-xhn8d               1/1     Running   0          6m25s
    `Output (do not copy)`
NAME                                      READY   STATUS    RESTARTS   AGE
grafana-5f798469fd-2s8k4                  1/1     Running   0          59m
istio-citadel-568747d88-87kdj             1/1     Running   0          59m
istio-egressgateway-8f454cf58-zj9fs       1/1     Running   0          60m
istio-galley-6b9495645d-qfdr6             2/2     Running   0          59m
istio-ingressgateway-5df799fdbd-2c9rc     1/1     Running   0          60m
istio-pilot-67fd786f65-nzhx4              2/2     Running   0          59m
istio-policy-74cf89cb66-4bc7f             2/2     Running   3          59m
istio-sidecar-injector-759bf6b4bc-grk24   1/1     Running   0          59m
istio-telemetry-77b6dfb4ff-6zr94          2/2     Running   4          60m
istio-tracing-cd67ddf8-grs9g              1/1     Running   0          60m
istiocoredns-5f7546c6f4-gxd66             2/2     Running   0          60m
kiali-7964898d8c-nhn52                    1/1     Running   0          59m
prometheus-586d4445c7-xr44v               1/1     Running   0          59m
  1. 両方の dev1 クラスタに Istio がインストールされていることを確認します。dev1 クラスタでは、Citadel、sidecar-injector、coredns のみが実行されます。ops-1 クラスタで実行されている Istio コントロール プレーンを共有します。
kubectl --context ${DEV1_GKE_1} get pods -n istio-system
kubectl --context ${DEV1_GKE_2} get pods -n istio-system
 
  1. 両方の dev2 クラスタに Istio がインストールされていることを確認します。dev2 クラスタでは、Citadel、sidecar-injector、coredns のみが実行されます。これらは、ops-2 クラスタで実行されている Istio コントロール プレーンを共有します。
kubectl --context ${DEV2_GKE_1} get pods -n istio-system
kubectl --context ${DEV2_GKE_2} get pods -n istio-system
 
    `Output (do not copy)`
NAME                                      READY   STATUS    RESTARTS   AGE
istio-citadel-568747d88-4lj9b             1/1     Running   0          66s
istio-sidecar-injector-759bf6b4bc-ks5br   1/1     Running   0          66s
istiocoredns-5f7546c6f4-qbsqm             2/2     Running   0          78s

共有コントロール プレーンのサービス検出を確認する

  1. 必要に応じて、Secret がデプロイされていることを確認します。
kubectl --context ${OPS_GKE_1} get secrets -l istio/multiCluster=true -n istio-system
kubectl --context ${OPS_GKE_2} get secrets -l istio/multiCluster=true -n istio-system
 
    `Output (do not copy)`
For OPS_GKE_1:
NAME                  TYPE     DATA   AGE
gke-1-apps-r1a-prod   Opaque   1      8m7s
gke-2-apps-r1b-prod   Opaque   1      8m7s
gke-3-apps-r2a-prod   Opaque   1      44s
gke-4-apps-r2b-prod   Opaque   1      43s

For OPS_GKE_2:
NAME                  TYPE     DATA   AGE
gke-1-apps-r1a-prod   Opaque   1      40s
gke-2-apps-r1b-prod   Opaque   1      40s
gke-3-apps-r2a-prod   Opaque   1      8m4s
gke-4-apps-r2b-prod   Opaque   1      8m4s

このワークショップでは、すべての GKE クラスタが作成される単一の共有 VPC を使用します。クラスタ間でサービスを検出するには、運用クラスタで Secret として作成された kubeconfig ファイル(各アプリケーション クラスタ用)を使用します。Pilot は、これらのシークレットを使用して、アプリケーション クラスタの Kube API サーバーにクエリを実行してサービスを検出します(上記のシークレットで認証されます)。両方の運用クラスタが、kubeconfig で作成された Secret を使用してすべてのアプリクラスタを認証できることがわかります。運用クラスタは、kubeconfig ファイルをシークレット メソッドとして使用して、サービスを自動的に検出できます。これには、運用クラスタの Pilot が他のすべてのクラスタの Kube API サーバーにアクセスできる必要があります。Pilot が Kube API サーバーにアクセスできない場合は、リモート サービスを ServiceEntries として手動で追加します。ServiceEntry は、サービス レジストリの DNS エントリと考えることができます。ServiceEntry は、完全修飾 DNS 名(FQDN)と到達可能な IP アドレスを使用してサービスを定義します。詳細については、Istio マルチクラスタのドキュメントをご覧ください。

6. インフラストラクチャ リポジトリの説明

インフラストラクチャ Cloud Build

ワークショップの GCP リソースは、Cloud Buildinfrastructure CSR リポジトリを使用してビルドされます。ローカル ターミナルからブートストラップ スクリプト(scripts/bootstrap_workshop.sh にあります)を実行しました。ブートストラップ スクリプトは、GCP フォルダ、Terraform 管理プロジェクト、Cloud Build サービス アカウントの適切な IAM 権限を作成します。Terraform 管理プロジェクトは、Terraform の状態、ログ、その他のスクリプトの保存に使用されます。これには、infrastructurek8s_repo の CSR リポジトリが含まれています。これらのリポジトリについては、次のセクションで詳しく説明します。terraform 管理プロジェクトには、他のワークショップ リソースは構築されていません。terraform 管理プロジェクトの Cloud Build サービス アカウントは、ワークショップのリソースをビルドするために使用されます。

infrastructure フォルダにある cloudbuild.yaml ファイルは、ワークショップ用の GCP リソースのビルドに使用されます。GCP リソースの作成に必要なすべてのツールを含むカスタム ビルダー イメージを作成します。これらのツールには、gcloud SDK、Terraform、その他のユーティリティ(Python、git、jq など)が含まれます。カスタム ビルダー イメージは、各リソースに対して terraform planapply を実行します。各リソースの Terraform ファイルは個別のフォルダにあります(詳細は次のセクションをご覧ください)。リソースは一度に 1 つずつ、通常構築される順序で構築されます(たとえば、GCP プロジェクトは、プロジェクト内にリソースが作成される前に構築されます)。詳しくは、cloudbuild.yaml ファイルをご覧ください。

infrastructure リポジトリに commit があるたびに、Cloud Build がトリガーされます。インフラストラクチャに対する変更は、Infrastructure as Code(IaC)として保存され、リポジトリに commit されます。ワークショップの状態は常にこのリポジトリに保存されます。

フォルダ構造 - チーム、環境、リソース

Infrastructure リポジトリは、ワークショップ用の GCP インフラストラクチャ リソースを設定します。フォルダとサブフォルダに構造化されています。リポジトリ内のベースフォルダは、特定の GCP リソースを所有する team を表します。次のフォルダレイヤは、チームの特定の environment(dev、stage、prod など)を表します。環境内の次のフォルダ階層は、特定の resource(host_project、gke_clusters など)を表します。必要なスクリプトと Terraform ファイルは、リソース フォルダ内に存在します。

434fc1769bb49b8c.png

このワークショップには、次の 4 種類のチームが参加します。

  1. infrastructure - クラウド インフラストラクチャ チームを表します。他のすべてのチームの GCP リソースを作成する責任を負います。リソースには Terraform 管理プロジェクトを使用します。インフラストラクチャ リポジトリ自体は、Terraform 管理プロジェクトにあります。Terraform 状態ファイル(後述)も同様です。これらのリソースは、ブートストラップ プロセス中に bash スクリプトによって作成されます(詳細については、モジュール 0 - 管理者のワークフローをご覧ください)。
  2. network - ネットワーキング チームを表します。VPC とネットワーキング リソースを担当します。次の GCP リソースを所有しています。
  3. host project - 共有 VPC ホスト プロジェクトを表します。
  4. shared VPC - 共有 VPC、サブネット、セカンダリ IP 範囲、ルート、ファイアウォール ルールを表します。
  5. ops - 運用チーム/DevOps チームを表します。次のリソースを所有しています。
  6. ops project - すべての ops リソースのプロジェクトを表します。
  7. gke clusters - リージョンごとに 1 つの ops GKE クラスタ。Istio コントロール プレーンは、各 ops GKE クラスタにインストールされます。
  8. k8s-repo - すべての GKE クラスタの GKE マニフェストを含む CSR リポジトリ。
  9. apps - アプリケーション チームを表します。このワークショップでは、app1app2 の 2 つのチームをシミュレートします。次のリソースを所有しています。
  10. app projects - 各アプリチームに独自のプロジェクト セットが割り当てられます。これにより、特定のプロジェクトの課金と IAM を制御できます。
  11. gke clusters - アプリケーション コンテナ/Pod が実行されるアプリケーション クラスタです。
  12. gce instances - 必要に応じて、GCE インスタンスで実行されるアプリケーションがある場合。このワークショップでは、app1 にアプリケーションの一部が実行される GCE インスタンスがいくつかあります。

このワークショップでは、同じアプリ(Hipster Shop アプリ)が app1 と app2 の両方を表します。

プロバイダ、状態、出力 - バックエンドと共有状態

google プロバイダと google-beta プロバイダは gcp/[environment]/gcp/provider.tf にあります。provider.tf ファイルは、すべてのリソース フォルダに symlinkedされています。これにより、リソースごとにプロバイダを個別に管理するのではなく、1 か所でプロバイダを変更できます。

各リソースには、リソースの tfstate ファイルの場所を定義する backend.tf ファイルが含まれています。この backend.tf ファイルは、スクリプト(scripts/setup_terraform_admin_project に配置)を使用してテンプレート(templates/backend.tf_tmpl に配置)から生成され、それぞれのリソース フォルダに配置されます。バックエンドには Google Cloud Storage(GCS)バケットが使用されます。GCS バケットのフォルダ名がリソース名と一致している。リソース バックエンドはすべて、Terraform 管理プロジェクトに存在します。

相互依存の値を持つリソースには output.tf ファイルが含まれます。必要な出力値は、その特定のリソースのバックエンドで定義された tfstate ファイルに保存されます。たとえば、プロジェクトに GKE クラスタを作成するには、プロジェクト ID を知っておく必要があります。プロジェクト ID は output.tf を介して tfstate ファイルに出力されます。このファイルは、GKE クラスタ リソースの terraform_remote_state データソースで使用できます。

shared_state ファイルは、リソースの tfstate ファイルを指す terraform_remote_state データソースです。他のリソースからの出力を必要とするリソース フォルダに shared_state_[resource_name].tf ファイル(または複数のファイル)が存在する。たとえば、ops プロジェクトで GKE クラスタを作成するには、プロジェクト ID と VPC の詳細が必要になるため、ops_gke リソース フォルダには ops_project リソースと shared_vpc リソースの shared_state ファイルがあります。shared_state ファイルは、スクリプト(scripts/setup_terraform_admin_project にあります)を使用してテンプレート(templates/shared_state.tf_tmpl にあります)から生成されます。すべてのリソースの shared_state ファイルは gcp/[environment]/shared_states フォルダに配置されます。必要な shared_state ファイルは、それぞれのリソース フォルダにシンボリック リンクされています。すべての shared_state ファイルを 1 つのフォルダに配置し、適切なリソース フォルダにシンボリック リンクすることで、すべての状態ファイルを 1 か所で簡単に管理できます。

変数

すべてのリソース値は環境変数として保存されます。これらの変数は、terraform 管理プロジェクトの GCS バケットにある vars.sh というファイルに(エクスポート ステートメントとして)保存されます。これには、組織 ID、課金アカウント、プロジェクト ID、GKE クラスタの詳細などが含まれます。任意のターミナルから vars.sh をダウンロードして取得し、設定の値を取得できます。

Terraform 変数は vars.shTF_VAR_[variable name] として保存されます。これらの変数は、それぞれのリソース フォルダに variables.tfvars ファイルを生成するために使用されます。variables.tfvars ファイルには、すべての変数とその値が含まれています。variables.tfvars ファイルは、同じフォルダ内のテンプレート ファイルからスクリプト(scripts/setup_terraform_admin_project にあります)を使用して生成されます。

K8s リポジトリの説明

k8s_repo は、Terraform 管理プロジェクトにある CSR リポジトリ(インフラストラクチャ リポジトリとは別)です。これは、GKE マニフェストを保存してすべての GKE クラスタに適用するために使用されます。k8s_repo は、インフラストラクチャ Cloud Build によって作成されます(詳細については、前のセクションをご覧ください)。最初のインフラストラクチャ Cloud Build プロセスでは、合計 6 つの GKE クラスタが作成されます。k8s_repo に 6 つのフォルダが作成されます。各フォルダ(GKE クラスタ名と一致する名前)は、それぞれのリソース マニフェスト ファイルを含む GKE クラスタに対応しています。インフラストラクチャの構築と同様に、Cloud Build は k8s_repo を使用して Kubernetes マニフェストをすべての GKE クラスタに適用するために使用されます。k8s_repo リポジトリに commit があるたびに、Cloud Build がトリガーされます。インフラストラクチャと同様に、すべての Kubernetes マニフェストは k8s_repo リポジトリにコードとして保存され、各 GKE クラスタの状態は常にそれぞれのフォルダに保存されます。

初期インフラストラクチャの構築の一環として、k8s_repo が作成され、すべてのクラスタに Istio がインストールされます。

プロジェクト、GKE クラスタ、Namespace

このワークショップのリソースは、複数の GCP プロジェクトに分割されています。プロジェクトは、会社の組織(またはチーム)の構造と一致している必要があります。さまざまなプロジェクト、プロダクト、リソースを担当するチーム(組織内)が、異なる GCP プロジェクトを使用している。プロジェクトを分離すると、IAM 権限の個別のセットを作成し、プロジェクト レベルで課金を管理できます。また、割り当てはプロジェクト レベルでも管理されます。

このワークショップには、それぞれ独自のプロジェクトを持つ 5 つのチームが参加しています。

  1. GCP リソースを構築するインフラストラクチャ チームは、Terraform admin project を使用します。インフラストラクチャをコードとして CSR リポジトリ(infrastructure)で管理し、GCP で構築されたリソースに関連するすべての Terraform 状態情報を GCS バケットに保存します。これらは、CSR リポジトリと Terraform 状態の GCS バケットへのアクセスを制御します。
  2. 共有 VPC を構築するネットワーク チームhost project を使用します。このプロジェクトには、VPC、サブネット、ルート、ファイアウォール ルールが含まれています。共有 VPC を使用すると、GCP リソースのネットワーキングを一元管理できます。すべてのプロジェクトで、ネットワーキングにこの単一の共有 VPC が使用されていました。
  3. GKE クラスタと ASM/Istio コントロール プレーンを構築する ops/プラットフォーム チームops project を使用します。GKE クラスタとサービス メッシュのライフサイクルを管理します。クラスタの強化、Kubernetes プラットフォームの復元性とスケーリングの管理を担当します。このワークショップでは、Kubernetes にリソースをデプロイする gitops メソッドを使用します。CSR リポジトリ(k8s_repo)が ops プロジェクトに存在します。
  4. 最後に、アプリケーションを構築する dev1 チームと dev2 チーム(2 つの開発チームを表す)は、独自の dev1dev2 projects を使用します。これらは、お客様に提供するアプリケーションとサービスです。これらは、運用チームが管理するプラットフォーム上に構築されます。リソース(デプロイ、サービスなど)は k8s_repo に push され、適切なクラスタにデプロイされます。このワークショップでは、CI/CD のベスト プラクティスとツールに焦点を当てていないことに注意してください。Cloud Build を使用して、Kubernetes リソースを GKE クラスタに直接デプロイする処理を自動化します。実際の運用環境では、適切な CI/CD ソリューションを使用して、アプリケーションを GKE クラスタにデプロイします。

このワークショップでは、2 種類の GKE クラスタを使用します。

  1. 運用クラスタ - 運用チームが DevOps ツールを実行するために使用します。このワークショップでは、ASM/Istio コントロール プレーンを実行してサービス メッシュを管理します。
  2. アプリケーション(アプリ)クラスタ - 開発チームがアプリケーションを実行するために使用します。このワークショップでは、Hipster Shop アプリを使用します。

運用/管理ツールをアプリケーションを実行するクラスタから分離すると、各リソースのライフサイクルを個別に管理できます。また、2 種類のクラスタは、それらを使用するチーム/プロダクトに関連する別のプロジェクトに存在するため、IAM 権限の管理も容易になります。

GKE クラスタは合計 6 つあります。ops プロジェクトに 2 つのリージョン オペレーション クラスタが作成されます。ASM/Istio コントロール プレーンが両方の運用クラスタにインストールされている。各運用クラスタは異なるリージョンにあります。また、4 つのゾーン アプリケーション クラスタがあります。これらは独自のプロジェクトで作成されます。このワークショップでは、それぞれ独自のプロジェクトを持つ 2 つの開発チームをシミュレートします。各プロジェクトには 2 つのアプリ クラスタが含まれています。アプリ クラスタは、異なるゾーンのゾーンクラスタです。4 つのアプリクラスタは、2 つのリージョンと 4 つのゾーンに配置されています。これにより、リージョンとゾーンの冗長性が実現します。

このワークショップで使用する Hipster Shop アプリケーションは、4 つのアプリ クラスタすべてにデプロイされています。各マイクロサービスは、すべてのアプリ クラスタ内の独自の Namespace に存在します。Hipster Shop アプリのデプロイ(Pod)が ops クラスタにデプロイされていません。ただし、すべてのマイクロサービスの Namespace と Service リソースも ops クラスタに作成されます。ASM/Istio コントロール プレーンは、サービス ディスカバリに Kubernetes サービス レジストリを使用します。サービス(運用クラスタ内)がない場合は、アプリクラスタで実行されているサービスごとに ServiceEntry を手動で作成する必要があります。

このワークショップでは、10 層のマイクロサービス アプリケーションをデプロイします。このアプリケーションは、「Hipster Shop」という名前のウェブベースの e コマース アプリです。このアプリで、ユーザーは、アイテムを閲覧し、カートに追加して購入できます。

Kubernetes マニフェストと k8s_repo

k8s_repo を使用して、すべての GKE クラスタに Kubernetes リソースを追加します。これを行うには、Kubernetes マニフェストをコピーして k8s_repo に commit します。k8s_repo へのすべての commit は、Kubernetes マニフェストをそれぞれのクラスタにデプロイする Cloud Build ジョブをトリガーします。各クラスタのマニフェストは、クラスタ名と同じ名前の個別のフォルダにあります。

6 つのクラスタ名は次のとおりです。

  1. gke-asm-1-r1-prod - リージョン 1 のリージョン オペレーション クラスタ
  2. gke-asm-2-r2-prod - リージョン 2 のリージョン オペレーション クラスタ
  3. gke-1-apps-r1a-prod - リージョン 1 ゾーン a のアプリ クラスタ
  4. gke-2-apps-r1b-prod - リージョン 1 ゾーン b のアプリ クラスタ
  5. gke-3-apps-r2a-prod - リージョン 2 ゾーン a のアプリ クラスタ
  6. gke-4-apps-r2b-prod - リージョン 2 ゾーン b のアプリクラスタ

k8s_repo には、これらのクラスタに対応するフォルダがあります。これらのフォルダに配置されたマニフェストは、対応する GKE クラスタに適用されます。各クラスタのマニフェストは、管理しやすいようにサブフォルダ(クラスタのメインフォルダ内)に配置されます。このワークショップでは、Kustomize を使用して、デプロイされるリソースを追跡します。詳細については、Kustomize の公式ドキュメントをご覧ください。

7. サンプルアプリをデプロイする

目標: アプリ クラスタに Hipster Shop アプリをデプロイする

  • k8s-repo のクローン
  • Hipster Shop マニフェストをすべてのアプリ クラスタにコピーする
  • 運用クラスタに Hipster Shop アプリの Service を作成する
  • グローバル接続をテストするために、運用クラスタに loadgenerators を設定する
  • Hipster Shop アプリへの安全な接続を確認する

コピー&ペースト方式のラボの手順

運用プロジェクトのソース リポジトリのクローンを作成する

初期の Terraform インフラストラクチャのビルドの一部として、k8s-repo は ops プロジェクトにすでに作成されています。

  1. git リポジトリ用の空のディレクトリを作成します。
mkdir $WORKDIR/k8s-repo
 
  1. Git リポジトリを初期化し、リモートを追加して、リモート リポジトリからマスターを pull します。
cd $WORKDIR/k8s-repo
git init && git remote add origin \
https://source.developers.google.com/p/$TF_VAR_ops_project_name/r/k8s-repo
 
  1. ローカル Git のローカル構成を設定します。
git config --local user.email $MY_USER
git config --local user.name "K8s repo user"
git config --local \
credential.'https://source.developers.google.com'.helper gcloud.sh
git pull origin master

マニフェストをコピー、コミット、プッシュする

  1. すべてのクラスタのソースリポジトリに Hipster Shop の Namespace とサービスをコピーします。
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/.

cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/.
 
  1. アプリフォルダの kustomization.yaml をすべてのクラスタにコピーします。
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/
 
  1. Hipster Shop の Deployment、RBAC、PodSecurityPolicy をアプリ クラスタのソースリポジトリにコピーします。
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/

cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
  1. 1 つを除くすべての開発クラスタから、cartservice デプロイ、rbac、podsecuritypolicy を削除します。Hipstershop はマルチクラスタ デプロイ用に構築されていないため、結果の不整合を避けるために、1 つの cartservice のみを使用しています。
rm $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/deployments/app-cart-service.yaml
rm $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/podsecuritypolicies/cart-psp.yaml
rm $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/rbac/cart-rbac.yaml

rm $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/deployments/app-cart-service.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/podsecuritypolicies/cart-psp.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/rbac/cart-rbac.yaml

rm $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/deployments/app-cart-service.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/podsecuritypolicies/cart-psp.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/rbac/cart-rbac.yaml
 
  1. 最初の開発クラスタの kustomization.yaml にのみ cartservice デプロイ、rbac、podsecuritypolicy を追加します。
cd ${WORKDIR}/k8s-repo/${DEV1_GKE_1_CLUSTER}/app
cd deployments && kustomize edit add resource app-cart-service.yaml
cd ../podsecuritypolicies && kustomize edit add resource cart-psp.yaml
cd ../rbac && kustomize edit add resource cart-rbac.yaml
cd ${WORKDIR}/asm
 
  1. ops クラスタの kustomization.yaml から podsecuritypolicies、deployments、rbac ディレクトリを削除
sed -i -e '/- deployments\//d' -e '/- podsecuritypolicies\//d' \
  -e '/- rbac\//d' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/kustomization.yaml
sed -i -e '/- deployments\//d' -e '/- podsecuritypolicies\//d' \
  -e '/- rbac\//d' \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/kustomization.yaml
  1. RBAC マニフェストの PROJECT_ID を置き換えます。
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev1_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV1_GKE_1_CLUSTER}/app/rbac/*
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev1_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV1_GKE_2_CLUSTER}/app/rbac/*
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev2_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV2_GKE_1_CLUSTER}/app/rbac/*
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev2_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV2_GKE_2_CLUSTER}/app/rbac/*
  
  1. IngressGateway マニフェストと VirtualService マニフェストを ops クラスタのソース リポジトリにコピーします。
cp -r $WORKDIR/asm/k8s_manifests/prod/app-ingress/* \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-ingress/
cp -r $WORKDIR/asm/k8s_manifests/prod/app-ingress/* \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-ingress/
 
  1. Config Connector リソースを各プロジェクトのクラスタのいずれかにコピーします。
cp -r $WORKDIR/asm/k8s_manifests/prod/app-cnrm/* \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-cnrm/
cp -r $WORKDIR/asm/k8s_manifests/prod/app-cnrm/* \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app-cnrm/
cp -r $WORKDIR/asm/k8s_manifests/prod/app-cnrm/* \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app-cnrm/
 
  1. Config Connector マニフェストの PROJECT_ID を置き換えます。
sed -i 's/${PROJECT_ID}/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-cnrm/*
sed -i 's/${PROJECT_ID}/'$TF_VAR_dev1_project_name'/g' \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app-cnrm/*
sed -i 's/${PROJECT_ID}/'$TF_VAR_dev2_project_name'/g' \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app-cnrm/*
 
  1. loadgenerator マニフェスト(Deployment、PodSecurityPolicy、RBAC)を ops クラスタにコピーします。Hipster Shop アプリは、グローバル Google Cloud ロードバランサ(GCLB)を使用して公開されます。GCLB はクライアント トラフィック(frontend 宛て)を受信し、Service の最も近いインスタンスに送信します。両方の運用クラスタに loadgenerator を配置すると、運用クラスタで実行されている両方の Istio Ingress ゲートウェイにトラフィックが確実に送信されます。ロード バランシングについては、次のセクションで詳しく説明します。
cp -r $WORKDIR/asm/k8s_manifests/prod/app-loadgenerator/. \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app-loadgenerator/. \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/. 
 
  1. 両方の運用クラスタの loadgenerator マニフェストで運用プロジェクト ID を置き換えます。
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g'  \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/loadgenerator-deployment.yaml
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/loadgenerator-rbac.yaml
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/loadgenerator-deployment.yaml
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/loadgenerator-rbac.yaml
 

  1. 両方の運用クラスタの kustomization.yaml に loadgenerator リソースを追加します。
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/
kustomize edit add resource loadgenerator-psp.yaml
kustomize edit add resource loadgenerator-rbac.yaml
kustomize edit add resource loadgenerator-deployment.yaml

cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/
kustomize edit add resource loadgenerator-psp.yaml
kustomize edit add resource loadgenerator-rbac.yaml
kustomize edit add resource loadgenerator-deployment.yaml
 

  1. k8s-repo に commit します。
cd $WORKDIR/k8s-repo
git add . && git commit -am "create app namespaces and install hipster shop"
git push --set-upstream origin master 
 
  1. 以前に開いたタブで、または次のリンクをクリックして、Ops プロジェクトの Cloud Build のステータスを表示します。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
  

アプリケーションのデプロイを確認する

  1. cart 以外のすべてのアプリケーション Namespace の Pod が、すべての開発クラスタで Running 状態であることを確認します。
for ns in ad checkout currency email frontend payment product-catalog recommendation shipping; do
  kubectl --context $DEV1_GKE_1 get pods -n $ns;
  kubectl --context $DEV1_GKE_2 get pods -n $ns;
  kubectl --context $DEV2_GKE_1 get pods -n $ns;
  kubectl --context $DEV2_GKE_2 get pods -n $ns;
done;
 

Output (do not copy)

NAME                               READY   STATUS    RESTARTS   AGE
currencyservice-5c5b8876db-pvc6s   2/2     Running   0          13m
NAME                               READY   STATUS    RESTARTS   AGE
currencyservice-5c5b8876db-xlkl9   2/2     Running   0          13m
NAME                               READY   STATUS    RESTARTS   AGE
currencyservice-5c5b8876db-zdjkg   2/2     Running   0          115s
NAME                               READY   STATUS    RESTARTS   AGE
currencyservice-5c5b8876db-l748q   2/2     Running   0          82s

NAME                            READY   STATUS    RESTARTS   AGE
emailservice-588467b8c8-gk92n   2/2     Running   0          13m
NAME                            READY   STATUS    RESTARTS   AGE
emailservice-588467b8c8-rvzk9   2/2     Running   0          13m
NAME                            READY   STATUS    RESTARTS   AGE
emailservice-588467b8c8-mt925   2/2     Running   0          117s
NAME                            READY   STATUS    RESTARTS   AGE
emailservice-588467b8c8-klqn7   2/2     Running   0          84s

NAME                        READY   STATUS    RESTARTS   AGE
frontend-64b94cf46f-kkq7d   2/2     Running   0          13m
NAME                        READY   STATUS    RESTARTS   AGE
frontend-64b94cf46f-lwskf   2/2     Running   0          13m
NAME                        READY   STATUS    RESTARTS   AGE
frontend-64b94cf46f-zz7xs   2/2     Running   0          118s
NAME                        READY   STATUS    RESTARTS   AGE
frontend-64b94cf46f-2vtw5   2/2     Running   0          85s

NAME                              READY   STATUS    RESTARTS   AGE
paymentservice-777f6c74f8-df8ml   2/2     Running   0          13m
NAME                              READY   STATUS    RESTARTS   AGE
paymentservice-777f6c74f8-bdcvg   2/2     Running   0          13m
NAME                              READY   STATUS    RESTARTS   AGE
paymentservice-777f6c74f8-jqf28   2/2     Running   0          117s
NAME                              READY   STATUS    RESTARTS   AGE
paymentservice-777f6c74f8-95x2m   2/2     Running   0          86s

NAME                                     READY   STATUS    RESTARTS   AGE
productcatalogservice-786dc84f84-q5g9p   2/2     Running   0          13m
NAME                                     READY   STATUS    RESTARTS   AGE
productcatalogservice-786dc84f84-n6lp8   2/2     Running   0          13m
NAME                                     READY   STATUS    RESTARTS   AGE
productcatalogservice-786dc84f84-gf9xl   2/2     Running   0          119s
NAME                                     READY   STATUS    RESTARTS   AGE
productcatalogservice-786dc84f84-v7cbr   2/2     Running   0          86s

NAME                                     READY   STATUS    RESTARTS   AGE
recommendationservice-5fdf959f6b-2ltrk   2/2     Running   0          13m
NAME                                     READY   STATUS    RESTARTS   AGE
recommendationservice-5fdf959f6b-dqd55   2/2     Running   0          13m
NAME                                     READY   STATUS    RESTARTS   AGE
recommendationservice-5fdf959f6b-jghcl   2/2     Running   0          119s
NAME                                     READY   STATUS    RESTARTS   AGE
recommendationservice-5fdf959f6b-kkspz   2/2     Running   0          87s

NAME                              READY   STATUS    RESTARTS   AGE
shippingservice-7bd5f569d-qqd9n   2/2     Running   0          13m
NAME                              READY   STATUS    RESTARTS   AGE
shippingservice-7bd5f569d-xczg5   2/2     Running   0          13m
NAME                              READY   STATUS    RESTARTS   AGE
shippingservice-7bd5f569d-wfgfr   2/2     Running   0          2m
NAME                              READY   STATUS    RESTARTS   AGE
shippingservice-7bd5f569d-r6t8v   2/2     Running   0          88s
  1. 最初の開発クラスタでのみ、cart Namespace の Pod が Running 状態であることを確認します。
kubectl --context $DEV1_GKE_1 get pods -n cart;
 

Output (do not copy)

NAME                           READY   STATUS    RESTARTS   AGE
cartservice-659c9749b4-vqnrd   2/2     Running   0          17m

Hipster Shop アプリにアクセスする

グローバル ロード バランシング

これで、Hipster Shop アプリが 4 つのアプリ クラスタすべてにデプロイされました。これらのクラスタは、2 つのリージョンと 4 つのゾーンにあります。クライアントは、frontend サービスにアクセスすることで Hipster Shop アプリにアクセスできます。frontend サービスは、4 つのアプリ クラスタすべてで実行されます。Google Cloud ロードバランサ(GCLB)は、クライアント トラフィックを frontend サービスの 4 つのインスタンスすべてに転送するために使用されます。

Istio Ingress ゲートウェイは、ops クラスタでのみ実行され、リージョン内の 2 つのゾーン アプリケーション クラスタに対するリージョン ロードバランサとして機能します。GCLB は、2 つの Istio Ingress ゲートウェイ(2 つの ops クラスタで実行)をグローバル フロントエンド サービスのバックエンドとして使用します。Istio Ingress ゲートウェイは、GCLB からクライアント トラフィックを受信し、アプリケーション クラスタで実行されているフロントエンド Pod にクライアント トラフィックを転送します。

4c618df35cb928ee.png

また、Istio Ingress ゲートウェイをアプリケーション クラスタに直接配置し、GCLB でそれらをバックエンドとして使用することもできます。

GKE Autoneg コントローラ

Istio Ingress ゲートウェイ Kubernetes Service は、ネットワーク エンドポイント グループ(NEG)を使用して、GCLB のバックエンドとして自身を登録します。NEG を使用すると、GCLB を使用したコンテナ ネイティブのロード バランシングが可能になります。NEG は Kubernetes Service の特別なアノテーションを介して作成されるため、NEG コントローラに登録できます。Autoneg コントローラは、NEG の作成を自動化し、Service アノテーションを使用して GCLB のバックエンドとして割り当てる特別な GKE コントローラです。Istio コントロール プレーン(Istio 上り(内向き)ゲートウェイを含む)は、最初のインフラストラクチャ Terraform Cloud Build の間にデプロイされます。GCLB と autoneg の構成は、最初の Terraform インフラストラクチャ Cloud Build の一部として行われます。

Cloud Endpoints とマネージド証明書を使用して Ingress を保護する

GCP マネージド証明書は、frontend GCLB サービスへのクライアント トラフィックを保護するために使用されます。GCLB は、グローバル frontend サービスにマネージド証明書を使用し、証明書は GCLB で終了します。このワークショップでは、マネージド証明書のドメインとして Cloud Endpoints を使用します。または、ドメインと frontend の DNS 名を使用して、GCP マネージド証明書を作成することもできます。

  1. Hipster ショップにアクセスするには、次のコマンドの出力リンクをクリックします。
echo "https://frontend.endpoints.$TF_VAR_ops_project_name.cloud.goog" 
 
  1. 証明書が有効かどうかは、Chrome タブの URL バーにある鍵のアイコンをクリックして確認できます。

6c403a63caa06c84.png

グローバル ロード バランシングを確認する

アプリケーションのデプロイの一環として、GCLB Hipster Shop Cloud Endpoints リンクにテスト トラフィックを生成するロード ジェネレータが両方の運用クラスタにデプロイされました。GCLB がトラフィックを受信し、両方の Istio Ingress ゲートウェイに送信していることを確認します。

  1. Hipster ショップの GCLB が作成されている ops プロジェクトの GCLB > モニタリング リンクを取得します。
echo "https://console.cloud.google.com/net-services/loadbalancing/details/http/istio-ingressgateway?project=$TF_VAR_ops_project_name&cloudshell=false&tab=monitoring&duration=PT1H" 
 
  1. 次の図に示すように、[Backend] プルダウン メニューで [All backends] から [istio-ingressgateway] に変更します。

6697c9eb67998d27.png

  1. 両方の istio-ingressgateways に送信されるトラフィックに注意してください。

ff8126e44cfd7f5e.png

istio-ingressgateway ごとに 3 つの NEG が作成されます。ops クラスタはリージョン クラスタであるため、リージョン内の各ゾーンに 1 つの NEG が作成されます。ただし、istio-ingressgateway Pod はリージョンごとに 1 つのゾーンで実行されます。トラフィックが istio-ingressgateway Pod に送信されていることがわかります。

負荷生成ツールは両方の運用クラスタで実行され、それぞれのリージョンからのクライアント トラフィックをシミュレートします。オペレーション クラスタ リージョン 1 で生成された負荷が、リージョン 2 の istio-ingressgateway に送信されています。同様に、ops クラスタ リージョン 2 で生成された負荷は、リージョン 2 の istio-ingressgateway に送信されます。

8. Stackdriver によるオブザーバビリティ

目標: Istio テレメトリーを Stackdriver に接続して検証します。

  • istio-telemetry リソースをインストールする
  • Istio Services ダッシュボードを作成/更新する
  • コンテナのログを表示する
  • Stackdriver で分散トレースを表示する

コピー&ペースト方式のラボの手順

Istio の主な機能の 1 つは、組み込みのオブザーバビリティ(「o11y」)です。つまり、ブラックボックスの計測されていないコンテナでも、オペレーターはこれらのコンテナに出入りするトラフィックをモニタリングし、顧客にサービスを提供できます。このオブザベーションは、指標、ログ、トレースといういくつかの異なる形式で取得されます。

また、Hipster Shop に組み込まれている負荷生成システムも使用します。オブザーバビリティは、トラフィックのない静的なシステムではうまく機能しないため、負荷生成によってオブザーバビリティの動作を確認します。この負荷はすでに実行されているため、表示されるだけです。

  1. istio to stackdriver 構成ファイルをインストールします。
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/istio-telemetry
kustomize edit add resource istio-telemetry.yaml

cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/istio-telemetry
kustomize edit add resource istio-telemetry.yaml
 
  1. k8s-repo に commit します。
cd $WORKDIR/k8s-repo
git add . && git commit -am "Install istio to stackdriver configuration"
git push 
 
  1. 以前に開いたタブで、または次のリンクをクリックして、Ops プロジェクトの Cloud Build のステータスを表示します。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
 
  1. Istio → Stackdriver の統合を確認します。Stackdriver ハンドラ CRD を取得します。
kubectl --context $OPS_GKE_1 get handler -n istio-system
 

出力には、stackdriver という名前のハンドラが表示されます。

NAME            AGE
kubernetesenv   12d
prometheus      12d
stackdriver     69s      # <== NEW!
  1. Istio 指標の Stackdriver へのエクスポートが機能していることを確認します。このコマンドの出力からリンクをクリックします。
echo "https://console.cloud.google.com/monitoring/metrics-explorer?cloudshell=false&project=$TF_VAR_ops_project_name"
 

Ops プロジェクトと同じ名前の新しいワークスペースを作成するよう求められます。[OK] を選択します。新しい UI に関するメッセージが表示された場合は、ダイアログを閉じてください。

Metrics Explorer の [リソースタイプと指標を探す] に「istio」と入力すると、[Kubernetes コンテナ] リソースタイプに [サーバー リクエスト数] などのオプションが表示されます。これにより、指標がメッシュから Stackdriver に流れていることがわかります。

(下の線を表示するには、destination_service_name ラベルでグループ化する必要があります)。

b9b59432ee68e695.png

ダッシュボードで指標を可視化する:

指標が Stackdriver APM システムに格納されたので、可視化する方法が必要です。このセクションでは、4 つの「ゴールデン シグナル」のうち 3 つの指標(トラフィック(リクエスト / 秒)、レイテンシ(この場合は 99 パーセンタイルと 50 パーセンタイル)、エラー(この例では飽和度は除外します))を示す事前構築済みのダッシュボードをインストールします。

Istio の Envoy プロキシは複数の指標を提供しますが、これらは開始するのに適した指標です。(すべてのリストはこちらをご覧ください)。各指標には、フィルタリングや集計に使用できるラベルのセットがあります(destination_service、source_workload_namespace、response_code、istio_tcp_received_bytes_total など)。

  1. 次に、事前定義された指標のダッシュボードを追加します。ここでは、Dashboard API を直接使用します。通常、API 呼び出しを手動で生成することはありません。自動化システムの一部として実行するか、ウェブ UI でダッシュボードを手動で作成します。これにより、すぐに開始できます。
sed -i 's/OPS_PROJECT/'${TF_VAR_ops_project_name}'/g' \
$WORKDIR/asm/k8s_manifests/prod/app-telemetry/services-dashboard.json
OAUTH_TOKEN=$(gcloud auth application-default print-access-token)
curl -X POST -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json" \
https://monitoring.googleapis.com/v1/projects/$TF_VAR_ops_project_name/dashboards \
 -d @$WORKDIR/asm/k8s_manifests/prod/app-telemetry/services-dashboard.json
 
  1. 以下の出力リンクに移動して、新しく追加された [サービス ダッシュボード] を表示します。
echo "https://console.cloud.google.com/monitoring/dashboards/custom/servicesdash?cloudshell=false&project=$TF_VAR_ops_project_name"
 
 

UX を使用してダッシュボードをインプレースで編集することもできますが、ここでは API を使用して新しいグラフをすばやく追加します。そのためには、ダッシュボードの最新バージョンをプルダウンし、編集を適用してから、HTTP PATCH メソッドを使用してプッシュバックする必要があります。

  1. 既存のダッシュボードを取得するには、Monitoring API をクエリします。追加したばかりの既存のダッシュボードを取得します。
curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json" \
https://monitoring.googleapis.com/v1/projects/$TF_VAR_ops_project_name/dashboards/servicesdash > /tmp/services-dashboard.json
 
  1. 新しいグラフを追加する(50 パーセンタイルのレイテンシ): [API リファレンス] これで、コードで新しいグラフ ウィジェットをダッシュボードに追加できます。この変更はピアレビューで確認し、バージョン管理にチェックインできます。50 パーセンタイル レイテンシ(中央値レイテンシ)を表示するウィジェットを追加します。

取得したダッシュボードを編集して、新しいスタンザを追加してみます。

NEW_CHART=${WORKDIR}/asm/k8s_manifests/prod/app-telemetry/new-chart.json
jq --argjson newChart "$(<$NEW_CHART)" '.gridLayout.widgets += [$newChart]' /tmp/services-dashboard.json > /tmp/patched-services-dashboard.json
 
  1. 既存のサービス ダッシュボードを更新します。
curl -X PATCH -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json" \
https://monitoring.googleapis.com/v1/projects/$TF_VAR_ops_project_name/dashboards/servicesdash \
 -d @/tmp/patched-services-dashboard.json
 
  1. 次の出力リンクに移動して、更新されたダッシュボードを表示します。
echo "https://console.cloud.google.com/monitoring/dashboards/custom/servicesdash?cloudshell=false&project=$TF_VAR_ops_project_name"
 
  1. 簡単なログ分析を行います。

Istio は、メッシュ内のすべてのネットワーク トラフィックに対して一連の構造化ログを提供し、それらを Stackdriver Logging にアップロードして、1 つの強力なツールでクラスタ間の分析を可能にします。ログには、クラスタ、コンテナ、アプリ、connection_id などのサービスレベルのメタデータが注釈として付加されます。

ログエントリの例(この場合は Envoy プロキシのアクセスログ)は次のようになります(切り捨てられています)。

*** DO NOT PASTE *** 
 logName: "projects/PROJECTNAME-11932-01-ops/logs/server-tcp-accesslog-stackdriver.instance.istio-system" 
labels: {
  connection_id: "fbb46826-96fd-476c-ac98-68a9bd6e585d-1517191"   
  destination_app: "redis-cart"   
  destination_ip: "10.16.1.7"   
  destination_name: "redis-cart-6448dcbdcc-cj52v"   
  destination_namespace: "cart"   
  destination_owner: "kubernetes://apis/apps/v1/namespaces/cart/deployments/redis-cart"   
  destination_workload: "redis-cart"   
  source_ip: "10.16.2.8"   
  total_received_bytes: "539"   
  total_sent_bytes: "569" 
...  
 }

ログは次の場所で確認できます。

echo "https://console.cloud.google.com/logs/viewer?cloudshell=false&project=$TF_VAR_ops_project_name"
 

Istio のコントロール プレーンのログを表示するには、[リソース] > [Kubernetes コンテナ] を選択し、「pilot」を検索します。

6f93b2aec6c4f520.png

ここでは、Istio コントロール プレーンが各サンプルアプリ サービスのサイドカー プロキシにプロキシ構成を push していることがわかります。「CDS」、「LDS」、「RDS」は、さまざまな Envoy API を表します(詳細)。

Istio のログだけでなく、コンテナログ、インフラストラクチャ ログ、その他の GCP サービスログもすべて同じインターフェースで確認できます。GKE のログクエリの例を次に示します。ログビューアでは、ログから指標(「特定の文字列に一致するエラーの数をカウントする」など)を作成することもできます。この指標は、ダッシュボードで使用したり、アラートの一部として使用したりできます。ログは、BigQuery などの他の分析ツールにストリーミングすることもできます。

Hipster Shop のサンプル フィルタ:

resource.type="k8s_container" labels.destination_app="productcatalogservice"

resource.type="k8s_container" resource.labels.namespace_name="cart"

  1. 分散トレースをご覧ください。

分散システムを使用しているため、デバッグには新しいツールである分散トレースが必要です。このツールを使用すると、サービス間のやり取りに関する統計情報を確認したり(下の図では、遅延の大きいイベントを特定しています)、生のサンプル トレースを詳しく調べて、実際に何が起こっているのかを把握したりできます。

タイムライン ビューには、すべてのリクエストが時間経過とともに表示されます。レイテンシまたは最初の要求から Hipster スタックを介してエンドユーザーに最終的に応答するまでの時間でグラフ化されます。ドットが上にあるほど、ユーザー エクスペリエンスが遅く(満足度が低い)なります。

ドットをクリックすると、そのリクエストの詳細なウォーターフォール ビューが表示されます。特定のリクエストの生の詳細(集計統計情報だけでなく)を見つけることができるこの機能は、サービス間の相互作用を理解するうえで非常に重要です。特に、サービス間のまれな、しかし悪い相互作用を追跡する場合に重要です。

ウォーターフォール ビューは、デバッガを使用したことがあるユーザーにはおなじみですが、この場合は、単一のアプリケーションのさまざまなプロセスで費やされた時間ではなく、別々のコンテナで実行されているサービス間のメッシュのトラバースに費やされた時間が表示されます。

トレースは次の場所にあります。

echo "https://console.cloud.google.com/traces/overview?cloudshell=false&project=$TF_VAR_ops_project_name"
 

ツールのスクリーンショットの例:

5ee238836dc9047f.png

9. 相互 TLS 認証

目標: マイクロサービス間の安全な接続(認証)。

  • メッシュ全体の mTLS を有効にする
  • ログを調べて mTLS を確認する

コピー&ペースト方式のラボの手順

アプリがインストールされ、オブザーバビリティが設定されたので、サービス間の接続を保護し、動作し続けるようにします。

たとえば、Kiali ダッシュボードで、サービスが MTLS を使用していないこと(鍵アイコンがない)を確認できます。トラフィックは流れ、システムは正常に機能しています。StackDriver Golden Metrics ダッシュボードにより、全体的に問題なく動作していることを確認できます。

  1. 運用クラスタで MeshPolicy を確認します。mTLS は PERMISSIVE であり、暗号化されたトラフィックと非 mTLS トラフィックの両方が許可されます。
kubectl --context $OPS_GKE_1 get MeshPolicy -o json | jq '.items[].spec'
kubectl --context $OPS_GKE_2 get MeshPolicy -o json | jq '.items[].spec'
 
    `Output (do not copy)`
{
  "peers": [
    {
      "mtls": {
        "mode": "PERMISSIVE"
      }
    }
  ]
}

Istio は、IstioControlPlane カスタム リソース(CR)を使用する Istio オペレータを使用して、すべてのクラスタで構成されます。IstioControlPlane CR を更新し、k8s-repo を更新して、すべてのクラスタで mTLS を構成します。IstioControlPlane CR で global > mTLS > enabled: true を設定すると、Istio コントロール プレーンに次の 2 つの変更が加えられます。

  • MeshPolicy は、すべてのクラスタで実行されているすべての Service に対してメッシュ全体の mTLS を有効にするように設定されています。
  • すべてのクラスタで実行されている Service 間の ISTIO_MUTUAL トラフィックを許可する DestinationRule が作成されます。
  1. kustomize パッチを istioControlPlane CR に適用して、クラスタ全体で mTLS を有効にします。すべてのクラスタの関連するディレクトリにパッチをコピーし、kustomize パッチを追加します。
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-replicated.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml

cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-replicated.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml

cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml

cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml

cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml

cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
 
  1. k8s-repo に commit します。
cd $WORKDIR/k8s-repo
git add . && git commit -am "turn mTLS on"
git push
 
  1. 以前に開いたタブで、または次のリンクをクリックして、Ops プロジェクトの Cloud Build のステータスを表示します。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"

 

mTLS を確認する

  1. 運用クラスタで MeshPolicy をもう一度確認します。mTLS は PERMISSIVE ではなくなり、mTLS トラフィックのみが許可されることに注意してください。
kubectl --context $OPS_GKE_1 get MeshPolicy -o json | jq .items[].spec
kubectl --context $OPS_GKE_2 get MeshPolicy -o json | jq .items[].spec
 

出力(コピーしないでください):

{
  "peers": [
    {
      "mtls": {}
    }
  ]
}
  1. Istio オペレーター コントローラによって作成された DestinationRule を説明します。
kubectl --context $OPS_GKE_1 get DestinationRule default -n istio-system -o json | jq '.spec'
kubectl --context $OPS_GKE_2 get DestinationRule default -n istio-system -o json | jq '.spec'

出力(コピーしないでください):

{
    host: '*.local',
    trafficPolicy: {
      tls: {
        mode: ISTIO_MUTUAL
      }
   }
}

ログで HTTP から HTTPS への移行を確認することもできます。

ログエントリを 1 つクリックし、表示するフィールドの値(この場合は「protocol:」の横にある「http」)をクリックすると、UI のログからこの特定のフィールドを表示できます。

d92e0c88cd5b2132.png

これにより、切り替えを視覚的にわかりやすく表現できます。

ea3d0240fa6fed81.png

10. カナリア デプロイ

目的: フロントエンド サービスの新しいバージョンをロールアウトします。

  • 1 つのリージョンで frontend-v2(次の本番環境バージョン)サービスをロールアウトする
  • DestinationRulesVirtualServices を使用して、トラフィックを frontend-v2 に徐々に転送する
  • k8s-repo への一連の commit を調べて、GitOps デプロイ パイプラインを検証する

コピー&ペースト方式のラボの手順

カナリア デプロイとは、新しいサービスの段階的なロールアウトです。カナリア デプロイでは、新しいバージョンに送信するトラフィックの量を増やしながら、残りの割合を現在のバージョンに送信します。一般的なパターンは、トラフィック分割の各ステージでカナリア分析を実行し、新しいバージョンのゴールデン シグナル(レイテンシ、エラー率、飽和度)をベースラインと比較することです。これにより、停止を防ぎ、トラフィック分割のすべての段階で新しい「v2」サービスの安定性を確保できます。

このセクションでは、Cloud Build と Istio トラフィック ポリシーを使用して、フロントエンド サービスの新しいバージョンの基本的なカナリア デプロイを作成する方法を学習します。

まず、DEV1 リージョン(us-west1)でカナリア パイプラインを実行し、そのリージョンの両方のクラスタにフロントエンド v2 をロールアウトします。次に、DEV2 リージョン(us-central)でカナリア パイプラインを実行し、そのリージョンの両方のクラスタに v2 をデプロイします。すべてのリージョンで並行してパイプラインを実行するのではなく、リージョンで順番に実行することで、構成の誤りや v2 アプリ自体のバグによるグローバルな停止を回避できます。

: 両方のリージョンでカナリア パイプラインを手動でトリガーしますが、本番環境では、レジストリに push された新しい Docker イメージタグなどに基づいて、自動トリガーを使用します。

  1. Cloud Shell で、残りのコマンドの実行を簡素化するために、いくつかの環境変数を定義します。
CANARY_DIR="$WORKDIR/asm/k8s_manifests/prod/app-canary/"
K8S_REPO="$WORKDIR/k8s-repo"
 
  1. repo_setup.sh スクリプトを実行して、ベースライン マニフェストを k8s-repo にコピーします。
$CANARY_DIR/repo-setup.sh 
 

次のマニフェストがコピーされます。

  • frontend-v2 デプロイ
  • frontend-v1 パッチ(「v1」ラベルと「/version」エンドポイントを含むイメージを含む)
  • HTTP レスポンスの分布を出力し、カナリア デプロイをリアルタイムで可視化するのに役立つ小さな Pod である respy
  • frontend Istio DestinationRule - 「version」デプロイ ラベルに基づいて、フロントエンド Kubernetes Service を v1 と v2 の 2 つのサブセットに分割します。
  • frontend Istio VirtualService - トラフィックの 100% を frontend v1 にルーティングします。これにより、Kubernetes Service のデフォルトのラウンド ロビン動作がオーバーライドされ、すべての Dev1 リージョン トラフィックの 50% がフロントエンド v2 に直ちに送信されます。
  1. k8s_repo に変更を commit します。
cd $K8S_REPO 
git add . && git commit -am "frontend canary setup"
git push
 
  1. 以前に開いたタブで、または次のリンクをクリックして、Ops プロジェクトの Cloud Build のステータスを表示します。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}" 
 
  1. OPS1 プロジェクトのコンソールで Cloud Build に移動します。Cloud Build パイプラインが完了するまで待ってから、両方の DEV1 クラスタの frontend Namespace で Pod を取得します。次の結果が表示されます。
watch -n 1 kubectl --context $DEV1_GKE_1 get pods -n frontend 
 

Output (do not copy)

NAME                           READY   STATUS    RESTARTS   AGE
frontend-578b5c5db6-h9567      2/2     Running   0          59m
frontend-v2-54b74fc75b-fbxhc   2/2     Running   0          2m26s
respy-5f4664b5f6-ff22r         2/2     Running   0          2m26s

tmux を使用して、Cloud Shell ウィンドウを 2 つのペインに分割します。

  • 下部のペインでは、watch コマンドが実行され、フロントエンド サービスの HTTP レスポンス分布が監視されます。
  • 上部のペインでは、実際のカナリア パイプライン スクリプトが実行されます。
  1. コマンドを実行して Cloud Shell ウィンドウを分割し、下部のペインで watch コマンドを実行します。
RESPY_POD=$(kubectl --context $DEV1_GKE_1 get pod \
-n frontend -l app=respy -o jsonpath='{..metadata.name}')
export TMUX_SESSION=$(tmux display-message -p '#S')
tmux split-window -d -t $TMUX_SESSION:0 -p33 \
-v "export KUBECONFIG=$WORKDIR/asm/gke/kubemesh; \
kubectl --context $DEV1_GKE_1 exec -n frontend -it \
$RESPY_POD -c respy /bin/sh -- -c 'watch -n 1 ./respy \
--u http://frontend:80/version --c 10 --n 500'; sleep 2"
 

出力(コピーしないでください)

500 requests to http://frontend:80/version...
+----------+-------------------+
| RESPONSE | % OF 500 REQUESTS |
+----------+-------------------+
| v1       | 100.0%            |
|          |                   |
+----------+-------------------+
  1. Dev1 リージョンでカナリア パイプラインを実行します。VirtualService で frontend-v2 トラフィックの割合を更新するスクリプト(重みを 20%、50%、80%、100% に更新)を提供します。更新の間、スクリプトは Cloud Build パイプラインが完了するまで待機します。Dev1 リージョンのカナリア デプロイ スクリプトを実行します。注 - このスクリプトの完了には約 10 分かかります。
K8S_REPO=$K8S_REPO CANARY_DIR=$CANARY_DIR \
OPS_DIR=$OPS_GKE_1_CLUSTER OPS_CONTEXT=$OPS_GKE_1 \
${CANARY_DIR}/auto-canary.sh
 

トラフィック分割は、respy コマンドを実行している下部のウィンドウでリアルタイムに確認できます。たとえば、20% のマークでは、次のようになります。

出力(コピーしないでください)

500 requests to http://frontend:80/version...
+----------+-------------------+
| RESPONSE | % OF 500 REQUESTS |
+----------+-------------------+
| v1       | 79.4%             |
|          |                   |
| v2       | 20.6%             |
|          |                   |
+----------+-------------------+
  1. frontend-v2 の Dev2 ロールアウトが完了すると、スクリプトの最後に成功メッセージが表示されます。
     Output (do not copy) 
    
✅ 100% successfully deployed
🌈 frontend-v2 Canary Complete for gke-asm-1-r1-prod
  1. Dev2 Pod からのすべてのフロントエンド トラフィックは frontend-v2 に転送されます。
     Output (do not copy) 
    
500 requests to http://frontend:80/version...
+----------+-------------------+
| RESPONSE | % OF 500 REQUESTS |
+----------+-------------------+
| v2       | 100.0%            |
|          |                   |
+----------+-------------------+
  1. 分割ペインを閉じます。
tmux respawn-pane -t ${TMUX_SESSION}:0.1 -k 'exit'
 
  1. 生成されたリンクで Cloud Source Repos に移動します。
echo https://source.developers.google.com/p/$TF_VAR_ops_project_name/r/k8s-repo

トラフィックの割合ごとに個別の commit が表示されます。リストの先頭には最新の commit が表示されます。

b87b85f52fd2ff0f.png

次に、Dev2 リージョンに対して同じプロセスを繰り返します。Dev2 リージョンは v1 で「ロック」されたままです。これは、ベースラインの repo_setup スクリプトで、すべてのトラフィックを v1 に明示的に送信する VirtualService を push したためです。このようにして、Dev1 で安全にリージョン カナリアを実行し、新しいバージョンをグローバルにロールアウトする前に正常に実行されることを確認できました。

  1. コマンドを実行して Cloud Shell ウィンドウを分割し、下部のペインで watch コマンドを実行します。
RESPY_POD=$(kubectl --context $DEV2_GKE_1 get pod \
-n frontend -l app=respy -o jsonpath='{..metadata.name}')
export TMUX_SESSION=$(tmux display-message -p '#S')
tmux split-window -d -t $TMUX_SESSION:0 -p33 \
-v "export KUBECONFIG=$WORKDIR/asm/gke/kubemesh; \
kubectl --context $DEV2_GKE_1 exec -n frontend -it \
$RESPY_POD -c respy /bin/sh -- -c 'watch -n 1 ./respy \
--u http://frontend:80/version --c 10 --n 500'; sleep 2"
 

出力(コピーしないでください)

500 requests to http://frontend:80/version...
+----------+-------------------+
| RESPONSE | % OF 500 REQUESTS |
+----------+-------------------+
| v1       | 100.0%            |
|          |                   |
+----------+-------------------+
  1. Dev2 リージョンでカナリア パイプラインを実行します。VirtualService で frontend-v2 トラフィックの割合を更新するスクリプト(重みを 20%、50%、80%、100% に更新)を提供します。更新の間、スクリプトは Cloud Build パイプラインが完了するまで待機します。Dev1 リージョンのカナリア デプロイ スクリプトを実行します。注 - このスクリプトの完了には約 10 分かかります。
K8S_REPO=$K8S_REPO CANARY_DIR=$CANARY_DIR \
OPS_DIR=$OPS_GKE_2_CLUSTER OPS_CONTEXT=$OPS_GKE_2 \
${CANARY_DIR}/auto-canary.sh
 

出力(コピーしないでください)

500 requests to http://frontend:80/version...
+----------+-------------------+
| RESPONSE | % OF 500 REQUESTS |
+----------+-------------------+
| v1       | 100.0%            |
|          |                   |
+----------+-------------------+
  1. Dev2 の Respy Pod から、Dev2 Pod のトラフィックがフロントエンド v1 から v2 に徐々に移行するのを確認します。スクリプトが完了すると、次のように表示されます。

出力(コピーしないでください)

500 requests to http://frontend:80/version...
+----------+-------------------+
| RESPONSE | % OF 500 REQUESTS |
+----------+-------------------+
| v2       | 100.0%            |
|          |                   |
+----------+-------------------+
  1. 分割ペインを閉じます。
tmux respawn-pane -t ${TMUX_SESSION}:0.1 -k 'exit'

このセクションでは、リージョン カナリア デプロイに Istio を使用する方法について説明しました。本番環境では、手動スクリプトの代わりに、コンテナ レジストリに push された新しいタグ付きイメージなどのトリガーを使用して、このカナリア スクリプトを Cloud Build パイプラインとして自動的にトリガーできます。また、各ステップの間にカナリア分析を追加して、v2 のレイテンシとエラー率を事前定義された安全しきい値と比較してから、トラフィックを送信することもできます。

11. 認可ポリシー

目標: マイクロサービス間の RBAC を設定します(AuthZ)。

  • マイクロサービスへのアクセスを拒否する AuthorizationPolicy を作成する
  • マイクロサービスへの特定のアクセスを許可する AuthorizationPolicy を作成する

コピー&ペースト方式のラボの手順

1 か所で実行できるモノリシック アプリケーションとは異なり、グローバルに分散されたマイクロサービス アプリはネットワーク境界を越えて呼び出しを行います。このため、アプリケーションのエントリ ポイントが増え、悪意のある攻撃を受ける可能性が高くなります。また、Kubernetes Pod には一時的な IP が割り振られるため、従来の IP ベースのファイアウォール ルールでは、ワークロード間のアクセスを十分に保護することはできません。マイクロサービス アーキテクチャでは、セキュリティに対する新しいアプローチが必要です。Istio は、サービス アカウントなどの Kubernetes セキュリティ ビルディング ブロックに基づいて、アプリケーション用の柔軟なセキュリティ ポリシーを提供します。

Istio ポリシーは認証と認可の両方を対象としています。認証は ID を検証し(このサーバーは自己申告どおりのサーバーか)、認可は権限を検証します(このクライアントは自己申告どおりのクライアントか)。モジュール 1(MeshPolicy)の相互 TLS セクションで Istio 認証について説明しました。このセクションでは、Istio の認可ポリシーを使用して、アプリケーション ワークロードの 1 つである currencyservice へのアクセスを制御する方法について説明します。

まず、4 つの Dev クラスタすべてに AuthorizationPolicy をデプロイし、currencyservice へのすべてのアクセスを遮断して、フロントエンドでエラーをトリガーします。次に、フロントエンド サービスのみが currencyservice にアクセスできるようにします。

  1. currency-deny-all.yaml の内容を調べます。このポリシーは、Deployment ラベル セレクタを使用して currencyservice へのアクセスを制限します。spec フィールドがないことに注意してください。つまり、このポリシーは選択したサービスへのすべてのアクセスを拒否します
cat $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-deny-all.yaml
 

出力(コピーしないでください)

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "currency-policy"
  namespace: currency
spec:
  selector:
    matchLabels:
      app: currencyservice
  1. 両方のリージョンの ops クラスタ用に、通貨ポリシーを k8s-repo にコピーします。
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-deny-all.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization/currency-policy.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization
kustomize edit add resource currency-policy.yaml
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-deny-all.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization/currency-policy.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization
kustomize edit add resource currency-policy.yaml
  1. 変更を push します。
cd $WORKDIR/k8s-repo 
git add . && git commit -am "AuthorizationPolicy - currency: deny all"
git push 
  1. 以前に開いたタブで、または次のリンクをクリックして、Ops プロジェクトの Cloud Build のステータスを確認します。
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name 
 
  1. ビルドが正常に完了したら、次のリンクでブラウザの hipstershop フロントエンドにアクセスしてみます。
echo "https://frontend.endpoints.$TF_VAR_ops_project_name.cloud.goog" 
 

currencyservice からの認可エラーが表示されます。

f120f3d30d6ee9f.png

  1. 通貨サービスがこの AuthorizationPolicy をどのように適用しているかを見てみましょう。まず、ブロックされた認可呼び出しはデフォルトではログに記録されないため、通貨 Pod の 1 つの Envoy プロキシでトレースレベルのログを有効にします。
CURRENCY_POD=$(kubectl --context $DEV1_GKE_2 get pod -n currency | grep currency| awk '{ print $1 }')
kubectl --context $DEV1_GKE_2 exec -it $CURRENCY_POD -n \
currency -c istio-proxy -- curl -X POST \
"http://localhost:15000/logging?level=trace"
 
  1. 通貨サービスのサイドカー プロキシから RBAC(認可)ログを取得します。「enforced denied」というメッセージが表示されます。これは、currencyservice がすべての受信リクエストをブロックするように設定されていることを表しています。
kubectl --context $DEV1_GKE_2 logs -n currency $CURRENCY_POD \
-c istio-proxy | grep -m 3 rbac
 

出力(コピーしないでください)

[Envoy (Epoch 0)] [2020-01-30 00:45:50.815][22][debug][rbac] [external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:67] checking request: remoteAddress: 10.16.5.15:37310, localAddress: 10.16.3.8:7000, ssl: uriSanPeerCertificate: spiffe://cluster.local/ns/frontend/sa/frontend, subjectPeerCertificate: , headers: ':method', 'POST'
[Envoy (Epoch 0)] [2020-01-30 00:45:50.815][22][debug][rbac] [external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:118] enforced denied
[Envoy (Epoch 0)] [2020-01-30 00:45:50.815][22][debug][http] [external/envoy/source/common/http/conn_manager_impl.cc:1354] [C115][S17310331589050212978] Sending local reply with details rbac_access_denied
  1. 次に、他のバックエンド サービスではなく、フロントエンドが currencyservice にアクセスできるようにします。currency-allow-frontend.yaml を開いて内容を確認します。次のルールが追加されていることに注意してください。
cat ${WORKDIR}/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend.yaml

出力(コピーしないでください)

rules:
 - from:
   - source:
       principals: ["cluster.local/ns/frontend/sa/frontend"]

ここでは、通貨サービスにアクセスするために特定の source.principal(クライアント)をホワイトリストに登録しています。この source.principal は Kubernetes サービス アカウントによって定義されます。この場合、ホワイトリストに登録するサービス アカウントは、フロントエンド Namespace のフロントエンド サービス アカウントです。

注: Istio AuthorizationPolicies で Kubernetes サービス アカウントを使用する場合は、モジュール 1 で行ったように、まずクラスタ全体の相互 TLS を有効にする必要があります。これは、サービス アカウントの認証情報がリクエストにマウントされるようにするためです。

  1. 更新された通貨ポリシーをコピーする
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization/currency-policy.yaml
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization/currency-policy.yaml
 
  1. 変更を push します。
cd $WORKDIR/k8s-repo
git add . && git commit -am "AuthorizationPolicy - currency: allow frontend"
git push
 
  1. 以前に開いたタブで、または次のリンクをクリックして、Ops プロジェクトの Cloud Build のステータスを表示します。
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name
  1. ビルドが正常に完了したら、Hipstershop フロントエンドを再度開きます。今回は、ホームページにエラーが表示されないはずです。これは、フロントエンドが現在のサービスへのアクセスを明示的に許可されているためです。
  2. 商品をカートに追加して [注文する] をクリックし、購入手続きを実行してみます。今回は、通貨サービスから価格変換エラーが表示されます。これは、フロントエンドのみをホワイトリストに登録したため、checkoutservice が currencyservice にアクセスできないためです。

7e30813d693675fe.png

  1. 最後に、currencyservice AuthorizationPolicy に別のルールを追加して、チェックアウト サービスが通貨にアクセスできるようにします。通貨へのアクセス権は、フロントエンドとチェックアウトの 2 つのサービスのみに付与します。他のバックエンドは引き続きブロックされます。
  2. currency-allow-frontend-checkout.yaml を開いて内容を確認します。ルールのリストは論理 OR として機能します。通貨は、これらの 2 つのサービス アカウントのいずれかを持つワークロードからのリクエストのみを受け入れます。
cat ${WORKDIR}/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend-checkout.yaml
 

出力(コピーしないでください)

apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
  name: "currency-policy"
  namespace: currency
spec:
  selector:
    matchLabels:
      app: currencyservice
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/frontend/sa/frontend"]
  - from:
    - source:
        principals: ["cluster.local/ns/checkout/sa/checkout"]
  1. 最終的な認可ポリシーを k8s-repo にコピーします。
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend-checkout.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization/currency-policy.yaml
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend-checkout.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization/currency-policy.yaml
 
  1. 変更を push
cd $WORKDIR/k8s-repo 
git add . && git commit -am "AuthorizationPolicy - currency: allow frontend and checkout"
git push
 
  1. 以前に開いたタブで、または次のリンクをクリックして、Ops プロジェクトの Cloud Build のステータスを表示します。
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name
 
  1. ビルドが正常に完了したら、チェックアウトを実行してみてください。正常に動作するはずです。

このセクションでは、Istio 認可ポリシーを使用して、サービス単位で粒度の細かいアクセス制御を適用する方法について説明しました。本番環境では、サービスごとに 1 つの AuthorizationPolicy を作成し、たとえば allow-all ポリシーを使用して、同じ Namespace 内のすべてのワークロードが相互にアクセスできるようにします。

12. インフラストラクチャのスケーリング

目標: 新しいリージョン、プロジェクト、クラスタを追加してインフラストラクチャをスケーリングします。

  • infrastructure リポジトリのクローンを作成する
  • 新しいリソースを作成するように Terraform ファイルを更新する
  • 新しいリージョンに 2 つのサブネット(運用プロジェクト用と新しいプロジェクト用)
  • 新しいリージョン(新しいサブネット内)の新しい ops クラスタ
  • 新しいリージョンの新しい Istio コントロール プレーン
  • 新しいリージョンの新しいプロジェクトに 2 つのアプリ クラスタ
  • infrastructure リポジトリにコミットする
  • インストールを確認する

コピー&ペースト方式のラボの手順

プラットフォームをスケーリングする方法はいくつかあります。既存のクラスタにノードを追加することで、コンピューティングを追加できます。リージョンにクラスタを追加できます。また、プラットフォームにリージョンを追加することもできます。プラットフォームのどの側面をスケーリングするかは、要件によって異なります。たとえば、リージョン内の 3 つのゾーンすべてにクラスタがある場合は、既存のクラスタにノード(またはノードプール)を追加するだけで十分な場合があります。ただし、単一リージョンの 3 つのゾーンのうち 2 つにクラスタがある場合は、3 つ目のゾーンに新しいクラスタを追加すると、スケーリングと追加の障害ドメイン(新しいゾーン)が提供されます。リージョンに新しいクラスタを追加する別の理由として、規制またはコンプライアンス上の理由(PCI や PII 情報を格納するデータベース クラスタなど)で単一テナント クラスタを作成する必要がある場合があります。ビジネスとサービスが拡大するにつれて、クライアントに近いサービスを提供するために新しいリージョンを追加することが不可避になります。

現在のプラットフォームは、2 つのリージョンと、リージョンごとに 2 つのゾーンのクラスタで構成されています。プラットフォームのスケーリングには、次の 2 つの方法があります。

  • 垂直 - 各リージョン内でコンピューティングを追加します。これは、既存のクラスタにノード(またはノードプール)を追加するか、リージョン内に新しいクラスタを追加することで行われます。これは infrastructure リポジトリを介して行われます。最も簡単な方法は、既存のクラスタにノードを追加することです。追加の構成は必要ありません。新しいクラスタを追加するには、追加のサブネット(とセカンダリ範囲)が必要になる場合があります。適切なファイアウォール ルールを追加し、新しいクラスタをリージョン ASM/Istio サービス メッシュ コントロール プレーンに追加して、新しいクラスタにアプリケーション リソースをデプロイします。
  • 水平方向 - リージョンを追加します。現在のプラットフォームでは、リージョン テンプレートが提供されます。これは、ASM/Istio コントロール プレーンが存在するリージョン オペレーション クラスタと、アプリケーション リソースがデプロイされる 2 つ以上のゾーン アプリケーション クラスタで構成されます。

このワークショップでは、垂直方向のユースケースの手順も含まれているため、プラットフォームを「水平方向」にスケーリングします。新しいリージョン(r3)をプラットフォームに追加してプラットフォームを水平方向にスケーリングするには、次のリソースを追加する必要があります。

  1. 新しい ops クラスタとアプリケーション クラスタのリージョン r3 のホスト プロジェクト共有 VPC のサブネット。
  2. ASM/Istio コントロール プレーンが存在するリージョン r3 のリージョン オペレーション クラスタ。
  3. リージョン r3 の 2 つのゾーンにある 2 つのゾーン アプリケーション クラスタ。
  4. k8s-repo を更新します。
  5. ASM/Istio コントロール プレーン リソースをリージョン r3 の ops クラスタにデプロイします。
  6. ASM/Istio 共有コントロール プレーン リソースをリージョン r3 のアプリクラスタにデプロイします。
  7. 新しいプロジェクトを作成する必要はありませんが、ワークショップの手順では、新しいチームをプラットフォームに追加するユースケースに対応するために、新しいプロジェクト dev3 を追加する方法を示します。

インフラストラクチャ リポジトリは、上記の新しいリソースを追加するために使用されます。

  1. Cloud Shell で WORKDIR に移動し、infrastructure リポジトリのクローンを作成します。
mkdir -p $WORKDIR/infra-repo
cd $WORKDIR/infra-repo
git init && git remote add origin https://source.developers.google.com/p/${TF_ADMIN}/r/infrastructure
git config --local user.email ${MY_USER}
git config --local user.name "infra repo user"
git config --local credential.'https://source.developers.google.com'.helper gcloud.sh
git pull origin master
  1. ワークショップのソース リポジトリ add-proj ブランチのクローンを add-proj-repo ディレクトリに作成します。
cd $WORKDIR
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git add-proj-repo -b add-proj

 
  1. ソース ワークショップ リポジトリの add-proj ブランチからファイルをコピーします。add-proj ブランチには、このセクションの変更が含まれています。
cp -r $WORKDIR/add-proj-repo/infrastructure/* $WORKDIR/infra-repo/
 
  1. add-proj リポジトリ ディレクトリの infrastructure ディレクトリを infra-repo ディレクトリへのシンボリック リンクに置き換えて、ブランチのスクリプトを実行できるようにします。
rm -rf $WORKDIR/add-proj-repo/infrastructure
ln -s $WORKDIR/infra-repo $WORKDIR/add-proj-repo/infrastructure
 
  1. add-project.sh スクリプトを実行して、共有状態と変数を新しいプロジェクト ディレクトリ構造にコピーします。
$WORKDIR/add-proj-repo/scripts/add-project.sh app3 $WORKDIR/asm $WORKDIR/infra-repo
  1. 変更を commit して push し、新しいプロジェクトを作成する
cd $WORKDIR/infra-repo
git add .
git status
git commit -m "add new project" && git push origin master
 

  1. この commit により、infrastructure リポジトリがトリガーされ、新しいリソースを使用してインフラストラクチャがデプロイされます。次のリンクの出力をクリックし、上部の最新のビルドに移動して、Cloud Build の進行状況を確認します。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_ADMIN}"
 

infrastructure の最後のステップでは、k8s-repo に新しい Kubernetes リソースが作成されます。これにより、k8s-repo(運用プロジェクト内)で Cloud Build がトリガーされます。新しい Kubernetes リソースは、前の手順で追加した 3 つの新しいクラスタ用です。ASM/Istio コントロール プレーンと共有コントロール プレーンのリソースは、k8s-repo Cloud Build を使用して新しいクラスタに追加されます。

  1. インフラストラクチャ Cloud Build が正常に完了したら、次の出力リンクをクリックして、k8s-repo 最新の Cloud Build 実行に移動します。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
 
  1. 次のスクリプトを実行して、新しいクラスタを vars ファイルと kubeconfig ファイルに追加します。
$WORKDIR/add-proj-repo/scripts/setup-gke-vars-kubeconfig-add-proj.sh $WORKDIR/asm
 
  1. 新しい kubeconfig ファイルを指すように KUBECONFIG 変数を変更します。
source $WORKDIR/asm/vars/vars.sh
export KUBECONFIG=$WORKDIR/asm/gke/kubemesh
 
  1. クラスタ コンテキストを一覧表示します。8 つのクラスタが表示されます。
kubectl config view -ojson | jq -r '.clusters[].name'
 
    `Output (do not copy)`
gke_user001-200204-05-dev1-49tqc4_us-west1-a_gke-1-apps-r1a-prod
gke_user001-200204-05-dev1-49tqc4_us-west1-b_gke-2-apps-r1b-prod
gke_user001-200204-05-dev2-49tqc4_us-central1-a_gke-3-apps-r2a-prod
gke_user001-200204-05-dev2-49tqc4_us-central1-b_gke-4-apps-r2b-prod
gke_user001-200204-05-dev3-49tqc4_us-east1-b_gke-5-apps-r3b-prod
gke_user001-200204-05-dev3-49tqc4_us-east1-c_gke-6-apps-r3c-prod
gke_user001-200204-05-ops-49tqc4_us-central1_gke-asm-2-r2-prod
gke_user001-200204-05-ops-49tqc4_us-east1_gke-asm-3-r3-prod
gke_user001-200204-05-ops-49tqc4_us-west1_gke-asm-1-r1-prod

Istio のインストールを確認する

  1. すべての Pod が実行され、ジョブが完了していることを確認して、新しい ops クラスタに Istio がインストールされていることを確認します。
kubectl --context $OPS_GKE_3 get pods -n istio-system
 
    `Output (do not copy)`
NAME                                      READY   STATUS    RESTARTS   AGE
grafana-5f798469fd-72g6w                  1/1     Running   0          5h12m
istio-citadel-7d8595845-hmmvj             1/1     Running   0          5h12m
istio-egressgateway-779b87c464-rw8bg      1/1     Running   0          5h12m
istio-galley-844ddfc788-zzpkl             2/2     Running   0          5h12m
istio-ingressgateway-59ccd6574b-xfj98     1/1     Running   0          5h12m
istio-pilot-7c8989f5cf-5plsg              2/2     Running   0          5h12m
istio-policy-6674bc7678-2shrk             2/2     Running   3          5h12m
istio-sidecar-injector-7795bb5888-kbl5p   1/1     Running   0          5h12m
istio-telemetry-5fd7cbbb47-c4q7b          2/2     Running   2          5h12m
istio-tracing-cd67ddf8-2qwkd              1/1     Running   0          5h12m
istiocoredns-5f7546c6f4-qhj9k             2/2     Running   0          5h12m
kiali-7964898d8c-l74ww                    1/1     Running   0          5h12m
prometheus-586d4445c7-x9ln6               1/1     Running   0          5h12m
  1. 両方の dev3 クラスタに Istio がインストールされていることを確認します。dev3 クラスタでは、Citadel、sidecar-injector、coredns のみが実行されます。ops-3 クラスタで実行されている Istio コントロール プレーンを共有します。
kubectl --context $DEV3_GKE_1 get pods -n istio-system
kubectl --context $DEV3_GKE_2 get pods -n istio-system
 
    `Output (do not copy)`
NAME                                      READY   STATUS    RESTARTS   AGE
istio-citadel-568747d88-4lj9b             1/1     Running   0          66s
istio-sidecar-injector-759bf6b4bc-ks5br   1/1     Running   0          66s
istiocoredns-5f7546c6f4-qbsqm             2/2     Running   0          78s

共有コントロール プレーンのサービス検出を確認する

  1. 6 つのアプリケーション クラスタすべてに対して、すべての運用クラスタに Secret がデプロイされていることを確認します。
kubectl --context $OPS_GKE_1 get secrets -l istio/multiCluster=true -n istio-system
kubectl --context $OPS_GKE_2 get secrets -l istio/multiCluster=true -n istio-system
kubectl --context $OPS_GKE_3 get secrets -l istio/multiCluster=true -n istio-system
 
    `Output (do not copy)`
NAME                  TYPE     DATA   AGE
gke-1-apps-r1a-prod   Opaque   1      14h
gke-2-apps-r1b-prod   Opaque   1      14h
gke-3-apps-r2a-prod   Opaque   1      14h
gke-4-apps-r2b-prod   Opaque   1      14h
gke-5-apps-r3b-prod   Opaque   1      5h12m
gke-6-apps-r3c-prod   Opaque   1      5h12m

13. サーキット ブレーキング

目標: 配送サービスの回路ブレーカーを実装します。

  • shipping サービスの DestinationRule を作成してサーキット ブレーカーを実装する
  • fortio(ロード生成ユーティリティ)を使用して、shipping サービスのサーキット ブレーカーを検証します。サーキットを強制的にトリップさせます。

Fast Track Script Lab の手順

Fast Track Script Lab がまもなくリリースされます。

コピー&ペースト方式のラボの手順

Istio 対応サービスの基本的なモニタリングとトラブルシューティングの戦略について学習したので、次に Istio がサービスの復元力を向上させ、トラブルシューティングの量を減らす方法について説明します。

マイクロサービス アーキテクチャでは、1 つのサービスの障害が依存関係に伝播し、その依存関係の依存関係にも伝播して、エンドユーザーに影響を与える可能性のある「波及効果」による停止を引き起こす、カスケード障害のリスクが生じます。Istio は、サービスを分離するのに役立つサーキット ブレーカー トラフィック ポリシーを提供します。これにより、ダウンストリーム(クライアントサイド)サービスが失敗したサービスを待機しないように保護し、アップストリーム(サーバーサイド)サービスがオンラインに戻ったときにダウンストリーム トラフィックが急増しないように保護します。全体として、サーキット ブレーカーを使用すると、1 つのバックエンド サービスの停止が原因ですべてのサービスが SLO に違反してしまう事態を回避できます。

回路ブレーカー パターンは、過剰な電流が流れたときに「トリップ」してデバイスを過負荷から保護する電気スイッチにちなんで名付けられました。Istio の設定では、Envoy がサーキット ブレーカーとなり、サービスの保留中のリクエスト数を追跡します。このデフォルトのクローズ状態では、リクエストは Envoy を中断なく通過します。

ただし、保留中のリクエストの数が定義したしきい値を超えると、回路ブレーカーがトリップ(開く)し、Envoy はすぐにエラーを返します。これにより、サーバーはクライアントに対して迅速に失敗を返し、過負荷状態のときにサーバー アプリケーション コードがクライアントのリクエストを受信しないようにします。

定義したタイムアウトの後、Envoy はハーフオープン状態に移行します。この状態では、サーバーは試験的にリクエストの受信を再開できます。リクエストに正常に応答できる場合は、回路ブレーカーが再び閉じ、サーバーへのリクエストが再び流れ始めます。

このは、Istio 回路ブレーカー パターンをまとめたものです。青い長方形は Envoy を表し、青い円はクライアントを表し、白い円はサーバー コンテナを表します。

2127a0a172ff4802.png

Istio DestinationRule を使用してサーキット ブレーカー ポリシーを定義できます。このセクションでは、次のポリシーを適用して、配送サービスの回路ブレーカーを適用します。

Output (do not copy)

apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
  name: "shippingservice-shipping-destrule"
  namespace: "shipping"
spec:
  host: "shippingservice.shipping.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
    connectionPool:
      tcp:
        maxConnections: 1
      http:
        http1MaxPendingRequests: 1
        maxRequestsPerConnection: 1
    outlierDetection:
      consecutiveErrors: 1
      interval: 1s
      baseEjectionTime: 10s
      maxEjectionPercent: 100

ここで注目すべき DestinationRule フィールドは 2 つあります。connectionPool は、このサービスで許可される接続数を定義します。outlierDetection フィールドでは、Envoy がサーキット ブレーカーを開くしきい値を決定する方法を構成します。ここでは、Envoy は 1 秒ごとに(間隔)、サーバー コンテナから受信したエラーの数をカウントします。consecutiveErrors のしきい値を超えると、Envoy サーキット ブレーカーが開き、productcatalog Pod の 100% が新しいクライアント リクエストから 10 秒間保護されます。Envoy サーキット ブレーカーが開くと(アクティブになると)、クライアントは 503(Service Unavailable)エラーを受け取ります。実際に見てみましょう。

  1. コマンドを簡素化するために、k8s-repo と asm ディレクトリの環境変数を設定します。
export K8S_REPO="${WORKDIR}/k8s-repo"
export ASM="${WORKDIR}/asm" 
 
  1. k8s-repo を更新する
cd $WORKDIR/k8s-repo
git pull
cd $WORKDIR
  1. 両方の Ops クラスタで配送サービスの DestinationRule を更新します。
cp $ASM/k8s_manifests/prod/istio-networking/app-shipping-circuit-breaker.yaml ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cp $ASM/k8s_manifests/prod/istio-networking/app-shipping-circuit-breaker.yaml ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml

cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit add resource app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit add resource app-shipping-circuit-breaker.yaml
 
  1. Fortio ロード ジェネレータ Pod を Dev1 リージョンの GKE_1 クラスタにコピーします。これは、shippingservice のサーキット ブレーカーをトリップするために使用するクライアント Pod です。
cp $ASM/k8s_manifests/prod/app/deployments/app-fortio.yaml ${K8S_REPO}/${DEV1_GKE_1_CLUSTER}/app/deployments/
cd ${K8S_REPO}/${DEV1_GKE_1_CLUSTER}/app/deployments; kustomize edit add resource app-fortio.yaml
 
  1. 変更を commit します。
cd $K8S_REPO 
git add . && git commit -am "Circuit Breaker: shippingservice"
git push
cd $ASM
 
  1. Cloud Build が完了するまで待ちます。
  2. Cloud Shell に戻り、fortio Pod を使用して、1 つの同時接続と合計 1,000 件のリクエストで shippingservice に gRPC トラフィックを送信します。connectionPool 設定を超えていないため、サーキット ブレーカーはトリップしません。
FORTIO_POD=$(kubectl --context ${DEV1_GKE_1} get pod -n shipping | grep fortio | awk '{ print $1 }')

kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c fortio /usr/bin/fortio -- load -grpc -c 1 -n 1000 -qps 0 shippingservice.shipping.svc.cluster.local:50051 
 

出力(コピーしないでください)

Health SERVING : 1000
All done 1000 calls (plus 0 warmup) 4.968 ms avg, 201.2 qps
  1. ここで、fortio を再度実行し、同時接続数を 2 に増やしますが、リクエストの合計数は一定に保ちます。サーキット ブレーカーがトリップしているため、リクエストの 3 分の 2 までが 「オーバーフロー」エラーを返すはずです。定義したポリシーでは、1 秒間に 1 つの同時接続のみが許可されています。
kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c fortio /usr/bin/fortio -- load -grpc -c 2 -n 1000 -qps 0 shippingservice.shipping.svc.cluster.local:50051 
 

出力(コピーしないでください)

18:46:16 W grpcrunner.go:107> Error making grpc call: rpc error: code = Unavailable desc = upstream connect error or disconnect/reset before headers. reset reason: overflow
...

Health ERROR : 625
Health SERVING : 375
All done 1000 calls (plus 0 warmup) 12.118 ms avg, 96.1 qps
  1. Envoy は、サーキット ブレーカーがアクティブなときに切断した接続の数を upstream_rq_pending_overflow 指標で追跡します。fortio Pod でこれを確認してみましょう。
kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c istio-proxy  -- sh -c 'curl localhost:15000/stats' | grep shipping | grep pending
 

出力(コピーしないでください)

cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.circuit_breakers.default.rq_pending_open: 0
cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.circuit_breakers.high.rq_pending_open: 0
cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_active: 0
cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_failure_eject: 9
cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_overflow: 565
cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_total: 1433
  1. 両方のリージョンからサーキット ブレーカー ポリシーを削除してクリーンアップします。
kubectl --context ${OPS_GKE_1} delete destinationrule shippingservice-circuit-breaker -n shipping 
rm ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit remove resource app-shipping-circuit-breaker.yaml
 

kubectl --context ${OPS_GKE_2} delete destinationrule shippingservice-circuit-breaker -n shipping 
rm ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit remove resource app-shipping-circuit-breaker.yaml
cd $K8S_REPO; git add .; git commit -m "Circuit Breaker: cleanup"; git push origin master
 

このセクションでは、サービスに単一のサーキット ブレーカー ポリシーを設定する方法について説明しました。ベスト プラクティスは、停止する可能性のあるアップストリーム(バックエンド)サービスにサーキット ブレーカーを設定することです。Istio サーキット ブレーカー ポリシーを適用すると、マイクロサービスを分離し、アーキテクチャにフォールト トレランスを組み込み、高負荷時のカスケード障害のリスクを軽減できます。

14. フォールト インジェクション

目的: 推奨事項サービスを本番環境にプッシュする前に、遅延を導入して復元力をテストします。

  • recommendation Service の VirtualService を作成して 5 秒の遅延を導入する
  • fortio 負荷生成ツールを使用して遅延をテストする
  • VirtualService の遅延を削除して検証する

Fast Track Script Lab の手順

Fast Track Script Lab がまもなくリリースされます。

コピー&ペースト方式のラボの手順

サービスにサーキット ブレーカー ポリシーを追加することは、本番環境のサービスに対する復元力を構築する 1 つの方法です。ただし、サーキット ブレーキングは障害(ユーザーに表示される可能性のあるエラー)につながるため、理想的ではありません。このようなエラーケースを事前に把握し、バックエンドがエラーを返したときにダウンストリーム サービスがどのように応答するかをより正確に予測するには、ステージング環境でカオス テストを採用します。カオス テストは、システムの弱点を分析してフォールト トレランスを向上させるために、サービスを意図的に中断するプラクティスです。カオス テストを使用して、バックエンドが失敗した場合にユーザーに表示されるエラーを軽減する方法(たとえば、フロントエンドにキャッシュに保存された結果を表示するなど)を特定することもできます。

Istio を使用して障害を挿入すると、本番環境のリリース イメージを使用し、ソースコードを変更する代わりにネットワーク レイヤで障害を追加できるため、便利です。本番環境では、本格的なカオス テストツールを使用して、ネットワーク レイヤに加えて Kubernetes/コンピューティング レイヤの復元力をテストすることがあります。

Istio を使用してカオス テストを行うには、「fault」フィールドを含む VirtualService を適用します。Istio は、遅延障害(タイムアウトを挿入)と中断障害(HTTP エラーを挿入)の 2 種類の障害をサポートしています。この例では、レコメンデーション サービス5 秒の遅延障害を挿入します。ただし、今回は、このハングしたサービスに対してサーキット ブレーカーを使用して「フェイル ファスト」を行うのではなく、ダウンストリーム サービスに完全なタイムアウトを強制します。

  1. 障害挿入ディレクトリに移動します。
export K8S_REPO="${WORKDIR}/k8s-repo"
export ASM="${WORKDIR}/asm/" 
cd $ASM
 
  1. k8s_manifests/prod/istio-networking/app-recommendation-vs-fault.yaml を開いて内容を検査します。Istio には、リクエストの一定の割合で障害を挿入するオプションがあります。ここでは、すべての recommendationservice リクエストにタイムアウトを導入します。

出力(コピーしないでください)

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: recommendation-delay-fault
spec:
  hosts:
  - recommendationservice.recommendation.svc.cluster.local
  http:
  - route:
    - destination:
        host: recommendationservice.recommendation.svc.cluster.local
    fault:
      delay:
        percentage:
          value: 100
        fixedDelay: 5s
  1. VirtualService を k8s_repo にコピーします。障害は両方のリージョンにまたがってグローバルに挿入されます。
cp $ASM/k8s_manifests/prod/istio-networking/app-recommendation-vs-fault.yaml ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit add resource app-recommendation-vs-fault.yaml

cp $ASM/k8s_manifests/prod/istio-networking/app-recommendation-vs-fault.yaml ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit add resource app-recommendation-vs-fault.yaml
 
  1. 変更を push
cd $K8S_REPO 
git add . && git commit -am "Fault Injection: recommendationservice"
git push
cd $ASM
 
  1. Cloud Build が完了するまで待ちます。
  2. サーキット ブレーカー セクションにデプロイされた fortio Pod に exec し、recommendationservice にトラフィックを送信します。
FORTIO_POD=$(kubectl --context ${DEV1_GKE_1} get pod -n shipping | grep fortio | awk '{ print $1 }')

kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c fortio /usr/bin/fortio -- load -grpc -c 100 -n 100 -qps 0 recommendationservice.recommendation.svc.cluster.local:8080
 
    Once the fortio command is complete, you should see responses averaging 5s:

出力(コピーしないでください)

Ended after 5.181367359s : 100 calls. qps=19.3
Aggregated Function Time : count 100 avg 5.0996506 +/- 0.03831 min 5.040237641 max 5.177559818 sum 509.965055
  1. 挿入した障害を確認するもう 1 つの方法は、ウェブブラウザでフロントエンドを開き、任意のプロダクトをクリックすることです。商品ページでは、ページの下部に表示されるおすすめ商品を取得するため、読み込みに 5 秒余計にかかります。
  2. 両方の Ops クラスタから障害挿入サービスを削除して、クリーンアップします。
kubectl --context ${OPS_GKE_1} delete virtualservice recommendation-delay-fault -n recommendation 
rm ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit remove resource app-recommendation-vs-fault.yaml

kubectl --context ${OPS_GKE_2} delete virtualservice recommendation-delay-fault -n recommendation 
rm ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit remove resource app-recommendation-vs-fault.yaml
 
  1. 変更を push する:
cd $K8S_REPO 
git add . && git commit -am "Fault Injection cleanup / restore"
git push
cd $ASM
 

15. Istio コントロール プレーンのモニタリング

ASM は、Pilot、Mixer、Galley、Citadel という 4 つの重要なコントロール プレーン コンポーネントをインストールします。各サービスは、関連するモニタリング指標を Prometheus に送信します。ASM には、運用担当者がこのモニタリング データを可視化し、コントロール プレーンの健全性とパフォーマンスを評価できる Grafana ダッシュボードが付属しています。

ダッシュボードの表示

  1. Istio でインストールされた Grafana サービスをポート転送する
kubectl --context ${OPS_GKE_1} -n istio-system port-forward svc/grafana 3000:3000 >> /dev/null
 
  1. ブラウザで Grafana を開く
  2. Cloud Shell ウィンドウの右上にある [ウェブでプレビュー] アイコンをクリックします。
  3. [ポート 3000 でプレビュー] をクリックします(注: ポートが 3000 ではない場合は、[ポートを変更] をクリックしてポート 3000 を選択します)。
  4. これにより、ブラウザのタブが開き、「BASE_URL/?orgId=1&authuser=0&environment_id=default」のような URL が表示されます。
  5. 利用可能なダッシュボードを表示する
  6. URL を「BASE_URL/dashboard」に変更します。
  7. [istio] フォルダをクリックして、使用可能なダッシュボードを表示します。
  8. これらのダッシュボードのいずれかをクリックすると、そのコンポーネントのパフォーマンスが表示されます。以降のセクションでは、各コンポーネントの重要な指標について説明します。

モニタリング パイロット

Pilot は、ネットワーキングとポリシーの構成をデータプレーン(Envoy プロキシ)に分散するコントロール プレーン コンポーネントです。Pilot は、ワークロードへのトラフィック量とは必ずしも比例しませんが、ワークロードとデプロイの数に比例してスケーリングする傾向があります。異常な Pilot は次のようになります。

  • 必要以上に多くのリソース(CPU や RAM など)を消費する
  • 更新された構成情報を Envoy に push する際の遅延が発生する

注: Pilot がダウンした場合や遅延が発生した場合でも、ワークロードはトラフィックを処理します。

  1. ブラウザで「BASE_URL/dashboard/db/istio-pilot-dashboard」に移動して、Pilot 指標を表示します。

重要なモニタリング指標

リソース使用量

許容される使用量の目安として、Istio のパフォーマンスとスケーラビリティのページをご覧ください。この値よりも大幅に高いリソース使用率が継続している場合は、GCP サポートにお問い合わせください。

5f1969f8e2c8b137.png

Pilot Push Information(試験運用に関するプッシュ通知)

このセクションでは、Pilot が Envoy プロキシに構成を push していることをモニタリングします。

  • [Pilot Pushes] には、特定の時点でプッシュされた構成のタイプが表示されます。
  • [ADS Monitoring] には、システム内の仮想サービス、サービス、接続されたエンドポイントの数が表示されます。
  • 既知のエンドポイントがないクラスタには、構成されているが実行中のインスタンスがないエンドポイントが表示されます(*.googleapis.com などの外部サービスを示している可能性があります)。
  • [パイロット エラー] には、経時的に発生したエラーの数が表示されます。
  • [競合] には、リスナーの構成が曖昧な競合の数が表示されます。

エラーまたは競合がある場合は、1 つ以上のサービスの設定が正しくないか、一貫性がありません。詳細については、データプレーンのトラブルシューティングをご覧ください。

Envoy 情報

このセクションには、コントロール プレーンに接続する Envoy プロキシに関する情報が含まれています。XDS 接続エラーが繰り返し発生する場合は、GCP サポートにお問い合わせください。

モニタリング ミキサー

Mixer は、Envoy プロキシからテレメトリー バックエンド(通常は Prometheus、Stackdriver など)にテレメトリーを転送するコンポーネントです。この容量では、データプレーンにはありません。これは、2 つの異なるサービス名(istio-telemetry と istio-policy)でデプロイされた 2 つの Kubernetes Job(Mixer と呼ばれる)としてデプロイされます。

Mixer を使用してポリシー システムと統合することもできます。このため、Mixer へのポリシー チェックが失敗するとサービスへのアクセスがブロックされるため、Mixer はデータプレーンに影響します。

Mixer はトラフィック量に応じてスケーリングされる傾向があります。

  1. ブラウザで「BASE_URL/dashboard/db/istio-mixer-dashboard」に移動して、Mixer 指標を表示します。

重要なモニタリング指標

リソース使用量

許容される使用量の目安として、Istio のパフォーマンスとスケーラビリティのページをご覧ください。この値よりも大幅に高いリソース使用率が継続している場合は、GCP サポートにお問い合わせください。

87ed83238f9addd8.png

Mixer の概要

  • 応答時間は重要な指標です。Mixer テレメトリーへのレポートはデータパスにはありませんが、これらのレイテンシが高いと、サイドカー プロキシのパフォーマンスが低下します。90 パーセンタイルは 1 桁のミリ秒、99 パーセンタイルは 100 ミリ秒未満になることが予想されます。

e07bdf5fde4bfe87.png

  • Adapter Dispatch Duration は、Mixer がアダプタの呼び出しで発生しているレイテンシを示します(Mixer はアダプタを介してテレメトリー システムとロギング システムに情報を送信します)。ここでレイテンシが高いと、メッシュのパフォーマンスに影響します。ここでも、p90 レイテンシは 10 ミリ秒未満である必要があります。

1c2ee56202b32bd9.png

モニタリング ギャラリー

Galley は、Istio の構成の検証、取り込み、処理、配信のコンポーネントです。Kubernetes API サーバーから Pilot に構成を伝達します。Pilot と同様に、システム内のサービスとエンドポイントの数に応じてスケーリングされる傾向があります。

  1. ブラウザで「BASE_URL/dashboard/db/istio-galley-dashboard」に移動して、Galley 指標を表示します。

重要なモニタリング指標

リソースの検証

検証に合格した、または失敗したさまざまなタイプのリソース(宛先ルール、ゲートウェイ、サービス エントリなど)の数を示す、最も重要な指標。

接続されているクライアント

Galley に接続されているクライアントの数を示します。通常は 3(pilot、istio-telemetry、istio-policy)で、これらのコンポーネントがスケーリングされるとスケーリングされます。

16. Istio のトラブルシューティング

データプレーンのトラブルシューティング

Pilot ダッシュボードに構成の問題が表示された場合は、Pilot ログを調べるか、istioctl を使用して構成の問題を見つける必要があります。

Pilot ログを調べるには、kubectl -n istio-system logs istio-pilot-69db46c598-45m44 discovery を実行します。istio-pilot-... は、トラブルシューティングする Pilot インスタンスの Pod ID に置き換えます。

生成されたログで、Push Status メッセージを検索します。次に例を示します。

2019-11-07T01:16:20.451967Z        info        ads        Push Status: {
    "ProxyStatus": {
        "pilot_conflict_outbound_listener_tcp_over_current_tcp": {
            "0.0.0.0:443": {
                "proxy": "cartservice-7555f749f-k44dg.hipster",
                "message": "Listener=0.0.0.0:443 AcceptedTCP=accounts.google.com,*.googleapis.com RejectedTCP=edition.cnn.com TCPServices=2"
            }
        },
        "pilot_duplicate_envoy_clusters": {
            "outbound|15443|httpbin|istio-egressgateway.istio-system.svc.cluster.local": {
                "proxy": "sleep-6c66c7765d-9r85f.default",
                "message": "Duplicate cluster outbound|15443|httpbin|istio-egressgateway.istio-system.svc.cluster.local found while pushing CDS"
            },
            "outbound|443|httpbin|istio-egressgateway.istio-system.svc.cluster.local": {
                "proxy": "sleep-6c66c7765d-9r85f.default",
                "message": "Duplicate cluster outbound|443|httpbin|istio-egressgateway.istio-system.svc.cluster.local found while pushing CDS"
            },
            "outbound|80|httpbin|istio-egressgateway.istio-system.svc.cluster.local": {
                "proxy": "sleep-6c66c7765d-9r85f.default",
                "message": "Duplicate cluster outbound|80|httpbin|istio-egressgateway.istio-system.svc.cluster.local found while pushing CDS"
            }
        },
        "pilot_eds_no_instances": {
            "outbound_.80_._.frontend-external.hipster.svc.cluster.local": {},
            "outbound|443||*.googleapis.com": {},
            "outbound|443||accounts.google.com": {},
            "outbound|443||metadata.google.internal": {},
            "outbound|80||*.googleapis.com": {},
            "outbound|80||accounts.google.com": {},
            "outbound|80||frontend-external.hipster.svc.cluster.local": {},
            "outbound|80||metadata.google.internal": {}
        },
        "pilot_no_ip": {
            "loadgenerator-778c8489d6-bc65d.hipster": {
                "proxy": "loadgenerator-778c8489d6-bc65d.hipster"
            }
        }
    },
    "Version": "o1HFhx32U4s="
}

プッシュ ステータスには、構成を Envoy プロキシにプッシュしようとしたときに発生した問題が表示されます。この例では、「Duplicate cluster」というメッセージが複数表示されています。これは、重複するアップストリーム宛先があることを示しています。

問題の診断については、Google Cloud サポートにお問い合わせください。

構成エラーの検出

istioctl を使用して構成を分析するには、istioctl experimental analyze -k --context $OPS_GKE_1 を実行します。これにより、システム内の構成の分析が実行され、問題と推奨される変更が示されます。このコマンドで検出できる構成エラーの完全なリストについては、ドキュメントをご覧ください。

17. クリーンアップ

管理者が cleanup_workshop.sh スクリプトを実行して、bootstrap_workshop.sh スクリプトで作成されたリソースを削除します。クリーンアップ スクリプトを実行するには、次の情報が必要です。

  • 組織名 - 例: yourcompany.com
  • ワークショップ ID - YYMMDD-NN 形式(例: 200131-01
  • 管理 GCS バケット - ブートストラップ スクリプトで定義されます。
  1. Cloud Shell を開き、次の操作をすべて Cloud Shell で行います。下のリンクをクリックしてください。

CLOUD SHELL

  1. 目的の管理者ユーザーで gcloud にログインしていることを確認します。
gcloud config list
 
  1. asm フォルダに移動します。
cd ${WORKDIR}/asm
 
  1. 削除する組織名とワークショップ ID を定義します。
export ORGANIZATION_NAME=<ORGANIZATION NAME>
export ASM_WORKSHOP_ID=<WORKSHOP ID>
export ADMIN_STORAGE_BUCKET=<ADMIN CLOUD STORAGE BUCKET>
 
  1. 次のようにクリーンアップ スクリプトを実行します。
./scripts/cleanup_workshop.sh --workshop-id ${ASM_WORKSHOP_ID} --admin-gcs-bucket ${ADMIN_STORAGE_BUCKET} --org-name ${ORGANIZATION_NAME}