Droneって?
コンテナと親和性の高いCIツールです。
drone.io
Drone動作環境
オンプレ(プライベートクラウド)のDocker上で稼働させています。
やりたいこと
- リポジトリがmasterにマージされたらAKS(ステージング環境)に自動デプロイする
- リポジトリでgit tagが打たれたら(リリース用タグ)、AKS(本番環境)に自動デプロイする
全体像
Azure AD サービスプリンシパルを作成する
- Azure CLIでサービスプリンシパルを作成します。(ポータルで作ってもよいです)
$ az login
$ az ad sp create-for-rbac -n "[Your SP Name]" --skip-assignment --years 10
-
このとき表示される、[appId],[password],[tenant]は後で使用するので控えておいてください。
-
次に、MC_[Your AKS Name]_[Your AKS Name][Region Name]というAKSのVMやDiskが作成されたリソースグループがあるので、このリソースグループのIAM設定で、作成したSPに対して、[共同作成者]権限を付与します。
Drone Secret作成
-
以下3つのSECRETを作成します。
- AZURE_APPLICATION_ID
- 事前にメモした[appId]の値
- AZURE_SECRET
- 事前にメモした[password]の値
- AZURE_TENANT_ID
- 事前にメモした[tenant]の値
- AZURE_APPLICATION_ID
Azure CLIコンテナイメージ作成
-
以下の記事を参考に、Drone CIが動作しているサーバのDockerリポジトリにAzure CLIコンテナイメージを作ります。
Azure CLIコマンドをdocker runと同時に実行して、実行が終わったらコンテナを破棄する -
イメージ名は[azurecli]、タグは[latest]で作成します。これは後ほどDroneでAKSにデプロイするときに使います。
.drone.yaml作成
- .drone.yamlをGitHubリポジトリに作成します。アプリケーションのビルドやテストのステップは割愛して、AKSデプロイ部分だけ記載しています。
kind: pipeline
name: staging
steps:
- name: deploy
image: azurecli:latest
pull: if-not-exists
environment:
AZURE_APPLICATION_ID:
from_secret: AZURE_APPLICATION_ID
AZURE_SECRET:
from_secret: AZURE_SECRET
AZURE_TENANT_ID:
from_secret: AZURE_TENANT_ID
IMAGE_TAG: ${DRONE_COMMIT_SHA:0:8}
commands:
- echo $IMAGE_TAG
- /usr/bin/az login --service-principal -u $AZURE_APPLICATION_ID -p $AZURE_SECRET --tenant $AZURE_TENANT_ID
- /usr/bin/az aks install-cli
- /usr/bin/az aks get-credentials -g [Staging ResourceGroup Name] -n [Staging AKS Name]
- kubectl apply -f [k8s Deployment Manifest] -n [k8s NameSpace]
- kubectl get po -n [k8s NameSpace]
- kubectl set image deployment.apps/[Pod Name] [Pod Name]=[ACR Server URL]/[Repository Name]:$IMAGE_TAG -n [k8s NameSpace]
when:
branch:
- master
event:
- push
trigger:
event:
exclude:
- tag
---
kind: pipeline
name: production
steps:
- name: deploy
image: azurecli:latest
pull: if-not-exists
environment:
AZURE_APPLICATION_ID:
from_secret: AZURE_APPLICATION_ID
AZURE_SECRET:
from_secret: AZURE_SECRET
AZURE_TENANT_ID:
from_secret: AZURE_TENANT_ID
IMAGE_TAG: ${DRONE_TAG}
commands:
- echo $IMAGE_TAG
- /usr/bin/az login --service-principal -u $AZURE_APPLICATION_ID -p $AZURE_SECRET --tenant $AZURE_TENANT_ID
- /usr/bin/az aks install-cli
- /usr/bin/az aks get-credentials -g [Production ResourceGroup Name] -n [Production AKS Name]
- kubectl apply -f [k8s Deployment Manifest] -n [k8s NameSpace]
- kubectl get po -n [k8s NameSpace]
- kubectl set image deployment.apps/[Pod Name] [Pod Name]=[ACR Server URL]/[Repository Name]:$IMAGE_TAG -n [k8s NameSpace]
when:
branch:
- master
trigger:
event:
- tag
-
kubectl set imageでイメージタグを変更している理由は、deploymentのマニフェストファイルでイメージタグをlatest固定にしたかったからです。本当はマニフェストファイルのタグを可変にできたらよかったのですが、Droneからだとどうにもできなかったので、一度latestで起動して、対象のタグに変更するという強引な手法を取っています。
-
イメージのタグは、ステージングだとGitのコミットIDが入って、本番だとリリースタグ(例えばv1.0.0など)が入ります。
リストア方法
まとめ
CI/CD最高です。この仕組みを作るまでは手動でデプロイしていましたが、生産性段違いです。
Gitリポジトリをオンプレに持っている都合上、オンプレのCIツールDroneを選択しましたが、Azure DevOpsでも同じことができると思います。(おそらくとても楽に)
今回かなり苦労しましたが、CI/CD環境は無理してでもリリース前に作る価値があると思いました。