こんにちは、株式会社QualiArts技術開発室でゲーム基盤を担当している曹 (ジョ)です。今回はGoogle Cloud Platform(以下GCP)のCloud Buildというプロダクトを検証したので紹介させて頂きたいと思います。

Cloud Buildとは?

CloudBuildLogo

先日、Google Cloud Next ’18で発表されたCloud BuildはGCP上で実行できるCI/CDツールです。Cloud BuildはCI/CDで必要なファイルのみ提供するだけで簡単にCI/CDができます。特徴は下記となります。

  • フルマネージドサービス
  • Dockerfileサポート
  • レポジトリの変更を検知して自動的に実行
  • 柔軟なビルドステップ

詳細はこちらを参照してください。

始める前に

Cloud Buildを使うためには下記のものを事前に準備しておく必要があります。

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

上記、準備ができましたらCloud Buildを使える状態になりました。

早速、Cloud BuildでどうやってCI/CDができるか二つに分けて説明致します。

  • Dockerfileを利用(CI)
  • cloudbuild.yaml利用(CI/CD)

Dockerfileを利用(CI)

先にDockerfileを利用してCIする方法を説明します。

1. ビルド対象のソースレポジトリ作成

今回の説明で利用するレポジトリはgithub.comで、ビルドするアプリケーションはgolangで作成した簡易ウェブサーバーになります。

※ソースファイル及びレポジトリ作成は省略させて頂きます。

2. Dockerfileを作成

Cloud BuildではDockerfileを利用してビルドすることができます。後述のトリガー作成で指定することになりますので、先に作成しましょう。

マルチステージビルド用Dockerfile

今回は「アプリのビルド」と「ビルドしたアプリからdocker imageを作成する」というマルチステージビルドを利用しており、作業内容は下記となります。

  • ステージ1
    • golangのdocker imageを取得
    • アプリのテスト
    • アプリのビルド
  • ステージ2
    • ステージ1でビルドしたアプリのイメージ作成

Dockerfile作成

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

# 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/cb-sample-server .

EXPOSE 8080

CMD ["/usr/local/bin/cb-sample-server"]

Dockerfile作成後、フォルダー構成はこんな感じです

$ tree
 .
 ├── Dockerfile
 ├── main.go
 └── main_test.go
 0 directories, 3 files 

作成したDockerfileをソースレポジトリにPushしましょう。

これでDockerfile用のトリガーを作成する準備ができました。

3. Dockerfileを利用してCloudBuildのトリガーを作成後、ビルド実施

ブラウザー上、GCPのWeb Console画面を開きます。

トリガー作成

そして、下記の手順でトリガーを作成しましょう。

左のナビゲーションメニューからTools > Cloud Build選択

Cloud Build メニューを洗濯

Cloud Build > Build triggers > Add triggerボタンクリック

トリガー作成トリガー追加ボタンをクリック

Github選択後、Continueボタンクリック

Githubを洗濯

レポジトリ選択

※github.comの認証は省略させて頂きます。

レポジトリを選択

トリガーの内容設定

トリガーの詳細内容を入力

これでトリガーの作成ができました。

トリガー確認後、ビルド、そして結果確認

次は作成されたトリガーを確認し、実行してその結果を確認しましょう。

作成されたトリガーの確認後、ビルド

Run TriggerボタンをクリックするとレポジトリまたはTag一覧が表示されます。その中で一つを選択するとビルドされます。

トリガー実行タグ選択

ビルド結果確認

実行結果

これで無事にビルドできることができました。

引き続き、cloudbuild.yamlを利用してCI/CDする方法を説明します。

cloudbuild.yamlを利用(CI/CD)

cloudbuild.yamlはCloud Buildが公式にサポートするデフォルト設定ファイルです。今回はこのファイルを利用してトリガーを作成してビルドします。

