1. はじめに
ウェブサイトやアプリケーションの運営は簡単ではありません。
予期せぬ問題が発生したり、サーバーがクラッシュしたり、需要の増加によって使用リソースが増大したりします。また、ダウンタイムなしで変更を加えるのは複雑で大変な作業です。
ウェブサイトやアプリの運用をすべてサポートし、自動化まで可能にするツールがあったらどうでしょう。GKE を使えば、これらすべてが可能なだけでなく簡単に行えます。この Codelab では、あなたは架空の会社 Fancy Store の e コマース ウェブサイトを運営するデベロッパーです。スケーリングとサービス停止に関する問題により、アプリケーションを GKE にデプロイする必要があります。
ここでは、一般的なクラウド デベロッパーが行う手順に沿って以下の順序で演習を進めます。
- GKE クラスタを作成する。
- Docker コンテナを作成します。
- コンテナを GKE にデプロイします。
- サービスを介してコンテナを公開します。
- コンテナを複数のレプリカにスケーリングします。
- ウェブサイトを変更します。
- ダウンタイムなしで新しいバージョンをロールアウトします。
アーキテクチャの図

学習内容
- GKE クラスタを作成する方法
- Docker イメージの作成方法
- Docker イメージを Kubernetes にデプロイする方法
- Kubernetes でアプリケーションをスケーリングする方法
- Kubernetes でローリング アップデートを実行する方法
前提条件
- プロジェクトを作成するための管理者権限を持つ Google アカウント、またはプロジェクト オーナーのロールを持つプロジェクト
- Docker と Kubernetes の基礎知識(基礎知識がない場合は、今すぐ Docker と Kubernetes を確認してください)。
2. 環境のセットアップ
セルフペース型の環境設定
Google アカウントをまだお持ちでない場合は、アカウントを作成する必要があります。Google Cloud コンソールにログインし、新しいプロジェクトを作成します。


プロジェクト ID は、すべての Google Cloud プロジェクトを通じて一意の名前にする必要があります(上記の名前はすでに使用されているため使用できません)。後で PROJECT_ID として参照します。
次に、Google Cloud リソースを使用するために、Cloud Console で課金を有効にする必要があります。Google Cloud の新規ユーザーは、300 ドル分の無料トライアルをご利用いただけます。新規ユーザーでない場合でも、この Codelab の費用は数ドル程度で済むため、ご安心ください。ただし、リソースを多く使用したり、実行したままにしたりすると、Codelab の費用が高くなる可能性があります(最後の「クリーンアップ」セクションを参照)。詳細は、料金をご覧ください。
Cloud Shell
Google Cloud と GKE はノートパソコンでリモートから操作できますが、この Codelab では Cloud Shell(Cloud 上で動作するコマンドライン環境)を使用します。
この Debian ベースの仮想マシンには、必要な開発ツールがすべて用意されています。仮想マシンは Google Cloud で稼働し、永続的なホーム ディレクトリが 5 GB 用意されているため、ネットワークのパフォーマンスと認証が大幅に向上しています。つまり、この Codelab に必要なのはブラウザだけです(Chromebook でも動作します)。
- Cloud Console から Cloud Shell を有効にするには、[Cloud Shell をアクティブにする]
をクリックします(環境のプロビジョニングと接続に若干時間を要します)。
Cloud Shell に接続すると、すでに認証は完了しており、プロジェクトに各自の PROJECT_ID が設定されていることがわかります。
gcloud auth list
コマンド出力
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
コマンド出力
[core] project = <PROJECT_ID>
なんらかの理由でプロジェクトが設定されていない場合は、次のコマンドを実行します。
gcloud config set project <PROJECT_ID>
PROJECT_ID が見つからない場合は、設定手順で使用した ID を確認するか、Cloud Console ダッシュボードで検索します。
Cloud Shell では、デフォルトで環境変数もいくつか設定されます。これらの変数は、以降のコマンドを実行する際に有用なものです。
echo $GOOGLE_CLOUD_PROJECT
コマンド出力
<PROJECT_ID>
- 最後に、デフォルトのゾーンとプロジェクト構成を設定します。
gcloud config set compute/zone us-central1-f
さまざまなゾーンを選択できます。詳細については、リージョンとゾーンをご覧ください。
3. GKE クラスタを作成する
作業用の開発環境が整ったので、ウェブサイトをデプロイするための GKE クラスタが必要になります。クラスタを作成する前に、適切な API が有効になっていることを確認する必要があります。次のコマンドを実行して、コンテナ API を有効にします。
gcloud services enable container.googleapis.com
これで、クラスタを作成できます。次の手順に沿って、3 つのノードを持つ fancy-cluster という名前のクラスタを作成します。
gcloud container clusters create fancy-cluster --num-nodes 3
クラスタの作成には数分かかることがあります。その後、次のコマンドを実行して、クラスタの 3 つのワーカー仮想マシン(VM)インスタンスを確認します。
gcloud compute instances list
出力:
NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS gke-fancy-cluster-default-pool-ad92506d-1ng3 us-east4-a n1-standard-1 10.150.0.7 XX.XX.XX.XX RUNNING gke-fancy-cluster-default-pool-ad92506d-4fvq us-east4-a n1-standard-1 10.150.0.5 XX.XX.XX.XX RUNNING gke-fancy-cluster-default-pool-ad92506d-4zs3 us-east4-a n1-standard-1 10.150.0.6 XX.XX.XX.XX RUNNING
Google Cloud コンソールでクラスタと関連情報を表示することもできます。左上のメニューボタンをクリックし、[Kubernetes Engine] までスクロールして [クラスタ] をクリックします。fancy-cluster というクラスタが表示されます。


