続々とELBに機能が追加されていますが、今更ですがNLBについて書きます。 今更NLBの記事を書くことに意味があるのか?と自問しましたが、一応 (初心者向け) と (HealthCheck) という切り口で、なるべく優しく書こうと思います。
NLBについて
先に言っておきたいこととして、NLBははっきり言って玄人好みで初見殺しです。いや、死ぬことは無いかも、そもそも思った通りに動かせない。
先にこの記事よりも遥かにレベルの高いものをエントリしておきます。下記を理解出来るレベルであればこのエントリは用済みです。
kanny.hateblo.jp
dev.classmethod.jp
dev.classmethod.jp
HealthCheckについて
早速本題です。 HealthCheck と ELB(TargetGroup)はセットで切り離せない存在ですが、NLBにSecurityGroupを当てることができません。
今までなら、ELBに X というSGを付けたら、バックエンドのサーバには X からのインバウンド 例えば TCP:80 とかを許可していました。SG設定できないなら、どうすんの? 答えは NLBの属するSubnetのIPレンジに対して許可するとなります。しかも上記の記事をちゃんと読んだ人ならわかるはずですが、NLBはバックエンドとの通信でAZを跨ぎません。よって、NLBが属するAZと同じAZにあるバックエンドに対して、設定すれば良いとなります。ここはAccess.logを見ても確認できます。
NLBの解説
なるべく簡単に
所謂リバースプロキシ型ではない
ALB, ELB (Classic ELB) は所謂リバースプロキシで、ロードバランサで一旦全てのリクエストを受けきって、ロードバランサのSourceIPでバックエンドにリクエストを飛ばします。当然レスポンスが戻って来るので、それを受け止めてリクエスタ(エンドユーザーのブラウザ等)に返します。雑に書くと、結構忙しい。だから暖気とか必要。 もっというと複雑なこともできる
となります。複雑なこととは SSL Terminate, Stickey Sessionなどです。
対して NLB はリバースプロキシではないです。厳密にはDSRとも違う?らしいですが、ロードバランサが一旦リクエストを受ける… の動きがなく、いきなりバックエンドのインスタンスにリクエストが来ます(来たように見えますが正しい)そして、ロードバランサを介さずレスポンスが戻ります。これまた雑に書くと、結構ヒマ、だけど複雑なことは無理
。
GCEの場合
敢えてGCEと比較します。 GCEが最初にだした、ネットワークロードバランサ(元々は単にローバランサ)はDSR方式です。ウチのLBは暖気要らずやで!どやぁ
と言っていたのはこのためです。 これは私の感覚ですが何度も出している言葉ですが、 Google は IP, AWS は DNS
という冗長のための仕組みの思想があるように思います。最初にDSRを作ったのもこの設計思想が強く反映されているように思います。しかしDSR型は機能が盛れない、SSL Terminateとかです。そこで HTTP(S) ロードバランサというリバースプロキシ型 + 地域分散型のLBを出しました。
話をHealthCheckに戻します。 GCEはHealthCheck、どうやってるのか? 答えは LB自身がヘルスチェックをせずに特定のIPアドレスからヘルスチェックが飛んでくる
、です。この特定のIPとは、プロジェクト(AWSで言うところのアカウント)が異なっても同じです。なので、ヘルスチェックだけを通す・殺すは一応可能です。
NLBのHealthCheckは誰がやんの?
誰がHealthCheckするのかは、他のLBと変わらずNLB自身がやります。
で、SGが指定できない。なので、今のところバックエンド側のinbound SG ルールを絞りたいとなったら、(個人的にはこれはやだなというのも含みますが)
- VPC の CIDRで妥協 (AWSドキュメントでおすすめとか言ってる)
- Subnet の CIDRで行く (AZ跨がない考慮を入れる・入れないで2段階)
- NLBだけを特定のSubnetに押し込めてそのCIDR (Subnetだらけになる、ただでさえ嫌いなのに)
- 固定かどうか分からないが、アクセスログに出てくるIPだけ許可する。(変わらない保証はない)
今のところ、これぐらいです。
おまけ1. 従来のPrivate Subnetにバックエンドを引っ込めるは出来るのか?
結論から言うとできます。 この構成は CLB,ALBともよくやっていると思います。バックエンドにグローバルIPアドレスを持たせない。DSRは自力でクライアントにデータを届けなくてはならないので一見無理そうですが、できます、できました。 必要なものは
- NLB は当然 Public Subnetにおく
- バックエンドは Private Subnet & グローバルIP無し(あっても意味ない)
- バックエンドが立つ Subnet は NAT-GatewayとかでOutboundが出来る
- バックエンドにSG
inbound TCP:80 0.0.0.0/0
とかを付ける
グローバルIPが無いインスタンスにinbound TCP:80 0.0.0.0/0
を付けるんです!気になるのは、NAT経由で戻る点ですが、帯域的にもまあ問題ないかと。そもそもこの構成で本当に行くなら、全AZにNAT-GW必須と言えると思います。理由は?冒頭のエントリ見直してみてください。
おまけ2. ECSと組み合わせ可能?
可能です。ただし、普通にPublic Subnetにおいてしまうと、ポート全開で丸裸にせざるを得ないので、Privateに引っ込めるのはかなりいい手だと思います。NLBもターゲットグループを参照するので、普通にECSと連携できます、Drainingはできませんが、そもそもDSR方式(じゃないけど)なら原理的にはそんなもん必要ないです。
まとめ
- healthcheck は VPC か Subnet のCIDRぐらいしか無い
- NLB + Privateに引っ込んだバックエンドの構成は可能
- ECS + NLB も一応イケる Privateに引っ込めるのがおすすめ
healthcheck はそのうち綺麗な方法がでるかも。一応、healthcheckにしか使わないよ!とUIで言って予防線張っても、ユーザーは NLBのSGに 0.0.0.0/0 とか絶対付けちゃうだろうし、NLBでIP制限出来るとか考えちゃうだろうから、NLBはSG無しとしたのは良い手だと思う。ただ、仕組み的にはhealthcheckだけSGは付けられるはず、だってhealthcheckするのは結局NLBだしローカルIPあるってことは、ENIがあるってこと、SGはインスタンスに付くのではなく、ENIに付くものなので仕組み上は絶対出来るはず。
結局あんまり初心者むけではなくなったような。。。