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

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

目標

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

始める前に

次の手順で Kubernetes Engine API を有効にします。
  1. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. Artifact Registry and Google Kubernetes Engine API を有効にします。

    API を有効にする

  5. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  6. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  7. Artifact Registry and Google Kubernetes Engine API を有効にします。

    API を有効にする

オプション 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. Cloud SDK をインストールする。これには、gcloud コマンドライン ツールが含まれています。

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

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

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

リポジトリを作成する

このチュートリアルでは、Artifact Registry にイメージを保存し、そのイメージをレジストリからデプロイします。Artifact Registry は、Google Cloud で推奨されるコンテナ レジストリです。このクイックスタートでは、hello-repo という名前のリポジトリを作成します。

  1. 環境変数 PROJECT_IDGoogle Cloud プロジェクト IDPROJECT_ID)を設定します。この環境変数は、コンテナ イメージをビルドしてリポジトリに push するときに使用します。

    export PROJECT_ID=PROJECT_ID
    
  2. PROJECT_ID 環境変数の値が正しいことを確認します。

    echo $PROJECT_ID
    
  3. gcloud コマンドライン ツールのプロジェクト ID を設定します。

    gcloud config set project $PROJECT_ID
    

    出力:

    Updated property [core/project].
    
  4. 次のコマンドを使用して hello-repo リポジトリを作成します。

    gcloud artifacts repositories create hello-repo \
       --repository-format=docker \
       --location=REGION \
       --description="Docker repository"
    

    REGION は、リポジトリのリージョン(us-west1 など)で置き換えます。使用可能なロケーションのリストを表示するには、次のコマンドを実行します。

     gcloud artifacts locations list
    

コンテナ イメージのビルド

このチュートリアルでは、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. hello-app の Docker イメージをビルドしてタグ付けします。

    docker build -t REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1 .
    

    このコマンドを実行すると、Docker は現在のディレクトリにある Dockerfile を使用してイメージをビルドし、ローカル環境に保存します。また、us-west1-docker.pkg.dev/my-project/hello-repo/hello-app:v1 などの名前を使用してイメージにタグを設定します。次のセクションで、このイメージを Artifact Registry に push します。

    • PROJECT_ID 変数は、コンテナ イメージを Google Cloud プロジェクトの hello-repo リポジトリに関連付けます。
    • us-west1-docker.pkg.dev 接頭辞は、リポジトリのリージョン ホストである Artifact Registry を表します。
  3. docker images コマンドを実行して、ビルドが成功したことを確認します。

    docker images
    

    出力:

    REPOSITORY                                                 TAG     IMAGE ID       CREATED          SIZE
    us-west1-docker.pkg.dev/my-project/hello-repo/hello-app    v1      25cfadb1bf28   10 seconds ago   54 MB
    

コンテナをローカルで実行する(省略可)

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

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

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

    curl http://localhost:8080
    

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

Docker イメージを Artifact Registry に push します。

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

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

    gcloud auth configure-docker REGION-docker.pkg.dev
    
  2. ビルドした Docker イメージをリポジトリに push します。

    docker push REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1
    

GKE クラスタの作成

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

Cloud Shell

  1. Compute Engine のゾーンまたはリージョンを設定します。GKE で使用するオペレーション モードに応じて、デフォルトのゾーンまたはリージョンを指定します。Standard モードを使用する場合、作成されるクラスタはゾーンクラスタ(このチュートリアルのケース)であるため、デフォルトのコンピューティング ゾーンを設定します。Autopilot モードを使用する場合、作成されるクラスタはリージョン クラスタであるため、デフォルトのコンピューティング リージョンを設定します。作成した Artifact Registry リポジトリに最も近いゾーンまたはリージョンを選択します。

    • Standard クラスタの場合(us-west1-a など)。

      gcloud config set compute/zone COMPUTE_ZONE
      
    • Autopilot クラスタの場合(us-west1 など)。

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

    • Standard クラスタの場合。

      gcloud container clusters create hello-cluster
      
    • Autopilot クラスタの場合。

      gcloud container clusters create-auto hello-cluster
      

    GKE クラスタの作成とヘルスチェックには数分を要します。

  3. このコマンドを実行したら、以下のコマンドを実行してクラスタの 3 つのノードを確認します。

    kubectl get nodes
    

    出力:

    NAME                                           STATUS   ROLES    AGE   VERSION
    gke-hello-cluster-default-pool-229c0700-cbtd   Ready    <none>   92s   v1.18.12-gke.1210
    gke-hello-cluster-default-pool-229c0700-fc5j   Ready    <none>   91s   v1.18.12-gke.1210
    gke-hello-cluster-default-pool-229c0700-n9l7   Ready    <none>   92s   v1.18.12-gke.1210
    

