Skip to content

필사 모드: IngressClass 詳解 — 1つのクラスタで複数の Ingress Controller を運用する

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

はじめに: コントローラが1つでは足りないとき

小さなクラスタでは Ingress Controller が1つで十分です。しかし運用規模が大きくなると、1つのクラスタにコントローラが2つ以上必要な状況が自然に生じます。たとえば、インターネットに公開される外部トラフィックと、社内ネットワークにのみ公開される内部トラフィックを分離したいとき、あるいはチームごとに独立した入口を置きたいとき、または ingress-nginx から別のコントローラへ段階的に移している最中などです。

このとき鍵となるメカニズムが **IngressClass** です。IngressClass は「この Ingress リソースをどのコントローラが処理するか」を決めます。本記事では IngressClass リソースの構造、デフォルトクラス、マルチコントローラのシナリオ、コントローラのスコープ設定、競合の防止、運用・コストの考慮を実務視点で深く扱います。

IngressClass リソースとデフォルトクラス

IngressClass はクラスタスコープのリソースで、どのコントローラ実装がこのクラスを担当するかを `spec.controller` で明示します。

apiVersion: networking.k8s.io/v1

kind: IngressClass

metadata:

name: nginx-external

spec:

controller: k8s.io/ingress-nginx

apiVersion: networking.k8s.io/v1

kind: IngressClass

metadata:

name: nginx-internal

spec:

controller: k8s.io/ingress-nginx

ここで2つの IngressClass が同じ `controller` 文字列(`k8s.io/ingress-nginx`)を使っている点に注目してください。`controller` 値は「どの種類のコントローラ実装か」を示すだけで、クラス自体は名前(`nginx-external`、`nginx-internal`)で区別されます。つまり同じ種類のコントローラを複数インスタンス立て、それぞれ異なるクラスを担当させられます。

Ingress リソースは `spec.ingressClassName` で自分がどのクラスに属するかを宣言します。

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: api-ingress

spec:

ingressClassName: nginx-external

rules:

- host: api.example.com

http:

paths:

- path: /

pathType: Prefix

backend:

service:

name: api-service

port:

number: 80

デフォルトクラス

IngressClass に次のアノテーションを付けると **デフォルトクラス** になります。

apiVersion: networking.k8s.io/v1

kind: IngressClass

metadata:

name: nginx-external

annotations:

ingressclass.kubernetes.io/is-default-class: "true"

spec:

controller: k8s.io/ingress-nginx

`ingressClassName` を指定しない Ingress はデフォルトクラスへ自動的に割り当てられます。注意すべきは **デフォルトクラスはクラスタに1つだけであるべき** という点です。2つ以上を default に指定するとどれが適用されるか曖昧になるため、マルチコントローラ環境ではできるだけすべての Ingress に `ingressClassName` を明示するのが安全です。

アノテーション vs spec.ingressClassName

かつてはクラスを次のアノテーションで指定していました。

metadata:

annotations:

kubernetes.io/ingress.class: nginx

しかしこの方式は **deprecated** であり、現在の推奨方式は `spec.ingressClassName` フィールドです。両者の違いは次のとおりです。

| 区分 | kubernetes.io/ingress.class(アノテーション) | spec.ingressClassName(フィールド) |

| --- | --- | --- |

| 状態 | deprecated | 推奨 |

| 検証 | 自由文字列、検証なし | IngressClass の存在を検証可能 |

| デフォルトクラス | 非サポート | is-default-class でサポート |

| マルチコントローラ | 動作するが非標準 | 標準メカニズム |

新規環境ではアノテーションを使わず `spec.ingressClassName` を使ってください。ただし一部のコントローラは後方互換のため依然アノテーションを認識するので、移行中は両方式が混在することがあります。その場合どちらが優先されるかはコントローラ実装によって異なるため、一方に統一すると混乱が減ります。

コントローラのスコープ — どの Ingress を watch するか

同じ種類のコントローラを複数インスタンス立てるときは、各インスタンスが **自分の担当するクラスの Ingress だけ** を処理するようにスコープを狭める必要があります。ingress-nginx はそのためのいくつかの引数を提供します。

--ingress-class / class の設定

各コントローラインスタンスに担当クラスを指定します。ingress-nginx の Helm values の例は次のとおりです。

controller:

ingressClassResource:

name: nginx-external

enabled: true

default: false

controllerValue: "k8s.io/ingress-nginx"

ingressClass: nginx-external

electionID: ingress-nginx-external-leader

内部用コントローラは別の values でデプロイします。

controller:

ingressClassResource:

