こんにちは、株式会社QualiArts技術開発室でゲーム基盤を担当している曹 (ジョ)です。今回の記事は先日紹介したGCPのCloud Buildを使おうという記事の後編で、Cloud Buildを活用してプロジェクトのCI/CDを完全に自動化することを目指します。

始める前に

今回の活用編でもGCPのCloud Buildを利用する為、下記のものを事前に準備しておく必要があります。

※下記、設定方法は省略させて頂きます。

今回の内容について

今回はCloud Buildを利用して、ソースリポジトリにPushすると自動的にDeployまでできることを目標にします。その目標を達成する為、説明する内容は下記となります。

※今回のソースリポジトリは前回の記事で利用してリポジトリを再利用します。

※自分のgithubのアカウントに今回使ったsample(ソースdevops)を公開しておきましたので、参照してください。

  • ソースリポジトリに各環境のブランチの設定
  • Devopsリポジトリの準備
  • 各環境用のGKE Clusterを作成と設定
  • ソースリポジトリとDevopsリポジトリの連携
  • ソースリポジトリへPushされた場合、DockerイメージをBuild & Pushできるように設定
  • DevopsリポジトリにTagが登録された場合、そのTagを利用してアプリをDeployできるように設定
  • 修正内容をソースリポジトリのdevelopブランチにPush後、Depoy結果確認
  • ソースリポジトリのstagingブランチへマージ後、Depoy結果確認
  • ソースリポジトリのmasterブランチへマージ後、Depoy結果確認
  • おまけ:手動でDEPLOYする方法

今回、話す内容を図として表すと下記となります。

この図に目を通しておくて、今回の記事の内容がもっと理解しやすいと思います。

cloud-build-auto

 

ソースリポジトリに各環境のブランチの設定

ソースリポジトリはGCPのCloud Buildを使おうで利用した「cb-sample-server」を再利用します。そのリポジトリに各環境で利用するブランチを用意します。

  • develop : 開発環境で利用します。
  • staging : ステージング環境で利用します。
  • master : 本番環境で利用します。

上記、3つのブランチをgithubのソースレポジトリに追加してください。

※masterブランチはすでにあると思いますので、その場合、developとstagingの追加で結構です。

 

Devopsリポジトリの準備

ソースと各環境の設定(開発環境, ステージング環境, 本番環境)を分離して運用したいのでDevopsリポジトリを用意します。その名前は「cb-sample-server-devops」としましょう。Devopsリポジトリの役割は下記となります。

※devopsリポジトリ作成手順は省略致します。

  • 各環境の設定ファイルの管理
  • Deployで利用するためのタグ登録

各環境の設定ファイルの準備

まずは各環境で利用する設定ファイルを下記のように用意します。

このconfig設定ファイルは単純で各環境を表示する設定が入ってます。

開発環境の設定ファイル(dev-config.yaml)

serverInfo:
  envName: dev

ステージング環境の設定ファイル(stg-config.yaml)

serverInfo:
  envName: stg

本番環境の設定ファイル(prd-config.yaml)

serverInfo:
  envName: prd

Deploy関連ファイルの準備

アプリをdeployするときにdeployment.yamlとservice.yamlを利用しますので、追加しておきます。

deployment.yamlの追加

config.yamlの設定場所はKubernetesのVolumeになりますので、関連情報をあらかじめ追加しておきましょう

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: cb-sample-server
spec:
  replicas: 1
  selector:
    matchLabels:
      name: cb-sample-server
  template:
    metadata:
      labels:
        name: cb-sample-server
        cluster_name: cb-sample-server
    spec:
      containers:
      - name: cb-sample-server
        image: gcr.io/${PROJECT_ID}/cb-sample-server:latest
        ports:
        - containerPort: 8080
          protocol: TCP
        # config用volumeMount追加
        volumeMounts:
        - mountPath: /usr/local/config
          name: config
      # config用volume設定    
      volumes:
      - name: config
        configMap:
          name: server-config
  revisionHistoryLimit: 100

