コンテナ化されたウェブ アプリケーションのデプロイ

このチュートリアルでは、ウェブ アプリケーションを Docker コンテナ イメージにパッケージ化し、そのコンテナ イメージを Google Kubernetes Engine(GKE)クラスタで実行する方法について説明します。ウェブ アプリケーションは、ユーザーのニーズに合わせてスケーリングできる負荷分散されたレプリカのセットとしてデプロイします。

目標

  • サンプル ウェブ アプリケーションを Docker イメージにパッケージ化する。
  • Docker イメージを Container Registry にアップロードする。
  • GKE クラスタを作成する。
  • サンプルアプリをクラスタにデプロイする。
  • デプロイの自動スケーリングを管理する。
  • サンプルアプリをインターネットに公開する。
  • サンプルアプリの新しいバージョンをデプロイする。

始める前に

次の手順で Kubernetes Engine API を有効にします。
  1. Google Cloud Console で Kubernetes Engine ページにアクセスします。
  2. プロジェクトを作成または選択します。
  3. API と関連サービスが有効になるのを待ちます。 これには数分かかることがあります。
  4. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

オプション A: Cloud Shell を使用する

このチュートリアルでは、このチュートリアルで使用する gclouddockerkubectl コマンドライン ツールと一緒にプリインストールされる Cloud Shell を使用できます。Cloud Shell を使用する場合は、これらのコマンドライン ツールをワークステーションにインストールする必要はありません。

Cloud Shell を使用するには:

  1. Google Cloud Console に移動します。
  2. Cloud Console ウィンドウの上部にある [Cloud Shell をアクティブにする] [Shell をアクティブにする] ボタン ボタンをクリックします。

    Cloud Console の一番下にある新しいフレームの中で Cloud Shell セッションが開き、コマンドライン プロンプトが表示されます。

    Cloud Shell セッション

オプション B: ローカルのコマンドライン ツールを使用する

このチュートリアルをワークステーションで行う場合は、次の手順で必要なツールをインストールします。

  1. Google Cloud SDK をインストールします。この SDK には gcloud コマンドライン ツールが含まれています。

  2. gcloud コマンドライン ツールを使用して、Kubernetes コマンドライン ツールをインストールします。kubectl は、GKE クラスタのクラスタ オーケストレーション システムである Kubernetes との通信に使用されます。

    gcloud components install kubectl
  3. Docker Community Edition(CE)をワークステーションにインストールします。これを使用して、アプリケーションのコンテナ イメージを作成します。

  4. GitHub からサンプル アプリケーションを取得するために Git ソース管理ツールをインストールします。

ステップ 1: コンテナ イメージを作成する

このチュートリアルでは、hello-app という名前のサンプル ウェブ アプリケーションをデプロイします。このウェブ アプリケーションは Go で作成されたウェブサーバーで、ポート 8080 のすべてのリクエストに対して「Hello, World!」というメッセージを返します。

GKE は、Docker イメージをアプリケーション デプロイ形式として受け入れます。hello-app を GKE にデプロイする前に、hello-app ソースコードを Docker イメージとしてパッケージ化する必要があります。

Docker イメージを作成するには、ソースコードと Dockerfile が必要です。Dockerfile には、イメージの作成方法に関する手順が含まれています。

  1. 次のコマンドを実行して、hello-app ソースコードと Dockerfile をダウンロードします。

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/hello-app
    
  2. PROJECT_ID 環境変数に Google Cloud プロジェクト IDproject-id)を設定します。PROJECT_ID 変数は、コンテナ イメージをプロジェクトの Container Registry に関連付けるために使用されます。

    export PROJECT_ID=project-id
    
  3. hello-app の Docker イメージをビルドしてタグを付けします。

    docker build -t gcr.io/${PROJECT_ID}/hello-app:v1 .
    

    このコマンドを実行すると、Docker は現在のディレクトリにある Dockerfile を使用してイメージをビルドし、gcr.io/my-project/hello-app:v1 などの名前を使用してタグ付けします。gcr.io 接頭辞は、イメージがホストされる Container Registry を表します。このコマンドを実行してもイメージはまだアップロードされません。

  4. docker images コマンドを実行して、ビルドが成功したことを確認します。

    docker images
    
    出力:
    REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
    gcr.io/my-project/hello-app    v1                  25cfadb1bf28        10 seconds ago      54 MB
    