name: nginx-internal

enabled: true

default: false

controllerValue: "k8s.io/ingress-nginx"

ingressClass: nginx-internal

electionID: ingress-nginx-internal-leader

ここで `electionID` をインスタンスごとに異なる値にするのが重要です。同じリーダー選出キーを共有すると2つのインスタンスが互いに干渉することがあります。

watch-namespace

コントローラが特定の名前空間の Ingress だけを watch するよう制限することもできます。

controller:

scope:

enabled: true

namespace: team-a

こうするとチーム A のコントローラは team-a 名前空間の Ingress だけを処理します。クラスベースの分離と名前空間ベースの分離を組み合わせると、より細かい隔離が可能です。

マルチコントローラのシナリオ

実務でよく登場する3つのシナリオをまとめます。

1. 内部/外部の分離

最も一般的なパターンです。外部コントローラはインターネットに公開される LoadBalancer を、内部コントローラは社内ネットワーク専用の LoadBalancer(または internal LB)を使います。

Internet Internal Network

│ │

▼ ▼

┌──────────────────┐ ┌──────────────────┐

│ External LB │ │ Internal LB │

└────────┬─────────┘ └────────┬─────────┘

│ │

▼ ▼

┌──────────────────────┐ ┌──────────────────────┐

│ ingress-nginx │ │ ingress-nginx │

│ class: nginx-external │ │ class: nginx-internal │

└──────────┬───────────┘ └──────────┬───────────┘

│ │

▼ ▼

public services admin/internal services

外部 Ingress は `ingressClassName: nginx-external`、内部 Ingress は `ingressClassName: nginx-internal` で分離します。こうすると管理画面のような機微なサービスを誤ってインターネットに公開する事故を減らせます。

2. チーム別の分離

マルチテナント環境でチームごとに独立したコントローラを置くパターンです。各チームは自分のクラス(例: team-a-nginx、team-b-nginx)だけを使い、コントローラもチームの名前空間だけを watch するようスコープを狭めます。こうすると、あるチームのトラフィック急増や設定ミスが他チームに及ぼす影響を減らせます。

3. 移行

ingress-nginx から別のコントローラ(例: Traefik、Envoy ベース)へ移している間は、2つのコントローラがしばらく共存します。既存サービスは既存クラスのまま残し、新しいサービスや一部のトラフィックだけを新しいクラスへ移してから段階的に切り替えます。2026年のコンテキストで Gateway API へ移す場合も、Ingress コントローラと Gateway コントローラがしばらく並行運用されます。

競合の防止

マルチコントローラの核心リスクは **2つのコントローラが同じ Ingress を同時に処理する、または同じホストを重複して公開する** ことです。次の原則で防ぎます。

1. **すべての Ingress に ingressClassName を明示**: デフォルトクラスに依存しないと「どのコントローラが掴むか」の曖昧さがなくなります。

2. **デフォルトクラスは最大1つ**: default を2つ以上に指定しません。

3. **electionID の分離**: 同じ種類のコントローラインスタンスごとにリーダー選出キーを異なる値にします。

4. **ホストの重複禁止**: 2つのクラスが同じホストを公開しないようにします。特に移行中はカットオーバーまでホストを分離します。

5. **スコープを狭める**: 必要なら watch-namespace でコントローラの管轄範囲を明確に制限します。

コストと運用の考慮

マルチコントローラは隔離と安全性をもたらしますが、コストと運用の複雑さを伴います。

- **ロードバランサのコスト**: コントローラごとに LoadBalancer タイプの Service を置くとクラウドのロードバランサが追加されます。内部コントローラは internal LB にする、あるいは単一の LB の背後でホストで分岐する方式でコストを抑えられます。

- **リソースのオーバーヘッド**: 各コントローラは自前の Pod、メモリ、CPU を消費します。コントローラの数が増えるほど管理対象も増えます。

- **運用の一貫性**: コントローラごとにバージョン、アノテーション構文、チューニングパラメータがバラバラだと運用が難しくなります。可能なら同じ種類のコントローラを複数クラスに分けるほうが運用の一貫性に有利です。

- **可観測性**: コントローラごとにメトリクス/ログを分離収集し、どのクラスがどのトラフィックを処理しているかをダッシュボードで明確にします。

また2026年現在 ingress-nginx がメンテナンスモード寄りの流れであることを踏まえると、新しいマルチ入口を設計する際は Gateway API の複数 Gateway モデルも併せて検討するのが合理的です。Gateway API は複数の Gateway を GatewayClass で区別するため、マルチ入口を標準的に表現できます。

