GKE+CircleCI 2.0で継続的デプロイ可能なアプリケーションをシュッと作る
こんにちは:) Pairsエンジニアの竹内です!
この記事は、eureka Engineering Advent Calendar 2017 8日目の記事です。
前回は高橋さんのPairs海外版におけるシステム構成の変遷を暴露するぜでした。
tl;dr
- GitHubへコードがPushされる度にGKEへデプロイ出来るプロジェクトを手順を追って説明します。
- Kubernetesのレシピも一緒にデプロイ出来るためReplicationの増減等も簡単に変更出来ます。
- ↑の環境が整ったプロジェクトをLeiningenテンプレートのspellcardを使って簡単に作れます。
はじめに
Google Kubernetes Engine(GKE)は、コンテナ化されたアプリケーションを複数のノードへデプロイして運用出来るKubernetesベースの便利なSaasです。
普段の業務ではフロントエンドでTypeScriptを書いていたり、サーバーサイドでGoを書いたりする事が多い私ですが、
個人的なウェブサービスの運用や自己研鑽の為にここ8ヶ月程GKEを利用しています。
自分のGKEクラスタでは表題のようにCircleCIを使って継続的デプロイ可能な環境を実現しているのですが、
環境構築にあたり参考にしたCircleCI公式ドキュメントが旧版のCircleCIを使ったドキュメントであったため、自前でCircleCI 2.0向けの設定に書き換えて運用しています。
そんな訳で、今回はその自前の設定を使ってアプリケーションのデプロイ環境を構築するまでの手順を紹介致します。
実現する継続的デプロイ可能な環境
上記の図のように、GitHubへKubernetesのレシピやアプリケーションコードの変更をpushする度に
- CircleCI上でコンテナをビルド
- ビルドしたコンテナをCircleCI上でテスト
- テストが通ったコンテナをGKEがクラスタへデプロイ
と言った形で自動でGKEへアプリケーションがデプロイされるようになります。
続いて、この環境を実現するための手順を一つずつ追っていきます。
1. GKEクラスタを準備する
まずはデプロイ先のGKEクラスタを用意します。
初めてGKEに触れるのであれば、こちらのGoogle Kubernetes Engine クイックスタートの gcloudコマンドラインツールのデフォルト設定
までを元に準備をすると良いでしょう。
また、もしあなたが作りたいアプリケーションをClojureで書く予定であれば、
Leiningenテンプレートのspellcardを用いて以下のコマンドだけでこの後の手順2,3を完了出来ます。
lein new spellcard <プロジェクト名> <gcpのプロジェクトID> <GKEクラスタ名>
chmod +x <プロジェクト名>/deploy.sh
以下に、手動で準備する場合についても手順を書いて行きます。
2. アプリケーション向けKubernetesレシピ(Service・Deployment)を用意する
※これから先の手順では、簡単の為に素のnginxコンテナをデプロイするものとして話を進めて行きます。
アプリケーションコンテナのデプロイに必要なKubernetesのDeploymentと、
ロードバランサの役割を果たすKubernetesのServiceを準備します。
sample/k8s/deployment.yml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: sample
labels:
app: sample
spec:
replicas: 2 # レプリケーションの増減数
selector:
matchLabels:
app: sample
template:
metadata:
labels:
app: sample
spec:
containers:
- name: sample
image: asia.gcr.io/${PROJECT_NAME}/sample:${CIRCLE_SHA1}
ports:
- containerPort: 80
sample/k8s/service.yml
apiVersion: v1
kind: Service
metadata:
name: sample
spec:
selector:
app: sample
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 80
name: http
この2つを以下のように配置します。
sample
└── k8s
├── deployment.yml <-
└── service.yml <-
GCPのproject-idは my-project-id
、アプリケーション名を sample
としています。
3. CircleCIの設定ファイルを準備する
CircleCIからコンテナのビルド・テスト・GKEへのデプロイを行うため、
- CircleCIの設定ファイル本体の
.circleci/config.yml
ファイル - コンテナのレシピとなる
Dockerfile
- コンテナへのテストを行うための
docker-compose.test.yml
ファイル - コンテナのデプロイを行うための
deploy.sh
ファイル
を追加します。
.circleci/config.yml
version: 2
jobs:
build:
working_directory: /app
environment:
PROJECT_NAME: my-project-id
CLUSTER_NAME: my-cluster-name
CLOUDSDK_COMPUTE_ZONE: asia-northeast1-a
DEBIAN_FRONTEND: noninteractive
GOOGLE_APPLICATION_CREDENTIALS: ${HOME}/account-auth.json
docker:
- image: google/cloud-sdk:171.0.0-alpine
steps:
- checkout
- setup_remote_docker
- restore_cache:
keys:
- v1-{{ .Branch }}
paths:
- /caches/app.tar
- run:
name: Install dependencies
command: |
apk add --no-cache
py-pip=9.0.0-r1
gettext
pip install
docker-compose==1.12.0
gcloud components install kubectl
- run:
name: Install Docker client
command: |
set -x
VER="17.05.0-ce"
curl -L -o /tmp/docker-$VER.tgz https://get.docker.com/builds/Linux/x86_64/docker-$VER.tgz
tar -xz -C /tmp -f /tmp/docker-$VER.tgz
mv /tmp/docker/* /usr/bin
- run:
name: Check docker version
command: |
docker version
- run:
name: Load Docker image layer cache
command: |
set +o pipefail
docker load -i /caches/app.tar | true
- run:
name: Build application Docker image
command: |
docker build --cache-from=asia.gcr.io/${PROJECT_NAME}/sample:latest -t asia.gcr.io/${PROJECT_NAME}/sample:$CIRCLE_SHA1 .
docker tag asia.gcr.io/${PROJECT_NAME}/sample:$CIRCLE_SHA1 asia.gcr.io/${PROJECT_NAME}/sample:latest
- run:
name: Save Docker image layer cache
command: |
mkdir -p /caches
docker save -o /caches/app.tar asia.gcr.io/${PROJECT_NAME}/sample:latest
- save_cache:
key: v1-{{ .Branch }}-{{ epoch }}
paths:
- /caches/app.tar
- run:
name: Run tests
command: |
docker-compose -f docker-compose.test.yml run --rm sample
- deploy:
name: Deploy application Docker image
command: |
if [ "${CIRCLE_BRANCH}" == "master" ]; then
echo $ACCT_AUTH | base64 -d > ${HOME}/account-auth.json
gcloud auth activate-service-account --key-file ${HOME}/account-auth.json
gcloud config set project $PROJECT_NAME
gcloud --quiet config set container/cluster $CLUSTER_NAME
gcloud config set compute/zone ${CLOUDSDK_COMPUTE_ZONE}
gcloud --quiet container clusters get-credentials $CLUSTER_NAME
gcloud config set container/use_client_certificate True
./deploy.sh
fi
Dockerfile
FROM nginx:1.13.7
docker-compose.test.yml
version: "2"
services:
sample:
image: asia.gcr.io/${PROJECT_NAME}/sample:$CIRCLE_SHA1
command: /bin/bash -c "nginx -t -c /etc/nginx/nginx.conf"
deploy.sh
#!/bin/bash# Exit on any error
set -efor f in k8s/*.yml
do
envsubst < $f > "generated-$(basename $f)"
done
gcloud docker -- push asia.gcr.io/${PROJECT_NAME}/sample:$CIRCLE_SHA1
kubectl apply -f generated-deployment.yml --record
kubectl apply -f generated-service.yml
以上のファイルもプロジェクトフォルダ内に配置します。
sample
├── .circleci
│ └── config.yml <-
├── deploy.sh <-
├── docker-compose.test.yml <-
├── Dockerfile <-
└── k8s
├── deployment.yml
└── service.yml
また、 deploy.sh がCircleCIから実行できるように実行権限を付与しておきます。
chmod +x deploy.sh
ここまでの準備が出来たら、GitHubレポジトリを立てて一旦コードをPushします。
おおむねこのレポジトリの状態になるはずです。
GitHubレポジトリを準備出来たら、CircleCIを連携させます。
4. CircleCIをGitHubレポジトリと連携させる
CircleCIの連携はCircleCIのダッシュボードから簡単に行なえますが、CircleCIからGKEへデプロイするためのService Account Keyを発行して登録する必要があります。
まず、Service Account Keyはhttps://console.developers.google.com/apis/credentials/serviceaccountkey?project=_のページから以下の手順で準備できます。
- GKEクラスタを作成したプロジェクトを選択
- 「認証情報を作成」->「サービスアカウントキー」
- 「サービスアカウント」を新しい「新しいサービスアカウント」へ選択し、「役割」に「Kubernetes Engine」-> 「Kubernetes Developer」と「ストレージ」-> 「ストレージ管理者」を追加してJSONでキーを作成する
Service Account Keyが準備出来たら、 base64 でbase64形式の文字列にして、CircleCIのダッシュボードから環境変数 $ACCT_AUTH として登録します。
ここまで準備が出来れば、後はGitHubへPushする度に自動でアプリケーションがGKEへデプロイされます。
おわりに
やや駆け足ですが、GKEとCircleCI 2.0を使った継続的デプロイ可能なアプリケーションを構築するまでの手順を紹介いたしました。
GKEを利用し始めてから、レプリケーションの増減や各種ミドルウェアの導入等もアプリケーションと同じ感覚で変更出来るようになり、大変快適な開発環境を得られているので
是非一度お試しいただければと思います:)
また途中にも登場しましたが、こちらのレポジトリに今回のコードサンプルが置いてありますのでご参考ください。
それでは、またの機会にお会いしましょう!
次回は山下さんの Go言語のプロファイリングツール、「pprofのWeb UI」がめちゃくちゃ便利なので紹介する です、お楽しみに!