ステップ 2: コンテナをローカルに実行する(省略可)

  1. ローカル Docker エンジンを使用してコンテナ イメージをテストします。

    docker run --rm -p 8080:8080 gcr.io/${PROJECT_ID}/hello-app:v1
    
  2. Cloud Shell を使用している場合は、[ウェブでプレビュー] ボタン [ウェブでプレビュー] ボタン をクリックして、ポート番号 8080 を選択します。GKE でプロキシ サービスのプレビュー用 URL が新しいブラウザ ウィンドウで開きます。

  3. それ以外の場合は、新しいターミナル ウィンドウ(または Cloud Shell タブ)を開いてコンテナを実行し、コンテナが稼働中でリクエストに「Hello, world!」を返すことを確認します。

    curl http://localhost:8080

    正常なレスポンスを確認したら、docker run コマンドを実行中のタブで Ctrl+C キーを押してコンテナをシャットダウンできます。

ステップ 3: Docker イメージを Container Registry に push する

GKE クラスタでコンテナ イメージをダウンロードして実行できるように、コンテナ イメージをレジストリにアップロードする必要があります。

  1. Docker コマンドライン ツールから Container Registry への認証を構成します。

    gcloud auth configure-docker
    
  2. ビルドした Docker イメージを Container Registry に push します。

    docker push gcr.io/${PROJECT_ID}/hello-app:v1
    

ステップ 4: GKE クラスタを作成する

Docker イメージが Container Registry に保存されたので、GKE クラスタを作成して hello-app を実行する必要があります。GKE クラスタは Kubernetes(GKE を強化するオープンソースのクラスタ オーケストレーション システム)を実行している Compute Engine VM インスタンスのプールで構成されます。

Cloud Shell

  1. gcloud ツールでプロジェクト IDCompute Engine ゾーンのオプションを設定します。

    gcloud config set project $PROJECT_ID
    gcloud config set compute/zone compute-zone
  2. hello-cluster という名前のクラスタを作成します。

    gcloud container clusters create hello-cluster
    

    GKE クラスタが作成され、ヘルスチェックが行われるまでに数分かかります。

  3. このコマンドを実行したら、次のコマンドを実行して、クラスタの 3 つのワーカー VM インスタンスを確認します。

    gcloud compute instances list
    
    出力:
    NAME                                           ZONE        MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP    STATUS
    gke-hello-cluster-default-pool-d8b498d3-0d6r  us-east1-b   e2-medium                   10.142.0.4   35.237.4.149   RUNNING
    gke-hello-cluster-default-pool-d8b498d3-k29m  us-east1-b   e2-medium                   10.142.0.3   34.75.248.193  RUNNING
    gke-hello-cluster-default-pool-d8b498d3-vcrj  us-east1-b   e2-medium                   10.142.0.2   35.196.51.235  RUNNING
    

Console

  1. Cloud Console で Google Kubernetes Engine のメニューに移動します。

    Google Kubernetes Engine のメニューに移動

  2. [クラスタを作成] ボタンをクリックします。

  3. [クラスタの基本] セクションで、名前 hello-cluster を入力します。

  4. プルダウン メニューから Compute Engine ゾーンを選択して、ゾーンを設定します。

  5. [作成] をクリックします。これにより、3 つのノードがある GKE クラスタが作成されます。

  6. クラスタが作成されるまで待ちます。クラスタの準備ができると、クラスタ名の横に緑色のチェックマークが表示されます。

ステップ 5: サンプルアプリを GKE にデプロイする

これで、ビルドした Docker イメージを GKE クラスタにデプロイする準備が整いました。

Kubernetes ではアプリケーションを Pod として表します。Pod とは、1 つ以上のコンテナを保有するスケーラブルなユニットのことです。Pod は、Kubernetes でデプロイ可能な最小単位です。通常は、Pod をレプリカのセットとしてデプロイし、クラスタ全体で一緒にスケーリングと分散を行えます。レプリカのセットをデプロイする 1 つの方法は、Kubernetes の Deployment を使用することです。

クラスタで hello-app を実行するための Kubernetes Deployment を作成します。この Deployment には 3 つのレプリカ(Pod)があります。1 つの Deployment Pod には 1 つのコンテナ(ここでは hello-app Docker イメージ)のみが含まれます。また、CPU 負荷に基づいて、Pod の数を 3 から 1~5 の値にスケーリングする HorizontalPodAutoscaler リソースを作成します。