Console

  1. Cloud Console で Google Kubernetes Engine ページに移動します。

    Google Kubernetes Engine に移動

  2. [ 作成] をクリックします。

  3. Standard モードまたは Autopilot モードを選択して、[構成] をクリックします。

  4. [名前] フィールドに、名前「hello-cluster」を入力します。

  5. ゾーンまたはリージョンを選択します。

    • Standard クラスタの場合: [ロケーション タイプ] で [ゾーン] を選択し、[ゾーン] プルダウン リストから Compute Engine ゾーンを選択します(us-west1-a など)。

    • Autopilot クラスタの場合: [リージョン] プルダウン リストから Compute Engine リージョンを選択します(us-west1 など)。

  6. [作成] をクリックします。これにより、GKE クラスタが作成されます。

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

サンプルアプリを GKE にデプロイする

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

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

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

Cloud Shell

  1. GKE クラスタに接続していることを確認します。

    gcloud container clusters get-credentials hello-cluster --zone COMPUTE_ZONE
    
  2. hello-app Docker イメージの Kubernetes Deployment を作成します。

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

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

    kubectl autoscale deployment hello-app --cpu-percent=80 --min=1 --max=5
    
  5. 作成した 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 の [ワークロード] ページに移動します。

    [ワークロード] に移動

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

  3. [コンテナ] セクションで、[既存のコンテナ イメージ] を選択します。

  4. [イメージパス] フィールドで [選択] をクリックします。

  5. [コンテナ イメージの選択] ペインで、Artifact Registry に push した hello-app イメージを選択して、[選択] をクリックします。

  6. [コンテナ] セクションで、[完了] をクリックしてから、[続行] をクリックします。

  7. [構成] セクションの [ラベル] で、[キー] に app、[] に hello-app を入力します。

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

  9. [閉じる] をクリックし、[デプロイ] をクリックします。

  10. Deployment Pod の準備が整うと、[デプロイの詳細] ページが開きます。

  11. [マネージド Pod] で、hello-app Deployment の 3 つの実行中の Pod をメモします。

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

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 の [ワークロード] ページに移動します。

    [ワークロード] に移動

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

  3. [デプロイの詳細] ページで [アクション] > [公開] の順にクリックします。

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

  5. [Service のタイプ] プルダウン リストから、[ロードバランサ] を選択します。

  6. [公開] をクリックして、hello-app の Kubernetes Service を作成します。

  7. ロードバランサの準備が整うと、[サービスの詳細] ページが開きます。

  8. [外部エンドポイント] フィールドまでスクロールし、IP アドレスをコピーします。

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

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

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

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

  1. hello アプリのソースコードと Dockerfile のクローンを作成した Cloud Shell に戻ります。main.go ファイルの関数 hello() を更新して、新しいバージョン 2.0.0 を報告します。

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

    docker build -t REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v2 .
    
  3. イメージを Artifact Registry に push します。

    docker push REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v2
    

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

Cloud Shell

  1. kubectl set image コマンドを使用して、イメージを更新して既存の hello-app Deployment にローリング アップデートを適用します。

    kubectl set image deployment/hello-app hello-app=REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/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 の [ワークロード] ページに移動します。

    [ワークロード] に移動

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

  3. [デプロイの詳細] ページで、 [アクション] > [ローリング アップデート] の順にクリックします。

  4. [ローリング アップデート] ダイアログで、[Image of hello-app] フィールドを REGION-docker.pkg.dev/PROJECT_ID/hello-repo/hello-app:v2 に設定します。

  5. [更新] をクリックします。

  6. [デプロイの詳細] ページで、[アクティブなリビジョン] セクションを確認します。1 と 2 の 2 つのリビジョンが表示されます。リビジョン 1 は、以前に作成した最初の Deployment に対応します。リビジョン 2 は、開始したばかりのローリング アップデートです。

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

  8. 別のタブで、コピーした Service IP アドレスにもう一度移動します。Version2.0.0. になっているはずです。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

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

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

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

    gcloud artifacts docker images delete \
        REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v1 \
        --delete-tags --quiet
    gcloud artifacts docker images delete \
        REGION-docker.pkg.dev/${PROJECT_ID}/hello-repo/hello-app:v2 \
        --delete-tags --quiet
    

次のステップ

使ってみる

Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオで GKE のパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。

GKE の無料トライアル