Cloud Build を使用した Google Kubernetes Engine(GKE)への継続的デプロイ

1. 概要

このラボでは、Cloud Build を使用して GKE 用の継続的デリバリー パイプラインを設定する方法を学びます。このラボでは、さまざまな Git イベントに対して Cloud Build ジョブをトリガーする方法と、GKE で自動カナリア リリースを行うための簡単なパターンについて説明します。

次の手順を実施します。

  • GKE アプリケーションを作成する
  • Git ブランチのデプロイを自動化する
  • Git main ブランチのデプロイを自動化する
  • Git タグのデプロイを自動化する

2. 始める前に

このリファレンス ガイドでは、Google Cloud プロジェクトが必要です。新しいプロジェクトを作成することも、すでに作成済みのプロジェクトを選択することもできます。

  1. Google Cloud プロジェクトを選択または作成します。

プロジェクトの選択ページに移動

  1. プロジェクトに対する課金を有効にします。

課金を有効にする

3. 環境の準備

  1. このチュートリアル全体を通して使用する環境変数を作成します。
    export PROJECT_ID=$(gcloud config get-value project)
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
    
    export ZONE=us-central1-b
    export CLUSTER=gke-progression-cluster
    export APP_NAME=myapp
    
  2. 以下の API を有効にします。
    • Resource Manager
    • GKE
    • Cloud Source Repositories
    • Cloud Build
    • Container Registry
    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        container.googleapis.com \
        sourcerepo.googleapis.com \
        cloudbuild.googleapis.com \
        containerregistry.googleapis.com \
        --async
    
  3. サンプルソースのクローンを作成し、ラボ ディレクトリに切り替えます。
    git clone https://github.com/GoogleCloudPlatform/software-delivery-workshop.git gke-progression
    
    cd gke-progression/labs/gke-progression
    rm -rf ../../.git
    
  4. サンプル リポジトリのプレースホルダ値を PROJECT_ID に置き換えます。このステップでは、現在の環境に固有のさまざまな構成ファイルのインスタンスを作成します。更新されるテンプレートの例を確認するには、次のコマンドを実行します。
    cat k8s/deployments/dev/frontend-dev.yaml.tmpl
    
    次のコマンドを実行して、変数を置換します。
    for template in $(find . -name '*.tmpl'); do envsubst '${PROJECT_ID} ${ZONE} ${CLUSTER} ${APP_NAME}' < ${template} > ${template%.*}; done
    
    置換後のファイルの例を確認するには、次のコマンドを実行します。
    cat k8s/deployments/dev/frontend-dev.yaml
    
  5. Cloud Shell で Git を初めて使用する場合は、使用する user.nameuser.email の値を設定します。
    git config --global user.email "YOUR_EMAIL_ADDRESS"
    git config --global user.name "YOUR_USERNAME"
    
  6. サンプル リポジトリのコードを Cloud Source Repositories に保存します。
    gcloud source repos create gke-progression
    git init
    git config credential.helper gcloud.sh
    git remote add gcp https://source.developers.google.com/p/$PROJECT_ID/r/gke-progression
    git branch -m main
    git add . && git commit -m "initial commit"
    git push gcp main
    
  7. GKE クラスタを作成します。
    gcloud container clusters create ${CLUSTER} \
        --project=${PROJECT_ID} \
        --zone=${ZONE}
    
  8. クラスタに対する Cloud Build の権限を付与します。Cloud Build はアプリケーションを GKE クラスタにデプロイするため、そのための権限が必要です。
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
        --role=roles/container.developer
    

環境の準備が整いました。

4. GKE アプリケーションの作成

このセクションでは、このチュートリアルを通じて使用する最初の本番環境アプリケーションをビルドしてデプロイします。

  1. Cloud Build を使用してアプリケーションをビルドします。
    gcloud builds submit --tag gcr.io/$PROJECT_ID/$APP_NAME:1.0.0 src/
    
  2. カナリア環境と本番環境に手動でデプロイする:kubectl apply コマンドを使用して、本番環境とカナリア環境のデプロイとサービスを作成します。
    kubectl create ns production
    kubectl apply -f k8s/deployments/prod -n production
    kubectl apply -f k8s/deployments/canary -n production
    kubectl apply -f k8s/services -n production
    
    ここでデプロイされたサービスは、カナリア デプロイと本番環境デプロイの両方にトラフィックをルーティングします。
  3. 実行中の Pod の数を確認します。フロントエンド用に 4 つの Pod(本番環境トラフィック用に 3 つ、カナリア リリース用に 1 つ)が実行されていることを確認します。つまり、カナリア リリースに加えた変更は、ユーザーの 4 人中 1 人(25%)にのみ影響します。
    kubectl get pods -n production -l app=$APP_NAME -l role=frontend
    
  4. 本番環境サービスの外部 IP アドレスを取得します。で確認できます。
    kubectl get service $APP_NAME -n production
    
    ロードバランサから IP アドレスが返されたら、次のステップに進みます。
  5. 後で使用できるように、外部 IP を保存します。
    export PRODUCTION_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}"  --namespace=production services $APP_NAME)
    
  6. アプリケーションを確認します。サービスのバージョン出力を確認します。「Hello World v1.0」と表示されます。
    curl http://$PRODUCTION_IP
    

これで、サンプルアプリがデプロイされました。次に、変更を継続的にデプロイするためのトリガーを設定します。

5. Git ブランチのデプロイの自動化