おめでとうございます!最初のクラスタが作成されました。
4. ソース リポジトリのクローンを作成する
ウェブサイトがすでに存在するため、ソースをリポジトリからクローンするだけで、後は Docker イメージの作成と GKE へのデプロイに集中できます。
次のコマンドを実行して、ソース リポジトリのクローンを Cloud Shell インスタンスに作成し、適切なディレクトリに変更します。Node.js 依存関係もインストールするので、デプロイする前にアプリケーションをテストできます。
cd ~ git clone https://github.com/googlecodelabs/monolith-to-microservices.git cd ~/monolith-to-microservices ./setup.sh
これにより、リポジトリのクローンが作成され、ディレクトリが変更され、アプリケーションをローカルで実行するために必要な依存関係がインストールされます。このスクリプトの実行には数分かかることがあります。
デュー デリジェンスを実施し、アプリケーションをテストしてください。次のコマンドを実行して、ウェブサーバーを起動します。
cd ~/monolith-to-microservices/monolith npm start
出力:
Monolith listening on port 8080!
アプリケーションをプレビューするには、Cloud Shell メニューの [ウェブでプレビュー] アイコンをクリックして、[ポート 8080 でプレビュー] を選択します。

新しいウィンドウが開き、動作中の Fancy Store が表示されます。

ウェブサイトを確認したら、そのウィンドウを閉じることができます。ターミナル ウィンドウで Control+C(Windows または Mac)を押して、ウェブサーバー プロセスを停止します。
5. Cloud Build を使用して Docker コンテナを作成する
ソースファイルを使用できる状態になったので、次はアプリケーションを Docker 化します。
通常、Docker コンテナを作成するには 2 ステップのアプローチを取る必要があります。具体的には、Docker コンテナをビルドするステップと、ビルドしたコンテナをレジストリに push してそのイメージを保管し、GKE がそこからイメージを pull できるようにするステップです。ただし、Cloud Build を使用して 1 つのコマンドで Docker コンテナを作成し、イメージを Container Registry に保存すると、作業が楽になります。(手動で Docker ファイルを作成して push するプロセスを確認するには、Container Registry のクイックスタートをご覧ください)。
Cloud Build がディレクトリにあるファイルを圧縮して Cloud Storage バケットに移動します。その後、ビルドプロセスでバケットからファイルを取得し、Dockerfile を使用して Docker ビルドプロセスを実行します。--tag フラグで Docker イメージのホストとして gcr.io を指定したため、ビルドされた Docker イメージは Container Registry に push されます。
まず、次のコマンドを実行して Cloud Build API を有効にする必要があります。
gcloud services enable cloudbuild.googleapis.com
API が有効になったら、Cloud Shell で次のコマンドを実行してビルドプロセスを開始します。
cd ~/monolith-to-microservices/monolith
gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 .
このプロセスには数分かかりますが、完了すると、ターミナルに次の出力が表示されます。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ID CREATE_TIME DURATION SOURCE IMAGES STATUS 1ae295d9-63cb-482c-959b-bc52e9644d53 2019-08-29T01:56:35+00:00 33S gs://<PROJECT_ID>_cloudbuild/source/1567043793.94-abfd382011724422bf49af1558b894aa.tgz gcr.io/<PROJECT_ID>/monolith:1.0.0 SUCCESS
ビルド履歴を表示したり、プロセスをリアルタイムで確認したりするには、Cloud コンソールに移動します。左上のメニューボタンをクリックし、[Ci/CD] までスクロールして [Cloud Build] をクリックし、最後に [履歴] をクリックします。過去のビルドのリストが表示されますが、作成したビルドが 1 つだけ表示されているはずです。

