Spinnaker と Kubernetes Engine を使用した継続的デリバリー パイプライン

このチュートリアルでは、Google Kubernetes Engine(GKE)、Cloud Source Repositories、Cloud Build、Spinnaker を使用して継続的デリバリー パイプラインを作成する方法を説明します。サンプルアプリを作成した後、これらのサービスのビルド、テスト、デプロイが自動的に行われるように構成します。アプリコードを変更すると、継続的デリバリー パイプラインがトリガーされ、新しいバージョンが自動的に再ビルド、再テスト、再デプロイされます。

パイプライン アーキテクチャ

次の図は、継続的デリバリー パイプラインのアーキテクチャを示しています。

デベロッパーとユーザーのためのパイプラインのアーキテクチャ。

アプリ更新をユーザーに継続的に配布するには、ソフトウェアを確実のビルド、テスト、更新を確実に行う自動プロセスが必要です。コード変更は、アーティファクトの作成、単体テスト、機能テスト、本番環境ロールアウトで構成されたパイプラインを自動的に通過する必要があります。場合によっては、コード更新をユーザーベース全体に配布する前にユーザーのサブセットにのみ適用し、実際の動作を確認したいケースもあるでしょう。これらのカナリアテストのいずれかで不十分なことが判明した場合は、ソフトウェア変更を自動的な手順ですばやくロールバックできる必要があります。

GKE と Spinnaker を使用すると、堅牢な継続的デリバリー フローを作成できます。これにより、ソフトウェアを開発して検証したらすぐに出荷できるようになります。迅速な繰り返しが最終目標ですが、各アプリ リビジョンが本番環境ロールアウトの候補になる前に、必ず一連の自動検証を通過する必要があります。特定の変更を自動化によって検査してから、アプリを手動で検証し、さらにプレリリース テストを実施することもできます。

アプリが本番環境用として準備が整ったとチームが判断したら、チームメンバーの 1 人が本番環境デプロイメント用として承認できます。

アプリ デリバリー パイプライン

このチュートリアルでは、次の図に示される継続的デリバリー パイプラインを作成します。

アプリ デリバリー パイプラインのアーキテクチャ。

このパイプラインの手順の概略は次のとおりです。

  1. デベロッパーがコードを変更してリポジトリに push します。

  2. Cloud Build によって、変更が検出され、Docker イメージのビルドとテストが行われてから Spinnaker にイメージが push されます。

  3. Spinnaker はイメージを検出すると、そのイメージを Canary にデプロイして、Canary デプロイメントのテストを行います。手動で承認すると、Spinnaker によってそのイメージが本番環境にデプロイされます。

目標

  • Cloud Shell の起動、GKE クラスタの作成、ID とユーザー管理スキームの構成によって、環境を設定する。
  • サンプルアプリのダウンロード、Git リポジトリの作成、Cloud Source Repositories へのアップロードを行う。
  • Helm を使用して Spinnaker を GKE にデプロイする。
  • Docker イメージをビルドする。
  • アプリが変更されたときに Docker イメージを作成するためのトリガーを作成する。
  • 確実かつ継続的にアプリを GKE にデプロイするように Spinnaker パイプラインを構成する。
  • コード変更をデプロイしてパイプラインをトリガーし、本番環境へのロールアウトを監視する。

料金

このチュートリアルでは、以下を含む Google Cloud Platform(GCP)の課金対象コンポーネントを使用します。

  • GKE
  • Cloud Load Balancing
  • Cloud Build

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを出すことができます。

GCP を初めて使用される方は、無料トライアルをご利用いただけます。

始める前に

  1. Google アカウントにログインします。

    Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。

  2. GCP Console のプロジェクト セレクタのページで、GCP プロジェクトを選択または作成します。

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

  3. Google Cloud Platform プロジェクトに対して課金が有効になっていることを確認します。 詳しくは、課金を有効にする方法をご覧ください。

  4. GKE、Cloud Build、Cloud Source Repositories API を有効にします。

    APIを有効にする

