ecspresso をさらに速く使うために --wait-until=deployed オプションを追加した話

忙しい人向けの情報

  • ecspresso 2.5 から ecspresso deploy --wait-until=deployed オプションを使うとデプロイ短縮できるようになったよ!!
  • 自分たちの環境では最大で 3 分程度短くなる
  • DRAINING 完了を待つか否かの差か。サービスの安定したリリースに問題なし

estie では ecspresso を使っています

こんにちは、 sugitak です。 estie で SRE をしております。

estie では ECS + Aurora RDS を基本の環境としていまして、その ECS の deploy にあたっては kayac/ecspresso を使用しています。

ECS のデプロイ時間

私、デプロイを短縮するのが好きです。趣味といえるかもしれません。

私たちのデプロイ時間の大部分は Next や Rust の build, npm install などにかかっているのですが、最近気になっていることがありました。 ecspresso deploy の時間が 7 分近くかかることがあるのです。3分くらいで終わってほしいところなので、なんだか感覚と合わない。

6分33秒かかっている様子

上画像で6分33秒かかっているジョブのうち、 ecspresso deploy の時間を見てみると6分28秒でした。いっぽうで、この ecspresso deploy に対応する ECS Service Deploy の時間を見てみたら、なんとたったの3分29秒。

差分の3分間は一体なんなのでしょうか。

3分29秒かかっている様子

このサービスでは Service Connect も使用していますが、 ServiceConnect にせよ DNS にせよ ALB にせよ、3分もかかるようなポイントはありません。謎です。

わからないなら、把握しに行くしかない。もうちょっと調査してみることにしました。

ECS Service の「デプロイ終了」の概念2つ

この差異を把握するうえで、知っておくべき概念が2個あります。

Services Stable

ecspresso で使われている、「サービスのデプロイ完了」を確認するための API 的なものです。上の例で言うところの6分28秒かかっている方です。

正確にはこれは API ではなく、 AWS 公式ライブラリが提供しているインターフェイスなのですが、 aws CLI にも golang SDK にも全く同じ仕様で作られているもののため、 API みたいな感覚で使えます。

この Services Stable には明示的な仕様があります。

Wait until JMESPath query length(services[?!(length(deployments) == 1 && runningCount == desiredCount)]) == 0 returns True when polling with describe-services. It will poll every 15 seconds until a successful state has been reached. This will exit with a return code of 255 after 40 failed checks.

services-stable — AWS CLI 1.40.27 Command Reference

aws ecs describe-services で返ってきた内容の中の deployments 配列の中身について、すべてが「デプロイ中ではなく、かつ desired == running と安定した状態である」ことを確認する、ということになっています。

なんかよさそうですよね。うん。よさそう。

Service Deployment

一方、上の例で3分29秒で終わる方は Service Deployment です。これは「デプロイ」の状況を確認できる機能です。詳細な仕様は開示されていませんが、 ECS インスタンス入れ替えができるとデプロイも終わる。概ねそういう感覚です。

公式ドキュメントには以下のように記述があります:

You can see the most recent 90-day history for deployments created on or after October 25, 2024. The service deployments can be in any of the following states:

  • In-progress
  • Pending
  • Completed

You can use this information to determine if you need to update how the service is being deployed, or the service revision.

Amazon ECS サービスデプロイの表示 - Amazon Elastic Container Service
うん……これも……よさそう…………

違いは?

Services Stable と Service Deployment との違いが3分間。この違いはどこから出ているのか、というと……。どうも、 Service Deployment 完了後、古い Service Revision の DRAIN が完了するまでの時間を、 Services Stable の方では待っているようなのです。

実際に自分たちが確認したステートの変化を表にします。