[ビルド ID] をクリックすると、そのビルドの詳細がすべて表示されます。詳細にはログ出力も含まれます。
[ビルドの詳細] ページで、ビルド情報のセクションにあるイメージ名をクリックすると、作成されたコンテナ イメージが表示されます。

6. コンテナを GKE にデプロイする
ウェブサイトをコンテナ化して、そのコンテナを Container Registry に push したので、次は Kubernetes にデプロイしましょう。
GKE クラスタにアプリケーションをデプロイして管理するには、Kubernetes クラスタ管理システムとの通信が必要になります。通常、これを行うには、kubectl コマンドライン ツールを使用します。
Kubernetes では、アプリケーションは Pod として表されます。Pod は、1 つのコンテナ(または密接に結合されたコンテナのグループ)を表す単位です。Pod は、Kubernetes でデプロイ可能な最小単位です。ここでは、各 Pod に monolith コンテナのみが含まれています。
アプリケーションをデプロイするには、Deployment を作成する必要があります。Deployment は、アプリケーションの複数のコピー(レプリカと呼ばれる)を管理し、クラスタ内の個々のノード上で実行されるようにスケジューリングします。この場合、Deployment ではアプリケーションの 1 つの Pod のみが実行されます。これらの処理を行うために、Deployment は ReplicaSet を作成します。ReplicaSet の役割は、指定された数のレプリカが常に実行されるようにすることです。
kubectl create deployment コマンドを実行すると、Kubernetes は 1 つのレプリカを含む monolith という Deployment をクラスタに作成します。
次のコマンドを実行して、アプリケーションをデプロイします。
kubectl create deployment monolith --image=gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0
デプロイメントを確認する
次のコマンドを実行して、Deployment が正常に作成されたことを確認します(Pod のステータスが「Running」になるまで数分かかることがあります)。
kubectl get all
出力:
NAME READY STATUS RESTARTS AGE pod/monolith-7d8bc7bf68-htm7z 1/1 Running 0 6m21s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.27.240.1 <none> 443/TCP 24h NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deployment.apps/monolith 1 1 1 1 20m NAME DESIRED CURRENT READY AGE replicaset.apps/monolith-7d8bc7bf68 1 1 1 20m
この出力から次のことを確認できます。現在の Deployment、必要な Pod 数が 1 の ReplicaSet、実行中の Pod を確認できます。すべて正常に作成されていることがわかります。
リソースを個別に表示するには、次のコマンドを実行します。
# Show pods kubectl get pods # Show deployments kubectl get deployments # Show replica sets kubectl get rs #You can also combine them kubectl get pods,deployments
Kubernetes のメリットを最大限に活用するには、サーバー クラッシュをシミュレートして Pod を削除し、何が起こるかを確認します。
前のコマンドで出力された Pod 名をコピーし、次のコマンドを実行して削除します。
kubectl delete pod/<POD_NAME>
反映されていない場合は、もう一度前述のコマンドを実行すると 2 つの Pod(1 つは終了、もう 1 つは作成中か実行中)が表示されます。
kubectl get all
出力:
NAME READY STATUS RESTARTS AGE pod/monolith-7d8bc7bf68-2bxts 1/1 Running 0 4s pod/monolith-7d8bc7bf68-htm7z 1/1 Terminating 0 9m35s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.27.240.1 <none> 443/TCP 24h NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deployment.apps/monolith 1 1 1 1 24m NAME DESIRED CURRENT READY AGE replicaset.apps/monolith-7d8bc7bf68 1 1 1 24m
なぜこのようなことが起こったのでしょうか?Pod の終了を検出した ReplicaSet が、目的のレプリカ数を維持するために新しい Pod をトリガーしたからです。後ほど説明しますが、スケールアウトして複数のインスタンスを実行すれば、いずれかが停止してもダウンタイムが発生することはありません。
7. GKE Deployment を公開する
アプリケーションを GKE にデプロイしましたが、クラスタの外部からアクセスする方法がありません。GKE で実行するコンテナには外部 IP アドレスがないため、デフォルトでは、このコンテナにインターネットからアクセスすることはできません。Service リソースを使用して、アプリケーションをインターネットからのトラフィックに明示的に公開する必要があります。Service は、アプリの Pod にネットワーキングと IP サポートを提供します。GKE は、アプリの外部 IP とロードバランサ(課金対象)を作成します。
次のコマンドを実行して、ウェブサイトをインターネットに公開します。
kubectl expose deployment monolith --type=LoadBalancer --port 80 --target-port 8080
出力:
service/monolith exposed
サービスへのアクセス
GKE は、Deployment ではなく Service リソースに外部 IP アドレスを割り当てます。GKE によってアプリケーション用にプロビジョニングされた外部 IP を確認するには、kubectl get service コマンドを使用して Service を調べます。
kubectl get service
出力:
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE monolith 10.3.251.122 203.0.113.0 80:30877/TCP 3d
アプリの外部 IP アドレスを確認したら、その IP アドレスをコピーします。ブラウザにその URL(http://203.0.113.0 など)を指定して、アプリにアクセスできるかどうかを確認します。

先ほどテストしたときと同じウェブサイトが表示されるはずです。おめでとうございます!これで、ウェブサイトが完全に Kubernetes で動作するようになりました。
8. GKE Deployment をスケーリングする
GKE でアプリのインスタンスが実行され、インターネットに公開されたことで、ウェブサイトへのアクセスが急増する可能性があります。そこで、トラフィックを処理できるように、アプリを複数のインスタンスにスケーリングする方法が必要です。アプリケーションを最大 3 つのレプリカにスケーリングする方法を学習します。
次のコマンドを実行して、Deployment を 3 つのレプリカにスケーリングします。
kubectl scale deployment monolith --replicas=3
出力:
deployment.apps/monolith scaled
スケーリングされたデプロイを確認する
次のコマンドを実行して、Deployment が正常にスケーリングされたことを確認します。
kubectl get all
出力:
NAME READY STATUS RESTARTS AGE pod/monolith-7d8bc7bf68-2bxts 1/1 Running 0 36m pod/monolith-7d8bc7bf68-7ds7q 1/1 Running 0 45s pod/monolith-7d8bc7bf68-c5kxk 1/1 Running 0 45s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.27.240.1 <none> 443/TCP 25h service/monolith LoadBalancer 10.27.253.64 XX.XX.XX.XX 80:32050/TCP 6m7s NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE deployment.apps/monolith 3 3 3 3 61m NAME DESIRED CURRENT READY AGE replicaset.apps/monolith-7d8bc7bf68 3 3 3 61m
Pod の 3 つのインスタンスが実行中になっているはずです。また、Deployment と ReplicaSet の必要数が 3 になっていることも確認してください。
9. ウェブサイトに変更を加える
マーケティング チームから、ウェブサイトのホームページを変更するよう依頼されました。マーケティング チームは、会社の概要と販売している製品のより詳しい情報を追加する必要があると考えています。このセクションでは、マーケティング チームからの依頼に応じたテキストをホームページに追加します。開発者の 1 人がすでに index.js.new というファイルで変更内容を作成したようです。ファイルを index.js にコピーするだけで、変更内容を反映できます。以下の手順に沿って適切な変更を行います。
次のコマンドを実行して、更新されたファイルを正しい名前のファイルにコピーし、その内容を出力して変更を確認します。
cd ~/monolith-to-microservices/react-app/src/pages/Home mv index.js.new index.js cat ~/monolith-to-microservices/react-app/src/pages/Home/index.js
変更後のコードは次のようになっています。
/*
Copyright 2019 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1
},
paper: {
width: "800px",
margin: "0 auto",
padding: theme.spacing(3, 2)
}
}));
export default function Home() {
const classes = useStyles();
return (
<div className={classes.root}>
<Paper className={classes.paper}>
<Typography variant="h5">
Fancy Fashion & Style Online
</Typography>
<br />
<Typography variant="body1">
Tired of mainstream fashion ideas, popular trends and societal norms?
This line of lifestyle products will help you catch up with the Fancy trend and express your personal style.
Start shopping Fancy items now!
</Typography>
</Paper>
</div>
);
}
これで React コンポーネントは更新されましたが、React アプリをビルドして静的ファイルを生成する必要があります。次のコマンドを実行して React アプリをビルドし、monolith の公開ディレクトリにコピーします。
cd ~/monolith-to-microservices/react-app npm run build:monolith
コードが更新されたので、次は Docker コンテナを再ビルドして Container Registry に公開する必要があります。前と同じコマンドを使用できますが、今回はバージョン ラベルを更新します。
次のコマンドを実行し、更新後のイメージ バージョン 2.0.0 を指定して新しい Cloud Build をトリガーします。
cd ~/monolith-to-microservices/monolith
#Feel free to test your application
npm start
gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:2.0.0 .
ターミナル ウィンドウで Control+C(Windows または Mac)を押して、ウェブサーバー プロセスを停止します。
次のセクションでは、このイメージを使用してダウンタイムなしでアプリケーションを更新します。
10. ダウンタイムなしでウェブサイトを更新する
変更が完了し、マーケティング チームも更新内容に満足してくれました。次は、ユーザーへのサービスを中断させずにウェブサイトを更新します。以下の手順に沿ってウェブサイトを更新してください。
GKE のローリング アップデートにより、実行中のすべてのレプリカで古いコンテナ イメージのインスタンスを新しいコンテナ イメージのインスタンスにシステムが置き換えるときでも、アプリケーションを稼働させたまま使用できます。
コマンドラインから、次のコマンドを使用して、Deployment のイメージを新しいバージョンに更新するように Kubernetes に指示できます。
kubectl set image deployment/monolith monolith=gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:2.0.0
出力:
deployment.apps/monolith image updated
Deployment を確認する
Deployment の更新を検証するには、次のコマンドを実行します。
kubectl get pods
出力:
NAME READY STATUS RESTARTS AGE monolith-584fbc994b-4hj68 1/1 Terminating 0 60m monolith-584fbc994b-fpwdw 1/1 Running 0 60m monolith-584fbc994b-xsk8s 1/1 Terminating 0 60m monolith-75f4cf58d5-24cq8 1/1 Running 0 3s monolith-75f4cf58d5-rfj8r 1/1 Running 0 5s monolith-75f4cf58d5-xm44v 0/1 ContainerCreating 0 1s
3 つの新しい Pod が作成され、古い Pod がシャットダウンしていることがわかります。新しい Pod か古い Pod かは期間(age)で確認できます。最終的には、3 つの Pod(更新された 3 つの Pod)のみが再度表示されます。
変更を確認するには、ロードバランサの外部 IP に再度アクセスし、アプリが更新されていることを確認します。
IP アドレスを忘れた場合は、次のコマンドを実行してサービスを一覧表示し、IP アドレスを確認します。
kubectl get svc
ウェブサイトのホームページ コンポーネントに追加したテキストが表示されるようになりました。

11. クリーンアップ
Git リポジトリを削除する
cd ~ rm -rf monolith-to-microservices
Container Registry イメージを削除する
注: 他のバージョンを作成した場合は、同じ構文を使用してそれらのイメージも削除できます。この Codelab は、タグが 2 つしかないことを前提としています。
# Delete the container image for version 1.0.0 of our monolith
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:1.0.0 --quiet
# Delete the container image for version 2.0.0 of our monolith
gcloud container images delete gcr.io/${GOOGLE_CLOUD_PROJECT}/monolith:2.0.0 --quiet
Cloud Storage から Cloud Build アーティファクトを削除する
注: この Codelab 以外のアーティファクトに Cloud Build を使用した場合は、Cloud Storage バケット gs://<PROJECT_ID>_cloudbuild/source からソースを手動で削除する必要があります。
# The following command will take all source archives from all builds and delete them from cloud storage
# Run this command to print all sources:
# gcloud builds list | awk 'NR > 1 {print $4}'
gcloud builds list | awk 'NR > 1 {print $4}' | while read line; do gsutil rm $line; done
GKE サービスを削除する
kubectl delete service monolith kubectl delete deployment monolith
GKE クラスタを削除する
gcloud container clusters delete fancy-cluster
注: このコマンドの処理には少し時間がかかる場合があります。
12. 完了
GKE でウェブサイトのデプロイ、スケーリング、更新を行いました。これで、Docker と Kubernetes の経験者になりました。