環境の設定

このセクションでは、チュートリアルを実行するために必要なインフラストラクチャと ID を構成します。

Cloud Shell インスタンスを開始して、GKE クラスタを作成する

このチュートリアルでは、Cloud Shell からすべてのデバイス コマンドを実行します。

  1. Cloud Shell を開きます。

    Cloud Shell を開く

  2. 次のコマンドを使用して、Spinnaker とサンプルアプリをデプロイするための GKE クラスタを作成します。

    gcloud config set compute/zone us-central1-f
    
    gcloud container clusters create spinnaker-tutorial \
        --machine-type=n1-standard-2
    

ID およびアクセス管理を構成する

Cloud Identity Access Management(Cloud IAM)サービス アカウントを作成して Spinnaker に権限を委任し、Cloud Storage にデータを保存できるようにします。Spinnaker は、パイプライン データを Cloud Storage に保存することで、信頼性と復元力を確保します。Spinnaker のデプロイメントが予期せず失敗した場合は、オリジナルと同じパイプライン データへのアクセス権を持つ同じデプロイメントを数分で作成できます。

  1. サービス アカウントを作成します。

    gcloud iam service-accounts create  spinnaker-account \
        --display-name spinnaker-account
    
  2. 後のコマンドで使用するために、サービス アカウントのメールアドレスと現在のプロジェクト ID を環境変数に格納します。

    export SA_EMAIL=$(gcloud iam service-accounts list \
        --filter="displayName:spinnaker-account" \
        --format='value(email)')
    export PROJECT=$(gcloud info --format='value(config.project)')
    
  3. storage.admin 役割をサービス アカウントにバインドします。

    gcloud projects add-iam-policy-binding \
        $PROJECT --role roles/storage.admin --member serviceAccount:$SA_EMAIL
    
  4. サービス アカウント キーをダウンロードします。このキーは、後で Spinnaker をインストールするときに GKE にアップロードする必要があります。

    gcloud iam service-accounts keys create spinnaker-sa.json --iam-account $SA_EMAIL
    

Spinnaker パイプラインをトリガーする Cloud Pub/Sub を設定する

  1. Container Registry からの通知に使用する Cloud Pub/Sub トピックを作成します。このコマンドは、「Resource already exists in the project」というエラーによって失敗する場合があります。これは、トピックがすでに作成されていることを意味します。

    gcloud beta pubsub topics create projects/$PROJECT/topics/gcr
    
  2. イメージの push についての通知を受け取れるように、Spinnaker から読み取ることができるサブスクリプションを作成します。

    gcloud beta pubsub subscriptions create gcr-triggers \
        --topic projects/${PROJECT}/topics/gcr
    
  3. Spinnaker のサービス アカウントに、gcr-triggers サブスクリプションからの読み取り権限を付与します。

    export SA_EMAIL=$(gcloud iam service-accounts list \
        --filter="displayName:spinnaker-account" \
        --format='value(email)')
    gcloud beta pubsub subscriptions add-iam-policy-binding gcr-triggers \
        --role roles/pubsub.subscriber --member serviceAccount:$SA_EMAIL
    

Helm を使用した Spinnaker のデプロイ

このセクションでは、Helm を使用して Charts リポジトリから Spinnaker をデプロイします。Helm は、Kubernetes アプリを構成してデプロイできるパッケージ マネージャです。