service.yamlの追加

cb-sample-serverリポジトリにあるものをそのまま利用します。

追加後構成は下記のような感じです。

$ tree
.
├── config
│ ├── dev-config.yaml
│ ├── prd-config.yaml
│ └── stg-config.yaml
├── deployment.yaml
└── service.yaml

1 directory, 5 files

 

各環境用のGKE Clusterを作成と設定

今回は開発、ステージング、本番、3つの環境を利用しますので、予め、各GKE clusterを作成して、設定しておきましょう。

※clusterはGCP上のGKEを利用します。GKE cluster作成の手順は省略致します。

開発用cluster作成

  • name : dev-cb-sample-server
  • location type : Zonal
  • zone : asia-northeast1-a

configファイル利用のためのconfigmap作成

$ cd ~/cb-sample-server-devops/config
$ gcloud container clusters get-credentials dev-cb-sample-server --zone asia-northeast1-a --project [PROJECT_ID]
$ kubectl create configmap server-config --from-file=config.yaml=dev-config.yaml

ステージング用Cluster作成

  • name : stg-cb-sample-server
  • location type : Zonal
  • zone : asia-northeast1-b

configファイル利用のためのconfigmap作成

$ cd ~/cb-sample-server-devops/config
$ gcloud container clusters get-credentials stg-cb-sample-server --zone asia-northeast1-b --project [PROJECT_ID]
$ kubectl create configmap server-config --from-file=config.yaml=stg-config.yaml

本番用Cluster作成と設定

  • name : prd-cb-sample-server
  • location type : Zonal
  • zone : asia-northeast1-c

configファイル利用のためのconfigmap作成

$ cd ~/cb-sample-server-devops/config
$ gcloud container clusters get-credentials prd-cb-sample-server --zone asia-northeast1-c --project [PROJECT_ID]
$ kubectl create configmap server-config --from-file=config.yaml=prd-config.yaml

 

ソースリポジトリとDevopsリポジトリの連携

ソースリポジトリに更新内容をPushするとCloud Buildの該当トリガーが実行されアプリのTestとBuildしたあと、Docker ImageのBuildとPushを行います。そのあと、devopsリポジトリにtagを登録すると、Cloud Buildの該当トリガーが実行されアプリをdeployします。なので、ソースリポジトリを利用するCloud Buildのトリガーの設定ファイルにdevopsリポジトリにアクセスと書き込み権限を設定する必要があります。その設定は下記となります。

  1. ssh鍵(private keyとpublic key)の用意
  2. public keyをdevopsリポジトリのdeploy keyとして登録
  3. GCPのKMS設定
  4. ソースリポジトリのcloudbuild.yamlファイルにdevopsリポジトリ取得ステップの設定追加

1から3の手順はこちらを参照してください。

RSA鍵生成とkms関連設定は下記となります。

$ ssh-keygen -t rsa -b 4096 -C "devops@casampleserver.com"
Generating public/private rsa key pair.
Enter file in which to save the key (~/.ssh/id_rsa): cb-sample-server-devops-github-rsa
$ gcloud kms keyrings create cb-sample-server-devops-keyring --location=global
$ gcloud kms keys create cb-sample-server-devops-github-key --location=global --keyring=cb-sample-server-devops-keyring --purpose=encryption
$ gcloud kms encrypt --plaintext-file=cb-sample-server-devops-github-rsa --ciphertext-file=cb-sample-server-devops-github-rsa.enc --location=global --keyring=cb-sample-server-devops-keyring --key=cb-sample-server-devops-github-key
$ ssh-keyscan -t rsa github.com > known_hosts

※githubのdevopsリポジトリにdeploy KEYを登録するときは書き込み権限にチェックすることはお忘れずに

github-deploykey-set

4. ソースリポジトリのcloudbuild.yamlファイルにdevopsリポジトリ取得ステップの設定追加

