このチュートリアルでは、ステートフル アプリケーションを作成し、アプリケーションを実行する Google Kubernetes Engine(GKE)クラスタをアップグレードする際のおすすめの方法を説明します。このチュートリアルでは、ステートフル アプリケーションをデプロイする例として Redis を使用しますが、GKE にデプロイされた他のタイプのステートフル アプリケーションにも同じコンセプトを適用できます。
目標
このチュートリアルでは、次の手順について説明します。
- リリース チャンネルに登録される GKE クラスタを作成します。
- GKE に Redis クラスタを作成します。
- Redis クライアント アプリケーションの GKE へのデプロイ
- ノードプールのアップグレードに関する次のベスト プラクティスを実施します。
- Pod 停止予算(PDB)を設定します。
- メンテナンスの時間枠と除外を設定します。
- ノードのアップグレード戦略をサージ アップグレードまたは Blue/Green アップグレードに設定します。
- アプリケーションをテストします。
- クラスタをアップグレードします。
- ワークロードの中断をテストします。
次の図は、このチュートリアルのクラスタ アーキテクチャの概要を示しています。
費用
このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。
始める前に
プロジェクトを設定する
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
-
In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the GKE API.
Google Cloud CLI のデフォルト値を設定する
Google Cloud コンソールで、Cloud Shell インスタンスを起動します。
Cloud Shell を開くこのサンプルアプリのソースコードをダウンロードします。
git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples cd kubernetes-engine-samples/quickstarts/hello-app-redis/manifests
デフォルトの環境変数を設定します。
gcloud config set project PROJECT-ID gcloud config set compute/zone COMPUTE-ZONE
次の値を置き換えます。
- PROJECT_ID: Google Cloud プロジェクト ID
- COMPUTE_ZONE: Compute Engine ゾーン。
リリース チャンネルに登録される GKE クラスタを作成する
GKE クラスタを作成するには、次の手順を行います。
3 つのノードを持つ
redis-test
という名前のクラスタを作成します。gcloud container clusters create redis-test \ --num-nodes=3 \ --release-channel regular
クラスタが作成されると、次のような出力が表示されます。
NAME: redis-test LOCATION: us-central1-c MASTER_VERSION: 1.22.10-gke.600 MASTER_IP: 34.69.67.7 MACHINE_TYPE: e2-medium NODE_VERSION: 1.22.10-gke.600 NUM_NODES: 3 STATUS: RUNNING
クラスタと通信を行うように
kubectl
を構成します。gcloud container clusters get-credentials redis-test
GKE に Redis クラスタを作成する
このセクションでは、ConfigMap、StatefulSet、ヘッドレス サービスをデプロイし、以前に作成した GKE クラスタの上に Redis クラスタを追加します。
Redis クラスタを作成するには、次の手順を完了します。
Redis 構成が格納されている ConfigMap ファイル(
redis-configmap.yaml
)を参照します。以下のスニペットは、readinessProbe と livenessProbe のスクリプトを示しています。readiness.sh
スクリプトとliveness.sh
スクリプトは、redis-cli ping を使用して、Redis サーバーが実行中かどうかを確認します。PONG
が返された場合、Redis サーバーは稼働しています。これらのスクリプトはredis-cluster.yaml
で使用されます。この ConfigMap の Redis パラメータの詳細については、Redis クラスタ チュートリアルで Redis クラスタ構成パラメータのセクションをご覧ください。
ConfigMap をデプロイします。
kubectl apply -f redis-configmap.yaml
readinessProbe と livenessProbe の使用方法を示す StatefulSet(
redis-cluster.yaml
)スニペットをご覧ください。Kubernetes でプローブを構成する方法については、プローブを構成するをご覧ください。
ノードプールをアップグレードする場合は、readinessProbe と livenessProbe を使用することを強くおすすめします。これにより、アップグレード中に Pod の準備ができます。
StatefulSet をデプロイします。
kubectl apply -f redis-cluster.yaml
redis-service.yaml
という名前のヘッドレス Service は、Redis ノードの接続用です。ヘッドレス Service を作成するために、clusterIP
フィールドはNone
に設定されています。サービスをデプロイします。
kubectl apply -f redis-service.yaml
約 2 分待ってから次のコマンドを使用して、すべての Pod が実行されていることを確認します。
kubectl get pods
出力は次の例のようになります。
NAME READY STATUS RESTARTS AGE redis-0 1/1 Running 0 2m29s redis-1 1/1 Running 0 2m8s redis-2 1/1 Running 0 107s redis-3 1/1 Running 0 85s redis-4 1/1 Running 0 54s redis-5 1/1 Running 0 23s
次のコマンドを実行して、永続ボリュームが作成されたことを確認します。
kubectl get pv
出力は次の例のようになります。
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-HASH 1Gi RWO Delete Bound default/data-redis-5 standard 75s pvc-HASH 1Gi RWO Delete Bound default/data-redis-1 standard 2m59s pvc-HASH 1Gi RWO Delete Bound default/data-redis-3 standard 2m16s pvc-HASH 1Gi RWO Delete Bound default/data-redis-2 standard 2m38s pvc-HASH 1Gi RWO Delete Bound default/data-redis-0 standard 3m20s pvc-HASH 1Gi RWO Delete Bound default/data-redis-4 standard 104s
この出力で、HASH は各永続ボリューム名に関連付けられたハッシュを表します。
Redis クラスタにロールを割り当てる
構成が完了したら、Redis クラスタにロールを割り当てます。
次のスクリプトは、Pod の IP アドレスを取得し、各 Pod IP アドレスをコマンドに渡してリーダーとフォロワーのロールを割り当てます。
Redis クラスタにロールを割り当てるには、次の手順を完了します。
スクリプトを実行します。
chmod +x ./roles.sh ./roles.sh
プロンプトが表示されたら、「
yes
」と入力します。Redis ノードにログインしてロールを確認します。たとえば、
redis-0
にリーダーのロールが割り当てられていることを確認するには、次のコマンドを実行します。kubectl exec -it redis-0 -- redis-cli role
出力は次の例のようになります。
1) "master" 2) (integer) 574 3) 1) 1) "10.28.2.3" 2) "6379" 3) "574"
Redis クライアント アプリケーションをデプロイする
作成した GKE クラスタにアプリケーションをデプロイするには、アプリケーション用の Deployment を定義します。app-deployment.yaml
という名前のファイルには、アプリケーションのデプロイメント定義が含まれています。
この Deployment で使用される Probe と Pod のアフィニティ ルールの詳細については、GKE のベスト プラクティス: 高可用性クラスタの設計と構築をご覧ください。
Deployment を作成するには、次の手順を行います。
Deployment を適用します。
kubectl apply -f app-deployment.yaml
ロードバランサ経由でアプリケーションを公開します。
kubectl expose deployment hello-web \ --type=LoadBalancer \ --port 80 \ --target-port 8080
約 1 分待ってから次のコマンドを実行して、アプリケーションの外部 IP アドレスを取得します。
kubectl get service
出力から、
hello-web's
EXTERNAL-IP
列に表示されている値をコピーします。NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-web LoadBalancer 10.13.10.55 EXTERNAL_IP 80:30703/TCP 166m
ウェブブラウザに EXTERNAL_IP を貼り付けて、アプリケーションが機能していることを確認します。出力は次の例のようになります。
I have been hit [1] times since deployment!
アクセス数をメモしておきます。これは、アプリケーションの中断テストで必要になります。
コピーした EXTERNAL_IP の変数を設定します。この値は、次のセクションでアプリケーションのテスト スクリプトを作成するときに使用します。
export IP=EXTERNAL_IP
ノードプールのアップグレードに関するベスト プラクティスを構成する
ステートフル アプリケーションに対して以下のベスト プラクティスを実施し、ノードプールのアップグレード中の可用性を最適化します。
Pod 停止予算(PDB)を設定する
Pod 停止予算を作成して、自発的な中断中に同時に停止される複製 Pod の数を制限します。これは、アップグレード中に使用可能なレプリカの数のクォーラムが必要なステートフル アプリケーションに役立ちます。
PDB の定義では:
app
は、この PDB を適用するアプリケーションを指定します。minAvailable
は、中断時に使用できる Pod の最小数を設定します。値または割合(例: 30%)を指定できます。maxUnavailable
は、中断中に使用できない Pod の最大数を設定します。値または割合を指定できます。
PDB を設定するには、次の手順を完了します。
PDB をデプロイします。
kubectl apply -f pdb-minavailable.yaml
PDB が作成されていることを確認します。
kubectl get pdb
メンテナンスの時間枠と除外を設定する
ノードの自動アップグレードによってアップグレード プロセスが効率化され、ユーザーに代わってコントロール プレーンがアップグレードされるときに、クラスタ内のノードが最新の状態に保たれます。この機能はデフォルトで有効になっています。 詳細は、ノードの自動アップグレードをご覧ください。
メンテナンスの時間枠とメンテナンスの除外を使用すると、時間枠を設定して、GKE クラスタでのメンテナンスの実行のタイミングを制御できます。
2022 年 8 月 19 日の午前 2 時(UTC)に開始し、4 時間後に終了するようにメンテナンスの時間枠を設定します。このメンテナンスの時間枠は毎日実行されます。この期間中は、自動メンテナンスが許可されます。
gcloud container clusters update redis-test \ --maintenance-window-start 2022-08-19T02:00:00Z \ --maintenance-window-end 2022-08-19T06:00:00Z \ --maintenance-window-recurrence FREQ=DAILY
除外時間枠を設定して、年末年始にメンテナンスが行われないようにします。このメンテナンスの除外は、
no_upgrades
スコープを使用します。この期間中は、あらゆる種類の自動メンテナンスが禁止されます。詳細については、除外するメンテナンスの範囲をご覧ください。gcloud container clusters update redis-test \ --add-maintenance-exclusion-name new-year \ --add-maintenance-exclusion-start 2022-12-26T00:00:00Z \ --add-maintenance-exclusion-end 2023-01-02T02:00:00Z \ --add-maintenance-exclusion-scope no_upgrades
メンテナンスの時間枠と除外が適用されていることを確認します。
maintenancePolicy:
をご覧ください。gcloud container clusters describe redis-test
詳細については、メンテナンスの時間枠と除外を構成するをご覧ください。
ノードのアップグレード戦略を構成する
GKE クラスタ内のノードプールには、Blue/Green アップグレードとサージ アップグレードという 2 つのノード アップグレード戦略があります。詳細については、ノードのアップグレード戦略をご覧ください。
Blue/Green アップグレード
ワークロードの中断を許容できず、リソース使用量の増加によって一時的な費用の増加が許容される場合は、Blue/Green アップグレードを選択します。
次のコマンドを実行して、現在のノードプールを Blue/Green アップグレード戦略に変更します。
gcloud container node-pools update default-pool \
--cluster=redis-test \
--enable-blue-green-upgrade \
--zone COMPUTE-ZONE \
--node-pool-soak-duration=120s
このチュートリアルの目的上、ノードプール ソーク期間は、ノードプールのソークフェーズで時間を節約するために 2 分間に設定しています。このフェーズは、Blue プールノードがドレインされた後、ワークロードの正常性を確認するために使用されます。ノードプール ソーク期間を 1 時間(3,600 秒)またはアプリケーションに最適な期間に設定することをおすすめします。
Pod の割り当ての管理の詳細については、Pod を特定のノードプールにデプロイすると特定のノードプールに Service をデプロイするをご覧ください。
Blue/Green アップグレードの構成の詳細については、Blue/Green アップグレードを構成するをご覧ください。
サージ アップグレード
コストの最適化が重要であり、ワークロードが 60 分未満で正常なシャットダウンを許容できる場合は、サージ アップグレードを選択します(GKE では PDB が最大 60 分間適用されます)。
次のコマンドを実行して、現在のノードプールをサージ アップグレード戦略に変更します。
gcloud container node-pools update default-pool \
--max-surge-upgrade=1 \
--max-unavailable-upgrade=0 \
--cluster=redis-test
この構成(maxSurge=1
と maxUnavailable=0
)では、アップグレード中にノードプールにサージノードを 1 つだけ追加できます。このため、一度にアップグレードできるノードは 1 つだけです。この設定では、アップグレード中の Pod の再起動が速くなります。
サージ アップグレードの構成の詳細については、サージ アップグレードを構成するをご覧ください。
現在のノードプールの構成を確認します。
gcloud container node-pools describe default-pool \
--cluster redis-test \
--zone COMPUTE-ZONE
ノードプールの表示の詳細については、クラスタ内のノードプールを表示するをご覧ください。
アプリケーションをテストする
このセクションでは、アプリケーションにリクエストを送信するスクリプトと、リクエストの成功率を測定する 2 つのスクリプトを使用します。これらのスクリプトを使用して、クラスタをアップグレードしたときに何が起こるかを測定します。
スクリプトを作成するには:
スクリプトが含まれているディレクトリに移動します。
cd cd kubernetes-engine-samples/quickstarts/hello-app-redis/scripts
generate_load.sh
という名前のスクリプトを参照します。このスクリプトは、秒間クエリ数(QPS)リクエストをアプリケーションに送信します。このスクリプトは、現在のディレクトリのoutput
という名前のファイルに HTTP レスポンス コードを保存します。output
の値は、次の手順で作成するスクリプトで使用します。generate_load.sh
によって生成される出力に基づいて成功率を計算するprint_error_rate.sh
という名前のスクリプトを参照してください。スクリプトの実行権限を付与します。
chmod u+x generate_load.sh print_error_rate.sh
QPS の数を格納する変数を設定します。この値は、EXTERNAL_IP に設定した変数と同様に
generate_load.sh
スクリプトで使用されます。値に 40 を設定することをおすすめします。export QPS=40
generate_load.sh
スクリプトを実行して QPS の送信を開始します。./generate_load.sh $IP $QPS 2>&1
generate_load.sh
スクリプトを実行したまま、新しいターミナルを開きます。新しいターミナルで、print_error_rate.sh
スクリプトを実行してエラー率を確認します。cd cd kubernetes-engine-samples/quickstarts/hello-app-redis/scripts watch ./print_error_rate.sh
QPS が発生すると 100% の成功率と 0% エラー率が表示されます。
両方のスクリプトを実行したまま、次のセクション用に 3 つ目のターミナルを開きます。
クラスタをアップグレードする
クラスタをアップグレードするには、次の手順を完了します。
redis-test
クラスタが使用している GKE のバージョンを確認します。V=$(gcloud container clusters describe redis-test | grep "version:" | sed "s/version: //") echo $V
出力は
1.22.9-gke.2000
のようになります。使用可能な Kubernetes バージョンのリストを取得します。
gcloud container get-server-config
バージョンのリストで
validMasterVersions:
セクションに移動し、前の手順で取得したredis-test
バージョンを探します。ノードと互換性のないバージョンを選択して GKE バージョン スキュー ポリシーに違反しないようにするには、redis-test
バージョンの直前にリストされているバージョンをコピーします。クラスタのコントロール プレーンを選択したバージョンにアップグレードします。プロンプトが表示されたら「
y
」と入力します。gcloud container clusters upgrade redis-test \ --master \ --cluster-version VERSION
VERSION は、前のステップで選択したバージョンに置き換えます。
コントロール プレーンのアップグレードには数分かかります。
クラスタのノードを選択したバージョンにアップグレードします。プロンプトが表示されたら「
y
」と入力します。gcloud container clusters upgrade redis-test \ --cluster-version=VERSION \ --node-pool=default-pool
VERSION は、リストで選択したバージョンに置き換えます。
ワークロードの中断をテストする
このセクションでは、アプリケーションのステータスをテストして、ワークロードの中断を観察します。
./print_error_rate.sh
を実行しているターミナル ウィンドウに戻り、アップグレード中の成功率の変化を確認します。アップグレードのためにノードが停止すると、成功率が若干低下し、アプリのネットワーク エラー率がわずかに増加します。Success rate
フィールドには、ウェブサイトに対して成功したアクセス数が表示されます。この値をメモします。関連するターミナルで「
CTRL+C
」と入力して、両方のスクリプトの実行を停止します。アプリケーションの IP アドレス(Redis クライアント アプリケーションのデプロイでコピーした EXTERNAL_IP)をブラウザに入力して、アプリケーションのウェブサイトに戻ります。
アプリのアクセス数を確認します。表示された数値は次のようになるはずです。
ORIGINAL_VISIT_NUMBER + SUCCESSFUL_VISIT_NUMBER
ORIGINAL_VISIT_NUMBER は、Redis クライアント アプリケーションをデプロイするの最後で記録した数字です。SUCCESSFUL_VISIT_NUMBER は、このセクションの最初のステップで記録した数値です。
クリーンアップ
チュートリアルが終了したら、作成したリソースをクリーンアップして、割り当ての使用を停止し、課金されないようにできます。次のセクションで、リソースを削除または無効にする方法を説明します。
プロジェクトの削除
課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。
プロジェクトを削除するには:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
クラスタを削除する
このチュートリアル用に作成したクラスタを削除するには、次のコマンドを実行します。
gcloud container clusters delete redis-test