「達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践」を執筆しました

「達人が教えるWebパフォーマンスチューニング 〜ISUCONから学ぶ高速化の実践」という本を6名の共著で執筆しました。技術評論社さんから、2022年6月4日発売予定です。電子版もでます。

gihyo.jp

Amazon はこちら。

タイトルの通り、ISUCON で出題されるようなWebサービスを例にして、Webサービスのサーバーサイドパフォーマンスチューニングを指南する内容です。通称「ISUCON本」と呼んでください。

2020年の末に、技術評論社さんからWebサービス高速化 × ISUCONに関する書籍を執筆しませんか、と藤原までお誘いをいただいたのが発端でした。

書きたい気持ちはあったものの、内容的にとても一人では書き切れる気がしなかったので、とあるISUCON関連のSlackチャンネルで一緒に書きたい人はいませんか、と募集しました。結果、6名での共著という形で本にすることができました。

執筆者のプロフィールは以下です。大変豪華なメンバーで、"ISUCON"がゲシュタルト崩壊を起こすレベルで埋まっておりますね…

藤原俊一郎 @fujiwara (2011年より面白法人カヤック。SREチーム所属。ISUCON優勝4回、出題3回)

馬場俊彰 @netmarkjp (株式会社X-Tech 5取締役CTO、株式会社iCARE技術顧問。ISUCON第一回にプロジェクターを持ち込んで参加しSELinux=Enforcingで入賞)

中西建登 @whywaita (株式会社サイバーエージェント所属。ISUCON8にて史上初の学⽣総合優勝)

長野雅広 @kazeburo (さくらインターネット株式会社所属。ISUCON1、ISUCON2、ISUCON9予選で問題作成。参加者として優勝も予選落ちも経験)

金子達哉 @catatsuy (株式会社PR TIMES開発本部長CTO。ピクシブ・メルカリを経て現職。ISUCON9予選・ISUCON6本選出題)

草野 翔 @rosylilly (宇宙海賊合同会社代表、株式会社ハンマーキットCTO、株式会社 Tech Consiglie CTO、プロモータル株式会社相談役、IPTech特許業務法人技術顧問。ISUCON9優勝、ISUCON4とISUCON10出題)

目次

  • 1章 チューニングの基礎知識 (@netmarkjp)
  • 2章 モニタリング (@whywaita)
  • 3章 基礎的な負荷試験 (@fujiwara)
  • 4章 シナリオを持った負荷試験 (@fujiwara)
  • 5章 データベースのチューニング (@kazeburo)
  • 6章 リバースプロキシの利用 (@catatsuy)
  • 7章 キャッシュの活用 (@catatsuy)
  • 8章 押さえておきたい高速化手法 (@catatsuy)
  • 9章 OSの基礎知識とチューニング (@whywaita)
  • 付録A private-isuの攻略実践 (@fujiwara)
  • 付録B ベンチマーカーの実装 (@rosylilly)

どんな人向けの本か

通称「ISUCON本」ですが、ISUCONに特化した本ではありません。一般的なWebアプリケーションやミドルウェアに対して、パフォーマンスを改善するためにはどうしたらいいかをまとめた本になります。

ただしパフォーマンスチューニングを説明するための例は、共著者の @catatsuy さんが公開している private-isu という社内ISUCONの問題を採用しています。そのため「ISUCONに学ぶ」というサブタイトルになっているわけですね。

github.com

本書「はじめに」からの引用です。

ISUCONは技術のコンテストですが、そこで題材として提供されるWebサービスは、通常のWebサービスと同様の技術で作られています。つまり ISUCON での高速化手法は、業務で作成されるような 通常のWebサービスにも適用できるのです。本書は、次のような方にお勧めします。

  • Webサービスを開発、運用しているが動作が重くて困っている
  • これまでWebサービスの速度について深く考えたことがなかった
  • ISUCONにこれから出場してみたい
  • ISUCONに出場したことはあるが、よい成績を収められなかった

本書を書いてみて改めて実感したのですが、Webサービスのパフォーマンスチューニングには関わる技術が非常に多く、多数のコンポーネントに対する知識が必要です。

