Kubernetes の LoadBalancer, Ingress と OpenShift の Routes の仕組み

Kubernetes の Service を調べていて、ネットワーク周りの実体が上手く想像出来なかったのでまとめてみました. ついでに OpenShift の Route も比較しています.

 

Kubernetes の Service は以下の4種類があります.

  • ClusterIP
  • NodePort
  • LoadBalancer
  • ExternalName

Service の説明はこちらの記事が分かりやすかったです.

Cluster IP と NodePort は Kubernetes の系の中のことなのでおおよそ想像することが出来たのですが、LoadBalancer からネットワークコンポーネントの実体がわからなくなりました.

ということで、Kubernetes のネットワーク周りを整理してみます.

Kubernetes LoadBalancer

LoadBalancer は以下の図のように、各ノードの特定のポート(図においては42397)に向けて負荷分散装置がトラフィックを振り分けます. 図において、Node が3枚重ねになっているところがポイントです. 負荷分散装置が各物理ノードに対してトラフィックを振り分けるのです.


“Kubernetes道場 9日目 – Serviceについて”より引用

では、この負荷分散装置はどこにデプロイされているのか?
負荷分散装置のルーティング設定はどこで行われているのか?
そんな疑問が湧くかと思います(私は湧きました)

それはこちらの記事で説明されています.

記事では HA-Proxy を使って負荷分散装置を構成されています.
設定は以下のようなものです.

listen http-in
    bind *:80
    server server1 172.18.201.121:30692
    server server2 172.18.201.122:30692
    server server3 172.18.201.123:30692
EOF

“Kubernetes の Service type LoadBalancer を手作業で作る”より抜粋

当たり前と言えば当たり前ですが、負荷分散装置は Kubernetes とは関係ないところにデプロイされていて、各物理ノードのIPとポートがルーティング設定に記載されています.

ではなぜ GCP や AWS 等の各クラウドベンダーにおいては特段苦労することなく LoadBalancer を使えるかと言うと、それは各ベンダーが先述のような負荷分散機構を作り込んでいるからです.

GKEやAWSなどのクラウドプロバイダではLoadBalancerタイプをデフォルトでサポートしており, GKEの場合は Cloud Load Balancing が自動的に利用され, L4 (TCP/UDP)のロードバランサとして動作します.

“KubernetesにおけるLoadBalancerとIngressの違いについて”より引用

というわけで、LoadBalancer はとてもお手軽にルーティング設定を作れますが、裏では従来的な負荷分散機構が普通に動いているということでした.

 

Kubernetes Ingress

ではこれが Ingress ではどうなるか、というのが次の話です.

Ingress については以下の記事がわかりやすかったです.
(結局オレオレ LoadBalancer なり Ingress を作ってみるのが一番理解できるのがわかってきた)

結局のところ、LoadBalancer と仕組みは同じで、各物理ノードの NodePort に対してトラフィック振り分けを行なっているだけです(この表現で言い切って良いか少し自信がありませんが).


“[Kubernetes] オンプレでも GKE Like な Ingress を使うために 自作 Ingress Controller を実装してみた”より引用

SSL 終端や L7 パスベースルーティング及び L7 ロードバランシングを行ってくれるのが LoadBalancer との違いでしょうか.

また、Ingress は CRD に近いという表現もかなりしっくり来ました.
これも LoadBalancer と同様にクラウドベンダー作り込みの負荷分散機構であり、GKE では Google Cloud LoadBalancer が実体のようです.

  • Ingress
    • Kubernetes のリソースの1種
    • ただの定義にすぎないため登録しただけでは何も起こらない(イメージ的には Custom Resource Definision に近い)
  • Ingress Controller
    • Ingress リソースの定義を読んで L7 ロードバランサを用意する

 

さて、ここまでで LoadBalancer も Ingress も YAML を適用すれば勝手にルーティングしてくれる魔法などではなく、裏には実体のある負荷分散装置が存在していることがわかりました.

この辺の実体に関して言及している記事が少ないように思えて少し混乱しました(YAMLのサンプルはたくさんあるが…)

 

OpenShift Route

最後に OpenShift の Route を比較します.

OpenShift の Route は先の Ingress の記事で言及されている Nginx Ingress Controller に動作原理的には近いように思えます.
図示するとまさしくこの図になるはずです.


“[Kubernetes] オンプレでも GKE Like な Ingress を使うために 自作 Ingress Controller を実装してみた”より引用

Router は Pod として各Infra(Worker)ノードにデプロイされています.
Router は hostnetowrk を利用して物理ノードの80ポートと443ポートを LISTEN していますので、前段に置く負荷分散装置が各物理ノードの80/443にトラフィックを振り分けます.
ここでも結局は Kubernetes の外にある負荷分散装置が登場するのです.

Route や Nginx Ingress Controller が LoadBalancer/Ingress と大きく違うところは NodePort(Service) を経由しないことです.

よくある勘違いとしてRouterはServiceにリクエストを転送する、というのがありますが、Serviceは基本的にヘルスチェックが不完全なL4ロードバランスとなっているため、Serviceにリクエストを転送したりはしません。RouterはPodのEndpointをバックエンドサーバとして登録するようになっており、そちらに転送します。oc exposeではServiceを指定するとRouteが作成されることがこの誤解の原因の一つだと思いますが、設定ファイルhaproxy.configを見るとそれは正しくないことがわかります。

“OpenShiftのRouteとRouter”より引用

この Service を経由しないルーティング経路を見ると「もしや Service を作らないで良いのか?」と思うかもしれませんが、それは出来ません.
Router は Service を経由して Pod の位置情報を取得しているので Service の作成は必須になります.

 

まとめ

いくつかの記事を引用して Kubernetes の LoadBalancer/Ingress, OpenShift の Route の仕組みを比較してみました.

結局のところ、Kubernetes の前段に負荷分散装置は必ずいるわけでして、YAML を適用するだけ振り分け設定が完成する魔法は、各クラウドベンダーの作り込みのおかげでした.

こういう仕組みを紐解いていくと、マネージド Kubernetes はすごく便利に出来ていると実感できます. オレオレ Ingress を作って運用するのは結構大変そうですよね.

その点、とにかく物理ノードの80/443にトラフィックを割り振れば良い OpenShift の Route は非常にお手軽と言えます.
従来の VM に対する振り分け設定と全く変わりませんね.

 

Kubernetes のネットワーク周りについてでした.

 

以上です.