1~3で設定した内容の上でcloudbuild.yaml下記を追加します。詳細は後述のcloudbuild設定を参照してください。

steps:
 - id: Decrypt ssh key
 name: 'gcr.io/cloud-builders/gcloud'
 args:
 - kms
 - decrypt
 - --ciphertext-file=cb-sample-server-devops-github-rsa.enc
 - --plaintext-file=/root/.ssh/cb-sample-server-devops-github-rsa
 - --location=global
 - --keyring=cb-sample-server-devops-keyring
 - --key=cb-sample-server-devops-github-key
 volumes:
 - name: 'ssh'
 path: /root/.ssh
 # Set up git with key and domain.
 - id: Move rsa file
 name: 'gcr.io/cloud-builders/git'
 entrypoint: 'bash'
 args:
 - '-c'
 - |
 chmod 600 cb-sample-server-devops-github-rsa
 mv cb-sample-server-devops-github-rsa /root/.ssh/cb-sample-server-devops-github-rsa
 cat <<EOF >/root/.ssh/config
 Hostname github.com
 IdentityFile /root/.ssh/cb-sample-server-devops-github-rsa
 EOF
 mv known_hosts /root/.ssh/known_hosts
 volumes:
 - name: 'ssh'
 path: /root/.ssh
 - id: Clone devops from github
 name: 'gcr.io/cloud-builders/git'
 args: ['clone', 'git@github.com:QualiArts/cb-sample-server-devops.git']
 volumes:
 - name: 'ssh'
 path: /root/.ssh
...他のstepsの設定内容...

 

ソースリポジトリへPushされた場合、DockerイメージをBuild & Pushできるように設定

ソースリポジトリに修正がPUSHされた場合、Docker イメージをBuildしてGCPのContainer RegistryにPushするように設定しましょう。Docker イメージのタグは下記となります。

  • 開発環境:dev-XXXXXXX(gitコミットのSHORT SHAの値)
  • ステージング環境:stg-XXXXXXX(gitコミットのSHORT SHAの値)
  • 本番環境:prd-XXXXXXX(gitコミットのSHORT SHAの値)

開発用cloudbuild.yamlの作成

developブランチにpushされると実行されるCloudBuildトリガーのビルド設定ファイルは「dev.cloudbuild.yaml」として保存しましょう

steps:
  # devopsリポジトリ利用のためsshキーを復号
  - id: Decrypt ssh key
    name: 'gcr.io/cloud-builders/gcloud'
    args:
    - kms
    - decrypt
    - --ciphertext-file=cb-sample-server-devops-github-rsa.enc
    - --plaintext-file=/root/.ssh/cb-sample-server-devops-github-rsa
    - --location=global
    - --keyring=cb-sample-server-devops-keyring
    - --key=cb-sample-server-devops-github-key
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # devopsリポジトリ利用のためrsaキーを設定
  - id: Move rsa file
    name: 'gcr.io/cloud-builders/git'
    entrypoint: 'bash'
    args:
    - '-c'
    - |
      chmod 600 cb-sample-server-devops-github-rsa
      mv cb-sample-server-devops-github-rsa /root/.ssh/cb-sample-server-devops-github-rsa
      cat <<EOF >/root/.ssh/config
      Hostname github.com
      IdentityFile /root/.ssh/cb-sample-server-devops-github-rsa
      EOF
      mv known_hosts /root/.ssh/known_hosts
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # devops リポジトリをcloneする
  - id: Clone devops from github
    name: 'gcr.io/cloud-builders/git'
    args: ['clone', 'git@github.com:QualiArts/cb-sample-server-devops.git']
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # 新しいDockerイメージを作成します。
  - id: Build Docker Image of API
    name: 'gcr.io/cloud-builders/docker'
    args: ['build', '--tag=asia.gcr.io/$PROJECT_ID/cb-sample-server:$_ENV-$SHORT_SHA', '.']
  # BuildしたイメージをPush
  - id: Push Docker Image of API
    name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'asia.gcr.io/$PROJECT_ID/cb-sample-server']
  # devopsリポジトリに登録するTagを作成する
  - id: Create Tag
    name: 'gcr.io/cloud-builders/git'
    dir: cb-sample-server-devops
    args: ['tag', '--force', '$_ENV-$SHORT_SHA']
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # $_ENV-commitID tagを作成します。これでDeployが実行されます。
  - id: Push Tag to devops repository
    name: 'gcr.io/cloud-builders/git'
    dir: cb-sample-server-devops
    args: ['push', 'origin', '$_ENV-$SHORT_SHA']
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # 削除まで5秒ぐらい待ちます
  - id: Sleep 5 seconds
    name: 'ubuntu'
    args: ['sleep', '5']
    timeout: 6s
  # 作成したtagを削除します。(tagが増えること防止するためです。)
  - id: Delete git tag
    dir: cb-sample-server-devops
    name: 'gcr.io/cloud-builders/git'
    args: ['tag', '-d', '$_ENV-$SHORT_SHA']
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # 削除tagをdevopsリポジトリにpushする      
  - id: Delete git tag push
    dir: cb-sample-server-devops
    name: 'gcr.io/cloud-builders/git'
    args: ['push', 'origin', ':refs/tags/$_ENV-$SHORT_SHA']
    volumes:
    - name: 'ssh'
      path: /root/.ssh

