Docker のコンテナ化したウェブアプリを GKE にデプロイする

このチュートリアルでは、コンテナ化したウェブ アプリケーションを Google Kubernetes Engine(GKE)クラスタにデプロイする方法について説明します。

このページは、クラウド リソースのプロビジョニングと構成、アプリとサービスのデプロイを行うオペレーターとデベロッパーを対象としています。 Google Cloudのコンテンツで使用されている一般的なロールとタスクの例の詳細については、一般的な GKE ユーザーのロールとタスクをご覧ください。

このページを読む前に、Kubernetes について理解しておいてください。

リポジトリを作成する

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

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

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

    echo $PROJECT_ID
    
  3. Google Cloud CLI のプロジェクト 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 の Docker イメージをビルドする

このチュートリアルでは、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/quickstarts/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
    
  4. サービス アカウントに IAM ポリシー バインディングを追加します。

    gcloud artifacts repositories add-iam-policy-binding hello-repo \
        --location=REGION \
        --member=serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com \
        --role="roles/artifactregistry.reader"
    

    PROJECT_NUMBER は、プロジェクトのプロジェクト番号に置き換えます。

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

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

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

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 のリージョンを設定します。

     gcloud config set compute/region REGION
    

    Standard ゾーンクラスタの場合は、Artifact Registry リポジトリに最も近い Compute Engine ゾーンを設定します。

  2. hello-cluster という名前のクラスタを作成します。

     gcloud container clusters create-auto hello-cluster
    

    GKE クラスタの作成とヘルスチェックには数分を要します。このチュートリアルを GKE Standard クラスタで実行するには、代わりに gcloud container clusters create コマンドを使用します。

コンソール

  1. Google Cloud コンソールで、[Autopilot クラスタの作成] ページに移動します。

    [Autopilot クラスタの作成] に移動

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

  3. [リージョン] プルダウン リストから us-west1 などの Compute Engine リージョンを選択します。

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

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

hello-app を 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
    
  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          90s
    hello-app-784d7569bc-jfkz5   1/1     Running   0          90s
    hello-app-784d7569bc-mnrrl   1/1     Running   0          95s
    

コンソール

  1. Google Cloud コンソールの [ワークロード] ページに移動します。

    [ワークロード] に移動

  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)。

コンソール

  1. Google Cloud コンソールの [ワークロード] ページに移動します。

    [ワークロード] に移動

  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 のいずれかに対応します。

hello-app の新しいバージョンをデプロイする

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

Kubernetes のローリング アップデートを使用すると、ダウンタイムなしで Deployment を更新できます。ローリング アップデート中、既存の hello-app Pod は GKE クラスタによって、新しいバージョンの 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. に設定されています。

コンソール

  1. Google Cloud コンソールの [ワークロード] ページに移動します。

    [ワークロード] に移動

  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. になっているはずです。