Dockerfileを利用してテスト&ビルドを行い、アプリのイメージを作成することまでできました。ただし、ビルドしたイメージをpushしてないし、デプロイもできてない状態です。今回はDockerfile + cloudbuild.ymlの組み合わせでCI/CDを行います。各ファイルの役割は下記となります。

  • Dockerfile(前述のDockerfileを利用): アプリのテスト&ビルド&アプリのDocker image作成(CI)
  • cloudbuild.yaml(今回、新規で作成): Dockerfileを実行し、ビルドしたイメージをGoogle Container Registry(以下GCR)にPushして、GKEクラスタにデプロイ(CI/CD)

1. GKEサーバーとデプロイ関連ファイルの準備

アプリをデプロイするためにはデプロイされるサーバーが必要です。今回はGCPのGoogle Kubernetes Engine(以下GKE)のクラスタを利用させて頂きます。

※今回検証ではGCPのLoad Balancing(以下LB)サービスを利用しております。LB作成手順は省略させて頂きます。

GKEクラスタ作成

今回のGKEクラスタは東京リーゾンを利用します。

クラスタ作成コマンド

export CLUSTER_NAME=cb-server-sample
export ZONE=asia-northeast1-a
export VPCNETWORK=ご自分のVPCネットワークを設定してください
export SUBNETWORK=ご自分のSUBネットワークを設定してください
export NODES=2
export MACHINE=n1-standard-1

gcloud container clusters create ${CLUSTER_NAME} --num-nodes ${NODES} --machine-type ${MACHINE} --network ${VPCNETWORK} --subnetwork ${SUBNETWORK} --zone ${ZONE}

デプロイ関連ファイル準備

GKEクラスタにウェブサーバーをデプロイする為に必要なファイルを準備しましょう

今回はdeployment.yamlとservice.yaml二つになります。

deployment.yaml作成

specのcontainersのimage名のプロジェクト名はご自分で設定してください。

imageはcloudbuild.yaml中で改めて設定します。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: cb-sample-server
spec:
  replicas: 2
  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/プロジェクト名設定/cb-sample-server:latest
        ports:
        - containerPort: 8080
          protocol: TCP
  revisionHistoryLimit: 100

service.yaml作成

GKE外部と連携のため、別途ポートを用意する必要があります。今回は30580ポートを利用します。この30580がLBからアクセスできるポートです。

※GCPのFirewallに30580ポートを許可するRuleを追加することをお忘れずに

apiVersion: v1
kind: Service
metadata:
  name: cb-sample-server
  labels:
    name: cb-sample-server
spec:
  ports:
  - port: 8080
    targetPort: 8080
    protocol: TCP
    nodePort: 30580
  type: NodePort
  selector:
    name: cb-sample-server

deployment.yaml、 service.yaml追加後の構成は下記のような感じです。

$ tree
.
├── Dockerfile
├── deployment.yaml
├── main.go
├── main_test.go
└── service.yaml

0 directories, 5 files

作成したdeployment.yaml、service.yamlはgithubレポジトリにPushしましょう。

次はトリガーで利用するcloudbuild.yamlの準備になります。

2. cloudbuild.yaml準備

今回のトリガーはcloudbuild.yamlを利用しますので、そのファイルを用意する必要があります。

cloudbuild.yamlのステップの説明とファイル作成

cloudbuild.yamlの中で行なっているステップの説明とファイルを作成します。

cloudbuild.yamlの中で行なっているステップの説明

cloudbuild.yamlの中身ですが、7つのステップ構成されております。

  • ステップ 1-Build : 既存のDockerfileを利用してアプリのテスト&ビルド&イメージ作成を行います。
  • ステップ 2-Push : アプリをデプロイするときにアプリのDockerイメージ取得する必要があるので、 作成したDocker imageをGCRにPUSHします。
  • ステップ 3-Get Cluster : クラスタへの作業を行う前に、利用するクラスタ情報を取得して設定する必要があります。
  • ステップ 4-Apply Deployment : デプロイ設定を適用します。
  • ステップ 5-Apply Service : 外部との通信の為、ポートフォーワードを行うサービスの設定します。
  • ステップ 6-Set Image: ビルドしたイメージを設定して、デプロイで使用するようにします。
  • ステップ 7-Rollout Status : デプロイステータス確認して、デプロイが完了するまで待ちます。

cloudbuild.yamlの作成