しかも、これも本書内で再三触れたことなのですが、システム全体の中でボトルネックになっている1点見つけ出してそこを改善しない限り、他の何をやっても大きな性能の向上は見込めないという厄介な性質があります。

そのため、小手先のチューニングテクニックというよりは全体的な概念を掴むこと、ボトルネックを見つけてそこに向き合うことを重視してほしいなという気持ちで執筆しました。

この本に書いてあることを理解していれば、仮にISUCONに参加しても手も足も出ないことはないと思います。予選通過ラインに近いところまではいけると思いますが、実際に予選を突破できるかどうかはさすがに運次第、というところでしょうか(著者陣でも予選を突破できないことがあるのでこれは仕方ないですね)。

個人的な見所

こういってはなんですが、本編もですが付録も面白いです!なにしろ付録だけで70ページ以上あります。

付録Aは本書内で例として取り上げた catatsuy/private-isu を実際に段階を踏んで攻略してみた、いわゆる攻略記事になっています。初期スコアの650点から最終的に32万点まで500倍に性能アップするところはもちろんですが、最後にとあることをして1万点に失速するところまで含めて、なかなか面白い読み物になっていると思います。

付録Bは、ISUCON のベンチマーカーを書くためのフレームワーク isucandar を使って実際にベンチマーカーを書くための勘所を、isucandar の作者が解説しています。普段から ISUCON の作問をする人はそれほどいないと思いますが、社内 ISUCON を開催するとか、本物 ISUCON の作問が突然降ってきたみたいな場合には必読です。

github.com

謝辞

執筆のお話を頂いた技術評論社の皆様、共著者の皆様、レビューに協力していただいた皆様、ISUCONを運営しているLINE株式会社の皆様(特に@941さん)、大変ありがとうございました。

(お断り) 本書と ISUCON 12 との関連

自分は今年の ISUCON 12 の作問担当でもありますが、作問の話自体はこの本がほぼ書き上がってから来たため、本書の内容と ISUCON 12 で出題される問題の内容に、関連は特にありません。念のため。

ecspresso tasks --trace でECSタスクのイベントログを一括表示する tracer を使えるようにした

メリークリスマス!(フライング)

AWS Containers Advent Calendar 2021 6日目の記事です。


先日、github.com/fujiwara/tracer という結構便利なやつを作りました。Amazon ECS タスクに関連するイベントとログを一括で出してくれる、シンプルな CLI です。

github.com

解説記事はこちら(会社のアドベントカレンダー)に書きましたのであわせてご覧下さい。

techblog.kayac.com

tracer は単体の CLI で動作するのでどのような手段で管理している ECS タスクにも使えるのですが、これを ecspresso からも呼び出せると便利では? と思い立ったのでそうしました、というのがこの記事です。

ecspresso tasks --trace

tracer は ECS クラスタ名とタスクIDを指定して動作します。ecspresso には tasks コマンドがあり、これは ecspresso が管理しているクラスタからタスクを特定する機能があります。つまり、

$ ecspresso tasks --trace

として、ecspresso 側でタスクを特定して、そのIDをtracerに引き渡して実行すれば完成です。実質10行ちょっとのpatchで実装できました。よかったですね。(tracer のコードを package として ecspresso 内部に組み込んであるので、tracer コマンドは不要です)

動作デモはこんな感じです。

ecspresso v1.7.2 で使えます

先ほどリリースした ecspresso v1.7.2 から使えます。

github.com

どうぞご利用ください。

ecspresso v1.7.0 をリリースしました

3ヶ月ぶりの ecspresso リリースのお知らせです。

Amazon ECS デプロイツール ecspresso の v1.7.0 をリリースしました。

github.com

新機能

定義ファイル (サービス / タスク / run --overrides-file) で Jsonnet の直接読み込みをサポートしました

これまで JSON 形式が要求されていた各種定義ファイルで、Jsonnet の読み込みがサポートされました。

ファイルの拡張子が .jsonnet の場合、ecspresso 内部で先に Jsonnet を処理して JSON に変換後、これまで通り (テンプレート記法による env, tfstate の展開などが行われて) 読み込まれるようになります。

