BIGIPで豪華なSorry画面を実装する方法~詳細解説~

F5
スポンサーリンク
スポンサーリンク

はじめに

この記事は下記のブログで解説されているiRuleの詳細解説となります。

BIG-IPでSORRY画面を表示される場合には、一般的には専用のsorryサーバを用意して、Pool Memberがダウンした場合にSORRY専用のサーバへアクセスを振り分ける事で、事前に用意したSORRY画面をクライアントに表示させることが可能です。

しかし、SORRYサーバを諸事情により用意することが出来ない場合には、BIG-IP単体でSORRY画面を表示させる必要があります。BIG-IPにはiFIleという概念があり、HTMLファイルをiFileとしてインポートすることが可能です。iRuleにこのファイルを指定することで、特定の条件下でSORRY画面を表示させることが可能です。

HTMLファイルのみを表示させるだけならば容易にすることが可能です。しかしながら、CSSや画像ファイルなどを組み合わせる場合には、実装難易度が爆上がりします。こうした問題に対して解決策を提示したのがエクセレンス★ブログさんの記事となります。

しかし、このブログの内容をすぐに理解するためにはある程度の製品知識が必要となります。そのため、この記事では詳細に解説を行うことで、少しでも無駄な時間を減らすことに貢献したいと思います。

前提

・最低限のiRuleを読む知識があること
・エクセレンス★ブログさんの記事を一通り読んでいること
・DataGroupListのStringタイプを手動で設定した経験があること(設定した経験がない方は、Local Traffic > iFile > DataGroupListを開いて新規作成してください)
※流石にこれらの前提がない状態で読んでも理解は厳しいです。

iRuleの解説

エクセレンス★ブログさんで紹介されているiRuleを整理すると下記のようになります。
こちら、筆者にて動作確認済みとなります。

when HTTP_REQUEST {

if { [HTTP::path] starts_with “/sorry/” || [HTTP::header Referer] starts_with “/sorry/” } {

if { [class match [HTTP::path] ends_with sorry_contents] } {

set ::content_name [lindex [split [HTTP::path] /] end]
HTTP::respond 200 content [ifile get $::content_name] “Content-Type” [class match -value $::content_name equals sorry_contents]

} else {

HTTP::respond 404

}

return

}

LB処理

}

 

when LB_FAILD {
    HTTP::respond 302 “Location” “https://[HTTP::host]/sorry/sorry.html”
}

 

iRuleの順番は上記である必要があります。

これだけ見ても経験が少ないと読み解くのに時間がかかってしまいます。
上から順番に解説します。

when HTTP_REQUEST {}

『HTTPリクエストをVirtual Serverが受信した場合』に{}の中で定義したアクションを実施することを意味します。
{}の中に更に処理内容を記述していきます。

if { [HTTP::path] starts_with “/sorry/” || [HTTP::header Referer] starts_with “/sorry/” } {}

これを解説する前にはまず下記を理解する必要があります。

when LB_FAILD {
HTTP::respond 302 “Location” “https://[HTTP::host]/sorry/sorry.html”
}
これは、ヘルスチェック対象のプールメンバーがダウンした場合には、一時リダイレクト先として、https://[HTTP::host]/sorry/sorry.htmlをHTTPレスポンスとしてクライアントへ返すことを意味します。[HTTP:host]はクライアントがアクセスした際に使用したURLのHOSTが入ります。
つまり、https://example.com/test/testcontentsにアクセスしようとしたクライアントの場合には、リダイレクト先としてhttps://example.com/sorry/sorry.htmlをクライアントに知らせます。
このレスポンスを受け取ったクライアントは、https://example.com/sorry/sorry.htmlへアクセスを試みます。その時にこのiRuleの処理の出番です。
[HTTP::path]はhttps://example.com/sorry/sorry.htmlの太字のことです。starts_withは『~で始まる』という意味です。つまり、リダイレクトさせたURLを条件式に引っ掛けることで、その他のクライアントからのアクセスの場合にはSORRYページに遷移をさせることを防止しています。||は『または』という意味です。[HTTP::header Referer] starts_with “/sorry/”はsorry.htmlから呼ばれるCSSやIMAGEに対応するために使用します。

