ISUCON過去問とprivate-isuの練習環境を、 公開AMIからAWS EC2上にコマンド一発で構築・破棄するCLI。
Homebrew(macOSのみ。Cask配布なのでLinuxbrewからは入らない):
brew install kyosu-1/tap/isuenvGo:
go install github.com/kyosu-1/isuenv@latestReleases から macOS / Linux(amd64・arm64)のバイナリを直接落としてもよい。
- AWS認証情報(
AWS_PROFILEなどSDKの標準的な方法で解決される) - リージョンは ap-northeast-1 固定
- EC2の vCPU クォータ(複数台構成を使う場合は6 vCPU以上)
isuenv problems # 対応問題一覧
isuenv up isucon13 # 環境作成(1台, TTL 8h, c5.large)
isuenv up private-isu # private-isu(1台, TTL 8h, c7a.large)
isuenv up isucon13 --nodes 3 # 本番同様の3台構成
isuenv up private-isu --bench # 競技1台 + ベンチマーカー専用1台(別のインスタンスタイプ)
isuenv list # 稼働中環境と概算コスト・残りTTL
isuenv ssh isucon13 # 1号機にSSH(isucon13-2 で2号機)
isuenv down isucon13 # 環境削除
isuenv nuke # isuenv管理の全リソース削除(VPC・キーペア含む)
isuenv version # バージョン表示環境を作成し、全ノードがrunningかつパブリックIPが付くまで待ってから結果を表示する。
起動に使うAMIは問題ごとの名前パターンで毎回いちばん新しいものが選ばれる(AMI IDは固定していない)。 上流が同じパターンのままAMIを差し替えることがあるので、解決したAMIのIDと名前を起動前に表示する。
$ isuenv up isucon14
Resolving AMI for isucon14...
-> ami-0fcf9e8e8675a9ee4 (isucon14-20260818100152)
Ensuring network...
| フラグ | 既定値 | 説明 |
|---|---|---|
--ttl |
8h |
この時間が経過したら自動でterminateする(挙動) |
--nodes |
1 |
起動台数。1以上 |
--instance-type |
問題ごと | EC2インスタンスタイプ。既定値は問題ごとに異なり、isuenv problems の TYPE 列で確認できる(ほとんどは c5.large、private-isuは推奨に合わせて c7a.large) |
--bench |
false |
ベンチマーカー専用ノードを1台追加する。タイプは isuenv problems の BENCH TYPE 列の値。推奨値の無い問題ではエラーになる |
--bench-instance-type |
なし | ベンチマーカー専用ノードのインスタンスタイプを明示する。指定すると --bench は省略できる |
同名の環境が既にある場合は起動せずエラーになる。作り直すときは先に down する。
--ttl の書式は Go の duration 文字列で、単位は h / m / s。組み合わせもできる。
isuenv up isucon13 --ttl 90m # 90分
isuenv up isucon13 --ttl 2h30m # 2時間30分日を表す d は使えない。 --ttl 1d はエラーになるので、24時間なら 24h と書く。
Error: invalid argument "1d" for "--ttl" flag: time: unknown unit "d" in duration "1d"
競技ノードと同じインスタンスタイプでベンチを回すと、アプリを最適化していった先で
ベンチマーカー側が先にCPU飽和し、スコアがアプリではなく負荷生成側の性能で頭打ちになる
(private-isuを競技1台+ベンチ1台のどちらも c7a.large で回したとき、ベンチ機のidleが1〜3%まで落ちても
アプリ機には37%残っていた)。--bench はこれを避けるために、ベンチ用ノードだけ別タイプで追加する。
isuenv up private-isu --bench # 競技1台(c7a.large) + ベンチ1台(c7a.xlarge)
isuenv up private-isu --nodes 3 --bench-instance-type c7a.2xlarge # 競技3台 + ベンチ1台(c7a.2xlarge)
isuenv up private-isu --nodes 4 # 従来どおりベンチノードなしベンチノードの番号は競技ノードの次になる(--nodes 3 --bench ならベンチは4号機)。
sshのホスト名は今までどおり <問題名>-<番号> なので isuenv ssh private-isu-4 で入れる。
ベンチノードがある構成では、up の結果にタイプとロールが並ぶ。
$ isuenv up private-isu --bench
...
private-isu-1 public 1.2.3.4 private 10.100.0.1 c7a.large app
private-isu-2 public 5.6.7.8 private 10.100.0.2 c7a.xlarge bench
稼働中の環境を一覧する。
| 列 | 内容 |
|---|---|
ENV |
問題名 |
NODES |
台数 |
TYPE |
インスタンスタイプ。ベンチノードがある場合は c7a.large +bench c7a.xlarge のように混在を表す |
UPTIME |
起動からの経過時間 |
EST COST |
概算費用。ノードごとの単価で合算する。あくまで目安 |
TTL LEFT |
自動terminateまでの残り時間 |
PUBLIC IPS |
各ノードのパブリックIP |
ノードにSSHする。番号を省略すると1号機に繋ぐ(isucon13 = isucon13-1)。
実行のたびに次の2つを行うので、グローバルIPが変わったら打ち直せば復旧する。
- セキュリティグループのingressを、現在のグローバルIPで貼り直す
~/.ssh/isuenv_configを稼働中の環境から再生成する
生成されたssh configは ~/.ssh/config からIncludeされるので、素の ssh isucon13-1 やVS Code Remoteからも使える。
その環境のインスタンスをterminateする。VPC・サブネット・SG・キーペアは残るので、次の up で再利用される。対象が無い場合も成功扱い。
isuenv管理下の全リソースを削除する。yes の入力を求められる。インスタンスの終了を待ってから、キーペア・SG・サブネット・IGW・VPCの順に消す。
対応している問題と、SSHユーザー、既定のインスタンスタイプ、ベンチマーカー専用ノードの推奨タイプ
(BENCH TYPE。推奨値の無い問題は -)、ベンチ手順へのリンクを一覧する。
TTLの実体はインスタンス内の仕組みで、次の3段構えで動く。
- 起動時のuser-dataが絶対期限(UNIX時刻)を
/var/lib/isuenv-expires-atに書く /etc/cron.d/isuenv-ttlが毎分その時刻を過ぎたか判定し、過ぎていればshutdown -P now- インスタンスは
instance-initiated-shutdown-behavior=terminateで起動しているため、停止ではなくterminateされる(EBSごと消えるので課金が完全に止まる)
絶対時刻をディスクに持つので、リブートしても期限は維持される。判定が毎分なので、実際にterminateされるのは期限から1分程度あと。ノートPCを閉じてもCLIを終了しても効く。
AWS上のリソースはすべて isuenv:managed=true タグが付き、nuke の対象はこのタグで判定される。
| リソース | 内容 |
|---|---|
| VPC | 10.100.0.0/16 |
| サブネット | 10.100.0.0/24(パブリックIP自動割当ON) |
| インターネットゲートウェイ | VPCにアタッチし、メインルートテーブルに 0.0.0.0/0 を向ける |
| セキュリティグループ | 名前 isuenv。実行時のグローバルIP/32からのtcp 22/80/443 と、自身のSGからの全プロトコル(ノード間通信用) |
| キーペア | 名前 isuenv |
| EC2インスタンス | --nodes の台数(--bench 指定時はベンチ用に+1台) |
インスタンスには isuenv:env(問題名)、isuenv:node(何号機か)、isuenv:role(app = 競技ノード /
bench = ベンチマーカー専用ノード)、isuenv:expires-at(TTLの絶対期限)のタグが付く。
CLIはローカルに状態を持たず、すべてこれらのタグから復元する。
ローカルには次のファイルが作られる。
| パス | 内容 |
|---|---|
~/.ssh/isuenv.pem |
キーペアの秘密鍵(0600)。AWS側にキーペアが無いときに作成され、このファイルも上書きされる(nuke 後の up など) |
~/.ssh/isuenv_config |
ホスト定義。up / ssh / down のたびに再生成される |
~/.ssh/config |
先頭に Include 行を一度だけ追加(パスは絶対パスで書かれる) |
VPC・サブネット・IGW・SG・キーペアは無料なので、down 後にこれらが残っていても費用は発生しない。
ap-northeast-1のオンデマンド概算で、c5.large(多くの問題の既定)が約$0.107/時、
c7a.large(private-isuの既定)が約$0.129/時、c7a.xlarge(private-isuのベンチ用)が約$0.258/時。
isuenv list の EST COST はノードごとの単価を合算した概算であり、実際の課金はAWSの請求を確認すること。
コードを変更したら以下を実施する:
go test ./... && go build -o isuenv ../isuenv up isucon14 --ttl 1h./isuenv list— 環境が表示され、TTL LEFTが1h弱であること./isuenv ssh isucon14— ログインできること。sudo -i -u isuconでアプリを確認- ブラウザで
http://<public ip>にアクセスできること ./isuenv down isucon14— 削除されること./isuenv list— 空になること- (まれに)
./isuenv nukeでVPCまで消えることをAWSコンソールで確認 - 複数台構成の疎通確認:
./isuenv up isucon13 --nodes 2→./isuenv ssh isucon13(1号機)でログイン →nc -zv <2号機のprivate ip> 22が成功すること(SGの自己参照ルールでノード間通信が通ることの確認)→./isuenv down isucon13
private-isuは提供元AMIがmatsuu/aws-isuconと別物なので、TTL(user-data)が効くかを個別に確認する。
./isuenv up private-isu --ttl 15m—c7a.largeで起動すること./isuenv list— EST COST が-でなく金額で出ること(cost.goに c7a.large の単価があること)./isuenv ssh private-isu— ログインでき、ブラウザでhttp://<public ip>が見えること- TTLの実体確認(ここが効かないと課金が止まらない):
cat /var/lib/isuenv-expires-at # UNIX時刻が入っていること ls -l /etc/cron.d/isuenv-ttl # 存在すること
- ベンチが通ること:
sudo su - isucon /home/isucon/private_isu/benchmarker/bin/benchmarker \ -u /home/isucon/private_isu/benchmarker/userdata -t http://localhost
- 15分後に実際にterminateされること(
./isuenv listが空になる) - ベンチ専用ノード構成:
./isuenv up private-isu --bench --ttl 1h→./isuenv listの TYPE がc7a.large +bench c7a.xlarge、EST COST が2台の単価の合算になること →./isuenv ssh private-isu-2でベンチ機(c7a.xlarge)に入れること →./isuenv down private-isu
main にタグを打つと GitHub Actions(.github/workflows/release.yml)が goreleaser を回し、
GitHub Releases へのバイナリ公開と kyosu-1/homebrew-tap の
Formula 更新まで自動で行われる。
git switch main && git pull
git tag v0.1.0
git push origin v0.1.0- タグは
vX.Y.Z形式のみ発火する(v0.1.0-rc1などは対象外) - tap への push には
HOMEBREW_TAP_TOKENシークレット(homebrew-tap へのContents: writeを持つPAT)が必要 - 設定を変更したらタグを打つ前に
goreleaser checkとgoreleaser release --snapshot --cleanで確認する(CIでも自動で検証される)
- ベンチマーカーはAMIに同梱されている。実行方法は問題ごとに異なるので
isuenv problemsのNOTESのリンク先を参照 - 消し忘れてもTTLで自己消滅するが、
isuenv listでの確認を習慣にすること
MIT License. 詳細は LICENSE を参照。
利用しているAMIは matsuu/aws-isucon(MIT)と catatsuy/private-isu(MIT)が公開しているもので、 本ツールはそれらのAMIを起動・破棄するだけであり、AMIそのものは配布していない。