Google Kubernetes Engine(GKE)でウェブサイトのデプロイ、スケーリング、更新を行う

1. はじめに

ウェブサイトやアプリケーションの運営は簡単ではありません。

予期せぬ問題が起きたり、サーバーがクラッシュしたり、需要の増加によって利用されるリソースが増加したりします。また、ダウンタイムなしで変更を加えるのは複雑でストレスがかかります。

これらすべてに役立ち、自動化もできるツールを想像してみてください。GKE を使用すれば、これらすべてが可能なだけでなく、簡単に実現できます。この Codelab では、架空の会社 Fancy Store で e コマース ウェブサイトを運営するデベロッパーの役割を前提としています。スケーリングとサービス停止の問題により、アプリケーションを GKE にデプロイする必要があります。

ここでは、一般的なクラウド デベロッパーのエクスペリエンスに沿って次の順序で演習を進めます。

  1. GKE クラスタを作成する。
  2. Docker コンテナを作成する。
  3. コンテナを GKE にデプロイする。
  4. サービスを介してコンテナを公開する。
  5. コンテナを複数のレプリカにスケーリングする。
  6. ウェブサイトを変更する。
  7. ダウンタイムなしで新しいバージョンをロールアウトします。

アーキテクチャの図

ddba666bd2b02d0d.png

学習内容

  • GKE クラスタの作成方法
  • Docker イメージの作成方法
  • Docker イメージを Kubernetes にデプロイする方法
  • Kubernetes でアプリケーションをスケーリングする方法
  • Kubernetes でローリング アップデートを実行する方法

前提条件

  • プロジェクトを作成するための管理者権限を持つ Google アカウント、またはプロジェクト オーナーのロールを持つプロジェクト
  • Docker と Kubernetes の基本知識(基礎知識がない場合は、DockerKubernetes を復習してください)

2. 環境のセットアップ

セルフペース型の環境設定

Google アカウントをまだお持ちでない場合は、アカウントを作成してください。Google Cloud コンソールにログインして、新しいプロジェクトを作成します。

53dad2cefdae71da.png

2016-02-10 12:45:26.png からのスクリーンショット

プロジェクト ID は、すべての Google Cloud プロジェクトで一意の名前であることにご注意ください(上の名前はすでに使用されているため、使用できません)。これ以降は PROJECT_ID と呼びます。

次に、Google Cloud リソースを使用するために、Cloud コンソールで課金を有効にする必要があります。Google Cloud の新規ユーザーは、$300 分の無料トライアルをご利用いただけます。この Codelab の費用は数ドル以内なので、新規ユーザーでなくても心配はいりません。ただし、この Codelab では、使用するリソースを増やしたり、実行したままにしたりすると、費用が増える可能性があります(最後の「クリーンアップ」セクションをご覧ください)。詳細は、料金をご覧ください。

Cloud Shell

ノートパソコンを使って Google Cloud と GKE をリモートで操作することもできますが、この Codelab では Cloud Shell(Google Cloud で実行されるコマンドライン環境)を使用します。

この Debian ベースの仮想マシンには、必要な開発ツールがすべて揃っています。永続的なホーム ディレクトリが 5 GB 用意されており、Google Cloud で稼働するため、ネットワークのパフォーマンスと認証が大幅に向上しています。つまり、この Codelab に必要なのはブラウザだけです(はい、Chromebook で動作します)。

  1. Cloud Console から Cloud Shell を有効にするには、[Cloud Shell をアクティブにする] fEbHefbRynwXpq1vj2wJw6Dr17O0np8l-WOekxAZYlZQIORsWQE_xJl-cNhogjATLn-YxLVz8CgLvIW1Ncc0yXKJsfzJGMYgUeLsVB7zSwz7p6ItNgx4tXqQjag7BfWPcZN5kP-X3Q をクリックします(環境のプロビジョニングと接続に若干時間を要します)。

I5aEsuNurCxHoDFjZRZrKBdarPPKPoKuExYpdagmdaOLKe7eig3DAKJitIKyuOpuwmrMAyZhp5AXpmD_k66cBuc1aUnWlJeSfo_aTKPY9aNMurhfegg1CYaE11jdpSTYNNIYARe01A

Screen Shot 2017-06-14 at 10.13.43 PM.png

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 コンソール ダッシュボードで確認します。