ステージング、本番環境用cloudbuild.yamlの作成

stagingとmasterブランチにpushされると実行されるCloudBuildトリガーのビルド設定ファイルは「cloudbuild.yaml」として保存しましょう

steps:
  # devopsリポジトリ利用のためsshキーを復号
  - id: Decrypt ssh key
    name: 'gcr.io/cloud-builders/gcloud'
    args:
    - kms
    - decrypt
    - --ciphertext-file=cb-sample-server-devops-github-rsa.enc
    - --plaintext-file=/root/.ssh/cb-sample-server-devops-github-rsa
    - --location=global
    - --keyring=cb-sample-server-devops-keyring
    - --key=cb-sample-server-devops-github-key
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # devopsリポジトリ利用のためrsaキーを設定
  - id: Set rsa file
    name: 'gcr.io/cloud-builders/git'
    entrypoint: 'bash'
    args:
    - '-c'
    - |
      chmod 600 cb-sample-server-devops-github-rsa
      mv cb-sample-server-devops-github-rsa /root/.ssh/cb-sample-server-devops-github-rsa
      cat <<EOF >/root/.ssh/config
      Hostname github.com
      IdentityFile /root/.ssh/cb-sample-server-devops-github-rsa
      EOF
      mv known_hosts /root/.ssh/known_hosts
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # devops リポジトリをcloneする    
  - id: Clone devops from github
    name: 'gcr.io/cloud-builders/git'
    args: ['clone', 'git@github.com:QualiArts/cb-sample-server-devops.git']
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # 既存のrelease tagイメージを取得します。
  - id: Pull Docker Image
    name: 'gcr.io/cloud-builders/docker'
    args: ['pull', 'asia.gcr.io/$PROJECT_ID/cb-sample-server:$_RELEASE_TAG']
  # 既存のrelease tagイメージを利用して新しいDockerイメージを作成します。
  - id: Build Docker Image
    name: 'gcr.io/cloud-builders/docker'
    args: ['build', '--cache-from=asia.gcr.io/$PROJECT_ID/cb-sample-server:$_RELEASE_TAG','--tag=asia.gcr.io/$PROJECT_ID/cb-sample-server:$_ENV-$SHORT_SHA', '.']
  # BuildしたイメージをPush  
  - id: Push Docker Image
    name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'asia.gcr.io/$PROJECT_ID/cb-sample-server:$_ENV-$SHORT_SHA']
  # devopsリポジトリに登録するTagを作成する
  - id: Create Tag
    name: 'gcr.io/cloud-builders/git'
    dir: cb-sample-server-devops
    args: ['tag', '--force', '$_ENV-$SHORT_SHA']
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # dev-commitID tagを作成します。これでDeployが実行されます。
  - id: Push Tag to devops repository
    name: 'gcr.io/cloud-builders/git'
    dir: cb-sample-server-devops
    args: ['push', 'origin', '$_ENV-$SHORT_SHA']
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # 削除まで5秒ぐらい待ちます
  - id: Sleep 5 seconds
    name: 'ubuntu'
    args: ['sleep', '5']
    timeout: 6s
  # 作成したtagを削除します。(tagが増えること防止するためです。)
  - id: Delete git tag
    dir: cb-sample-server-devops
    name: 'gcr.io/cloud-builders/git'
    args: ['tag', '-d', '$_ENV-$SHORT_SHA']
    volumes:
    - name: 'ssh'
      path: /root/.ssh
  # 削除tagをdevopsリポジトリにpushする
  - id: Delete git tag push
    dir: cb-sample-server-devops
    name: 'gcr.io/cloud-builders/git'
    args: ['push', 'origin', ':refs/tags/$_ENV-$SHORT_SHA']
    volumes:
    - name: 'ssh'
      path: /root/.ssh

