NodePort vs. LoadBalancer vs. Ingress: 最適なサービス公開方法の選択

NodePort、LoadBalancer、Ingressを比較しながら、Kubernetesサービスを外部に公開する重要な選択肢を解説します。このガイドでは、各方式のアーキテクチャ、動作レイヤー(L4 vs. L7)、ユースケース、コストと複雑さの主な違いを詳しく説明します。テスト用のシンプルなNodePort、単一サービス向けの専用LoadBalancer、または集中管理されたコスト効率の高いレイヤー7ルーティングと複雑なマルチサービス環境に最適な強力なIngressを、いつ使用すべきかを学びます。

NodePort vs. LoadBalancer vs. Ingress: 最適なサービス公開方法の選択

KubernetesはPodに一時的なIPを割り当て、その後Serviceを使用して安定した到達手段を提供します。クラスター内部では、通常のClusterIP Serviceで十分なことがよくあります。クラスター外部から接続する必要がある場合、問題はより興味深いものになります。

最もよく登場する3つの名前は、NodePortLoadBalancerIngressです。これらは関連していますが、互換性はありません。NodePortは各ノードにポートを開きます。LoadBalancerはインフラストラクチャプロバイダーに外部ロードバランサーを要求します。IngressはHTTPルーティングルールを定義し、それらのルールを実現するためにIngressコントローラーが必要です。


1. サービス公開タイプ: NodePort

NodePortサービス型は、サービスを外部に公開する最もシンプルで原始的な方法です。サービスをNodePortとして定義すると、Kubernetesはクラスター内のすべてのノードに特定の静的ポートを開きます。任意のノード上のそのポートに送信されたトラフィックは、直接サービスにルーティングされます。

NodePortの仕組み

  1. 指定された範囲(デフォルト: 30000-32767)内のランダムなポートが自動的に選択されます。
  2. このポートがすべてのクラスターノードで開かれます。
  3. ServiceはこのNodePortでリッスンし、トラフィックを適切なPodに転送します。

アプリケーションにアクセスするには、http://<Node_IP>:<NodePort>を使用します。

ユースケースと制限事項

機能 説明
ユースケース 開発、テスト環境、または外部ロードバランシングが外部のクラウド以外のアプライアンスによって処理される場合。
複雑さ 非常に低い。
コスト ゼロ(基盤となるVMコストを無視する場合)。
制限 外部ファイアウォールルールを手動で管理する必要がある。ノードIPは動的であることが多い。ポート範囲の制限(30000-32767)。

NodePortの例

apiVersion: v1
kind: Service
metadata:
  name: my-app-nodeport
spec:
  type: NodePort
  selector:
    app: my-web-app
  ports:
    - port: 80
      targetPort: 8080
      # オプション: NodePortを指定する。指定しない場合は自動的に選択される
      # nodePort: 30001 

警告: NodePortはノードIPとハイポートを介してサービスを公開します。特にベアメタル上で、独自の外部ロードバランサーの背後で役立つことがありますが、本番Webアプリのパブリックインターフェースとしては扱いにくいです。


2. サービス公開タイプ: LoadBalancer

LoadBalancerサービス型は、クラウド環境(AWS EKS、GCP GKE、Azure AKS)でアプリケーションをパブリックインターネットに公開するための標準的な方法です。

サービスがLoadBalancerとして定義されると、Kubernetesはクラスターのロードバランサー統合機能に外部ロードバランサーのプロビジョニングを要求します。マネージドクラウドクラスターでは、これは多くの場合クラウドL4ロードバランサーを意味します。ベアメタルクラスターでは、MetalLBなどのプロジェクトや他のローカル統合を意味する場合があります。結果として、通常はServiceにトラフィックを転送する安定した外部アドレスが得られます。

クラウドプロバイダー統合

LoadBalancerの主な差別化要因は、基盤となるクラウドインフラストラクチャとの深い統合です。クラウドプロバイダーは、ロードバランサーのライフサイクル、ヘルスチェック、ルーティングを処理します。