Cloud Shell

  1. hello-app Docker イメージの Kubernetes Deployment を作成します。

    kubectl create deployment hello-app --image=gcr.io/${PROJECT_ID}/hello-app:v1
    
  2. Deployment レプリカのベースライン数を 3 に設定します。

    kubectl scale deployment hello-app --replicas=3
    
  3. Deployment の HorizontalPodAutoscaler リソースを作成します。

    kubectl autoscale deployment hello-app --cpu-percent=80 --min=1 --max=5
    
  4. 作成した Pod を表示するには、次のコマンドを実行します。

    kubectl get pods
    
    出力:
    NAME                         READY   STATUS    RESTARTS   AGE
    hello-app-784d7569bc-hgmpx   1/1     Running   0          10s
    hello-app-784d7569bc-jfkz5   1/1     Running   0          10s
    hello-app-784d7569bc-mnrrl   1/1     Running   0          15s
    

Console

  1. Cloud Console で Google Kubernetes Engine の [ワークロード] メニューに移動します。

    [ワークロード] メニューに移動

  2. [ワークロード] メニューから [デプロイ] をクリックします。

  3. 表示される [デプロイメントの作成] ウィンドウで、[既存のコンテナ イメージ] をクリックします。

  4. プルダウン メニューを使用して、Container Registry に push した hello-app イメージをクリックします。

  5. [YAML を表示] をクリックします。これにより、クラスタにデプロイしようとしている 2 つの Kubernetes API リソース(1 つの Deployment とその Deployment の 1 つの HorizontalPodAutoscaler)を定義する YAML 構成ファイルが開きます。

  6. [デプロイ] をクリックします。

  7. Deployment Pod の準備が整うまで待ちます。GKE クラスタで 3 つの hello-app Pod がデプロイされると、青色の回転しているホイールが表示され、Pod が正常にデプロイされると緑色のチェックマークが表示されます。

  8. [Kubernetes Engine]、[ワークロード] の順に移動して、Pod の準備が整うまで待ちます。hello-app をクリックし、[マネージド Pod] セクションまでスクロールします。3 つの hello-app Pod が表示されます。

ステップ 6: サンプルアプリをインターネットに公開する

Pod には個別に割り当てられた IP アドレスがありますが、これらの IP にはクラスタ内からしかアクセスできません。また、GKE Pod はエフェメラルで、スケーリングのニーズに基づいて起動または停止するよう設計されています。また、エラーのために Pod がクラッシュした場合、GKE でその Pod が自動的に再デプロイされ、新しい Pod IP アドレスが割り当てられます。

つまり、どの Deployment でも、アクティブな Pod のセットに対応する IP アドレスのセットが動的になります。1)Pod を 1 つの静的ホスト名にグループ化し、2)Pod のグループをクラスタ外のインターネット上に公開する方法が必要です。

Kubernetes Service で、この両方の問題を解決します。Service により、クラスタ内の任意の Pod から到達可能な 1 つの静的 IP アドレスに Pod がグループ化されます。また、GKE ではその静的 IP に DNS ホスト名を割り当てます(例: hello-app.default.svc.cluster.local)。

GKE のデフォルトの Service タイプは ClusterIP で、クラスタ内からのみ到達可能な IP アドレスを取得します。Kubernetes Service をクラスタ外に公開するには、LoadBalancer タイプの Service を作成します。このタイプの Service では、インターネット経由で到達可能な一連の Pod の外部ロードバランサ IP が生成されます。

次に、LoadBalancer タイプの Service を使用して hello-app Deployment をインターネットに公開します。

Cloud Shell

  1. kubectl expose コマンドを使用して、hello-app デプロイ用の Kubernetes Service を生成します。

    kubectl expose deployment hello-app --name=hello-app-service --type=LoadBalancer --port 80 --target-port 8080
    

    ここで、--port フラグはロードバランサ上で構成されたポート番号を指定し、--target-port フラグは hello-app コンテナがリッスンするポート番号を指定します。

  2. 次のコマンドを実行して、hello-app-service の Service の詳細を取得します。

    kubectl get service
    
    出力:
    NAME                 CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
    hello-app-service    10.3.251.122    203.0.113.0     80:30877/TCP     10s
    
  3. EXTERNAL_IP アドレスをクリップボードにコピーします(例: 203.0.113.0)。