そして、deployment.yaml, service.yamlはdevopsリポジトリに移動したので、ソースリポジトリからは削除しましょう。

Dockerfileの修正

アプリを起動するときにconfigファイル利用しますので、Dockerfileにも少し修正を入れましょう

# Build Server
FROM golang:latest as builder
ENV GOBIN /go/bin
WORKDIR /go/src/github.com/QualiArts/cb-sample-server
COPY / .
RUN cd pkg && go test
RUN cd pkg && GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o ../bin/cb-sample-server

# COPY theserver file to image from builder
FROM alpine:latest
WORKDIR /usr/local/bin/
COPY --from=builder /go/src/github.com/QualiArts/cb-sample-server/bin/cb-sample-server .
# ConfigファイルをCopy
WORKDIR /usr/local/config/
COPY --from=builder /go/src/github.com/QualiArts/cb-sample-server/config.yaml .

EXPOSE 8080
# Configファイルを設定してアプリを起動
CMD ["/usr/local/bin/cb-sample-server", "-config=/usr/local/config/config.yaml"]

各ファイルを追加した後の構成は下記ような感じです。

$ tree
.
├── Dockerfile
├── Gopkg.lock
├── Gopkg.toml
├── Makefile
├── bin
│   └── cb-sample-server
├── cb-sample-server-devops-github-rsa
├── cb-sample-server-devops-github-rsa.enc
├── cloudbuild.yaml
├── config.yaml
├── dev.cloudbuild.yaml
├── known_hosts
├── pkg
│   ├── config.go
│   ├── config_test.go
│   ├── main.go
│   └── main_test.go
└── service.yaml

2 directories, 17 files

 

ソースリポジトリの各ブランチに対するCloud Buildのtriggerを追加しましょう。

開発環境

Cloud_Build_-_setup-dev

ステージング環境

Cloud_Build_-_setup-stg

 

本番環境

Cloud_Build_-_setup-prd

 

各環境のトリガー追加結果

Cloud_Build_-_setup-list

ここまでできましたら、developブランチにファイルをpushしたら開発環境用のCloud Buildが正常に動作しているか確認しましょう。

Dev環境テスト&ビルド結果

Cloud_Build_-_build-result-dev

そして、開発環境が問題なく動作したらstagingブランチにPR後、マージされるとステージング環境用のCloud Build トリガーが正常に動作するか確認して、最後にはstagingブランチからmasterブランチにPR後、マージし本番環境のトリガーも正常に動作するか確認しましょう。

ステージング環境テスト&ビルド結果