JSON は人が読み書きするのは不便なことが多いため、 ecspresso advent calendar 2020 day 20 - Jsonnetによる定義ファイル生成 の記事などで Jsonnet 形式をお勧めしていました。これまでは事前に自分で jsonnet コマンドを実行して JSON に変換してから ecspresso を起動する必要がありましたが、その処理が不要になりました。

github.com/google/go-jsonnet をライブラリとして組み込んでいるため、jsonnet コマンドは不要です。CI/CD 環境でも jsonnet のインストールが不要になって嬉しいですね。

各種定義ファイルで使用できない key を発見すると警告を表示するように

ecspresso が使用するタスク/サービス定義のファイルは aws-sdk-go で定義している構造体にマッピングされます。

これまでは JSON ファイル中の要素名(key) を間違った場合など、構造体に対応するものがない場合は、単に無視されていました。そのため要素名を typo した場合など、気が付かないうちに要素自体が省略されてしまい、意図しない構成がデプロイされてしまうことがありました。

v1.7 では、構造体に対応する要素が存在しない場合は warning を表示するようになりました。

f:id:sfujiwara:20211101152937p:plain

タスク定義リビジョンを取り扱う revisions, deregister コマンド追加

revisons コマンドは、存在しているタスク定義のリビジョンを表示できます。 IN USE の欄には、現在サービス内で利用しているタスクの情報が表示されます。単体タスクが使用している場合は RUNNING task, サービスに設定されているものは *** deployment となります。

$ ecspresso revisions
ecspresso --envfile envfile revisions
|        NAME        |       IN USE       |
+--------------------+--------------------+
| ecspresso-test:386 |                    |
| ecspresso-test:387 |                    |
| ecspresso-test:388 |                    |
| ecspresso-test:389 | ACTIVE deployment  |
| ecspresso-test:390 | RUNNING task       |
| ecspresso-test:391 |                    |
| ecspresso-test:392 | PRIMARY deployment |

古い revision を登録解除する、deregsiter コマンドも追加されました。

deregister コマンドでは以下のオプションのどちらかが必要です。

  • --revision=リビジョン番号 を指定すると指定したリビジョンを登録解除します
  • --keeps=保持する数 現在利用中のものを除いて指定した数だけリビジョンを保持し、古いリビジョンを登録解除します
    • 「現在利用中のものを除いて」= revisions コマンドで IN USE の欄が空欄のものが対象

revision が増えすぎて困る!とか、間違って動作しない revision を登録してしまったのでうっかり使わないようにしたい、という場合にご利用ください。

Fargate Windows Containers 対応

先日リリースされたばかりの、Fargate での Windows Containers の起動に対応しました。

aws.amazon.com

タスク定義の image, runtimePlatform を適切に指定すると起動できます。

// せっかくなので Jsonnet 形式で
{
  image: 'mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019',  
  runtimePlatform: {
    operatingSystemFamily: 'WINDOWS_SERVER_2019_CORE',
  },
  // ....
}

f:id:sfujiwara:20211101155543p:plain

バグ修正

サービス定義の desiredCount が設定されている(未定義ではない) 場合に create を行うと、その設定を無視して desiredCount=1 を設定してしまうバグを修正しました。


おしらせ

ecspresso handbook で、コマンドリファレンスの章も追加で無料公開しました。

現在 v1.5 対応版ですが、近日中に v1.7 対応に更新予定です。

zenn.dev

ISUCON11で優勝しました

勝った!!引退!!!

取り乱しました。

ずっと参加してきているWebアプリケーションパフォーマンスチューニングコンテスト ISUCON、ISUCON11本選にチーム「fujiwara組」で参加して、優勝しました。

ISUCON11 まとめ : ISUCON公式Blog

fujiwara組は初回のISUCONから参加している老舗チームで、自分(fujiwara)以外のメンバーは都度入れ替わっているのですが、今回はISUCON10の時と同様に会社(面白法人カヤック)の同僚である acidlemon と macopy とのチームです。

f:id:sfujiwara:20210921113931p:plain
チーム紹介スライド

過去に ISUCON1, 2, 5 で優勝しているので、6年ぶり4度目の優勝になりました。もう引退していいよね!(というか941さんに出禁って言われた気がする…)

やったこと

リポジトリはこちらです。

github.com

