ISUCON8予選 序盤環境構築覚え書き

Category: diary

一つ前の記事は予選の流れや感想を書きましたが、こちらはISUCON8の予選の序盤にやったことのメモです。

予備知識ほぼゼロで予選に突っ込んだ初心者のメモなので初歩的な内容だと思います。

今回の予選で使用したリポジトリは https://github.com/Tatamo/isucon8-q です。

解析ツール

初心者なので、ISUCONをやる人がだいたい入れてるらしいツールを入れました。 入れるツールは予選前日の夜に適当にググって決めました。

netdata

自動インストーラが用意されており、コマンド一発でモニタリングができるところまでいくのでとても便利です。 (私は担当ではなかったのでよくわかりませんが、メンバーは一応これを入れるのに手間取っていました… ファイアウォールの設定はちゃんと見るべきらしいです) とりあえずベンチマークを走らせると負荷の状況が一目でわかりますし、負荷が上がることでベンチマークが実行されていることがわかって安心できたりします。

alp

zipを落としてくるだけなのでこちらも導入が簡単です。 ただしnginxやh2oのログの形式をalpに対応したフォーマットに変えないといけないので注意が必要です。 実際これを使って表を眺めるだけでも重そうな処理がだいたいわかってくるような気がするので、入れておくべきだと思います。

pt-query-digest

入れましたが使いませんでした。 他の人が使ったのかどうかは知りません。 そもそもめちゃくちゃ重いクエリはalpのログやソースコードを見れば見当がつきますし、それで発見できない中程度の遅さのクエリの修正にまで取り掛かるだけの時間がありませんでした。

今回は使用しませんでしたが、docker経由でphpMyAdminを使えばDBの見通しが良くなるので、導入してもよかったかと思います。

デプロイ環境構築

アプリケーションをgit管理するにしても、サーバー上で直接編集すると確実にコンフリクトします。 また、サーバーが3台あったので更新をいちいち手動で反映していると死にます。

SSH

自動デプロイの円滑化に絡んでくるため、SSHの設定は重要です。 まずローカルでは、メンバー全員で~/.ssh/configの接続ホストを共有します。

Host isuA
	HostName 222.222.222.221
	User isucon

Host isuB
	HostName 222.222.222.222
	User isucon

Host isuC
	HostName 222.222.222.223
	User isucon

のようにして、メンバー全員が同じ解決名でサーバーに入れるようにすることが必要です。 また、全メンバーは競技開始直後にssh-copy-idで自らの公開鍵を3台のサーバーすべてに送信しておきます。 ssh-addで自分の秘密鍵をssh-agentに登録しておけば、SSH鍵のパスフレーズを入力せずサーバーに入れるようになります。

次に、3台ある競技用マシンすべてで新しく鍵を作成し、これらをすべてGitHubに登録しておきます。

GitHub private repository

メンバーがローカルで編集したファイルをGitHubにpushし、競技用サーバーではそれをpullするという構成にしました。 publicなリポジトリでこれをやってしまうとレギュレーション違反で失格なので注意が必要です。 とはいえ不具合が出た時などは直接サーバーに入ったほうが楽なこともあるので、基本は編集衝突を避けてローカルで編集しつつ臨機応変に、という感じです。

私たちのチームでは、専用のGitHubアカウントを作ってそこに公開鍵を登録するようにしました。 (※GitHubの利用規約に抵触しないようにするため、 「**-bot」のような名前にして予選終了後は消すことで、Machine userと言い張ることにします。実際自動化のために用いるので…)

そして、前述したSSH公開鍵のGitHubへの登録ができたら、競技用サーバーに用意されているディレクトリをgit管理下に置きます。 このとき、~/.gitconfig に以下のように書いておきます。

[url "git@github.com:"]
	Insteadof = https://github.com/

これでgithubへのアクセスがsshを経由して行われるようになります。 サーバーのファイルを直接編集してもコミットできるように、author情報も同時に書いておくといいかもしれません。

必要ならssh-agentを起動するなどして、少なくとも認証なしでgit pullできるようになると良いです。

git管理下に置く方法としては、3台あるうち適当な1台でgit管理したい全ファイルをGitHubにpushして、他のサーバーでは既に存在するファイル群を消してから同じ場所にgit cloneするのが早いと思います。

デプロイ用スクリプトを用意する

https://blog.bitjourney.com/entry/2017/11/09/101740
ここに「デプロイスクリプトは超大事」って書いてありました。 ここで紹介されている https://github.com/gfx/isucon7-qualify のrestart.shとrestart-all-from-local.shを真似します。

https://github.com/Tatamo/isucon8-q/blob/master/restart.sh
https://github.com/Tatamo/isucon8-q/blob/master/restart-all-from-local.sh

こんな感じになりました。 おそらく重要だと思うのは、ssh isuA ... のようにメンバー全員でhost名が共有されていること、ローカルでのsshおよびサーバーのrestart.shのgitコマンドが認証なしで通るようになっていることだと思います。 SSHまわりの設定をしておけば、一切の認証が発生しないため./restart-all-from-local.shの一発で全サーバーにGitHib上の最新のコミットを反映させることができます。

実際のところ、おそらく競技サーバー側の鍵生成は必要なくて、ssh-agentで鍵を使い回せばローカルのgithub用公開鍵をそのまま使ってサーバーのgitを触れる気がしますが、あまりよく調べていません。

リポジトリで管理する範囲について

ホームディレクトリ以下にサービス名のついたフォルダがあったので、そこをgit管理すればいいかなと思いました。 nginxなどの設定ファイルの類は、リポジトリの下にetc/みたいなフォルダを作ってそこで管理しました。 サーバーごとに分ける必要が出てきたらその都度増やします。 これも自動で反映できるよう、もともとの設定ファイルをシンボリックリンクに置き換えておきます。


準備のための時間があるなら、これらの構築作業はchefやansibleやシェルスクリプトで自動化しておくと効果は高いと思います。 競技開始時にやるべきことは予め決めておけるので、そういった作業を簡単なコマンドで行えるようにしておけば確実に節約できます。