Helm をインストールする

  1. helm バイナリをダウンロードしてインストールします。

    wget https://storage.googleapis.com/kubernetes-helm/helm-v2.10.0-linux-amd64.tar.gz
    
  2. ファイルをローカル システムに解凍します。

    tar zxfv helm-v2.10.0-linux-amd64.tar.gz
    
    cp linux-amd64/helm .
    
  3. Helm のサーバー側である Tiller に、クラスタ内での cluster-admin 役割を付与します。

    kubectl create clusterrolebinding user-admin-binding --clusterrole=cluster-admin --user=$(gcloud config get-value account)
    kubectl create serviceaccount tiller --namespace kube-system
    kubectl create clusterrolebinding tiller-admin-binding --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
    
  4. Spinnaker に cluster-admin 役割を付与し、すべての名前空間にリソースをデプロイできるようにします。

    kubectl create clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:default spinnaker-admin
    
  5. Helm を初期化して、クラスタに Tiller をインストールします。

    ./helm init --service-account=tiller
    ./helm update
  6. 次のコマンドを実行して、Helm が適切にインストールされていることを確認します。Helm が正しくインストールされている場合は、クライアントとサーバーの両方に v2.10.0 が表示されます。

    ./helm version
    Client: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"}
    Server: &version.Version{SemVer:"v2.10.0", GitCommit:"9ad53aac42165a5fadc6c87be0dea6b115f93090", GitTreeState:"clean"}
    

Spinnaker を構成する

  1. Spinnaker でパイプライン構成を保存するためのバケットを作成します。

    export PROJECT=$(gcloud info \
        --format='value(config.project)')
    export BUCKET=$PROJECT-spinnaker-config
    gsutil mb -c regional -l us-central1 gs://$BUCKET
  2. Spinnaker のインストール方法の構成を記述するファイル(spinnaker-config.yaml)を作成します。

    export SA_JSON=$(cat spinnaker-sa.json)
    export PROJECT=$(gcloud info --format='value(config.project)')
    export BUCKET=$PROJECT-spinnaker-config
    cat > spinnaker-config.yaml <<EOF
    gcs:
      enabled: true
      bucket: $BUCKET
      project: $PROJECT
      jsonKey: '$SA_JSON'
    
    dockerRegistries:
    - name: gcr
      address: https://gcr.io
      username: _json_key
      password: '$SA_JSON'
      email: 1234@5678.com
    
    # Disable minio as the default storage backend
    minio:
      enabled: false
    
    # Configure Spinnaker to enable GCP services
    halyard:
      spinnakerVersion: 1.10.2
      image:
        tag: 1.12.0
      additionalScripts:
        create: true
        data:
          enable_gcs_artifacts.sh: |-
            \$HAL_COMMAND config artifact gcs account add gcs-$PROJECT --json-path /opt/gcs/key.json
            \$HAL_COMMAND config artifact gcs enable
          enable_pubsub_triggers.sh: |-
            \$HAL_COMMAND config pubsub google enable
            \$HAL_COMMAND config pubsub google subscription add gcr-triggers \
              --subscription-name gcr-triggers \
              --json-path /opt/gcs/key.json \
              --project $PROJECT \
              --message-format GCR
    EOF
    

Spinnaker チャートをデプロイする

  1. Helm コマンドライン インターフェースを使用して、作成済みの構成を設定したチャートをデプロイします。このコマンドは通常、完了するまでに 5~10 分程度かかります。

    ./helm install -n cd stable/spinnaker -f spinnaker-config.yaml --timeout 600 \
        --version 1.1.6 --wait
  2. コマンドが完了したら、次のコマンドを実行して、Cloud Shell から Spinnaker UI へのポート転送を設定します。

    export DECK_POD=$(kubectl get pods --namespace default -l "cluster=spin-deck" \
        -o jsonpath="{.items[0].metadata.name}")
    kubectl port-forward --namespace default $DECK_POD 8080:9000 >> /dev/null &
    
  3. Spinnaker ユーザー インターフェースを開くには、Cloud Shell で「ウェブでプレビュー」をクリックし、[プレビューのポート: 8080] をクリックします。

    プレビューが選択されているウェブ プレビューのプルダウン リスト。

  4. ようこそ画面が表示されてから、Spinnaker UI が表示されます。

    挨拶を表示するようこそ画面。

    Spinnaker のホームページ

Docker イメージのビルド

このセクションでは、アプリ ソース コードの変更を検出して Docker イメージをビルドしてから、Container Registry に push するように Cloud Build を構成します。