アプリケーションの変更は PR になっているので、それを順に見ると分かりやすいかと思います。 Pull requests · fujiwara/isucon11-f · GitHub

方針としては以下で、結果的には全員のやることがなくなってしまうことがなく、最後まで手を打ち続けられたのが勝因かなと思います。

  • fujiwara がインフラまわりの初期設定とチューニング、モニタリング、複数台構成を組むなどの足回りを整備
  • その間に acidlemon, macopy が大きめのアプリケーション改造に取りかかる
    • GetGrades の SingleFlight 化
    • JOIN はずし
    • 既読管理の Redis 化
  • fujiwara が細かいコードの改善を片付けて露払いする
    • zip生成での外部コマンド呼び出しを archive/zip 化
    • 1行だけ DB を引くような部分をオンメモリキャッシュ化 (メモリになければDBを見てメモリ(sync.Map)に載せる
    • 外部キーを全部やめる
    • echo(フレームワーク) の JSONSerializer を自作して goccy/go-json
    • 参照だけのエンドポイントで無駄にトランザクションを張っていたのをやめる
  • 大きめの改善を merge して伸ばしていく

fujiwara組が負けるときのパターンは、インフラ担当の自分がやることがなくなってしまって手が空いてしまうことが多いのですが、今回は3人がフル回転できてよかったですね。

個人的ハイライトは、archive/zip 化を決意して、10分で一発実装、ベンチ通過できたところでしょうか。AWS Lamba デプロイツールである lambroll を実装したときに Go での zip 生成は経験があったので、それをみながらスッとできました。いろんなコードを書いてみるものですね。

archive/zipにする by fujiwara · Pull Request #5 · fujiwara/isucon11-f · GitHub

スコア推移

やっていて、これだけ苦しい ISUCON は初めてかも知れません。何をしてもスコアに明確に響かない(けどサーバの負荷は僅かに下がる気がする)手を、最後には効くと信じて打ち込み続けるというのが本当にしんどい。

リアルでのパフォーマンスチューニングでは、明確に数字が上がらない施策を無闇に入れるのは避けるべきですよね。得られるパフォーマンスと、コードや運用の複雑さがペイしないと技術負債(しかもメリットなし)まっしぐらなので。競技中、ずっとしんどいしんどいって言ってました。

f:id:sfujiwara:20210921113651p:plain
スコア推移(最終上位3チーム+特別賞)

スコア推移を見ると、リーダーボードで自チーム以外のスコアが閲覧できなくなる17時直前に大きく伸びているのが分かります。

この時点で大きめの改善がマージ済みだったものの、db.SetMaxOpenConns(10) のままで MySQL の負荷が上がりきらないことに気が付いたので、 MaxOpenConns を 10 -> 20 -> 40 -> 60 と調整して最適値を探ってスコアを上げ、最後にダメ押しで今までずっと有効にしていた MySQL の slow query log を無効化して更に数字を伸ばした、というやつでした。

最終的には2位の NaruseJun もこの直後に10万点を超えて来ていたようなので、スコアが公開されている17時前に少しは盛り上げられてよかったかなと思います。

実際のスコアはリポジトリに保存してあります。 isucon11-f/scores.txt at main · fujiwara/isucon11-f · GitHub

最後に

近年の ISUCON ではもう年を食った社会人は若者や学生には勝てないんじゃないか、などといわれたこともありましたが、平均年齢38.7歳のおじさんチームでもまだまだ戦えることが示せてよかったです。

ただ個人的には、競技として洗練されて高度化していく方向が極まってきて、8時間以内に運営が想定したポイントを何個クリアできるか、あらかじめ設定された問題をどれだけ早く正確にこなすかのゲーム、になっているのが多少気になるところではあります。初期の頃の、誰がどんな手を繰り出して何をやってくるのか分からないみたいな空気を多少懐かしく思いつつ、まあこれも業界や時代の流れかなとは思いますが。

最後になりますが、楽しく快適な競技を提供して頂いた運営チーム、作問チーム、アドバイザリーの皆様ほか、スタッフの皆様にお礼申し上げます。本当に快適で楽しい ISUCON でした!(しんどかったけど…)

ISUCON11予選を4位で通過しました

今年もやってきました ISUCON の季節です。

ISUCON は 8 までは(出題を含めて)予選本選の全てに参加できていたのですが、9, 10 では連続で予選落ちしていました。10は予選であと1チーム上回れば、というところで及ばずでしたが、本選には並行参加チームというオープン参加扱いで参加させてもらい、ひっそり全体の3位相当のスコアを出していたんですよね。なのでチームのポテンシャルとしてはまだまだいけるはず!ということで ISUCON 11 にも10と同様、同僚の @acidlemon と @mackee_w (macopy) と参戦しました。

結果、全体の4位のスコアで予選を通過できました!

isucon.net

やったこととか

使用したのは Go 実装です。ミドルウェアは特に変更せず、最後まで nginx + MariaDB のままでした。 3台のうち1台を MySQL(MariaDB)専用、残りの2台を nginx + アプリケーションにしています。

コードの変更については、リポジトリを公開しています。

github.com

最終的に取りこまれた PR のタイトルとスコア、時刻をざっと並べるとこんな感じでした。

  • isu_conditionのorder by狙い #1 by mackee
    • 最初に slowlow をみて index を貼ったやつ。これで初期スコアから 16,168 へ (11:10:12)
  • いつものinterpolateParams=true #2 by acidlemon
    • Go の MySQL ドライバでデフォルトだと server side prepeare をするのをやめるやつ。17,918
  • debugのログをoffにする #3 by mackee
  • generateIsuGraphResponseが全部取るのは意味がないので1日の範囲だけにする #4 by mackee
  • trendは最新だけだからLIMIT 1 #6 by acidlemon
    • このあたりでスコア 30,000 程度 (まだ1台) (12:27:17)
  • isu_character_idx 追加 #7 by fujiwara
  • ログレベルをINFOにしてアクセスログも黙らせる #8 by mackee
  • 9割落としてるのはわかったので静かにしてもらう #9 by acidlemon
  • 9割おじさんから8割おじさんへ #10 by acidlemon
    • dropProbability という数値の調整でスコアの傾向を探っています
    • ここで3台構成にして 39,704 までアップ (13:00:43)
  • 9割に戻しつつpostIsuをbulk insert #11 by mackee
    • 48,346 (13:04:11)
  • initializeでalter #16 by acidlemon
  • image はファイルに書く#17 by fujiwara
    • isu.image カラムに入っていた画像バイナリをファイルで読み書きするよう改修
  • condition_true_countカラムに対応するstruct定義にする #18 by acidlemon
    • 1カラムに文字列で入っていたフラグを分解して true の数を別に持つ改修
  • true_countで絞り込み #19 by mackee
  • userテーブルへのfetchをキャッシュする #23 by mackee
    • オンメモリ化を進めている 73,570 (15:31:31)
  • 全量さばけるようになったので全部コメントアウト!#24 by mackee
    • ここで dropProbability=0 で通るようになったのでスコアが跳ね上がりました。一気に桁が上がって 374,366 (15:41:40)
  • isu nameをオンメモリ #26 by fujiwara
  • isuの画像をNULLで潰す #28 by acidlemon
  • isuを引いてくるところでcacheする #29 by mackee
    • このあたりで並行して Redis branch を作っていました(by acidlemon)がスコアが出ず、取り込みは諦め
  • インデックス1個にまとめて書き込み負荷を下げる #30 by mackee
    • 最後、isu_condition の primary key を変更して復号 pkey にしたのが効果を発揮して 684,959 (18:31:27)
    • id bigint AUTO_INCREMENTid bigint DEFAULT NULL (カラム自体は使わないけど残す)
    • PRIMARY KEY(jia_isu_uuid, timestamp)

再起動試験後、18:38:02 に 704,779 を記録して打ち止めでした。

f:id:sfujiwara:20210823173306p:plain
スコア推移(最終上位4チーム)

感想とお礼

出題はなるほど IoT で時系列データ(今までなかったのでそろそろ来そうだとは思った)、極端なところがなくて、いい問題でしたね。最終的には isu_condition の書き込みをどう捌くかに帰着するので、ここを上手く圧縮できたらもっとブレイクスルーできたのかな…と思います。時系列DBを使ったチームとかあったんでしょうか。

ベンチは大変快適で、例年ありがちな謎 fail に悩まされることがほぼなかったので、競技に集中できてとてもありがたかったです。近年、めきめきと ISUCON 運営力の向上を感じますね。頼もしい限りです。

運営の皆様、大変良い問題をありがとうございました。3大会ぶりの本選参加なので、本選でも楽しみたいと思います。よろしくおねがいします!

ecspresso v1.6.0 をリリースしました

このブログはすっかり ecspresso のリリースノートとなっている昨今ですが、今回もリリースのお知らせです。

Amazon ECS デプロイツール ecspresso の v1.6.0 をリリースしました。

github.com

非互換変更

これまで GitHub で配布しているリリースバイナリのパッケージが .zip 形式でしたが、リリースを GoReleaser で行うようにした関係で、tar.gz 形式に変更になっています。 (追記: GoReleaserでもzipにはできるのですが、パッケージ内部のファイル名を揃えることが難しかったため、どのみちインストーラーなどの対応が必要になるためtar.gzに変更しました)

手動でインストールしている場合は、zip ではなく tar で展開してください。

CircleCI Orb の場合は、 fujiwara/ecspresso@0.0.15 を使用してください。それ以前のバージョンでは、latest や v1.6.0 以降のバージョンが正しくインストールできません。

GitHub Actions の場合は、kayac/ecspresso@v1 で latest, v1.6.0 以降もインストールできるようになっています。もしまだ @v0 を使用している場合は @v1 へ更新をお願いします。

Homebrew でのインストールは今まで通り行えます。

新機能

ECS サービスなしでのコマンド実行

ecspresso はこれまで、一見 ECS にサービスが存在しなくてもよさそうな操作でも、サービスが存在しないと行えない操作がありました。単体タスクの実行 (run)、タスクの一覧 (tasks)、ECS Exec (exec) の各コマンドは、ECS サービスが存在している状態でないと正常に動作しませんでした。

v1.6.0 ではこれらの機能を、ECS にサービスがなくても実行できるようになりました。

  • run については、実行時の networkConfiguration など、ECS サービス定義と同等の情報が必要なため、サービス定義ファイルが必要です
  • tasks, exec については、サービス定義も不要です。タスク定義の family が同一なものを ECS クラスタ内から検索して操作対象とします

tfstate 参照機能で Terraform Cloud, Terraform Enterprise をサポート

Terraform Cloud で管理している tfstate を参照できるようになりました。URL を指定する場合は remote://app.terraform.io/{myorg}/{myworkspace} という形式で指定してください。

認証情報は TFE_TOKEN 環境変数から読み取ります。

--config のデフォルト値として ecspresso.yml が設定されます

これまで ecspresso の設定ファイルを指定する --config オプションの値はデフォルト値が存在しませんでしたが、ecspresso.yml というデフォルト値が設定されました。

バグ修正

exec コマンドでログ出力を KMS 暗号化する設定の場合動作しないのを修正しました

session-manager-plugin の呼び出し方法の問題でした。

CodeDeploy アプリケーションが100個以上ある場合にデプロイできない問題を修正しました

APIで一度に100個しか取得できない関係で、失敗することがありました。世の中にはいっぱいアプリケーションがある環境があるんですね…

tfstate 参照のキーに - が入っていると panic する問題を修正しました

outputs を定義している場合、リソース名には - が含まれる可能性があります。

CodeDeploy で使用する AppSpec に CapacityProviderStrategy を追加しました

ドキュメントの英語の誤りが修正されました

英語がグダグダなのを直していただいて、ありがとうございます!

短い ARN 形式を利用している場合に ecspresso init が失敗する問題を修正しました


パッケージングが変更になった以外は基本的に互換性を保ったリリースとなっています。Pull Requestをお寄せいただいた皆様、ありがとうございました。

どうぞご利用ください。

ECS Execに対応した ecspresso v1.5.0 をリリースしました

Amazon ECS のデプロイツール、ecspresso の v1.5.0 をリリースしたのでお知らせです。

github.com

今回は Amazon ECS Exec という新機能対応が目玉です。ほかにもお送りいただいたPRを取りこんだ各種修正が入ったリリースになります。どうぞご利用ください。

PRをお送りいただいた皆様、ありがとうございました!

新機能

ECS Exec への対応を追加しました

ホストから docker exec するように、Fargate に対しても起動しているコンテナに入ってコマンドを実行できる ECS Exec 機能がリリースされています。

aws.amazon.com

ecspresso v1.5 では exec コマンドを追加して、AWS CLI なしで exec できるようにしました。session-manager-plugin は必要です。

exec を使用するためには、まずサービス定義で enableExecuteCommand を true に設定して create / deploy します。(起動中の ECS サービスに対してもあとから変更可能です)

{
  "enableExecuteCommand": true
}

必要な権限などが揃っているかどうかは amazon-ecs-exec-checker で確認すると便利です。

その後は ecspresso exec コマンドを使用して、起動中のタスクに対して exec ができます。タスクに複数コンテナがある場合は、更に選択肢がでます。

実際に実行してみた様子は以下をご覧ください。

この例ではタスクやコンテナの絞り込みに peco を使っていますが、絞り込みに使うコマンドは設定ファイルの filter_command で指定可能です。未指定の場合は ID / コンテナ名入力するダイアログが表示されます。

タスクを一覧/詳細表示する tasks コマンドを追加

これまで ecspresso ではサービスとタスク定義の管理に主眼を置いていたため、起動済みのタスクの情報を見る手段がありませんでした。

ecspresso tasks を実行すると、サービスから起動されたタスクと、同じタスク定義を持ったタスク(単体で run されたものも含む) を表示します。

$ ecspresso --config config.yaml
|                ID                |   TASKDEFINITION   | INSTANCE |   LASTSTATUS   | DESIREDSTATUS |         CREATEDAT         |         GROUP         |  TYPE   |
+----------------------------------+--------------------+----------+----------------+---------------+---------------------------+-----------------------+---------+
| 28852184e15e48e0aad6b7549f92ed65 | ecspresso-test:274 |          | RUNNING        | RUNNING       | 2021-04-13T13:45:23+09:00 | service:nginx-local   | FARGATE |
| bed89f2e492e44cd82d75776ff2d8a7f | ecspresso-test:276 |          | RUNNING        | RUNNING       | 2021-04-13T13:48:04+09:00 | service:nginx-local   | FARGATE |
| fad8863654f945588273916a3a56bd95 | ecspresso-test:275 |          | DEPROVISIONING | STOPPED       | 2021-04-13T13:46:21+09:00 | family:ecspresso-test | FARGATE |

--find オプションを付けると exec 同様にタスクを絞り込んで、決定するとそのタスクの情報を JSON で出力もできます。

停止したタスクについても API で取得できる時点までは閲覧できるので、なぜか上手く起動できずに落ちてしまったタスクでも詳細を表示すれば、マネージメントコンソールを見に行かずに理由が分かります。

次の例では、"stoppedReason": "Essential container in task exited" などが読み取れます。

$ ecspresso --config config.yaml --id fad8863654f945588273916a3a56bd95 --output json
{
  "attachments": [ ... ],
  "availabilityZone": "ap-northeast-1c",
  "capacityProviderName": "FARGATE",
  "clusterArn": "arn:aws:ecs:ap-northeast-1:123456789012:cluster/ecspresso-test",
  "connectivity": "CONNECTED",
  "connectivityAt": 1618289185.693,
  "containers": [ ... ],
    {
      "containerArn": "arn:aws:ecs:ap-northeast-1:123456789012:container/ecspresso-test/fad8863654f945588273916a3a56bd95/8a04958b-4918-4a15-b6d4-6b40791c4fba",
      "cpu": "0",
      "exitCode": 137,
      "healthStatus": "UNKNOWN",
      "image": "debian:buster-slim",
      "lastStatus": "STOPPED",
      "managedAgents": [
        {
          "lastStatus": "STOPPED",
          "name": "ExecuteCommandAgent"
        }
      ],
      "name": "bash",
      "networkBindings": [],
      "networkInterfaces": [
        {
          "attachmentId": "bcb4aa98-1dfe-4a08-9a29-9db6e15d8334",
          "privateIpv4Address": "10.3.3.161"
        }
      ],
      "runtimeId": "fad8863654f945588273916a3a56bd95-987533343",
      "taskArn": "arn:aws:ecs:ap-northeast-1:123456789012:task/ecspresso-test/fad8863654f945588273916a3a56bd95"
    }
  ],
  "cpu": "256",
  "createdAt": 1618289181.026,
  "desiredStatus": "STOPPED",
  "enableExecuteCommand": true,
  "executionStoppedAt": 1618289229,
  "group": "family:ecspresso-test",
  "healthStatus": "UNKNOWN",
  "lastStatus": "STOPPED",
  "launchType": "FARGATE",
  "memory": "512",
  "overrides": {
    "containerOverrides": [
      {
        "command": [
          "nginx",
          "-V"
        ],
        "name": "nginx"
      },
      {
        "name": "bash"
      }
    ],
    "inferenceAcceleratorOverrides": []
  },
  "platformVersion": "1.4.0",
  "pullStartedAt": 1618289214.039,
  "pullStoppedAt": 1618289223.039,
  "startedAt": 1618289229.039,
  "stopCode": "EssentialContainerExited",
  "stoppedAt": 1618289345.672,
  "stoppedReason": "Essential container in task exited",
  "stoppingAt": 1618289280.886,
  "tags": [],
  "taskArn": "arn:aws:ecs:ap-northeast-1:123456789012:task/ecspresso-test/fad8863654f945588273916a3a56bd95",
  "taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:123456789012:task-definition/ecspresso-test:275",
  "version": 6
}

