多くのアーキテクチャドキュメントには、「Ingress」と書かれた箱から Pod の列へ矢印が一直線に伸びる図があります。一見問題なさそうですが、502 エラーを調査している人が「TLS はどこで終端するのか」「接続を保持しているのはどのプロキシか」「Ingress を通っているはずのトラフィックを、なぜ NetworkPolicy がブロックするのか」と尋ねた瞬間に役に立たなくなります。よい Kubernetes Ingress 構成図は、こうした質問が出る前に答えを示します。この記事では、リクエストの経路をホップごとにたどり、最小構成の Ingress マニフェストを箱と矢印に対応づけ、レビューでよく見かける間違いを整理し、同じ図を Archboard で作る手順を紹介します。
リクエストの経路をホップごとに
https://shop.example.com/api/orders へのリクエストを、クライアントからコンテナまで追ってみましょう。
- クライアント → DNS。 クライアントが
shop.example.comを名前解決します。レコード(A/AAAA、CNAME、またはプロバイダーのエイリアス)が指すのはクラウドのロードバランサーで、ノードではありません。 - DNS → クラウドロードバランサー。 クライアントはロードバランサーに接続します。多くのクラスターでは、Ingress コントローラーが
type: LoadBalancerの Service で公開されているためにこのロードバランサーが存在し、クラウド連携がそれをプロビジョニングして、ノードポートまたはコントローラーの Pod へ直接転送します。 - ロードバランサー → Ingress コントローラー。 コントローラーは通常のワークロード(Deployment または DaemonSet)で、NGINX、Envoy、HAProxy、Traefik などのリバースプロキシを動かしています。接続を受け付け、リクエストをプロキシするのはこのコンポーネントです。
- Ingress ルール(host/path)。 コントローラーは自分のクラスの Ingress オブジェクトを監視し、プロキシ設定に変換します。Ingress オブジェクト自体はパケットに一切触れません。あくまで設定です。
- Service(ClusterIP)。 各ルールは Service の名前とポートを指します。Service は安定した名前を提供し、ラベルで Pod を選択します。
- EndpointSlices。 コントロールプレーンは、各 Service の背後にある Pod の IP を、それぞれの Ready コンディションとともに EndpointSlice オブジェクトに記録します。ingress-nginx を含む多くのコントローラーは EndpointSlices を読み取り、ClusterIP ではなく Pod の IP に直接トラフィックを送ります。それでも Service は必要です。コントローラーはそれを手がかりにエンドポイントを見つけるからです。
- Pod。 リクエストは Ready な Pod のいずれかのコンテナポートに届きます。
ingress-nginx について補足します。コミュニティ版 ingress-nginx コントローラーは 2026 年 3 月に引退し、リリース、バグ修正、セキュリティパッチはもう提供されていません。現在も最もよく知られた例ですが、新しいクラスターでは、メンテナンスが続いているコントローラーか Gateway API を選んでください。
TLS 終端:境界を決めて図に描く
HTTPS が終端する場所は、主に次の 3 つです。
| TLS の終端場所 | 証明書を持つもの | 図に描くもの |
|---|---|---|
| クラウドロードバランサー | プロバイダーの証明書サービス | 境界は LB で終わる。LB → コントローラー間を HTTP か再暗号化 HTTPS としてラベル付け |
| Ingress コントローラー | spec.tls で参照される kubernetes.io/tls タイプの Secret |
Ingress に接続した Secret。境界はコントローラーで終わる |
| Pod(パススルー) | アプリケーション | コントローラーが SNI に基づき TLS をそのまま転送。境界は Pod で終わる。Ingress 仕様ではなくコントローラー固有の機能 |
Secret は、それを参照する Ingress と同じ namespace に置く必要があります。ロードバランサーで終端してからコントローラーまで再暗号化する場合は、TLS 区間を 1 本ではなく 2 本描いてください。
ホストベースとパスベースのルーティング
- ホストベースのルーティングは、ホスト名ごとに別のバックエンドへ振り分けます(
shop.example.comとadmin.example.comなど)。ホストごとにエッジのグループを描きます。 - パスベースのルーティングは、1 つのホストを URL パスで分割します。
pathType: Prefixでは/で区切られたパス要素単位で照合するため、/apiは/api/ordersに一致しますが/apiv2には一致しません。Exactはそのパスだけに一致し、ImplementationSpecificの挙動はコントローラー次第です。 - 複数のパスが一致した場合は、最も長いパスが優先されます。実際の Ingress の多くは、ホストとパスのルールを組み合わせています。
NetworkPolicy が効く場所
NetworkPolicy は Pod のトラフィックを L3/L4 でフィルタリングし、クラスターのネットワークプラグインが対応している場合にのみ機能します。ホストやパスは認識せず、Ingress オブジェクトにも紐づきません。図の上で NetworkPolicy が関わるのは、コントローラーの Pod → アプリケーションの Pod というホップです。アプリ側の namespace に受信の default-deny ポリシーがある場合は、コントローラーの namespace からのトラフィックを許可するポリシーを追加します。たとえば kubernetes.io/metadata.name: ingress-nginx に対する namespaceSelector を使います。ロードバランサー → コントローラーのホップは、クラウドのファイアウォールルールと、コントローラー側 namespace のポリシーで制御されます。
複数の Ingress クラス
クラスターでは、公開用と社内用、あるいは移行中の旧版と新版など、複数のコントローラーを動かすことがよくあります。各コントローラーが IngressClass を受け持ち、各 Ingress は spec.ingressClassName でそのいずれかを選びます。アノテーション ingressclass.kubernetes.io/is-default-class: "true" を付けると、そのクラスがデフォルトになります。図では、コントローラーごとに専用のロードバランサーからの経路を描き、各 Ingress にクラス名のラベルを付けましょう。そうしないと、読み手はすべてを 1 つのプロキシが処理していると思い込みます。
Gateway API について簡単に
Gateway API(gateway.networking.k8s.io)は、ロール指向の新しい選択肢です。GatewayClass が実装を表し、Gateway がリスナーと TLS を定義し(通常はプラットフォームチームが管理)、HTTPRoute がルーティングルールを持ちます(通常はアプリチームが管理)。コアの HTTP ルーティングは 2023 年の v1.0 から GA です。Ingress API も引き続き GA でサポートされていますが、機能は凍結されており新機能は追加されません。図の形はほとんど変わりません。Gateway がコントローラーのリスナーの位置に、HTTPRoute が Ingress ルールの位置に入ります。
最小構成の Ingress と Kubernetes Ingress 構成図の対応
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop
namespace: shop
spec:
ingressClassName: nginx
tls:
- hosts:
- shop.example.com
secretName: shop-example-com-tls
rules:
- host: shop.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: orders-api
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: storefront
port:
number: 80
| フィールド | 図上の箱・矢印 |
|---|---|
metadata.namespace: shop |
Ingress、Secret、Service、Deployment を囲む Namespace フレーム |
spec.ingressClassName: nginx |
どのコントローラーが扱うか。そのコントローラーから Ingress への破線の「監視」エッジ |
spec.tls[].hosts + secretName |
Ingress に接続した Secret ノード。コントローラーで終わる TLS 境界 |
rules[].host |
DNS レコードのラベルと、ロードバランサーからの入口エッジ |
paths[0]: /api → orders-api:8080 |
コントローラーから orders-api Service へのエッジ(ラベル /api) |
paths[1]: / → storefront:80 |
コントローラーから storefront Service へのエッジ(ラベル /) |
backend.service.port.number |
各コントローラー → Service エッジ上のポートラベル |
/api/orders は両方のパスに一致しますが、/api のほうが長いため orders-api に送られます。
よくある間違い
- Ingress をプロキシとして描く。 LB → Ingress → Pod という図は、Ingress が Pod であるかのように読めてしまいます。プロキシはコントローラーで、Ingress はコントローラーが読む設定です。コントローラーをデータ経路上に置き、Ingress は破線のエッジでそこにぶら下げましょう。
- Service を省略する。 Ingress のバックエンドが参照するのは Pod ではなく Service です。トラフィックが Pod の IP に直接届く場合でも、ラベルがずれたときに壊れるのは Service のセレクターなので、図に残しておきましょう。
- TLS 境界がない。 HTTPS の終端場所が図にないと、VPC 内のトラフィックが平文かどうか誰にも判断できません。
- 宙に浮いた NetworkPolicy。 制御対象のホップにエッジでつながっていないポリシーは、何も説明しません。
Archboard で作る
Archboard の Kubernetes パックには、IngressClass、Gateway、Route を含む上記のオブジェクトに対応するポート付きの正式なノードがあり、DNS とロードバランサーは Network パックでカバーできます。完成版は下の図で、Archboard で開く で自分のワークスペースにコピーできます。/examples/kubernetes-ingress-flow は Ingress → Service → Pods の小さめのスケッチです。自分で作るには、次の手順に従います。
- 図を作成し、クライアント(Core の Box か Icon、または C4 の Person)を置きます。続いて Network パックから DNS ノードとロードバランサーノードを配置します。
ingress-nginxという名前の Namespace フレームを追加し、コントローラー用の Deployment と Pod を入れます。ロードバランサーからのエッジはこの Pod につなぎます。これがプロキシだからです。shopという名前の 2 つ目の Namespace フレームを追加します。その中に Ingress、Secret(shop-example-com-tls)、そして Service ノードを 2 つ(orders-apiとstorefront)置き、それぞれを Deployment と Pod に接続します。- データ経路に沿ってポートをつなぎます:クライアント → DNS → ロードバランサー → コントローラーの Pod → 各 Service(エッジに
/apiと/のラベル)→ Pod。Service → Pod のエッジには「EndpointSlices」とラベルを付けます。こうすることで、トラフィックが Pod にどう届くかが読み手に伝わります。 - コントローラーから Ingress へ破線の「監視」エッジを引き、Secret を Ingress に接続します。
shopフレームに NetworkPolicy ノードを追加し、それが許可するコントローラー → アプリケーションのホップに接続します。- 暗号化区間を Core の Frame か Box で囲んで TLS 境界を示し、どこで終端するかをラベルで書きます。
- Ingress の YAML をキャンバス上の Markdown ブロックに貼り付け、対応する箱の隣に置きます。
ダイアグラムの内容
- Kubernetes cluster
- ingress-nginx
- shop
- Clients
- DNS · shop.example.com
- Cloud load balancer
- ingress-nginx-controller
- shop-example-com-tls
- orders-api
- storefront
- allow-from-ingress
- DNS lookup
- HTTPS :443
- TCP :443
- /api
- /
- EndpointSlices
- allows ingress-nginx → :8080
- watches
- TLS certificate
Free プランでは 1 つの図につきダイアグラムノード 15 個まで、それに加えてメモ・テキスト 150 件まで使えます。上の完全な構成では 18 個使うので、コントローラーの分も含めて 3 つの Deployment ノードを外し、Service を Pod に直接つなぎましょう。トラフィックの経路はそのまま残ります。SVG や PNG(Free では透かし入り)、またはマニフェストと一緒に管理できる構造化 JSON としてエクスポートできます。クラスター全体の図は /examples/kubernetes-microservices と Kubernetes 向けの Archboard をご覧ください。公式リファレンスは Kubernetes の Ingress ドキュメントです。
よくある質問
Ingress はアプリケーションの namespace の中に描くべきですか? はい。Ingress は namespace に属するオブジェクトで、同じ namespace の Service と TLS Secret しか参照できません。コントローラーは通常、専用の namespace で動いています。
トラフィックは Service の ClusterIP を通りますか? コントローラーによります。多くは EndpointSlices をもとに Pod の IP へ直接プロキシします。それでも Service は図に描き、エッジにラベルを付けてください。
新しいクラスターでは Ingress と Gateway API のどちらを使うべきですか? コントローラーが対応していれば Gateway API です。Ingress API は凍結されています。図の描き方は同じです。