LoginSignup
11
2

More than 3 years have passed since last update.

GKE(ingress)配下のNginxでClinet IPアドレスを取得する方法

Last updated at Posted at 2019-10-10

概要

GKE上にNginxのpodを起動し、起動したNginxでIPアドレスによるアクセス制御するという要件があり、
その時にいろいろハマったのでご紹介。

何にハマったのか?

構成は、

Client -> Ingress -> (NodePort) -> Nginx(pod) -> GAE(アプケーション)

という構成です。

Nginxのログはデフォルトだとremote_addrを使ってクライアントIPを出力するようなのですが、
アクセスログを見ると、remote_addrがClientのIPアドレスではなく、何やらPrivateなIPアドレスが表示されています。
この時点では、なんとなくX-Forwarded-Forの設定を入れればいいかなー?と思っていたのですが、
それだけではなかったというお話です。

調査結果

調査を進めると、LoadBalancer配下のNginxがClientIPアドレスを取得する方法が出てきました。
GCP HTTP(S) load balancing 配下のnginxでクライアントIPを取得する方法

remote_addrx-forwarded-forについては、以下のブログが分かりやすかったです。
remote_addrとかx-forwarded-forとかx-real-ipとか

上記を参考にNginxを設定しても、NginxがクライアントIPアドレスを取得できません。
ずっとNginxの設定ばかりみていたのですが、実はIngressとNginxに間にあるNodePortの設定が原因でした。

NodePortのexternalTrafficPolicyについて

NodePortはWokerノードに到達したパケットをロードバランスする機能があるようです。
その設定は、externalTrafficPolicy で設定可能で、

  • cluster(デフォルト)
  • local

が設定できます。

externalTrafficPolicy Clusterモード

デフォルトの設定です。
こちらの文献によると、

NodePortではノード上のNodePortに到達したパケットは、さらにノードをまたいだPodへもロードバランシングされる形となっています。

とあります。
このパケット転送を行う際、各Wokerノードで起動しているkube-proxyがSNATでSrouce IP AddressDestination IP Addressが書き換えられ、ロードバラシングしてるようです。

今回、 このSrouce IP Addressの書き換えによって、ClientIPアドレスの取得できませんでした。

以下、参考文献をご紹介。

Source IP for Services with Type=NodePort

externalTrafficPolicy localモード

一方、localモードでは、パケットはバラシングされません。
Clusterモードの場合、パケットを転送する分ホップ数が増えるため、結果レイテンシーが増えます。
しかしlocalモードは、当該ノード到達後にノードをまたいだロードバランシングを行わず、当該ノードのPodにパケットを転送しようとするため、Clusterモードと比較して早いようです。
よって、当該ノードに該当するラベルのPodが存在しない場合は、レスポンスを返すことができなくなりエラーが返ります。
localモードを使用する際は、全ノードへPodがデプロイされるDaemonSetが必須 ということになります。

まとめ

externalTrafficPolicyがClusterモードで動いている場合、
Client -> Ingressとリクエストが流れきて、ingressが各Wokerノードにリクエストをロードバランスする。
さらにロードバランスした先のWokerノードで起動しているkube-proxyによって、各Pod間でロードバランスされる。
この際、負荷分散対象となるPodは、NodePortでラベル指定しているPodが対象となり、そのIPアドレスは、NodePortのEndpointsに登録してある。
と理解しました。(間違ってたら指摘してください)

NodePortと一言で言っても裏ではいろんな仕組みが動いているし、そもそもその概念を理解するのが難しい。
なんとなく動いちゃってるから普段は意識しないが、こうやっていろいろ調べてみると勉強になる。

参考文献

この記事は以下の情報を参考にして執筆しました。
KubernetesのDiscovery&LBリソース(その1)
GKE/Kubernetes でなぜ Pod と通信できるのか
ネットワークの概要
Source IP for Services with Type=NodePort

11
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
2