Cloud_Build_-_build-result-stg

本番環境テスト&ビルド結果

Cloud_Build_-_build-result-prd

ソースリポジトリに対するCloudBuild トリガーが無事に実行できました。次はdevopsリポジトリを設定しましょう

DevopsリポジトリにTagが登録された場合、そのTagを利用してアプリをDeployできるように設定

devopsリポジトリではtagイベントドリブンでCloudBuildを実行してアプリをDeployします。そのためにcloudbuild.yaml作成とCloud Buildのトリガーを作成します。

Deploy用cloudbuild.yaml作成

開発用cloudbuild.yamlの作成

devopsリポジトリに「dev-*」tagが登録されると実行されるCloudBuildトリガーのビルド設定ファイルは「dev.cloudbuild.yaml」として保存しましょう

steps:
  # Clusterを取得
  - id: get cluster
    name: 'gcr.io/cloud-builders/gcloud'
    args:
    - beta
    - container
    - clusters
    - get-credentials
    - $_ENV-cb-sample-server
    - --zone=$_ZONE
    - --project=$PROJECT_ID
  # 既存のConfigを削除
  - id: delete config for app
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'delete'
    - 'configmap'
    - 'server-config'
  # 新しいのConfigを設定
  - id: set config for app
    name: 'gcr.io/cloud-builders/kubectl'
    # configフォルダを利用します
    dir: config
    args:
    - 'create'
    - 'configmap'
    - 'server-config'
    - '--from-file=config.yaml=$_ENV-config.yaml'
  # アプリをデプロイする
  - id: Deploy Application
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'apply'
    - '--filename=deployment.yaml'
  # イメージをDeploymentにセットする
  - id: Set image for Deploy
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'set'
    - 'image'
    - 'deployment/cb-sample-server'
    - 'cb-sample-server=asia.gcr.io/$PROJECT_ID/cb-sample-server:$TAG_NAME'
  # NodePortのサービスを登録する 30580->8080
  - id: Set service
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'apply'
    - '--filename=service.yaml'
  # デプロイのステータス確認
  - id: Rollout status
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'rollout'
    - 'status'
    - 'deployment/cb-sample-server'

ステージング、本番用cloudbuild.yaml作成

devopsリポジトリに「stg-*」または「prd-*」tagが登録されると実行されるCloudBuildトリガーのビルド設定ファイルは「cloudbuild.yaml」として保存しましょう

設定内容で開発環境と異なる点はdeploy後、roll statusを確認して問題なくdeployできたらDocker Build Imageをreleaseタグとして登録することです。

steps:
  # Clusterを取得
  - id: get cluster
    name: 'gcr.io/cloud-builders/gcloud'
    args:
    - beta
    - container
    - clusters
    - get-credentials
    - $_ENV-cb-sample-server
    - --zone=$_ZONE
    - --project=$PROJECT_ID
  # 既存のConfigを削除
  - id: delete old a config for app
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'delete'
    - 'configmap'
    - 'server-config'
  # 新しいのConfigを設定
  - id: set new a config for app
    name: 'gcr.io/cloud-builders/kubectl'
    # configフォルダを利用します
    dir: config
    args:
    - 'create'
    - 'configmap'
    - 'server-config'
    - '--from-file=config.yaml=$_ENV-config.yaml'
  # アプリをデプロイする
  - id: Deploy Application
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'apply'
    - '--filename=deployment.yaml'
  # イメージをDeploymentにセットする
  - id: Set image for Deploy
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'set'
    - 'image'
    - 'deployment/cb-sample-server'
    - 'cb-sample-server=asia.gcr.io/$PROJECT_ID/cb-sample-server:$TAG_NAME'
  # NodePortのサービスを登録する 30580->8080
  - id: Set service
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'apply'
    - '--filename=service.yaml'
  # デプロイのステータス確認
  - id: Rollout status
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'rollout'
    - 'status'
    - 'deployment/cb-sample-server'
  # デプロイが無事に終了したら、realease tagを更新する
  - id: Pull Docker Image
    waitFor: ['Rollout status']
    name: 'gcr.io/cloud-builders/docker'
    args: ['pull', 'asia.gcr.io/$PROJECT_ID/cb-sample-server:$TAG_NAME']
  - id: Docker image tag update
    waitFor: ['Pull Docker Image']
    name: 'gcr.io/cloud-builders/docker'
    args: ['tag', 'asia.gcr.io/$PROJECT_ID/cb-sample-server:$TAG_NAME', 'asia.gcr.io/$PROJECT_ID/cb-sample-server:$_RELEASE_TAG']
  - id: Push Docker Image
    waitFor: ['Docker image tag update']
    name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'asia.gcr.io/$PROJECT_ID/cb-sample-server']