実習 YAML

内部/外部の2クラスを作り、それぞれに Ingress を付ける全体例です。

apiVersion: networking.k8s.io/v1

kind: IngressClass

metadata:

name: nginx-external

spec:

controller: k8s.io/ingress-nginx

apiVersion: networking.k8s.io/v1

kind: IngressClass

metadata:

name: nginx-internal

spec:

controller: k8s.io/ingress-nginx

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: public-api

namespace: shop

spec:

ingressClassName: nginx-external

rules:

- host: api.example.com

http:

paths:

- path: /

pathType: Prefix

backend:

service:

name: api-service

port:

number: 80

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: admin-panel

namespace: shop

spec:

ingressClassName: nginx-internal

rules:

- host: admin.internal.example.com

http:

paths:

- path: /

pathType: Prefix

backend:

service:

name: admin-service

port:

number: 80

作成後の確認コマンドは次のとおりです。

kubectl get ingressclass

kubectl get ingress -A -o custom-columns=NAME:.metadata.name,CLASS:.spec.ingressClassName,HOSTS:.spec.rules[*].host

落とし穴とトラブルシューティング

**1. Ingress がどのコントローラにも掴まれない。**

`ingressClassName` が実在する IngressClass 名と異なるか、デフォルトクラスがなくクラス未指定の Ingress が放置されている場合です。IngressClass の一覧と Ingress のクラス指定を突き合わせます。

kubectl get ingressclass

kubectl describe ingress admin-panel

**2. 2つのコントローラが同じ Ingress を処理する。**

同じ種類のコントローラがクラススコープを正しく狭めていないと起こり得ます。各コントローラの `ingressClass` 設定と `electionID` が分離されているか確認します。

**3. デフォルトクラスが2つあり動作が予測不能。**

`is-default-class: "true"` が2つの IngressClass に付いていないか確認し、1つだけ残します。

kubectl get ingressclass -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.metadata.annotations.ingressclass\.kubernetes\.io/is-default-class}{"\n"}{end}'

**4. 内部サービスがインターネットに公開された。**

内部用 Ingress に外部クラスを誤って指定した場合です。機微なサービスの `ingressClassName` を再確認し、ポリシー(例: OPA/Kyverno)で強制することを検討します。

**5. 移行中にトラフィックが混ざる。**

既存クラスと新しいクラスが同じホストを同時に公開するとトラフィックが分散します。カットオーバーまではホストや重みで分離し、一度に切り替えます。

おわりに

マルチコントローラ運用の出発点は IngressClass を正確に理解することです。`spec.controller` でコントローラの種類を、IngressClass 名でインスタンスを区別し、Ingress の `spec.ingressClassName` でどのクラスが処理するかを明示します。デフォルトクラスは1つだけにし、同じ種類のコントローラは `ingressClass` と `electionID` でスコープを分離し、必要なら watch-namespace で管轄を狭めます。

内部/外部の分離、チーム別の隔離、移行という代表的なシナリオで、マルチコントローラは強力なツールです。ただしロードバランサのコストと運用の複雑さという代償が伴うため、競合防止の原則を守り、可観測性を備えることが重要です。2026年のコンテキストでは ingress-nginx のメンテナンスの流れを踏まえ、新しいマルチ入口の設計には Gateway API の複数 Gateway モデルも併せて検討することをお勧めします。

参考資料

- Kubernetes 公式ドキュメント — Ingress (IngressClass): https://kubernetes.io/docs/concepts/services-networking/ingress/#ingress-class

- Kubernetes 公式ドキュメント — Ingress Controllers: https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/

- ingress-nginx — Multiple controllers: https://kubernetes.github.io/ingress-nginx/user-guide/multiple-ingress/

- ingress-nginx 公式ドキュメント: https://kubernetes.github.io/ingress-nginx/

- Traefik 公式ドキュメント: https://doc.traefik.io/traefik/

- Project Contour 公式ドキュメント: https://projectcontour.io/docs/

- Gateway API 公式サイト: https://gateway-api.sigs.k8s.io/

- Kyverno 公式ドキュメント: https://kyverno.io/docs/

- cert-manager 公式ドキュメント: https://cert-manager.io/docs/

- HAProxy 公式ドキュメント: https://www.haproxy.com/documentation/

현재 단락 (1/191)

小さなクラスタでは Ingress Controller が1つで十分です。しかし運用規模が大きくなると、1つのクラスタにコントローラが2つ以上必要な状況が自然に生じます。たとえば、インターネットに公...

작성 글자: 0원문 글자: 8,039작성 단락: 0/191