このチュートリアルでは、Google Kubernetes Engine(GKE)、Cloud Source Repositories、Cloud Build、Spinnaker を使用して継続的デリバリー パイプラインを作成する方法を説明します。サンプルアプリを作成した後、これらのサービスのビルド、テスト、デプロイが自動的に行われるように構成します。アプリコードを変更すると、継続的デリバリー パイプラインがトリガーされ、新しいバージョンが自動的に再ビルド、再テスト、再デプロイされます。
パイプライン アーキテクチャ
次の図は、継続的デリバリー パイプラインのアーキテクチャを示しています。
アプリ更新をユーザーに継続的に配布するには、ソフトウェアを確実のビルド、テスト、更新を確実に行う自動プロセスが必要です。コード変更は、アーティファクトの作成、単体テスト、機能テスト、本番環境ロールアウトで構成されたパイプラインを自動的に通過する必要があります。場合によっては、コード更新をユーザーベース全体に配布する前にユーザーのサブセットにのみ適用し、実際の動作を確認したいケースもあるでしょう。これらのカナリアテストのいずれかで不十分なことが判明した場合は、ソフトウェア変更を自動的な手順ですばやくロールバックできる必要があります。
GKE と Spinnaker を使用すると、堅牢な継続的デリバリー フローを作成できます。これにより、ソフトウェアを開発して検証したらすぐに出荷できるようになります。迅速な繰り返しが最終目標ですが、各アプリ リビジョンが本番環境ロールアウトの候補になる前に、必ず一連の自動検証を通過する必要があります。特定の変更を自動化によって検査してから、アプリを手動で検証し、さらにプレリリース テストを実施することもできます。
アプリが本番環境用として準備が整ったとチームが判断したら、チームメンバーの 1 人が本番環境デプロイメント用として承認できます。
アプリ デリバリー パイプライン
このチュートリアルでは、次の図に示される継続的デリバリー パイプラインを作成します。
このパイプラインの手順の概略は次のとおりです。
デベロッパーがコードを変更してリポジトリに push します。
Cloud Build によって、変更が検出され、Docker イメージのビルドとテストが行われてから Spinnaker にイメージが push されます。
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 を初めて使用される方は、無料トライアルをご利用いただけます。始める前に
-
Google アカウントにログインします。
Google アカウントをまだお持ちでない場合は、新しいアカウントを登録します。
-
GCP Console のプロジェクト セレクタのページで、GCP プロジェクトを選択または作成します。
-
Google Cloud Platform プロジェクトに対して課金が有効になっていることを確認します。 詳しくは、課金を有効にする方法をご覧ください。
- GKE、Cloud Build、Cloud Source Repositories API を有効にします。
環境の設定
このセクションでは、チュートリアルを実行するために必要なインフラストラクチャと ID を構成します。
Cloud Shell インスタンスを開始して、GKE クラスタを作成する
このチュートリアルでは、Cloud Shell からすべてのデバイス コマンドを実行します。
Cloud Shell を開きます。
次のコマンドを使用して、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 のデプロイメントが予期せず失敗した場合は、オリジナルと同じパイプライン データへのアクセス権を持つ同じデプロイメントを数分で作成できます。
サービス アカウントを作成します。
gcloud iam service-accounts create spinnaker-account \ --display-name spinnaker-account
後のコマンドで使用するために、サービス アカウントのメールアドレスと現在のプロジェクト ID を環境変数に格納します。
export SA_EMAIL=$(gcloud iam service-accounts list \ --filter="displayName:spinnaker-account" \ --format='value(email)') export PROJECT=$(gcloud info --format='value(config.project)')
storage.admin
役割をサービス アカウントにバインドします。gcloud projects add-iam-policy-binding \ $PROJECT --role roles/storage.admin --member serviceAccount:$SA_EMAIL
サービス アカウント キーをダウンロードします。このキーは、後で Spinnaker をインストールするときに GKE にアップロードする必要があります。
gcloud iam service-accounts keys create spinnaker-sa.json --iam-account $SA_EMAIL
Spinnaker パイプラインをトリガーする Cloud Pub/Sub を設定する
Container Registry からの通知に使用する Cloud Pub/Sub トピックを作成します。このコマンドは、「Resource already exists in the project」というエラーによって失敗する場合があります。これは、トピックがすでに作成されていることを意味します。
gcloud beta pubsub topics create projects/$PROJECT/topics/gcr
イメージの push についての通知を受け取れるように、Spinnaker から読み取ることができるサブスクリプションを作成します。
gcloud beta pubsub subscriptions create gcr-triggers \ --topic projects/${PROJECT}/topics/gcr
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 をインストールする
helm
バイナリをダウンロードしてインストールします。wget https://storage.googleapis.com/kubernetes-helm/helm-v2.10.0-linux-amd64.tar.gz
ファイルをローカル システムに解凍します。
tar zxfv helm-v2.10.0-linux-amd64.tar.gz
cp linux-amd64/helm .
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
Spinnaker に
cluster-admin
役割を付与し、すべての名前空間にリソースをデプロイできるようにします。kubectl create clusterrolebinding --clusterrole=cluster-admin --serviceaccount=default:default spinnaker-admin
Helm を初期化して、クラスタに Tiller をインストールします。
./helm init --service-account=tiller
./helm update
次のコマンドを実行して、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 を構成する
Spinnaker でパイプライン構成を保存するためのバケットを作成します。
export PROJECT=$(gcloud info \ --format='value(config.project)') export BUCKET=$PROJECT-spinnaker-config gsutil mb -c regional -l us-central1 gs://$BUCKET
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 チャートをデプロイする
Helm コマンドライン インターフェースを使用して、作成済みの構成を設定したチャートをデプロイします。このコマンドは通常、完了するまでに 5~10 分程度かかります。
./helm install -n cd stable/spinnaker -f spinnaker-config.yaml --timeout 600 \ --version 1.1.6 --wait
コマンドが完了したら、次のコマンドを実行して、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 &
Spinnaker ユーザー インターフェースを開くには、Cloud Shell で「ウェブでプレビュー」をクリックし、[プレビューのポート: 8080] をクリックします。
ようこそ画面が表示されてから、Spinnaker UI が表示されます。
Docker イメージのビルド
このセクションでは、アプリ ソース コードの変更を検出して Docker イメージをビルドしてから、Container Registry に push するように Cloud Build を構成します。
ソースコード リポジトリを作成する
Cloud Shell で、サンプル ソース コードをダウンロードします。
wget https://gke-spinnaker.storage.googleapis.com/sample-app-v2.tgz
ソースコードを展開します。
tar xzfv sample-app-v2.tgz
ディレクトリをソースコードに変更します。
cd sample-app
このリポジトリの Git commit にユーザー名とメールアドレスを設定します。
[EMAIL_ADDRESS]
を Git メールアドレスに、[USERNAME]
を Git ユーザー名にそれぞれ置き換えます。git config --global user.email "[EMAIL_ADDRESS]" git config --global user.name "[USERNAME]"
ソースコード リポジトリへの最初の commit を行います。
git init git add . git commit -m "Initial commit"
コードをホストするリポジトリを作成します。
gcloud source repos create sample-app git config credential.helper gcloud.sh
新しく作成したリポジトリをリモートとして追加します。
export PROJECT=$(gcloud info --format='value(config.project)') git remote add origin https://source.developers.google.com/p/$PROJECT/r/sample-app
コードを新しいリポジトリのマスター ブランチに push します。
git push origin master
コンソールにソースコードが表示されることを確認します。
ビルドトリガーを構成する
次の図は、このセクションで作成するトリガーです。
Git タグをソース リポジトリに push するたびに Docker イメージのビルドと push が行われるように Cloud Build を構成します。Cloud Build はソースコードを自動的にチェックアウトして、リポジトリ内の Dockerfile から Docker イメージをビルドし、そのイメージを Container Registry に push します。
GCP Console の [Cloud Build] セクションで、[ビルドトリガー] をクリックします。
[Cloud Source Repositories] を選択し、[続行] をクリックします。
新しく作成した
sample-app
リポジトリをリストから選択し、[続行] をクリックします。次のトリガー設定を指定します。
- 名前:
sample-app-tags
- トリガーの種類: タグ
- タグ(正規表現):
v.*
- ビルド構成:
cloudbuild.yaml
- cloudbuild.yaml の場所:
cloudbuild.yaml
- 名前:
[トリガーを作成] をクリックします。
これ以降、文字 "v" が先頭に付いている Git タグをソースコード リポジトリに push すると、Cloud Build が自動的にアプリをビルドして、Docker イメージとして Container Registry に push します。
Spinnaker で使用するために Kubernetes マニフェストを準備する
Spinnaker は、クラスタにデプロイするために Kubernetes マニフェストにアクセスする必要があります。このセクションでは、Cloud Build での CI プロセス中にマニフェストを保存する Cloud Storage バケットを作成します。マニフェストが Cloud Storage に保存されると、Spinnaker はパイプラインの実行中にマニフェストをダウンロードして適用できます。
バケットを作成します。
export PROJECT=$(gcloud info --format='value(config.project)') gsutil mb -l us-central1 gs://$PROJECT-kubernetes-manifests
バケットに対するバージョニングを有効にして、マニフェストの履歴を取得できるようにします。
gsutil versioning set on gs://$PROJECT-kubernetes-manifests
kubernetes デプロイ マニフェストに正しい GCP プロジェクト ID を設定します。
sed -i s/PROJECT/$PROJECT/g k8s/deployments/*
リポジトリへの変更を commit します。
git commit -a -m "Set project ID"
イメージをビルドする
次の手順で最初のイメージを push します。
- Cloud Shell でソースコード フォルダに移動します。
Git タグを作成します。
git tag v1.0.0
タグを push します。
git push --tags
[Cloud Build] で [履歴] をクリックし、ビルドがトリガーされたことを確認します。トリガーされていない場合は、前のセクションでトリガーが適切に構成されたことを確認します。
デプロイメント パイプラインの設定
これでイメージが自動的にビルドされるようになりました。それらを Kubernetes クラスタにデプロイする必要があります。
次の図は、デプロイメント パイプラインの手順を示しています。
統合テストに備えてスケールダウンされた環境にデプロイします。統合テストに合格したら、コードを本番環境サービスにデプロイするための変更を手動で承認する必要があります。
Spinnaker を管理する spin CLI をインストールする
Spin は、Spinnaker のアプリケーションとパイプラインを管理するコマンドライン ユーティリティです。
spin
の最新バージョンをダウンロードします。curl -LO https://storage.googleapis.com/spinnaker-artifacts/spin/1.5.2/linux/amd64/spin
spin
を実行可能にします。chmod +x spin
デプロイメント パイプラインを作成する
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 に到着したことを検出するようにパイプラインが構成されます。
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 がトリガーされます。これで、トリガーされたパイプラインを確認できるようになります。
[パイプライン] をクリックして、パイプラインのページに戻ります。
[詳細] をクリックして、パイプラインの進行状況の詳細を表示します。このセクションで、デプロイメント パイプラインのステータスとそのステップを確認できます。青色のステップは現在実行中です。緑色は正常に完了したステップ、赤色は失敗したステップを示します。ステージをクリックして、その詳細を表示します。
3~5 分後に統合テストフェーズが完了し、デプロイメント続行のための手動承認をパイプラインから要求されます。
[Push to production] の上にポインタを置き、[Continue] をクリックします。
ロールアウトが本番環境フロントエンドと本番環境バックエンドのデプロイメントに進みます。これは数分で完了します。
Spinnaker UI で [インフラストラクチャ] > [ロードバランサ] をクリックして、アプリを表示します。
ロードバランサのリストを下にスクロールし、[sample-frontend-production] の下の [デフォルト] をクリックします。
右側の詳細ウィンドウを下にスクロールし、Ingress IP のクリップボード ボタンをクリックしてアプリの IP アドレスをコピーします。Spinnaker UI からの上り IP リンクはデフォルトで HTTPS を使用しますが、アプリケーションは HTTP を使用するように構成されています。
アドレスをブラウザに貼り付けて、アプリの本番環境バージョンを表示します。
これで、アプリをビルド、テスト、デプロイするためのパイプラインを手動でトリガーしました。
コードの変更によるパイプラインのトリガー
このセクションでは、コードの変更、Git タグの push、レスポンスでのパイプライン実行の監視を通して、パイプラインをエンドツーエンドでテストします。"v" で始まる Git タグを push すると、新しい Docker イメージをビルドして Container Registry に push するための Cloud Build がトリガーされます。Spinnaker は新しいイメージタグが "v" で始まることを検出すると、イメージをカナリアにデプロイしてテストを実行し、同じイメージをデプロイメント内のすべてのポッドにロールアウトするためのパイプラインをトリガーします。
アプリケーションの色をオレンジ色から青色に変更します。
sed -i 's/orange/blue/g' cmd/gke-info/common-service.go
変更にタグを付け、ソースコード リポジトリに push します。
git commit -a -m "Change color to blue" git tag v1.0.1 git push --tags
新しいビルドが Cloud Build のビルド履歴に表示されます。
[パイプライン] をクリックして、パイプラインがイメージのデプロイを開始するのを監視します。
Canary のデプロイを観察します。デプロイが一時停止され、本番環境へのロールアウトを待機している間に、アプリを含むタブの更新を開始します。バックエンドのうちの 4 つがアプリの以前のバージョンを実行しており、カナリアを実行しているバックエンドは 1 つだけです。10 回更新するごとにアプリの新しい青色バージョンが表示されます。
テストが完了したら、[Spinnaker] タブに戻り、デプロイを承認します。
パイプラインが完了すると、アプリは次のスクリーンショットのようになります。バージョン フィールドには、
v1.0.1
と表示されます。これで、アプリを本番環境全体に正常にロールアウトできました。
必要に応じて前回の commit を元に戻し、この変更をロールバックできます。ロールバックすると新しいタグ
(v1.0.2
)が追加され、v1.0.1
をデプロイするときに使用したのと同じパイプラインを通してタグが戻されます。git revert v1.0.1 git tag v1.0.2 git push --tags
クリーンアップ
このチュートリアルで使用するリソースについて、Google Cloud Platform アカウントに課金されないようにする手順は次のとおりです。
Spinnaker のインストールを削除します。
../helm delete --purge cd
サンプル アプリケーション サービスを削除します。
kubectl delete -f k8s/services
サービス アカウントの 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
サービス アカウントを削除します。
export SA_EMAIL=$(gcloud iam service-accounts list \ --filter="displayName:spinnaker-account" --format='value(email)') gcloud iam service-accounts delete $SA_EMAIL
GKE クラスタを削除します。
gcloud container clusters delete spinnaker-tutorial --zone=us-central1-f
リポジトリを削除します。
gcloud source repos delete sample-app
バケットを削除します。
export PROJECT=$(gcloud info --format='value(config.project)') export BUCKET=$PROJECT-spinnaker-config gsutil -m rm -r gs://$BUCKET
コンテナ イメージを削除します。
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
上記のオプションのロールバック ステップで
v1.0.2
を作成した場合は、そのコンテナ イメージを削除します。gcloud container images delete gcr.io/$PROJECT/sample-app:v1.0.2
次のステップ
- Spinnaker に既存の Google Kubernetes Engine クラスタを登録する。
- Jenkins による継続的デプロイメントについて理解する。
- Jenkins を GKE にデプロイする。
- Spinnaker の Kubernetes プロバイダについて学習する。
- Google Cloud Platform のその他の機能を試す。チュートリアルをご覧ください。