見出し画像

KubernetesのIngress でルーティングするのと、Web サーバ側でルーティングするのって何が違うの?

Kubernetes を使っていると、「Ingress でルーティングするのと、Web サーバ側でルーティングするのって何が違うの?」 と思ったことはありませんか?
実際、net/http や gin を使えば、アプリケーション内でルーティングできるし、Ingress を使わなくても動きますよね。
「じゃあ、Web サーバ側でルーティングすれば Ingress なんて不要では?」と考えるのも自然です。

でも、Ingress にはIngressを使う理由があります。
結論からいうと、Ingress は「どのサービスにリクエストを送るか?」を決める役割を持っている のに対し、Web サーバ側のルーティングは「アプリケーション内でどの処理を実行するか?」を決めるものです。
つまり、ルーティングのスコープが違うんです。


Web サーバ側のルーティング(アプリケーションレベル)

まず、Web サーバのルーティングは、「1つのアプリケーション内で、リクエストをどの処理に振り分けるか?」 を決めます。
たとえば、Golang の gin を使うと、こんな感じでルーティングできます。

r := gin.Default()

r.GET("/api/users", getUsersHandler)
r.POST("/api/users", createUserHandler)
r.GET("/images/:filename", serveImageHandler)

r.Run(":8080")

このルーティングでは、

  • /api/users の GET リクエスト → getUsersHandler

  • /api/users の POST リクエスト → createUserHandler

  • /images/:filename のリクエスト → serveImageHandler

と、アプリ内の処理を振り分けています。

つまり、Web サーバ側のルーティングは、「このリクエストをどの関数で処理するか?」を決める役割 を持っているわけですね。


Ingress のルーティング(Kubernetes レベル)

一方で、Ingress は 「Kubernetes クラスタ内のどのサービスにリクエストを送るか?」 を決めます。

例えば、こんな感じの Ingress 設定を考えてみましょう。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /api/
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80
      - path: /images/
        pathType: Prefix
        backend:
          service:
            name: static-service
            port:
              number: 80

この設定では、

  • /api/ のリクエスト → api-service へ

  • /images/ のリクエスト → static-service へ

と、それぞれ異なる Kubernetes の Service にルーティングされています。

Ingress は 「このリクエストはどのコンテナ(サービス)に送るか?」 を決める役割を持っています。
なので、アプリケーション内部のルーティングとは全く別の役割を果たしている んですね。


「Ingress いらなくない?」と思う場面とその問題点

ここで、「でも Web サーバ側で /api/ や /images/ のリクエストを振り分ければ、Ingress なんて不要では?」と思うかもしれません。
確かに、1つの Web サーバにすべてのリクエストを集約して、アプリケーション内でルーティングすれば、Ingress を使わずに動かすことはできます。

でも、そのやり方にはいくつか問題があります。

(1) スケールが難しくなる

例えば、API サーバと静的ファイルサーバを別々にスケールさせたい場合、Ingress を使えば 個別にスケール できますが、Web サーバでルーティングしてしまうと 1つのサーバに負荷が集中 してしまいます。

  • Ingress を使う場合

    • api-service のみをスケールアウト可能

    • static-service のみをスケールアウト可能

  • Web サーバ内でルーティングする場合

    • すべてのリクエストが 1 つのサーバに集中

    • 1 つの Web サーバがボトルネックになる

(2) 異なるサービスのデプロイが複雑になる

API サーバと静的ファイルサーバを 別々にデプロイ したいのに、Web サーバが両方を処理するルールを持っていると、アプリの更新が面倒になります。
Ingress を使えば、各サービスを独立してデプロイしやすくなる ので、変更の影響を最小限に抑えることができます。

(3) マルチドメインや外部リクエストの管理が大変

Ingress を使えば、

  • api.example.com は API サーバへ

  • static.example.com は 静的ファイルサーバへ

のように、異なるドメインのリクエストを適切なサービスに振り分ける ことも簡単にできます。
Web サーバだけでやろうとすると、リクエストのヘッダを見て処理を変えるなど、実装が複雑になってしまいます。


結論:Ingress は Web サーバのルーティングとはスコープが違う

最終的に、Ingress のルーティングと Web サーバのルーティングは、目的が違う ということです。

  • Web サーバのルーティングアプリ内のルーティング(エンドポイント単位)

  • Ingress のルーティングどの Kubernetes サービスにリクエストを送るか決める(サービス単位)

もし、Web サーバ側で /api/ や /images/ のリクエストを振り分けると、

  1. スケールしにくい

  2. デプロイが複雑になる

  3. マルチドメインや外部リクエストの管理が難しくなる

といった問題が発生します。

だから、Kubernetes では Ingress を使って「どのサービスに送るか?」を決めて、Web サーバ側で「そのサービス内でどう処理するか?」を決めるのがベスト なんです。

結局、「適材適所で使い分けることが大事」 ということですね!

いいなと思ったら応援しよう!