旧 Service Revision 新 Service Revision Service Deployment Services Stable
1 Desired, 1 Running
(ACTIVE)
1 Desired, 0 Running
(PRIMARY)
開始 開始
1 Desired, 1 Running
(ACTIVE)
1 Desired, 1 Running
(PRIMARY)
↓↓ ↓↓
0 Desired, 1 Running
(ACTIVE)
1 Desired, 1 Running
(PRIMARY)
↓↓ ↓↓
0 Desired, 0 Running
(DRAINING)
1 Desired, 1 Running
(PRIMARY)
完了 ↓↓
0 Desired, 0 Running
(DRAINING)
1 Desired, 1 Running
(PRIMARY)
↓↓
0 Desired, 0 Running
(COMPLETE)
1 Desired, 1 Running
(PRIMARY)
↓↓
1 Desired, 1 Running
(PRIMARY)
完了

古いインスタンスがなくなった時点で Service Deployment は完了するものの、これは Services Stable の終了条件には当てはまらず、古い Service Revision が完全に DRAIN されて describe-services に表示されなくなるまでは Services Stable とはならないわけです。 Services Stable の条件を見るとこれは納得できます。

おことわり

この内容は AWS の仕様そのものの話ではなく、あくまで2025年5月段階での私たちの観測結果を sugitak が解釈したものです。じっさいの仕様は現時点でも異なる可能性があり、また今後の仕様もさらに変化していく可能性があります。

Service Deployment に切り換えることの問題はあるか?

Services Stable から Service Deployment に切り換えると、単純に3分短くなるだけなんでしょうか、デメリットはないのでしょうか?先ほどの例を見て、挙動を考えてみましょう。

Service Deployment では、概ねインスタンス入れ替え完了までを追っているようです。つまり、 Service Deployment が完了した時点で、新しいインスタンスはすべて立ち上がって ALB に登録もされ、古いインスタンスも Auto Scaling Group の参照から落ちています。

いっぽうの Services Stable は、 Deployment が終わったあと、旧 Service Revision の後片付けが完了するまで待っています。この時間を CI/CD で待つ必要はありませんね。

つまり Service Deployment を待てば十分で、 Services Stable となるまで待つ必要はないわけです。

そして Contribute へ……

以上の調査結果から、私たちの環境ではデプロイの終了判定には Services Stable よりも Service Deployment を使いたいと、そのような気持ちになったのでした。そして気持ちがあるなら実装すれば良いということで、 ecspresso に Pull Request を送り、無事受理されました

Feature Request: new option: wait for Service Deployment, not for Service Stable by sugitak · Pull Request #821 · kayac/ecspresso · GitHub

おかげさまで先日リリースされた 2.5.0 からは無事このオプションを利用できるようになっています。

Release v2.5.0 · kayac/ecspresso · GitHub

ecspresso v2.5.0をリリースしました - 酒日記 はてな支店

この効果のほどですが、ユーザによってまったく違うと思います。使ってみたいという方はぜひご自身の ecspresso 通常実行結果と deployment 時間とを比較してみたうえで、適用の可否をご検討くださいませ。

なお、実装にあたっては fujiwara さんにたいへんお世話になりました。上記のコンセプト的な Pull Request の修正はもちろんのこと、 ecspresso コマンドとして成立するようあとから多くの追加実装を頂き、 ecspresso の世界観を保ったままこちらの機能を提供できる状態となりました。 fujiwara さん、改めてありがとうございました。

ちなみに個人的な話ですが、 v1 のときには ecspresso の README ドキュメント英語の改善をしたことがありました。今回はちゃんとコードの形で contribute できることになり、たいへん嬉しいです。

おわりに

そんなわけで私たちのデプロイは3分ほど速くなったのでした。3分あればアルデンテな donbei ができますからね。貴重な時間です。

私たちは、デプロイに魂を燃やしているような SRE / Platform Engineer も大いに募集しております!現在、フロントエンドのビルドに強いメンバーが SRE にいないので、ここを補強してくれる人は特に歓迎です。少しでも興味あればぜひ一度お話しさせていただければと思います!

hrmos.co

hrmos.co

© 2019- estie, inc.