ソースコード リポジトリを作成する

  1. Cloud Shell で、サンプル ソース コードをダウンロードします。

    wget https://gke-spinnaker.storage.googleapis.com/sample-app-v2.tgz
    
  2. ソースコードを展開します。

    tar xzfv sample-app-v2.tgz
    
  3. ディレクトリをソースコードに変更します。

    cd sample-app
    
  4. このリポジトリの Git commit にユーザー名とメールアドレスを設定します。[EMAIL_ADDRESS] を Git メールアドレスに、[USERNAME] を Git ユーザー名にそれぞれ置き換えます。

    git config --global user.email "[EMAIL_ADDRESS]"
    git config --global user.name "[USERNAME]"
    
  5. ソースコード リポジトリへの最初の commit を行います。

    git init
    git add .
    git commit -m "Initial commit"
    
  6. コードをホストするリポジトリを作成します。

    gcloud source repos create sample-app
    git config credential.helper gcloud.sh
    
  7. 新しく作成したリポジトリをリモートとして追加します。

    export PROJECT=$(gcloud info --format='value(config.project)')
    git remote add origin https://source.developers.google.com/p/$PROJECT/r/sample-app
    
  8. コードを新しいリポジトリのマスター ブランチに push します。

    git push origin master
  9. コンソールにソースコードが表示されることを確認します。

    [ソースコード] ページに移動

ビルドトリガーを構成する

次の図は、このセクションで作成するトリガーです。

Spinnaker のワークフロー

Git タグをソース リポジトリに push するたびに Docker イメージのビルドと push が行われるように Cloud Build を構成します。Cloud Build はソースコードを自動的にチェックアウトして、リポジトリ内の Dockerfile から Docker イメージをビルドし、そのイメージを Container Registry に push します。

  1. GCP Console の [Cloud Build] セクションで、[ビルドトリガー] をクリックします。

    ビルドトリガー ページに移動

  2. [Cloud Source Repositories] を選択し、[続行] をクリックします。

  3. 新しく作成した sample-app リポジトリをリストから選択し、[続行] をクリックします。

  4. 次のトリガー設定を指定します。

    • 名前: sample-app-tags
    • トリガーの種類: タグ
    • タグ(正規表現): v.*
    • ビルド構成: cloudbuild.yaml
    • cloudbuild.yaml の場所: cloudbuild.yaml
  5. [トリガーを作成] をクリックします。

    トリガーを作成するときのトリガー設定。

これ以降、文字 "v" が先頭に付いている Git タグをソースコード リポジトリに push すると、Cloud Build が自動的にアプリをビルドして、Docker イメージとして Container Registry に push します。

Spinnaker で使用するために Kubernetes マニフェストを準備する

