ヘルスチェックが何なのか全く分かってなかった件

この記事はだいぶ前に書かれたものなので情報が古いかもしれません
ゼーットみたいな感じで

おまとめ三行

この可愛い娘は本当にこのお店にいるのかな?
うっかり八兵衛よりもうっかりしてました
ワンピースのゲダツよりもうっかりしてました

ヘルスチェックって言っても、あれですよ。デリバリーヘルスのサイトを見て「この可愛い娘は本当にこのお店にいるのかな?」って思って、他県にある別のお店を見て同じ写真がないかチェックする……みたいなことではないですよ。

こないだ、初めてロードバランサーってのを使ってみまして……ええ、実は今まで使ったことなかったんですよ。使い方もよう分からんかった、今までは。

僕は仕事でAWSのサーバーを使ってるんですが、AWSはロードバランサーの設定がそんなに難しくない。SSLの証明書を使うこともそんなに難しくないし、ドメインを当てるのもそんなに難しくない。まあ、その辺の設定については機会があれば語るとして、今日は、そのロードバランサーにおけるヘルスチェックについて、僕が全っ然何も分かってなかったっつー話をさせていただきやす。



Health Checkとは

どういう風に説明するのが正しいのかはよく分からないのですが、とりあえず、ロードバランサーと対象のサーバーがつながっているかどうかを確認するような機能です。僕たちがロードバランサー経由でウェブサイトを見れるかどうか、一定時間ごとにチェックしている、そんな感じの機能です。

じゃあどうやってチェックしてるのかって話なのですが、AWSの場合(他の場合も同じかもしれないけど)、コンソール画面で設定しているヘルスチェック用のURLにアクセスできるかどうかで判断してます。そのURLからHTTPステータスの200が返ってくればOK。うっかり404とかが返って来ちゃうと、ロードバランサーの方で設定しているURLにアクセスしても、サイトが表示されません。

僕はまず、これが分かっていませんでした。だから後述するようなうっかりミスをしてしまいました。うっかり八兵衛よりもうっかりしてました。

AWSの場合、ELBとEC2が正常につながっている場合は「InService」というステータスになります。上手くつながらない場合は「OutOfService」というステータスになる。これはコンソール画面で確認できます。

アウトオブバウンズみたいだね

この画像の場合、ロードバランサーに二台のインスタンスがくっついているのですが、片方は「OutOfService」なのでロードバランサー経由ではアクセスできない状態です。



Health Checkの設定

ヘルスチェック用のURLもAWSの場合はコンソール画面から行います。上の画像の上部に「Health Check」っていうタブがありますが、そこから設定できる。

ヒムさんチェックみたいだね

実際の設定画面はこんな感じ。真ん中辺りに「Ping Path」ってのがありますが、そこに適当なURLを入れる。ただし適当っつっても、あまり適当すぎると後で良くないことが起こるかもしれない。そう、僕のように。

ProtocolやPortはそれぞれ「HTTP」「80」で良いでしょう。もし対象のEC2インスタンスがHTTPではアクセスできない場合や80番ポートを解放してない場合は、この値を別にしなきゃいけないけど。

上の画像ではPing Pathが「health.html」ってなってますので、あとはインスタンスのドキュメントルートに「ヘルスチェーック!!(CV:水木一郎)」とでも書いたhealth.htmlを置いときゃ、ELBとEC2が正常につながった状態を保てます。

僕はここもよく分かってなかった。僕の中でヘルスチェックってのは初期設定みたいなものだと思ってたので、一回無事に「InService」の状態になれば、ここは何でも良いんだと思ってました。だから適当に「test.php」みたいな感じにしてた。

これが後に悲劇を招くことに……完全にうっかりしてました。ワンピースのゲダツよりもうっかりしてました。



うっかりファイルを消してしまった

基本的には問題なかったんです。実際、僕はインスタンスのドキュメントルートに「test.php」を置いてました。ちょっとした動作検証に使ってたファイルで、「phpinfo()」とか出力させたりしてました。

んで、テスト環境で実際にロードバランサーを使ってみて、それで上手く行ったから、本番環境の方も全く同じ手順で、Ping Pathを「test.php」にして、それで無事にELB経由でアクセスできることも確認しました。