ここまで終わりましたが、次はCloud Buildで該当tagが登録されると実行されるトリガーを作成しましょう。

Deploy用Cloud Build トリガー作成

開発環境Deploy用、トリガー作成

Cloud_Build_-_dev-tag-trigger

 

ステージング環境用、DEPLOYトリガー作成

Cloud_Build_-_stg-tag-trigger

本番環境用、DEPLOYトリガー作成

Cloud_Build_-_prd-tag-trigger

これで、3つのトリガーを作成しました。作成後、下記のように表示されると思います。

Cloud_Build_-_tag-trigger-list

 

修正内容をソースリポジトリのdevelopブランチにPush後、Depoy結果確認

ソースを修正してdevlopブランチにPushしたら、問題なく開発環境にDeployされるか確認しましょう

現在のDevの状態を確認しましょう。

Version v0.1.2で表示されていることが確認できます。

cloudbuild-dev-before-new-deploy

pkg/config.goのversionをv0.2.0に修正します。

const Version = "v0.2.0"

そのあと、devlopブランチにpushしましょう。

$ git commit -i pkg/config.go -m 'change version'
$ git push origin develop

開発環境のCloud BuildのBuild結果確認と開発環境への反映確認

ソースリポジトリのdevelopブランチへのPushトリガーとdevopsリポジトリへの「dev-*」tag登録トリガーが問題なく実行され、開発環境に修正内容が反映されたか確認しましょう。

Cloud_Build_-_dev-build-deploy-result

開発環境のDEPLOY結果確認

開発環境のアプリケーションが問題なくVersion v0.2.0になっていることが確認できます。

cloudbuild-dev-after-new-deploy

 

ソースリポジトリのstagingブランチへマージ後、Depoy結果確認

次はdevlopブランチからstagingブランチにPull Requestを作成してマージした後、ステージング環境へdeployされるか確認しましょう。

現状のステージング環境の状態を確認

Version v0.1.2で表示されていることが確認できます。

cloudbuild-stg-before-new-deploy

developブランチからstagingへのPull Request作成後、マージ

develop-pr-to-staging

staging-merge-pr-from-develop

ステージングのCLOUD BUILDのBUILD結果確認とステージング環境への反映確認

ソースリポジトリのstagingブランチへのPushトリガーとdevopsリポジトリへの「stg-*」tag登録トリガーが問題なく実行され、ステージング環境に修正内容が反映されたか確認しましょう。

Cloud_Build_-_stg-build-deploy-result

ステージング環境のDEPLOY結果確認

ステージング環境のアプリケーションが問題なくVersion v0.2.0になっていることが確認できます。

cloudbuild-stg-after-new-deploy

次は最後、本番環境の確認になります。

ソースリポジトリのmasterブランチへマージ後、Depoy結果確認

次はstagingブランチからmasterブランチにPull Requestを作成してマージした後、本番環境へdeployされるか確認しましょう。

現状の本番環境の状態を確認

Version v0.1.2で表示されていることが確認できます。

cloudbuild-prd-before-new-deploy

 