Console

  1. Cloud Console で Google Kubernetes Engine の [ワークロード] メニューに移動します。

    [ワークロード] メニューに移動

  2. [hello-app] をクリックします。

  3. [デプロイの詳細] ページで [公開] をクリックします。

  4. [デプロイメントの公開] メニューで、[ターゲット ポート] を 8080 に設定します。これは、hello-app コンテナがリッスンするポートです。

  5. [公開] をクリックして、hello-app 用の hello-app-service という Kubernetes Service を生成します。

  6. 外部ロードバランサが作成されるまで待ちます。Google Cloud Console に青い回転しているホイールが表示されます。ロードバランサの準備が整うと、hello-app-service の Service の [詳細] ページにリダイレクトされます。

  7. [外部エンドポイント] フィールドまでスクロールし、アドレスをクリップボードにコピーします。

hello-app Pod が Kubernetes Service を介してインターネットに公開されたので、新しいブラウザタブを開き、クリップボードにコピーした Service の IP アドレスに移動します。Hello, World! メッセージと Hostname フィールドが表示されます。Hostname は、HTTP リクエストをブラウザに提供する 3 つの hello-app Pod のいずれかに対応します。

ステップ 7: サンプルアプリの新しいバージョンをデプロイする

このセクションでは、新しい Docker イメージをビルドして GKE クラスタにデプロイし、hello-app を新しいバージョンにアップグレードします。

GKE のローリング アップデート機能を使用すると、ダウンタイムなしで Deployment を更新できます。ローリング アップデート中に、GKE クラスタによって既存の hello-app Pod が、新しいバージョンの Docker イメージを含む Pod に段階的に置き換えられます。このアップデート中、ロードバランサ サービスは使用可能な Pod にのみトラフィックをルーティングします。

  1. hello アプリのソースコードと Dockerfile のクローンを作成した Cloud Shell に戻ります。main.go を更新して新しいバージョン 2.0.0 をレポートすることによって、hello-app ソースコードの新しいバージョンを作成します。

  2. 新しい hello-app Docker イメージをビルドしてタグを付けます。

    docker build -t gcr.io/${PROJECT_ID}/hello-app:v2 .
    
  3. イメージを Container Registry に push します。

    docker push gcr.io/${PROJECT_ID}/hello-app:v2
    

これで、新しい Docker イメージを使用するように hello-app Kubernetes Deployment を更新する準備が整いました。

Cloud Shell

  1. イメージを更新して既存のデプロイにローリング アップデートを適用します。

    kubectl set image deployment/hello-app hello-app=gcr.io/${PROJECT_ID}/hello-app:v2
    
  2. v1 イメージを実行している実行中の Pod が停止し、v2 イメージを実行している新しい Pod が起動するのを確認します。

    watch kubectl get pods
    
    出力:
    NAME                        READY   STATUS    RESTARTS   AGE
    hello-app-89dc45f48-5bzqp   1/1     Running   0          2m42s
    hello-app-89dc45f48-scm66   1/1     Running   0          2m40s
    
  3. 別のタブで、hello-app-service 外部 IP に再度移動します。Version2.0.0. に設定されています。

Console

  1. Cloud Console で Google Kubernetes Engine の [ワークロード] メニューに移動します。

    [ワークロード] メニューに移動

  2. hello-app をクリックします。

  3. [アクション] で [ローリング アップデート] をクリックします。

  4. 表示されるウィンドウで、[イメージ] フィールドを gcr.io/[YOUR_PROJECT_ID]/hello-app:v2 に設定します。

  5. [更新] をクリックして、ローリング アップデートを開始します。

  6. hello-app の [Deployment] ビューに戻り、[アクティブなリビジョン] までスクロールします。1 と 2 の 2 つのリビジョンが表示されます。リビジョン 1 は、以前に作成した最初の Deployment に対応します。リビジョン 2 は、開始したばかりのローリング アップデートです。

  7. しばらくしてからページを更新します。[マネージド Pod] で、hello-app のすべてのレプリカがリビジョン 2 に対応していることを確認します。

  8. 別のタブで、hello-app-service 外部 IP に再度移動します。Version2.0.0. に設定されています。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。

  1. Service を削除する: Service に作成した Cloud Load Balancer の割り当てを解除します。

    kubectl delete service hello-app-service
  2. クラスタを削除する: クラスタを構成するリソース(コンピューティング インスタンス、ディスク、ネットワーク リソースなど)を削除します。

    gcloud container clusters delete hello-cluster
  3. コンテナ イメージを削除する: Container Registry に push した Docker イメージを削除します。

     gcloud container images delete gcr.io/${PROJECT_ID}/hello-app:v1  --force-delete-tags --quiet
    

次のステップ