こんにちは、株式会社QualiArts技術開発室でゲーム基盤を担当している曹 (ジョ)です。今回はGoogle Cloud Platform(以下GCP)のCloud Buildというプロダクトを検証したので紹介させて頂きたいと思います。
Cloud Buildとは?
先日、Google Cloud Next ’18で発表されたCloud BuildはGCP上で実行できるCI/CDツールです。Cloud BuildはCI/CDで必要なファイルのみ提供するだけで簡単にCI/CDができます。特徴は下記となります。
- フルマネージドサービス
- Dockerfileサポート
- レポジトリの変更を検知して自動的に実行
- 柔軟なビルドステップ
詳細はこちらを参照してください。
始める前に
Cloud Buildを使うためには下記のものを事前に準備しておく必要があります。
※下記、設定方法は省略させて頂きます。
- GCP Project
- Docker
- Gcloud SDK
- ソースレポジトリ(下記のいずれか一つ)
上記、準備ができましたら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 > Build triggers > Add triggerボタンクリック
Github選択後、Continueボタンクリック
レポジトリ選択
※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 役割を追加」の部分を参照してください。)
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する方法を説明しましたが、次回はいろんな設定方法を活用して説明させて頂きたいと思います。