CircleCIオンプレ版 Builderインスタンスの安全なスケールイン方法 / How to scale in CircleCI - Speaker Deck
2018年12月3日に「CircleCI Japan ユーザコミュニティキックオフ」というイベントがあり、そこで CircleCI Enterprise 管理者向けの話として、Builderインスタンスのスケールインの方法について話してきました。当日の資料と、補足の情報を残しておきます。
AWS で自動化する場合の補足
資料の中で一番情報量の多い AWS の自動化のページの補足です。利用している AWS サービスや API のリンクをまとめました。
AutoScalingGroup の Desired capacity を減らす
Desired capacity の操作は AutoScalingGroup の Scheduled Action を使って操作しています。朝9時に2台にして、昼前に5台に増やして、お昼休みに2台に減らして、という感じです。
Amazon EC2 Auto Scaling のスケジュールに基づくスケーリング - Amazon EC2 Auto Scaling (日本語)
AutoScaling の LifecycleHook でインスタンスの Terminating 状態をフックし、SQS にメッセージを送る
インスタンスの停止をフックして、停止するまでの間に処理を挟み込むことができます。この後 Lambda に処理を行わせるので、通知先を SQS にしておきます。
Amazon EC2 Auto Scaling ライフサイクルフック - Amazon EC2 Auto Scaling (日本語)
SQS から Lambda を起動
SQS から Lambda を起動するように設定します。SQL から Lambda を起動すると、リトライ処理を SQS に任せることができて良いです。Lambda のタイムアウト時間を気にする必要もなくなります。
AWS Lambda を Amazon SQS に使用する - AWS Lambda
イレギュラー時に Lambda が何度もリトライを繰り返して「終了しないループ」に入ってしまうことがありますので、ループしないように Lambda のコードに抜け道を作っておく必要があります。他にも無限ループ対策として、キュー内のメッセージの保存期間を短めにしておいたり、デッドレターキューを使うなどご検討ください。
Lambda で Nomad の Drain API の実行
Lambda で Nomad Drain API を叩くには、少し工夫が必要です。
Nodes Drain node - HTTP API - Nomad by HashiCorp から Drain API 仕様を確認すると、Path が /v1/node/:node_id/drain
となっていて、API を叩くために node_id が必要です。node_id とは Nomad Client を識別する ID です。SQS からは終了予定のインスタンス ID しか情報が渡ってこないので、インスタンス ID を頼りに node_id を取得する必要があります。
node_id は以下のようにして取得することができます。
- AWS SDK を使って、インスタンス ID から privateDNSName を取得する
- Nodes - HTTP API - Nomad by HashiCorpを叩く
- レスポンスの
ID
に node_id が、Name
にホスト名が入っているので、privateDNSName の値でレスポンスの json をフィルタリングして node_id を取得する
node_id が取れたら、それを使って Nodes Drain node - HTTP API を叩きます。
Lambda でビルドが実行中かどうか調べる
Drain モードにできたら、Nomad の Allocations API を使って終了予定のインスタンス内でビルドが実行中かどうか調べます。
Allocations - HTTP API - Nomad by HashiCorp
Allocations API の レスポンス にある ClientStatus
から調べることができます。
ビルドが実行中だったら Lambda をエラーで終了させる
Lambda をエラーで終了させると、SQS にメッセージが戻り、Lambda がリトライされます。リトライ間隔を伸ばしたい場合は、Amazon SQS 可視性タイムアウト - Amazon Simple Queue Service を少し長めに設定します。
ビルドが実行されていなかったら AutoScaling に完了を通知する
AWS SDK で LifecycleHook に完了を通知します。
Amazon EC2 Auto Scaling ライフサイクルフック - Amazon EC2 Auto Scaling (日本語)
Lambda を正常終了させると SQS からメッセージが自動的に削除されます。