if { [class match [HTTP::path] ends_with sorry_contents] }{}

ends_withは『~で終わる』という意味です。

つまり、もし、https://example.com/sorry/sorry.htmlの太字の箇所が、DataGroupListの『sorry_contents』という名前で登録したリストの中のStringにsorry.htmlがある場合には、という意味です。

DataGroupListのリストの中のStringの値を使用する場合には、class matchというコマンドを使用する必要があります。

set ::content_name [lindex [split [HTTP::path] /] end]

setは関数を定義する場合に使用します。
set ::content_nameをすることで、::content_nameは関数を表します。
この関数の中身は[lindex [split [HTTP::path] /] end]となります。

[lindex [split [HTTP::path] /]を理解するにはまず、 [split [HTTP::path] /]を理解する必要があります。『https://example.com/sorry/sorry.htmlを/(スラッシュ)で分割する』という意味なので、①https:②example.com③sorry④sorry.htmlという値がそれぞれ配列に格納されているイメージです。

[lindex [split [HTTP::path] /]とあるので、この配列の最後(Last)のインデックスを取得します。つまり、④sorry.htmlが対象となります。この処理のおかげで、::content_name = sorry.htmlとなります。

実際にはsorry.htmlから取り込まれたCSSやPNGファイルもこの条件式に当てはまるので、::content_name =test.cssになることも、::content_name =test.pngになることもあります。

HTTP::respond 200 content [ifile get $::content_name] “Content-Type” [class match -value $::content_name equals sorry_contents]

基本構文は下記となります。
HTTP::respond 200 content [ifile get コンテンツファイル] “Content-Type” MIMETYPE

HTTP::respond 200

HTTP::respond 200とすることで、SORRYページをレスポンスする場合にはステータスコード200をセットします。ここで注意なのは、ステータスコード400や500番台にするとHTMLファイルのみが出力されてしまうことです。HTMLファイルからCSSなどのファイルを読み込まなくなります。

content [ifile get $::content_name]

content [ifile get $::content_name]によって、 ifileとして登録したsorry.htmlファイルを取得してsorryコンテンツとして表示することが可能です。
実際にはsorry.htmlから読み込まれたCSSファイルやPNGファイルについても同様の処理がなされます。

“Content-Type” [class match -value $::content_name equals sorry_contents]

“Content-Type” [class match -value $::content_name equals sorry_contents]について解説します。

この構文の意味は「sorry_contentsというDataGroupListのStringの値で、それと合致するValue(=MIMETYPE)が変数 ::content_nameに格納された値と同じであるならば、それを表示させる」です。

こうすることで、読み込まれるファイルの種類(HTML、CSS、PNGなど)に応じたMIMETYPEが表示されるので、豪華なsorryページをBIG-IPだけで表示することが可能となります。

equalsは『~と等しい』という意味です。また、class match -valueは sorry_contentsというDataGroupListの中で、Stringの値に対応したValueを使う場合に使用します。

一番初めにリダイレクトされたURLの末尾はsorry.htmlであるため、sorry_contentsの中にはStringとしてsorry.html、それに対応するValueとしてtext/htmlが登録されています。

class match -value $::content_name equals sorry_contents の意味することは、『$::content_name = sorry.htmlに対応するStringがsorry_contentsで定義されている場合はそのStringに対応したValueを返す』という意味になります。そのため、text.htmlが表示されます。

実際にはHTMLファイルから読み込まれるCSSやPNGファイルも対象となるため、https://example.com/sorry/test.cssやhttps://example.com/sorry/test.pngが同様の処理をされることで、 $::content_name = test.css になる場合もあれば、$::content_name = test.pngになる場合もあります。sorry_contentsにはこれらのファイル名(String)に対応するMIMEタイプ(Value)が定義されているので、自動的に”Content-Type”として適切なMIMEタイプが定義されることになります。

このような処理をさせることで、ヘルスチェックが失敗している場合にはCSSを含むsorryコンテンツをBIG-IPだけで表示させることが可能となります。sorryサーバを専用で設置することをせずに済みます。それにより、構築・運用費用の削減、EOL対象を減らすことにつながります。

コメント