概要
GKE 上で Jenkins を動かすことで Canary リリースを簡単に実現することができます
GKE で k8s クラスタを構築しそこに Jenkins をデプロイします
そして Cloud Source Repository 上でアプリのソースコードを管理して、Canary デプロイを実現します
今回は k8s + Jenkins の構築方法と実際にアプリを修正して Canary リリースまでやってみました
なお作業は Google Cloud Shell 上ですべて行います
環境
- Google Kubernetes Engine (2018/09/04 時点)
- Google Cloud Source Repository (2018/09/04 時点)
- Google Cloud Shell
- Jenkins 2.121.3
ディスク作成
gcloud config set compute/zone us-east1-d
gcloud compute disks create cd-jenkins
Jenkins の永続領域として使います
クラスタ作成
gcloud container clusters create jenkins-cd --num-nodes 2 --machine-type n1-standard-2 --scopes "https://www.googleapis.com/auth/projecthosting,cloud-platform"
gcloud container clusters get-credentials jenkins-cd
kubectl get pods
クラスタ内のノードは 2 台です
クラスタの認証情報を保存して kubectl でアクセスできることを確認します
サンプルアプリの取得
git clone https://github.com/GoogleCloudPlatform/continuous-deployment-on-kubernetes.git
cd continuous-deployment-on-kubernetes
ここに k8s 上にデプロイする Jenkins の定義やサンプルアプリの定義が含まれています
基本はこれを使っていきます
helm インストール
wget https://storage.googleapis.com/kubernetes-helm/helm-v2.9.1-linux-amd64.tar.gz
tar zxfv helm-v2.9.1-linux-amd64.tar.gz
cp linux-amd64/helm .
helm を使って Jenkins をデプロイするために使います
RBAC 設定
kubectl create clusterrolebinding cluster-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
./helm init --service-account=tiller
./helm update
./helm version
helm を使ってクラスタにアクセスするサービスアカウントを作成します
アカウント名などは変更しても OK ですがそのままでも OK です
Jenkins デプロイ
./helm install -n cd stable/jenkins -f jenkins/values.yaml --version 0.16.6 --wait
kubectl get pods
NAME READY STATUS RESTARTS AGE
cd-jenkins-7c786475dd-smknn 1/1 Running 0 1h
Jenkins 用の Pod が Running になるまで待ちましょう
もしうまく Pod が上がらない場合は一旦削除して再度試してみてください
./helm del --purge cd
Jenkins ログイン
export POD_NAME=$(kubectl get pods -l "component=cd-jenkins-master" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 8080:8080 >> /dev/null &
kubectl get svc
8080 で LISTEN していることを確認します
Google Cloud Shell のプレビュー機能を使って Jenkins を開きます
printf $(kubectl get secret cd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
これで admin ユーザのパスワードが表示できるのでログインしましょう
サンプルアプリのデプロイ
とりあえず手動でデプロイします
cd sample-app
kubectl create ns production
kubectl --namespace=production apply -f k8s/production
kubectl --namespace=production apply -f k8s/canary
kubectl --namespace=production apply -f k8s/services
kubectl --namespace=production scale deployment gceme-frontend-production --replicas=4
kubectl --namespace=production get service gceme-frontend
これでアプリにアクセスするための EXTERNAL-IP を確認しましょう
LoadBalancer を作成しているので有効になるのに少々時間がかかります
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
gceme-frontend LoadBalancer 10.59.255.179 35.193.81.133 80:31835/TCP 58m
これでブラウザでアクセスすると青色のアプリの画面が確認できると思います
export FRONTEND_SERVICE_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}" --namespace=production services gceme-frontend)
while true; do curl http://$FRONTEND_SERVICE_IP/version; sleep 1; done
この 2 つのコマンドはアプリを Canary リリースしたときに確認するコマンドなのでまだ実行しないで大丈夫です
Cloud Source Repository にアプリをコミットする
cd sample-app
git init
git config credential.helper gcloud.sh
gcloud source repos create gceme
git remote add origin https://source.developers.google.com/p/your-project-id/r/gceme
git config --global user.email "your-mail-address@domain.com"
git config --global user.name "your-name"
git add .
git commit -m "Initial commit"
git push origin master
とりあえず現在のソースを Cloud Resource Repository をプッシュします
ここに変更を加えてブランチを作成しブランチを Canary デプロイします
Jenkins に Credential を登録する
GKE 上にアクセスするための Credential を登録します
- 左メニュー認証情報を選択
- global を選択
- 認証情報の追加を選択
- 種類 -> Google Service Account from metadata を選択
- OK
Jenkins にデプロイジョブの作成
Cloud Resource Repository から GKE にブランチをデプロイするためのジョブを作成します
- Jenkins のトップに戻る
- 「新しいジョブを作成」を選択
- 「Multibranch Pipeline」を選択して名前を「sample-app」で入力しジョブを作成
- Branch Sources -> Add source -> Git -> https://source.developers.google.com/p/your-project-id/r/gceme
- 認証情報はプロジェクト ID を選択
- Scan Multibranch Pipeline Triggers -> 他のビルドが起動していなければ定期的に起動 -> 間隔 -> 1 minute に設定
Canary ブランチをデプロイしてみる
少し修正を加えてそれを Canary デプロイしてみます
git checkout -b canary
vim Jenkinsfile
冒頭の project の部分を自分のプロジェクト ID に変更します
-def project = 'PROJECT_ID'
+def project = 'your-project-id'
続いて canary ブランチになったのがわかるように色を変更します
- vim html.go
-<div class="card blue">
+<div class="card orange">
バージョンも変更します
- vim main.go
-const version string = "1.0.0"
+const version string = "2.0.0"
上記の変更を push します
git add .
git commit -m "Version 2"
git push origin canary
push が完了したら Jenkins のジョブに戻って「Scan Multibranch Pipeline Now」をスタートしましょう
ビルドが完了したあとでブラウザでアプリにアクセスし続けるとオレンジの画面がたまに表示されるようになります
Canary デプロイはすべてのアプリを切り替えるのではなく一部のアプリだけを切り替えることができます
master にマージする
git checkout master
git merge canary
git push origin master
再度「Scan Multibranch Pipeline Now」をスタートしてビルドが完了したあとにアプリにアクセスするとすべてのアクセスが 2.0.0 のアプリになっています
お掃除
gcloud compute disks delete cd-jenkins
gcloud container clusters delete jenkins-cd
gcloud source repos delete gceme
最後に
GKE 上に Jenkins をデプロイしてアプリの CI/CD 環境を構築してみました
ほぼサンプルを試しただけなので Jenkins のパイプラインの詳細は追っていませんが GKE 上で CI/CD する流れは掴めたかなと思います
アプリをデプロイするときは Slave 用の pod が立ち上がりデプロイするようです
公式のやり方ではあるのでこれで問題はないですが、既存の Jenkins がある場合はそこからデプロイするための連携とかしたいかなと個人的には思っています
Jenkins の k8s のプラグインをうまく設定すればできると思いますが、なぜか k8s と Jenkins の連携をするサンプルのほとんどが k8s 上に Jenkins もデプロイする方法なのが気になりました
0 件のコメント:
コメントを投稿