steps:
# Dockerfileを利用してアプリのテストビルドとイメージのビルドを行う。$_VERSIONはトリガーの変数として設定します。
# $PROJECT_IDには使用中のプロジェクトIDが自動的に挿入されます
- name: 'gcr.io/cloud-builders/docker'
  args: ['build', '-f', 'Dockerfile', '--tag=gcr.io/$PROJECT_ID/cb-sample-server:$_VERSION', '.']
# 作成したcb-sample-serverイメージをPUSHする
- name: 'gcr.io/cloud-builders/docker'
  args: ["push", "gcr.io/$PROJECT_ID/cb-sample-server:$_VERSION"]
# Clusterを取得。$_ZONEはトリガーの変数として設定します。
- name: 'gcr.io/cloud-builders/gcloud'
  args:
  - beta
  - container
  - clusters
  - get-credentials
  - cb-sample-server
  - --zone=$_ZONE
  - --project=$PROJECT_ID
# アプリのデプロイ設定
- name: 'gcr.io/cloud-builders/kubectl'
  args:
  - 'apply'
  - '--filename=deployment.yaml'
# NodePortのサービスを登録する 30580->8080
- name: 'gcr.io/cloud-builders/kubectl'
  args:
  - 'apply'
  - '--filename=service.yaml'
# イメージをDeploymentにセットする。
- name: 'gcr.io/cloud-builders/kubectl'
  args:
  - 'set'
  - 'image'
  - 'deployment/cb-sample-server'
  - 'cb-sample-server=gcr.io/$PROJECT_ID/cb-sample-server:$_VERSION'
# デプロイのステータス確認
- name: 'gcr.io/cloud-builders/kubectl'
  args:
  - 'rollout'
  - 'status'
  - 'deployment/cb-sample-server'

cloudbuild.yaml作成後、構成は下記のような感じです。

$ tree
.
├── Dockerfile
├── cloudbuild.yaml
├── deployment.yaml
├── main.go
├── main_test.go
└── service.yaml

0 directories, 6 files

作成したcloudbuild.yamlはgithubレポジトリにpushしましょう

次はトリガー作成になります。

3. トリガー作成

cloudbuild.yamlを利用するトリガーを作成しましょう。

トリガー詳細内容を入力

作成手順はDockerfile用のトリガー作成とほとんど同じですが、設定内容が少し異なります。そして今回はcloudbuild.yaml中で利用する変数も設定しました。

ここまで準備できましたので、実行したいところですが、もう一つの設定が必要です。

4. IAMのcloudbuildサービスアカウントにGKE権限追加

Cloud Buildではサービスアカウントを利用して通信を行います。GKEクラスタにデプロイするためにはGKE関連の権限が必要なので、IAMメニューにてcloudbuildサービスアカウントにKubernetes Engine Adminロールを追加してください。(詳細はこちらの「2.Kubernetes Engine IAM 役割を追加」の部分を参照してください。)

add_gke_admin_to_iam

5. トリガー実行と動作確認

作成したトリガーを実行してテスト→ビルド→イメージ作成→デプロイが問題なく動作しているか確認しましょう。

トリーガーを実行して結果確認

実行して問題なければ下記のように表示されると思います。

実行結果確認

Webサーバーの動作確認

そして、ブラウザを開き、LBのIPアドレスまたはURLを入力して問題なく動作しているか確認しましょう。

動作確認

Hello, Worldが表示されました。これでCloud BuildのCI/CDができることが確認できました。

まとめ

Cloud BuildではDockerfileのサポート、ソースレポジトリの連携でもっと楽にCI/CDができるようになったと感じました。もし、この記事を読んでいる読者の方もGCPをご使用中であれば是非お試しして頂ければと思います。弊社は今までCI/CDツールとして主にJenkinsを使用しておりましたが、Cloud Buildの利用することでCI/CD用のJenkinsサーバーを立てる必要もなくなり、面倒なメンテ作業も不要になるので、これからはどんどんCloud Buildを活用して行きます。今回の記事では基本設定を利用して簡単にCI/CDする方法を説明しましたが、次回はいろんな設定方法を活用して説明させて頂きたいと思います。

 

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