ISUCON13で13位だった

この記事は CAMPHOR- Advent Calendar 2023 の 1 日目の投稿です。

どうも、@saza_ku です。チーム MONOS として ISUCON13 に参加したので色々と振り返ります。

戦歴は以下の通り。

  • ISUCON11: 何もできず、ほぼ初期スコアで予選落ち
  • ISUCON12: 惜しいところまで行ったが、fail して予選落ち

今年は予選なしの一発本選でしたが、前回までから一気に飛躍して全体 13 位、学生 3 位という好成績を取りました。いい話。

ISUCON13の結果スクショ

ISUCON13 で 13 位という栄えある順位でした。

チーム

改めてみると非常に良いバランスのチームですね。ちなみにチーム名の MONOS はメンバーのそれぞれの ID からいい感じに文字列を抜き出してくると作れます。

オペレーション自動化

昨年はオペレーションミスにより fail というつらい終わり方をしたため、今年はオペレーションの自動化に力を入れました。
できるだけ SSH せずに済む、インフラにステートを持たせない、計測結果が参照しやすい、複数台構成でもそのまま使える、などの要件を設定していい感じにできないかな〜と考えました。
最終的には、ローカルで書いたコードやミドルウェアの設定ファイルなどがコマンド一発で各サーバーにデプロイされて、ベンチマーカーを回すと自動で計測スクリプトが走り、ベンチマークが終わった頃に自動で GitHub のリポジトリに Issue が立ってそこに計測結果が書き込まれる、という仕組みを作りました。Ansible とか rsync とか GitHub の API などを使っています。Issues に計測結果を貼るようにすることで修正との対応が取りやすいというのが推しポイントです。

こんな感じ

計測結果のスクショ

これのおかげでオペレーションの手間が省けたり、複数台構成でも一瞬でデプロイと計測ができたりと、今回の結果に大きく影響していたと思います。

やったこと

リポジトリは Saza-ku/isucon13 にあります。
以下は主に僕の動き方の振り返りになります。他のメンバーがやってたことは @hiroyaonoe のブログ に書かれています。(いい感じの時系列順に整理されており大変見やすい)

9:30 ~ 10:00

朝マックを食べながらリポジトリを作ったりなんやかんや準備をしました。

10:00 ~ 10:30

競技開始後 CloudFormation を立ち上げます。AWS のリージョンを間違えており 15 分ロス。

10:30 ~ 11:15

サーバーに計測ツールやスクリプトを仕込んだり、コードをローカルに落としてきたりといった準備をして、初めの計測をやろうとしていました。/etc/hosts のフォーマットを間違えるなどモタモタしていました。

11:15 ~ 11:45

ベンチマーカーを回すも DNS 周りのトラブルで計測できず。ゾーン情報をリセットしたり DNS の問い合わせ先を変えたりするなどしてやっと対応。

11:45 ~ 12:15

ようやくベンチマーカーが正常に回り、計測完了。僕がモタモタしている間に他のメンバーたちがエスパーでいい感じに修正してくれてたやつをマージするなどしました。

とりあえず app が使っている MySQL を2台目のサーバーに移して複数台構成にしました。MySQL の bind-address を書き忘れるなどしてモタモタしていました。

12:15 ~ 12:45

2 台目に app の MySQL を移してもなお 1 台目の CPU 使用率は MySQL が支配的だったので、PowerDNS が使う MySQL を 3 台目に分離した。加えて MySQL や nginx の秘伝のタレを流し込むなどしました。

他の 2 人が app 側の修正をモリモリやってくれていたので、インフラ担当として DNS 水責め攻撃の対策をしようとしました。ここからが地獄の始まりだ

12:45 ~ 17:15

なんとこの 5 時間半ほど、1 コミットもできませんでした。DNS 水責め攻撃をいい感じに捌こうとあれこれ調べたり試したりしましたが、なんの成果も得られませんでした

DNS サーバーの運用とか DDoS 攻撃の対策とかやったことないので、「DNS水責め攻撃 対策」みたいな感じでググりました。すると作問者の方のブログとか発表資料とかがたくさん出てきて笑顔になりました。

まずは dnsdist の導入をやろうとしました。ドキュメントを読んだり手元で触ったりして何ができるかとかを調べましたが、アローリストにサブドメインを動的に追加するのがかなり厳しそうだったので諦めました。

次に PowerDNS のレコードを MySQL ではなくオンメモリで持たせようとしました。PowerDNS でメモリ上にレコードを持たせるには設定ファイルを読み込ませるという形を取る必要があるらしく、やはり動的にアローリストを追加することができず、断念。