ユースケースとコストへの影響

機能 説明
ユースケース 専用の安定したIPアドレスを必要とするシンプルな公開アプリケーション。非HTTP/Sプロトコル(TCP/UDP)に適しています。
複雑さ 低い(設定面)。
コスト クラウド環境では、各Serviceが個別のロードバランサーリソースを作成する可能性があるため、多くの場合高くなります。
利点 即時の高可用性と自動ヘルスチェックを提供します。

LoadBalancerの例

apiVersion: v1
kind: Service
metadata:
  name: my-app-loadbalancer
spec:
  type: LoadBalancer
  selector:
    app: my-api-service
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

作成時に、クラスターはクラウドプロバイダーによって管理される外部IPアドレス(サービスのステータスに表示されます)を割り当てます。


3. Kubernetes Ingress: レイヤー7ルーティング

IngressはNodePortやLoadBalancerとは根本的に異なります。IngressはServiceのタイプではなく、通常はHTTPおよびHTTPS(レイヤー7)の外部アクセスルールを定義するAPIオブジェクトです。

Ingressは中央エントリポイントとして機能し、ホスト名とURLパスに基づいた高度なルーティングを可能にします。このアプローチは、複数のサービスを単一のIPアドレスで管理する場合に不可欠です。

Ingressコントローラーの役割

Ingressルールを機能させるには、まずingress-nginx、Traefik、HAProxy、またはクラウドプロバイダーコントローラーなどのIngressコントローラーをデプロイする必要があります。Istioなどのサービスメッシュもゲートウェイ形式のトラフィック管理を提供できますが、基本的なKubernetes Ingress APIと同じものではありません。

Ingressコントローラー自体は、通常、単一のLoadBalancerまたはNodePort Serviceを使用して公開されます。

Ingressの高度な機能

Ingressは、高度なトラフィック管理機能が必要な場合に真価を発揮します。

  1. コスト最適化: アプリケーションサービスごとに1つのLoadBalancerを使用する代わりに、単一のクラウドLoadBalancer(コントローラーを公開するため)を使用します。
  2. 仮想ホスティング: ホスト名に基づいてトラフィックをルーティングします(api.example.comはサービスAへ、www.example.comはサービスBへ)。
  3. パスベースルーティング: URLパスに基づいてトラフィックをルーティングします(/v1/usersはサービスAへ、/v2/postsはサービスBへ)。
  4. SSL/TLS終端: 証明書管理と復号化を集中的に処理します。

Ingressリソースの例

この例では、api.example.com/v1へのトラフィックをmy-api-v1サービスにルーティングします。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  ingressClassName: nginx # 使用するコントローラーを指定
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /v1
        pathType: Prefix
        backend:
          service:
            name: my-api-v1
            port:
              number: 80
  # ... 他のサービス/ホストのルール

4. 比較と選択ガイド

最適な方法を選択するには、環境、複雑さ、機能セット、運用コストなどの要素を考慮する必要があります。

機能比較表

機能 NodePort LoadBalancer Ingress
レイヤー L4 (TCP/UDP) L4 (TCP/UDP) L7 (HTTP/S)
安定性 (IP) 不安定(ノードIPを使用) 安定(専用クラウドIP) 安定(コントローラーのIPを使用)
コスト 低い(運用オーバーヘッドは高い) 高い(サービスごとのリソースコスト) 中程度(コントローラー用に1つのLoadBalancer)
ルーティングロジック シンプルなポート転送 シンプルなポート転送 ホスト名、パス、SSL終端
クラウド依存性 なし プロバイダー統合に依存 コントローラーと公開方法に依存
本番対応 場合による、通常は別のロードバランサーの背後 シンプルなL4公開には対応 HTTP/Sルーティングには対応