R7chO4PKQfLC3bvFBNZJALLTUiCgyLEq_67ECX7ohs_0ZnSjC7GxDNxWrJJUaoM53LnqABYamrBJhCuXF-J9XBzuUgaz7VvaxNrkP2TAn93Drxccyj2-5zz4AxL-G3hzxZ4PsM5HHQ

Cloud Shell では、デフォルトで環境変数もいくつか設定されます。これらの変数は、以降のコマンドを実行する際に有用なものです。

echo $GOOGLE_CLOUD_PROJECT

コマンド出力

<PROJECT_ID>
  1. 最後に、デフォルトのゾーンとプロジェクト構成を設定します。
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

Cloud コンソールでクラスタと関連情報を確認することもできます。左上のメニューボタンをクリックし、[Kubernetes Engine] まで下にスクロールして、[クラスタ] をクリックします。fancy-cluster というクラスタが表示されます。

795c794b03c5d2b0.png

6b394dfb8a6031f2.png

これで、最初のクラスタが作成されました。

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 でプレビュー] を選択します。

5869738f0e9ec386.png

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

9ed25c3f0cbe62fa.png

ウェブサイトを閲覧した後、このウィンドウは閉じることができます。ターミナル ウィンドウで Control+C(Windows または Mac)を押してウェブサーバー プロセスを停止します。

5. Cloud Build を使用して Docker コンテナを作成する

ソースファイルを使用できる状態になったので、次はアプリケーションを Docker 化します。

通常は、Docker コンテナを構築し、それをレジストリに push して GKE が pull するイメージを保存するという 2 段階のアプローチを取る必要があります。ただし、Cloud Build を使用して 1 つのコマンドで Docker コンテナを作成し、イメージを Container Registry に配置することで、作業を楽にすることができます。(手動で Docker ファイルを作成して push するプロセスを確認するには、Container Registry のクイックスタートをご覧ください)。

Cloud Build は、ディレクトリにあるファイルを圧縮して Cloud Storage バケットに移動します。次に、ビルドプロセスでバケットからファイルを取得し、Dockerfile を使用して Docker ビルドプロセスを実行します。Docker イメージのホストを gcr.io として --tag フラグを指定したため、生成された 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]、[履歴] の順にクリックします。以前のビルドのリストが表示されますが、ここには作成したビルドのみが表示されるはずです。

4c753ede203255f6.png

[Build id] をクリックすると、そのビルドのすべての詳細が表示されます。詳細にはログ出力も含まれます。

[ビルドの詳細] ページで、ビルド情報セクションの [イメージ] 名をクリックすると、作成されたコンテナ イメージが表示されます。

6e88ed1643dfe629.png

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

サーバー クラッシュをシミュレートし、Pod を削除して、どうなるかを確認して、Kubernetes のメリットをすべて確かめましょう。

前のコマンドで取得した 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 をトリガーしたからです。後ほど、複数のインスタンスを実行して、1 つのインスタンスがダウンしてもユーザーのダウンタイムが発生しないようにスケールする方法を紹介します。

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 アドレスを確認したら、それをコピーします。ブラウザでその URL(http://203.0.113.0 など)にアクセスして、アプリにアクセスできるかどうかを確認します。

9ed25c3f0cbe62fa.png

先ほどテストしたときと同じウェブサイトが表示されるはずです。これで、あなたのウェブサイトは 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. ウェブサイトに変更を加える

マーケティング チームから、ウェブサイトのホームページを変更するよう依頼されました。同社は、会社の概要と実際に販売しているものを説明することで、より有益な情報を提供するべきだと考えています。このセクションでは、マーケティング チームの満足度を高めるために、ホームページにテキストを追加します。Google のデベロッパーの 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 &amp; 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 がシャットダウンされます。どの年齢が新しいか、どの古いかがわかります。最終的には、再び 3 つの Pod(更新された 3 つの Pod)のみが表示されます。

変更を確認するには、ロードバランサの外部 IP に再度アクセスして、アプリが更新されたことを確認します。

次のコマンドを実行してサービスを一覧表示し、IP アドレスを忘れた場合は確認します。

kubectl get svc

ウェブサイトには、ホームページ コンポーネントに追加したテキストが表示されます。

8006c9938dbd5aa5.png

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 の操作に慣れました。

参考情報