このセクションでは、main 以外のブランチの commit 時に Cloudbuild ジョブを実行するトリガーを設定します。ここで使用する Cloud Build ファイルは、既存または新規のブランチに対する名前空間とデプロイメントを自動的に作成し、デベロッパーはメインブランチと統合する前にコードをプレビューできます。

  1. トリガーを設定する:このトリガーの主なコンポーネントは、main に一致する branchName パラメータと、true に設定された invertRegex パラメータを使用して、main 以外のすべてに一致するように branchName パターンを変更することです。参考までに、build/branch-trigger.json に次の行があります。
      "branchName": "main",
      "invertRegex": true
    
    さらに、このトリガーで使用される Cloud Build ファイルの最後の数行では、ジョブをトリガーしたブランチの名前が付けられた Namespace を作成し、その新しい Namespace 内にアプリケーションとサービスをデプロイします。参考までに、build/branch-cloudbuild.yaml
      kubectl get ns ${BRANCH_NAME} || kubectl create ns ${BRANCH_NAME}
      kubectl apply --namespace ${BRANCH_NAME} --recursive -f k8s/deployments/dev
      kubectl apply --namespace ${BRANCH_NAME} --recursive -f k8s/services
    
    に次の行があります。 使用するメカニズムを理解できたところで、以下の gcloud コマンドを使用してトリガーを作成します。
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/branch-trigger.json
    
  2. トリガーを確認するには、コンソールの [Cloud Build トリガー] ページに移動します。[トリガー] に移動
  3. 新しいブランチを作成します。
    git checkout -b new-feature-1
    
  4. v1.1 を示すようにコードを変更して src/app.py を編集し、レスポンスを 1.0 から 1.1 に変更します
    @app.route('/')
    def hello_world():
        return 'Hello World v1.1'
    
  5. 変更を commit してリモート リポジトリに push します。
    git add . && git commit -m "updated" && git push gcp new-feature-1
    
  6. 進行中のビルドを確認するには、コンソールで Cloud Build の [履歴] ページに移動します。[ビルド] に移動ビルドが完了したら、次のステップに進みます。
  7. 新しくデプロイされたブランチ サービスの外部 IP アドレスを取得します。で確認できます。
    kubectl get service $APP_NAME -n new-feature-1
    
    ロードバランサから IP アドレスが返されたら、次のステップに進みます。
  8. 後で使用できるように、外部 IP を保存します。
    export BRANCH_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}"  --namespace=new-feature-1 services $APP_NAME)
    
  9. applicationCheck でサービスのバージョン出力を確認します。「Hello World v1.0」と表示されます。
    curl http://$BRANCH_IP
    

6. git main ブランチのデプロイの自動化

コードを本番環境にリリースする前に、すべてのトラフィックを新しいコードベースに移行する前に、ライブ トラフィックの小さなサブセットにコードをリリースするのが一般的です。

このセクションでは、コードがメインブランチに commit されたときに有効化されるトリガーを実装します。トリガーにより、新しいリビジョンへのすべてのライブ トラフィックの 25% を受信するカナリア デプロイがデプロイされます。

  1. main ブランチのトリガーを設定します。
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/main-trigger.json
    
  2. 新しいトリガーを確認するには、コンソールの [Cloud Build トリガー] ページに移動します。[トリガー] に移動
  3. ブランチをメインラインにマージして、リモート リポジトリに push します。
    git checkout main
    git merge new-feature-1
    git push gcp main
    
  4. 進行中のビルドを確認するには、コンソールの Cloud Build の履歴ページに移動します。[ビルド] に移動ビルドが完了したら、次のステップに進みます。
  5. server からの複数のレスポンスを確認します。次のコマンドを実行します。レスポンスの約 25% が Hello World v1.1 の新しいレスポンスを示していることがわかります。
    while true; do curl -w "\n" http://$PRODUCTION_IP; sleep 1;  done
    
    準備ができたら Ctrl+c を押してループを終了します。

7. Git タグのデプロイを自動化する

トラフィックの小規模なサブセットでカナリア デプロイを検証したら、残りのライブ トラフィックにデプロイをリリースします。

このセクションでは、リポジトリ内でタグを作成するときに有効にするトリガーを設定します。トリガーによってイメージに適切なタグのラベルが付けられた後、その更新が本番環境にデプロイされ、100% のトラフィックがタグ付けされたイメージにアクセスできるようになります。

  1. タグトリガーをセットアップする:
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/tag-trigger.json
    
  2. 新しいトリガーを確認するには、コンソールの [Cloud Build トリガー] ページに移動します。[トリガー] に移動
  3. 新しいタグを作成し、リモート リポジトリに push します。
    git tag 1.1
    git push gcp 1.1
    
  4. 進行中のビルドを確認するには、コンソールの Cloud Build の履歴ページに移動します。[ビルド] に移動
  5. serverRun で複数のレスポンスを確認します。次のコマンドを実行し、レスポンスの 100% が Hello World v1.1 の新しいレスポンスを示していることを確認します。新しい Pod がデプロイされ、GKE 内でヘルスチェックされるため、しばらく時間がかかることがあります。
    while true; do curl -w "\n" http://$PRODUCTION_IP; sleep 1;  done
    
    準備ができたら Ctrl+c を押してループを終了します。お疲れさまでした。アプリを GKE にデプロイするためのブランチとタグ用に、Cloud Build で CI/CD トリガーを作成しました。

8. クリーンアップ

プロジェクトの削除

  1. Cloud コンソールで、[リソースの管理] ページに移動します。
  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。