rollback コマンドが CodeDeploy に対応

これまで ecspresso rollback は CodeDeploy でデプロイされた場合には機能しませんでしたが、機能するようになりました。 Feature Request: Rollback by CodeDeploy by cohalz · Pull Request #261 · kayac/ecspresso · GitHub

タスク定義へのタグ付けに対応

これまではタスク定義ファイルに tags を記述してもタグを付与することができませんでしたが、タグをつけられるようになりました。

これに伴って、タスク定義ファイルを取り扱うときに AWS SDK Go の ecs.TaskDefinition を使用していた部分が、ecs.RegisterTaskDefinitionInput を使用するように変わっています。JSON ファイルとして扱う場合には互換性を持たせていますが、もし何か問題がありましたらお知らせください。

{
  "tags": [
     {
        "key": "TagKey",
        "value": "TagValue"
     }
   ]
}

Feature Request: Support add Tags to TaskDefinition by Hirofumi-Narita · Pull Request #256 · kayac/ecspresso · GitHub

Support tagging for task definition. by fujiwara · Pull Request #260 · kayac/ecspresso · GitHub

バグ修正

init コマンド実行時に ECS サービスの propagateTags 属性を扱えるように

これまでは init コマンドで既存 ECS サービスを定義ファイル化した時点で propagateTags 属性が消えていましたが、保持するようになりました。

Support tags&propagateTags to `init` & `create` by cohalz · Pull Request #270 · kayac/ecspresso · GitHub

verify コマンド実行時に ELB の検証をタスク実行ロールではなく ecspresso の実行権限で行うように

これまでは verify コマンド実行時の ELB (target group) の検証を、タスク実行ロール(にAssumeRoleした状態)で行っていましたが、ecspresso 自体の実行権限で行うように変更しました。

タスク実行ロールには最小限の権限しか持たせない方が望ましい、という理由です。v1.5 の時点ではecspresso の実行権限での検証に失敗した場合、タスク実行ロールでの検証にフォールバックしますが、この挙動は移行措置として次のリリースで削除する予定です。

Don't require `elasticloadbalancing:DescribeTargetGroups` in task execution role to `verify` by cohalz · Pull Request #262 · kayac/ecspresso · GitHub

ecspresso handbook も改訂予定です

すみません、v1.4.0 リリース時に改訂予定としていましたが、まだ handbook は v1.3 対応のままです。v1.4, 1.5 での変更について加筆予定ですので、引き続きよろしく願いします。

zenn.dev

GitHub Sponsors はじめました

github.com

One-time のスポンサーもできるようになっていますので、よろしければこちらもご検討ください。