Spinnaker は、クラスタにデプロイするために Kubernetes マニフェストにアクセスする必要があります。このセクションでは、Cloud Build での CI プロセス中にマニフェストを保存する Cloud Storage バケットを作成します。マニフェストが Cloud Storage に保存されると、Spinnaker はパイプラインの実行中にマニフェストをダウンロードして適用できます。

  1. バケットを作成します。

    export PROJECT=$(gcloud info --format='value(config.project)')
    gsutil mb -l us-central1 gs://$PROJECT-kubernetes-manifests
    
  2. バケットに対するバージョニングを有効にして、マニフェストの履歴を取得できるようにします。

    gsutil versioning set on gs://$PROJECT-kubernetes-manifests
    
  3. kubernetes デプロイ マニフェストに正しい GCP プロジェクト ID を設定します。

    sed -i s/PROJECT/$PROJECT/g k8s/deployments/*
    
  4. リポジトリへの変更を commit します。

    git commit -a -m "Set project ID"
    

イメージをビルドする

次の手順で最初のイメージを push します。

  1. Cloud Shell でソースコード フォルダに移動します。
  2. Git タグを作成します。

    git tag v1.0.0
  3. タグを push します。

    git push --tags
  4. [Cloud Build] で [履歴] をクリックし、ビルドがトリガーされたことを確認します。トリガーされていない場合は、前のセクションでトリガーが適切に構成されたことを確認します。

    ビルド履歴に移動

    ビルド履歴

デプロイメント パイプラインの設定

これでイメージが自動的にビルドされるようになりました。それらを Kubernetes クラスタにデプロイする必要があります。

次の図は、デプロイメント パイプラインの手順を示しています。

デプロイメント パイプラインを構成する

統合テストに備えてスケールダウンされた環境にデプロイします。統合テストに合格したら、コードを本番環境サービスにデプロイするための変更を手動で承認する必要があります。

Spinnaker を管理する spin CLI をインストールする

Spin は、Spinnaker のアプリケーションとパイプラインを管理するコマンドライン ユーティリティです。

  1. spin の最新バージョンをダウンロードします。

    curl -LO https://storage.googleapis.com/spinnaker-artifacts/spin/1.5.2/linux/amd64/spin
    
  2. spin を実行可能にします。

    chmod +x spin
    

デプロイメント パイプラインを作成する

  1. spin を使用して Spinnaker でアプリを作成します。

    ./spin application save --application-name sample \
                            --owner-email example@example.com \
                            --cloud-providers kubernetes \
                            --gate-endpoint http://localhost:8080/gate
    

次に、継続的デリバリー パイプラインを作成します。このチュートリアルでは、"v" という接頭辞が付いた Docker イメージが Container Registry に到着したことを検出するようにパイプラインが構成されます。

  1. Cloud Shell の新しいタブで、ソースコード ディレクトリで次のコマンドを実行し、パイプラインの例を Spinnaker インスタンスにアップロードします。

    export PROJECT=$(gcloud info --format='value(config.project)')
    sed s/PROJECT/$PROJECT/g spinnaker/pipeline-deploy.json > pipeline.json
    ./spin pipeline save --gate-endpoint http://localhost:8080/gate -f pipeline.json
    

パイプラインの実行を表示する

作成した構成は、Spinnaker パイプラインをトリガーするためにプッシュされる新しくタグ付けされたイメージの通知を使用します。前のステップでは、タグを Cloud Source Repositories に push しました。これによって、Cloud Build でイメージの構築と Container Registry への push がトリガーされます。これで、トリガーされたパイプラインを確認できるようになります。

  1. [パイプライン] をクリックして、パイプラインのページに戻ります。

  2. [詳細] をクリックして、パイプラインの進行状況の詳細を表示します。このセクションで、デプロイメント パイプラインのステータスとそのステップを確認できます。青色のステップは現在実行中です。緑色は正常に完了したステップ、赤色は失敗したステップを示します。ステージをクリックして、その詳細を表示します。

    3~5 分後に統合テストフェーズが完了し、デプロイメント続行のための手動承認をパイプラインから要求されます。

  3. [Push to production] の上にポインタを置き、[Continue] をクリックします。

    ロールアウトが本番環境フロントエンドと本番環境バックエンドのデプロイメントに進みます。これは数分で完了します。

  4. Spinnaker UI で [インフラストラクチャ] > [ロードバランサ] をクリックして、アプリを表示します。

    ロードバランサが選択された [インフラストラクチャ] プルダウン リスト。

  5. ロードバランサのリストを下にスクロールし、[sample-frontend-production] の下の [デフォルト] をクリックします。

    デフォルトのロードバランサ

  6. 右側の詳細ウィンドウを下にスクロールし、Ingress IP のクリップボード ボタンをクリックしてアプリの IP アドレスをコピーします。Spinnaker UI からの上り IP リンクはデフォルトで HTTPS を使用しますが、アプリケーションは HTTP を使用するように構成されています。

    アプリの IP アドレスを含む詳細ペイン。

  7. アドレスをブラウザに貼り付けて、アプリの本番環境バージョンを表示します。

    アプリの本番環境バージョン。

    これで、アプリをビルド、テスト、デプロイするためのパイプラインを手動でトリガーしました。

コードの変更によるパイプラインのトリガー

このセクションでは、コードの変更、Git タグの push、レスポンスでのパイプライン実行の監視を通して、パイプラインをエンドツーエンドでテストします。"v" で始まる Git タグを push すると、新しい Docker イメージをビルドして Container Registry に push するための Cloud Build がトリガーされます。Spinnaker は新しいイメージタグが "v" で始まることを検出すると、イメージをカナリアにデプロイしてテストを実行し、同じイメージをデプロイメント内のすべてのポッドにロールアウトするためのパイプラインをトリガーします。

  1. アプリケーションの色をオレンジ色から青色に変更します。

    sed -i 's/orange/blue/g' cmd/gke-info/common-service.go
    
  2. 変更にタグを付け、ソースコード リポジトリに push します。

    git commit -a -m "Change color to blue"
    git tag v1.0.1
    git push --tags
    
  3. 新しいビルドが Cloud Build のビルド履歴に表示されます。

  4. [パイプライン] をクリックして、パイプラインがイメージのデプロイを開始するのを監視します。

  5. Canary のデプロイを観察します。デプロイが一時停止され、本番環境へのロールアウトを待機している間に、アプリを含むタブの更新を開始します。バックエンドのうちの 4 つがアプリの以前のバージョンを実行しており、カナリアを実行しているバックエンドは 1 つだけです。10 回更新するごとにアプリの新しい青色バージョンが表示されます。

  6. テストが完了したら、[Spinnaker] タブに戻り、デプロイを承認します。

  7. パイプラインが完了すると、アプリは次のスクリーンショットのようになります。バージョン フィールドには、v1.0.1 と表示されます。

    更新されたアプリの本番環境バージョン。

    これで、アプリを本番環境全体に正常にロールアウトできました。

  8. 必要に応じて前回の commit を元に戻し、この変更をロールバックできます。ロールバックすると新しいタグ (v1.0.2)が追加され、v1.0.1 をデプロイするときに使用したのと同じパイプラインを通してタグが戻されます。

    git revert v1.0.1
    git tag v1.0.2
    git push --tags

クリーンアップ

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

  1. Spinnaker のインストールを削除します。

    ../helm delete --purge cd
    
  2. サンプル アプリケーション サービスを削除します。

    kubectl delete -f k8s/services
    
  3. サービス アカウントの IAM バインディングを削除します。

    export SA_EMAIL=$(gcloud iam service-accounts list \
        --filter="displayName:spinnaker-account" --format='value(email)')
    export PROJECT=$(gcloud info --format='value(config.project)')
    gcloud projects remove-iam-policy-binding $PROJECT --role roles/storage.admin --member serviceAccount:$SA_EMAIL
    
  4. サービス アカウントを削除します。

    export SA_EMAIL=$(gcloud iam service-accounts list \
        --filter="displayName:spinnaker-account" --format='value(email)')
    gcloud iam service-accounts delete $SA_EMAIL
    
  5. GKE クラスタを削除します。

    gcloud container clusters delete spinnaker-tutorial --zone=us-central1-f
    
  6. リポジトリを削除します。

    gcloud source repos delete sample-app
    
  7. バケットを削除します。

    export PROJECT=$(gcloud info --format='value(config.project)')
    export BUCKET=$PROJECT-spinnaker-config
    gsutil -m rm -r gs://$BUCKET
    
  8. コンテナ イメージを削除します。

    export PROJECT=$(gcloud info --format='value(config.project)')
    gcloud container images delete gcr.io/$PROJECT/sample-app:v1.0.0
    gcloud container images delete gcr.io/$PROJECT/sample-app:v1.0.1
    
  9. 上記のオプションのロールバック ステップで v1.0.2 を作成した場合は、そのコンテナ イメージを削除します。

    gcloud container images delete gcr.io/$PROJECT/sample-app:v1.0.2
    

次のステップ

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...