決定基準: 公開方法の選択

  1. 内部またはテストのみの場合: クラスター内の接続をテストするだけの場合、または外部ネットワーキングを自分で管理する場合(例:ベアメタル環境)は、NodePortを使用します。

  2. シンプルで専用のL4公開の場合: アプリケーションが非HTTPプロトコル(カスタムTCPプロトコルやUDPなど)を使用する場合、または即座に専用のL4アクセスが必要な単一のパブリックアプリケーションしかない場合は、LoadBalancerを使用します。

  3. 複雑なマルチサービスL7公開の場合: 公開するサービスが複数ある場合、パスベースまたはホスト名ベースのルーティングが必要な場合、集中SSL終端が必要な場合、または単一の外部IPを共有してクラウドコストを最小限に抑えたい場合は、Ingressを使用します。

多くの本番HTTP/Sアプリケーションでは、Ingressが証明書とルーティングを集中管理するため、通常の選択肢です。データベース、メッセージブローカー、ゲームサーバー、生のTCPサービス、またはHTTPではないものには、LoadBalancer Serviceの方が明確な場合があります。ベアメタルクラスターでは、NodePortが設計の一部である可能性がありますが、通常は適切な外部ロードバランサーまたはファイアウォールルールの背後に配置されます。

実際のクラスターでの連携方法

混乱する点の1つは、これらのオプションが互いに積み重ねられることです。Ingressオブジェクトはそれ自体でパケットを公開しません。コントローラーは何らかの方法でトラフィックを受信し、その「何らかの方法」は、クラウドクラスターでは多くの場合LoadBalancer Serviceです。

インターネット
  -> クラウドロードバランサー
  -> ingress-nginx用のService type LoadBalancer
  -> IngressコントローラーPod
  -> Ingressルール
  -> ClusterIP Service
  -> アプリケーションPod

ベアメタルでは、パスは代わりにNodePortを使用する場合があります。

インターネットまたはオフィスネットワーク
  -> 外部ロードバランサー / ファイアウォール
  -> NodeIP:NodePort
  -> IngressコントローラーPod
  -> アプリケーションService

そのため、「LoadBalancerの代わりにIngressを使用する」という言い方は少し不正確です。Ingressは依然としてロードバランサーを使用することがよくありますが、多くのHTTPアプリケーションが1つのエントリポイントを共有できるようにします。

実践的な例

ラボクラスターのデバッグ、サービスを一時的にプライベートネットワークに公開する場合、または既に管理しているロードバランシングハードウェアと統合する場合は、NodePortを使用します。これが本当に内部ツールでない限り、ユーザーにhttps://app.example.com:31427を覚えさせないでください。

1つのサービスが安定した外部アドレスを必要とし、L4転送で十分な場合は、LoadBalancerを使用します。パブリックTCP API、UDPサービス、または単一の内部管理エンドポイントは、この方法でよりシンプルになります。また、アプリケーションプロトコルが通常のHTTPホスト/パスルーティングに適合しない場合にも役立ちます。

Webアプリケーションがある場合は、Ingressを使用します。api.example.comdocs.example.comapp.example.comがすべて同じクラスターにある場合、IngressはホストルーティングとTLSを管理するための1つの場所を提供します。cert-managerを追加すると、証明書の更新が手動のサーバータスクではなく、通常のクラスターワークフローになります。

セキュリティと運用のチェック

公開オブジェクトは、本番環境の決定の一部にすぎません。エンドポイントに誰が到達できるか、TLSがどこで終了するか、ソースIPがどのように保持されるか、障害がどのように監視されるかも確認する必要があります。

NodePortを使用する場合は、ファイアウォールルールを注意深く確認してください。Kubernetesはすべてのノードでポートを開く可能性がありますが、外部の世界がそれに到達できるかどうかは、依然としてネットワークが決定します。クラウド環境では、セキュリティグループまたはファイアウォールルールでNodePort範囲を許可する必要があることがよくあります。ベアメタルでは、同じ懸念が境界ファイアウォールに存在する可能性があります。プライベート管理ツールがVPNからのみ到達可能であることを意図している場合は、Kubernetesの内部と同様に、Kubernetesの外部でもそれを強制します。