STAGINGブランチからMASTERへのPULL REQUEST作成後、マージ

staging-pr-to-master

 

master-merge-pr-from-staging

本番環境のCLOUD BUILDのBUILD結果確認と本番環境への反映確認

ソースリポジトリのmasterブランチへのPushトリガーとdevopsリポジトリへの「prd-*」tag登録トリガーが問題なく実行され、本番環境に修正内容が反映されたか確認しましょう。

Cloud_Build_-_prd-build-deploy-result

本番環境のDeploy結果確認

本番環境のアプリケーションが問題なくVersion v0.2.0になっていることが確認できます。

cloudbuild-prd-after-new-deploy

これで全ての環境が問題なくDeployされていることを確認しました。

これで最後ですが、おまけとして、手動でアプリケーションをdeployする方法を紹介します。

おまけ:手動でDeployする方法

何らかの問題で、各環境へのdeployが失敗する可能性があります。その場合、手動でDeployする方法とトリガーが変更を検知して自動的に実行されることを防止する策を紹介したいと思います。

cloudbuild.yamlファイルの準備

特定リリースタグを利用して、アプリを手動でDeployするrestart.cloudbuild.yamlを作成しましょう。

steps:
  # Clusterを取得
  - id: get cluster
    name: 'gcr.io/cloud-builders/gcloud'
    args:
    - beta
    - container
    - clusters
    - get-credentials
    - $_ENV-cb-sample-server
    - --zone=$_ZONE
    - --project=$PROJECT_ID
  # 既存のConfigを削除
  - id: delete old a config for app
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'delete'
    - 'configmap'
    - 'server-config'
  # 新しいのConfigを設定
  - id: set new a config for app
    name: 'gcr.io/cloud-builders/kubectl'
    # configフォルダを利用します
    dir: config
    args:
    - 'create'
    - 'configmap'
    - 'server-config'
    - '--from-file=config.yaml=$_ENV-config.yaml'
  # アプリをデプロイする
  - id: Deploy Application
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'apply'
    - '--filename=deployment.yaml'
  # イメージをDeploymentにセットする
  - id: Set image for Deploy
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'set'
    - 'image'
    - 'deployment/cb-sample-server'
    - 'cb-sample-server=asia.gcr.io/$PROJECT_ID/cb-sample-server:$_RELEASE_TAG'
  # NodePortのサービスを登録する 30580->8080
  - id: Set service
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'apply'
    - '--filename=service.yaml'
  # デプロイのステータス確認
  - id: Rollout status
    name: 'gcr.io/cloud-builders/kubectl'
    args:
    - 'rollout'
    - 'status'
    - 'deployment/cb-sample-server'

手動でDeployするトリガーの作成

今回のトリガーは基本的に手動で実行したいので、リポジトリの内容の変更で自動で動かすことを防止したいです。その方法としてはIncluded files filter (glob)の項目にに普段使わないファイル名を設定することで、devopsリポジトリにPushしてもトリガーが動作しないことにしておくことです。

Cloud_Build_-_restart-trigger

手動Deployトリガーの実行

トリガーのRun Triggerを選択するとブランチ一覧が表示されますが、そこで表示されているmasterブランチを選択することでトリガーを実行することができます。

Cloud_Build_-_restart-build

これでもし、通常のdeployで問題が発生しても、安定したビルドイメージを利用してデDeployイして戻すことができます。

まとめ

これでCloud Buildを使って、ソースリポジトリにPushするだけで自動的にDeployすることができました。こういうふうににCloud Buildを使うことでテスト、ビルド、そしてDeployする手間と時間を減らすことができたと思います。これはあくまで一つの例なのでもっと良いプラティクスができたら共有したいと思います。

sanleon
2012年中途入社のサーバーサイドエンジニアです。株式会社QualiArtsの技術開発室でゲーム側が使用するAssetBundle、課金基盤を主に担当しており、最近はGCP, GKE, golangを利用した開発に専念しております。