Drone はモダンなCIサービスを実現するOSSです。CircleCIやTravisCI風のCIを自前で構築することができます。
単一のマシンにインストール、複数マシンをエージェント(実際にジョブを走らせるノード)として使う、あるいはkubernetesを使う選択肢がありますが ( https://docs.drone.io/installation/github/ )、別の選択肢として Drone Autoscale という仕組みが存在し、これはジョブの待ち状況によってエージェント(AWSの場合はEC2)の数を自動で増減させるものです。droneはkubernetesでも動かせるので似たようなことはできるかもしれませんが、autoscalerの方が素直な感じがするというかkubernetesの知識が不要で楽です。
ライセンス
droneは5000 builds per yearまでならStarterプランとして無料で使えるようです。
あれ、AutoscaleのFAQにはそんなことが書かれていませんね。どっちが正しいんでしょうか?
Open Source Editionでは使えないようです。Open Source EditionはSingle Nodeなのでそれはそう。Open Source Editionの説明は今の https://drone.io からのリンクが見当たらないような気がしますね。
構成
楽するためにdrone serverとdrone autoscalerを一つのEC2インスタンスで立てる構成を考えました。レジストリはECRを使います。
以下のdocker-compose.ymlでなんとなく動きます。
version: '3.7'
services:
server:
image: drone/drone:1
volumes:
- serverdata:/data
ports: [ "80:80" ]
restart: always
environment:
- DRONE_GITHUB_SERVER=https://github.com
- DRONE_SERVER_HOST=your.drone.server
- DRONE_GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID}
- DRONE_GITHUB_CLIENT_SECRET=${GITHUB_CLIENT_SECRET}
- DRONE_RPC_SECRET=${DRONE_SERVER_SECRET}
- DRONE_USER_CREATE=username:${DRONE_ADMIN_USER},machine:false,admin:true,token:${DRONE_ADMIN_TOKEN}
- DRONE_AGENTS_ENABLED=true
- DRONE_SERVER_PROTO=http
- DRONE_LOGS_TRACE=true
- DRONE_GIT_ALWAYS_AUTH=true # github enterpriseの場合は必要
autoscaler:
image: drone/autoscaler
links:
- server:your.drone.server
volumes:
- autoscalerdata:/data
ports: [ "8080:8080" ]
restart: always
environment:
- DRONE_SERVER_PROTO=http
- DRONE_SERVER_HOST=your.drone.server
- DRONE_SERVER_TOKEN=${DRONE_ADMIN_TOKEN}
- DRONE_AGENT_TOKEN=${DRONE_SERVER_SECRET}
- DRONE_LOGS_TRACE=true
- DRONE_INTERVAL=30s
- DRONE_POOL_MIN_AGE=2h
- DRONE_POOL_MIN=0
- DRONE_POOL_MAX=4
- DRONE_AMAZON_SUBNET_ID=${DRONE_AMAZON_SUBNET_ID}
- DRONE_AMAZON_SECURITY_GROUP=${DRONE_AMAZON_SECURITY_GROUP}
- DRONE_AMAZON_IMAGE=${DRONE_AMAZON_IMAGE}
- DRONE_AMAZON_IAM_PROFILE_ARN=${DRONE_AMAZON_IAM_PROFILE_ARN}
- DRONE_AMAZON_SSHKEY=${DRONE_AMAZON_SSHKEY}
- DRONE_AMAZON_REGION=ap-northeast-1
- DRONE_AMAZON_INSTANCE=t2.small
- DRONE_AMAZON_DEVICE_NAME=/dev/xvda
- AWS_IAM=true
volumes:
serverdata:
autoscalerdata:
必要な環境変数は.envなどに書きます。
- server/autoscalerの
DRONE_LOGS_TRACE
よくわからんところで止まるので、ログはたくさん出すようにしましょう。
- autoscalerの
DRONE_SERVER_HOST
autoscalerのDRONE_SERVER_HOST
はautoscalerがserverとやり取りするためのものですが、agentにもそのまま渡されるので、agentからも到達可能なドメインを指定する必要があります。ここではDRONE_SERVER_HOST
としてはpublicなドメインを指定して、linksでautoscalerからも名前解決できるようにしています。
- volume
droneはデフォルトではsqliteを使います。そのファイルを置く場所です。
DRONE_SERVER_SECRET
agentがserverとやり取りするときに使われる値です。server側はDRONE_RPC_SECRET
、autoscaler側はDRONE_AGENT_TOKEN
という環境変数に与えます。autoscalerがagentを起動するときにそのまま渡すものだと思います。
-
DRONE_ADMIN_USER
,DRONE_ADMIN_TOKEN
DRONE_USER_CREATE
という環境変数があれば、これに従ってserver起動時にuserが作られます。autoscaler側でもサーバに対してAPI呼び出しをするためにadmin userのtokenが必要なので、一緒に指定します( autoscaler側ではDRONE_SERVER_TOKEN
)。
- min ageの挙動
agentが起動してからDRONE_POOL_MIN_AGE
以内はそのインスタンスは削除されません。越えると削除されます。今までどれくらいビルドしてたかは関係ないみたいです。初めはなんとなく、最後のビルドが終わってからDRONE_POOL_MIN_AGE
が経過すれば削除されるのかなと思っていましたが、そんなことはありませんでした。
- IAM Roleとagentの起動とセキュリティグループ
アクセスキーとアクセスシークレットを指定します。あるいは、AWS_IAM=trueにするとEC2 IAM Roleが使われます。必要なactionは以下でした。
ec2:CreateTags
ec2:DescribeInstances
ec2:RunInstances
ec2:TerminateInstances
EC2インスタンス作成後、autoscalerはagentノードに対してagentのdockerイメージをpull & runします。このため、autoscalerからagentに対して2376ポートでアクセスできるようにします。ここは分かりにくいところで、FAQにも記載があります。
DRONE_AMAZON_IMAGE
DRONE_AMAZON_IMAGE
に何も指定しなければそのリージョンのデフォルトのAMIが使われます。気になる人は自分でAMIを作りましょう。dockerがインストールしてあって起動後自動でdockerが立ち上がるようになっていればOKです。このときAMIによってはDRONE_AMAZON_DEVICE_NAME
に何か値を指定する必要があるかもしれません。違ったdevice nameだとインスタンスが起動後すぐ停止します。
DRONE_AMAZON_IAM_PROFILE_ARN
今回はECRを使いたいので、ECRが使えるIAM Roleを作って、そのARNをこの環境変数に指定します。agentノード立ち上げ時にそのIAM Roleが割り当てられます。
ECRへのアクセスはこちらを参考にしました。
ホストの/var/run/docker.sock
をマウントし、事前のstepでイメージをpullします。ホストのディレクトリをマウントするのでリポジトリがtrustedである必要があります。serviceでprivate imageが使いたい場合はこれでpullしてから普通のstepでdetach: true
にすればできます ( https://docs.drone.io/user-guide/pipeline/services/#detached-steps )。
steps:
- name: pull
image: docker:18
commands:
- apk --update add python3 && pip3 install awscli
- $(aws ecr get-login --region ap-northeast-1 --no-include-email)
- docker pul account.dkr.ecr.ap-northeast-1.amazonaws.com/image
volumes:
- name: docker
path: /var/run/docker.sock
- CLI
本体とautoscalerのドキュメントで情報が違います。autoscalerを使う場合はautoscalerの方が参考になります。
https://docs.drone.io/cli/
https://autoscale.drone.io/cli/
DRONE_TOKEN=http://localhost
DRONE_AUTOSCALER=http://localhost:8080
DRONE_TOKEN=${DRONE_ADMIN_TOKEN}
上記の設定で、EC2内からdrone cliが使えます。
感想
AWSのアクセスキーは発行したくないとかセキュリティグループはなるべく厳しくしたいとか考えており、そもそもの情報不足と色々知識がないせいもあって難しかったです。droneの気持ちになるというか全体的な動作の仕組みが頭に入っていると構築がやりやすいと思います。