CircleCI Server版 Builderインスタンスの安全なスケールイン方法

2018年12月4日

CircleCI

CircleCIオンプレ版 Builderインスタンスの安全なスケールイン方法 / How to scale in CircleCI - Speaker Deck

2018年12月3日に「CircleCI Japan ユーザコミュニティキックオフ」というイベントがあり、そこで CircleCI Enterprise 管理者向けの話として、Builderインスタンスのスケールインの方法について話してきました。当日の資料と、補足の情報を残しておきます。

AWS で自動化する場合の補足

資料の中で一番情報量の多い AWS の自動化のページの補足です。利用している AWS サービスや API のリンクをまとめました。

AWSで自動化する例

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 は以下のようにして取得することができます。

  1. AWS SDK を使って、インスタンス ID から privateDNSName を取得する
  2. Nodes - HTTP API - Nomad by HashiCorpを叩く
  3. レスポンス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 からメッセージが自動的に削除されます。

-技術ブログ
-,