でもtest.phpなんて、本番環境の方ではわざわざ残しておく必要のないファイル。ってか残してて誰かがうっかりアクセスとかしてきても困っちゃう。そんなわけで後日、test.phpが本番環境に残っていることに気づいたときに、このファイルを削除してしまったんですね。

ここまで読んできた方はもうお分かりだと思いますが、ELBってのはヘルスチェックを行って404エラーとか返ってきちゃうと、OutOfServiceの状態になってしまう。そして僕がPing Pathに設定していたtest.phpは、削除された状態。つまり「http://sample.com/test.php」にアクセスすると、404エラーが返ってきてしまうわけですね。

そんなことは露知らずな僕は、うちのウェブサービスを使っているお客さんから「何かサイトにアクセスすると画面が真っ白なんですけど」ってお問い合わせが来るまで、完全に気づいていませんでした。しかもお問い合わせが来た後も、ヘルスチェックに200が返ってくるものを設定してないせいだってことを知らないから、一向に直すことができない。ネットで検索しても「インスタンスを一回外して再度くっつければInServiceの状態に戻る」っていう情報ばっかり出てくるから、それを試すも元に戻らない。

もう、めっちゃ焦りましたね。よりにもよって、それなりにアクセスの多い時間帯にそんなことしちゃったもんだから、もうどうしたら良いのか分からなくて、急遽新しいロードバランサーを起動して、そっちで再設定しようかと思ったほどでした。でもまあ、何とかそうなる前にヘルスチェックにtest.phpなんて設定してたのがダメらしいってことが分かったおかげで、何とか事なきを得ました。いや、本番稼動しているウェブサイトが一時間近くアクセスできない状態だったから、事なきを得たと言っていいかは怪しいけれども。先方さんには謝り倒しておきました。

ヘルスチェックの設定がちゃんとできていれば、確かにOutOfServiceになってもインスタンスをくっつけ直すだけでInServiceの状態に戻りました。実際に試してみたから間違いない。



OutOfServiceになっちゃうパターン

僕のうっかりミスは論外として、どういうときにOutOfServiceになってしまうかってことなんですけど、ELBにくっつけた状態のままEC2インスタンスを再起動した場合なんかに、OutOfServiceになってしまうようです。これも実際にやって試してみた。

なんで、インスタンスを再起動する際は、一度ELBから外して、それで再起動をしてもう一度くっつけるっていう作業が必要みたいですね。

あと、ヘルスチェックで200が返ってこないといけないってことなので、当然ながらBASIC認証なんかかけちゃったりすると、OutOfServiceになります。401エラーが返ってきちゃいますからね。これもやってみたから間違いない。

もしELBを使っていてBASIC認証をかける必要がある場合は、ヘルスチェック用のURLだけは認証が効かない状態にしておかないといけません。上記の場合だと「health.html」だけ認証から外すことになりますね。まあ、それかPing ProtocolをHTTPじゃないやつにすればすれば良いのかな……? ヘルスチェック用に適当なTCPポートを開いてやれば、BASIC認証は関係なくなると思うけど、その辺は試してないんでちょっと分かんないっす。すまんっす。そういうのやりたい方は別途ググってくだせえ。

ちなみに特定のURLだけ認証から外すのは、.htaccessの設定でできます。

AuthUserFile /var/www/html/.htpasswd
AuthGroupFile /dev/null
AuthName "Protected"
AuthType Basic
require valid-user

Satisfy Any
SetEnvIf Request_URI "/health.html" healthcheck
Order Deny,Allow
Deny from all
Allow from env=healthcheck

例えば「/health.html」だけ外すなら、こんな感じかな。






ってなことで、ヘルスチェックの話でした。

まあ、ようは俺みたいに「test.php」みたいな適当なことすんなっつー話よ。分からないことがあったらテストのうちにきちんと調べとけっつー話よ。そういうの知らないで本番稼動しちゃうと、オジサンのようになっちゃうからね。気をつけましょうね。

デリバリーヘルスのサイトで見つけた可愛い娘さんとどうしても本番がしたい場合も、気をつけましょうね。

まだコメントはいただけてないみたい……
もしかしたら何か関連しているかも?