最後に試したのが、全てのサブドメインに対して A レコードを返し app 側で存在しないサブドメインへのアクセスに対しては 404 を返す、という実装。これなら PowerDNS のレコードをオンメモリ化しつついい感じに攻撃を捌くことができそうだと思ったんですが、どうやらベンチマーカーの仕様的に存在しないサブドメインであっても A レコードを返したからには app 側でも正常系(200 番台)のレスポンスを返す必要があるらしく、fail でした。

この時点で試合終了間近になってしまい、結局何もできず。
「DNS サーバーの運用経験を積みたい人生だった」「つらすぎる〜」「まず DDoS とかやってるやつキモすぎる」など意味のない言葉を叫びながら椅子を温めた 5 時間半でした。

しかし裏では他の 2 人がすごいペースで改善を積んでいってくれたようで、結構良いスコアが出ていました(70000 点ぐらい)。
主に @moririn2528_c が SQL の改善、@hiroyaonoe がアイコン画像の処理をやってくれたらしいです。

17:15 ~ 17:40

ここで PowerDNS の MySQL サーバーをよく調べてみるとインデックス貼れることに気付きやってみました。すると PowerDNS の MySQL サーバーの負荷は下がったものの、スコアは下がってしまいました。なぜなのかはわからないんですが、PowerDNS の応答が早くなったことで水責め攻撃の並列度が上がってしまったからかなと想像しています。結局インデックスは剥がして元通りにしました。もしかするとインデックスを貼った上でさらに PowerDNS も 3 台目に移すとかするとスコアが上がったかもしれないなぁと試合後に思いました。

17:40 ~ 18:00

最後に @hiroyaonoe がやってくれたキャッシュ化の改善を入れて、さらにログとか netdata を止めた状態でベンチマーク回すと、11万ぐらいのスコアが出ました。終了直前に申し訳程度の再起動試験とブラウザチェックをやって終了。(再起動試験対策は、ちゃんとやろう)

振り返り

よかったこと

  • 初手で複数台構成組むという方針は事前に決めていたのですが、かなり有効でした。
  • 役割分担がうまくいっていました。インフラ担当の @saza_ku が DNS、アプリもインフラも見れる @hiroyaonoe がアイコン、アプリ特化の @moririn2528_c が SQL などの改善というように、チームメンバーの特性に合った分担ができていました。(DNS に関しては結局何もできなかったのだが...)

ダメだったこと

  • 序盤のオペレーションミスが多すぎる。落ち着こう。
    • チートシートをもう少し充実させた方がよかったかもしれないです。
  • 結果論になってしまうかもしれないんですが、DNS は諦めた方がよかったです。自分が DNS 諦めてアプリの改善に入ってればもっと高得点取れたことを考えると、非常に悔しい。
    • DNS をどうにかしないとスコア上がらないみたいな状況になるまで放置するという方針を取ることもできたのです。
    • が、その状態になって初めて DNS の諸々を調べ始めていると流石に間に合わない気がしたので、やっぱり今回の作戦が合理的だったようにも思えますね。
    • ただ、さすがに時間かけすぎなのでぼちぼちのところで打ち切りにしておくという判断ができればよかったです。
  • ベンチマーカーが不具合で動かないという自体が多発したんですが、そういう事態を想定していなかったのは良くなかったかもしれないです。
    • ベンチマーカーが動かなくてもある程度デバッグできるような仕組みを何か作っておいた方が良いかもしれないです。

感想

5 時間半 DNS に費やして結局何もできなかったので、なんか振り返ってみると ISUCON らしいこと何もできなかったですね。立ち回り方次第でまだまだスコアも出そうだったし、悔しいこともたくさんありますが、去年までと比較してかなり良い成績を残せたこと自体がとても嬉しいので、割と良い気分ではあります。

後半からほぼ 2 人チームみたいなものだったのにここまで良いスコア出してくれて、チームメンバーたちほんとすごいなという気持ちです。ありがとう。

問題については、今まで通りの要素と今までと違う要素がちょうど良いバランスでとてもよかったと思います。今まで通りの要素ばかりだと知識ゲーというか経験ゲーになって面白くないし、逆に今までと違いすぎると競技性が低くなってしまうし、その辺のバランスってかなり重要で難しそうだなと思っているんですが、今回は非常に良い具合になっているのではないでしょうか。

来年も開催されるかはわかりませんが(開催されてほしい...!)、開催されたら次こそは入賞したいです。

運営の方々へ。お疲れ様でした。今年も楽しいイベントをありがとうございました。是非とも来年もよろしくお願いいたします。

おまけ

15 時ごろに突然訪れたスクショタイム。

一瞬だけ2位になった時のスクショ