LoadBalancerを使用する場合は、プロバイダー固有のアノテーションを検査します。これらは、ロードバランサーが内部向けかインターネット向けか、使用するプロトコル、プローブするヘルスチェックパス、クライアントソースIPを保持するかどうかを制御することがよくあります。これらの詳細はプロバイダーによって異なるため、あるクラウドからコピーしたマニフェストが別のクラウドでも同じように動作するとは想定しないでください。

Ingressを使用する場合、運用の中心はコントローラーに移ります。アプリケーションPodだけでなく、コントローラーPodからのログとメトリクスが必要です。ルートが失敗した場合、ServiceとPodは正常である可能性がありますが、コントローラーがルールを拒否した、間違ったイングレスクラスを使用した、TLSシークレットを見逃した、または間違ったバックエンドパスにルーティングした可能性があります。クイックチェックリストが役立ちます。

kubectl get ingress
kubectl describe ingress example-ingress
kubectl get svc -n ingress-nginx
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller

TLSについても明確にしてください。Ingressは通常、コントローラーでHTTPSを終了し、バックエンドServiceにHTTPを送信します。これは多くの内部クラスターでは問題ありませんが、一部のチームではアプリケーションPodまでの暗号化を要求します。それが要件である場合は、Ingressが自動的に提供することを想定するのではなく、バックエンドTLSを意図的に構成してください。

一般的な障害モード

NodePortがあるノードでは機能するが別のノードでは機能しない場合は、kube-proxyまたはクラスターCNIが障害が発生しているノードで正常であるかどうかを確認してください。また、外部ファイアウォールが使用する予定のすべてのノードIPへのトラフィックを許可しているかどうかも確認してください。

LoadBalancer ServiceがPendingのままの場合、クラスターはおそらく外部ロードバランサーをプロビジョニングできません。マネージドKubernetesでは、これはクラウドコントローラー統合、権限、サブネットタグ、クォータ、またはプロバイダー固有の設定の欠如を意味する可能性があります。ベアメタルKubernetesでは、通常、ロードバランサーの実装がインストールされていないことを意味します。

Ingressがデフォルトのバックエンドページまたはコントローラーからの404を返す場合、リクエストはコントローラーに到達しましたが、ホストまたはパスルールと一致しませんでした。DNS、Hostヘッダー、ingressClassName、パスタイプ、およびService名とポートが正しいかどうかを確認してください。間違ったホスト名のTLS証明書を取得した場合は、Ingressによって参照されているシークレットと、別のIngressルールが同じホストを要求していないかを確認してください。

シンプルな決定のショートカット

プロトコルから始めてください。HTTPまたはHTTPSであり、複数のアプリが最終的にエントリポイントを共有する可能性がある場合は、Ingressを使用します。生のTCPまたはUDPであり、安定した外部アドレスが必要な場合は、LoadBalancerを使用します。テスト中、独自のネットワーク機器と統合中、またはベアメタルパスを構築中の場合、NodePortが答えの一部になる可能性があります。

次に、運用モデルを確認します。1つのパブリックAPIを実行する小規模チームは、明白でデバッグが簡単なため、1つのLoadBalancerを好む場合があります。数十のWebサービスをホストするプラットフォームチームは、共有ルーティング、証明書、ポリシーが追加のコントローラーレイヤーよりも重要であるため、通常はIngressを好みます。

最後に

どのオブジェクトがより高度に聞こえるかではなく、プロトコルと運用に基づいて選択してください。NodePortは構成要素です。LoadBalancerは簡単な外部L4アクセスです。Ingressはコントローラーを介したHTTP/Sルーティングです。小規模なクラスターでは、3つすべてが同じ設計に現れる可能性があり、それぞれに明確な役割がある限り、それは問題ありません。