K8s 中級 #3 Ingress と Ingress Controller — 外部入口

読了 19分

K8s 中級シリーズの 3 番目の記事です。#2 まで扱ったのがクラスタ内のデータが生き残るモデルだったとすれば、この記事の視点はクラスタの外に移ります。外部トラフィックがどうクラスタ内の Service へ入ってくるか のモデルです。基礎 #5 の LoadBalancer が外部入口の標準ですが、1 つのクラスタに外部公開が必要な Service が数十個あれば、その数だけ LoadBalancer を立てるのはコスト・管理の両面で負担です。この記事ではその負担を 1 か所に集めるオブジェクト Ingress と、そのマニフェストを実際のルーティングに解いてくれる Ingress Controller の 2 層を 1 サイクルで追います。

このシリーズは K8s 中級 7 編です。

LoadBalancer 1 つでは解けないこと — 出発点 #

基礎 #5 で押さえた LoadBalancer Service の形を 1 行に縮めると次のとおりです — type: LoadBalancer 1 行でクラウドプロバイダが外部 LB を自動で作ってくれて、その LB の外部 IP で 1 つの Service のバックエンド Pod へトラフィックが流れます。単純で十分強力なモデルです。

問題は Service が 1 つを越えるところから 始まります。運用クラスタのよくある形を描いてみるとこうです。

  • web Service — ユーザー向け Web ページ
  • api Service — REST API バックエンド
  • admin Service — 運用者向け管理ページ
  • static Service — 静的アセット専用

この 4 つをすべて外部に公開しようとそれぞれ type: LoadBalancer を付けると、クラウド LB が 4 つできます。AWS の NLB・ALB であろうと GCP の LB であろうと Azure の LB であろうと、LB はそれ自体に時間あたりコストがあり、このコストが Service 数に比例して積み上がります。Service が数十個あれば LB コストが無視できないレベルになります。

コストだけが負担ではありません。運用面の負担も一緒に増えます。

  • ドメインを LB の数だけ管理 — 外部に見せるドメインが LB ごとに別々に紐づく形なので、DNS レコードもその数だけ管理しなければなりません。
  • TLS 証明書を LB ごとに別々に — 証明書の発行・更新を LB 単位で持っておかなければなりません。
  • ホスト・パスベースのルーティングができないexample.com/apiapi Service へ、example.com/staticstatic Service へ流したくても、LoadBalancer Service 1 つは 1 つの Service のバックエンドだけを見ます。このルーティングを解くには誰かがもう 1 段乗せなければなりません。

この 3 つを 1 か所に集めて解いてくれる抽象化が Ingress です。1 つのクラウド LB の後ろに 1 つの Ingress Controller が立ち、そのコントローラがドメイン・パスを見てクラスタ内の複数 Service へトラフィックを分けます。TLS 終端も 1 か所で処理します。外から見ると LB が 1 つに見えますが、内側では Ingress マニフェストのルーティング規則に従って分岐する形です。

Ingress の 2 層 — オブジェクトとコントローラ #

K8s でよく罠になる部分がここにあります。Ingress マニフェストだけ書いてもトラフィックは流れない 点です。Ingress は 2 層が一緒になければ動きません。

何か誰が作るか
Ingress オブジェクト「どの host のどの path をどの Service へ送る」という意図を書いたマニフェストアプリ開発者または運用者
Ingress Controllerその Ingress オブジェクトを読んで実際にトラフィックをルーティングするランタイムクラスタ管理者が一度インストール

Deployment・Service のようなオブジェクトは K8s 本体(コントロールプレーン)が自分のコントローラで直接処理しますが、Ingress は違います。Ingress コントローラは K8s 本体に含まれておらず、外部コンポーネントとしてクラスタに別途インストール しなければなりません。コントローラのないクラスタに Ingress マニフェストを適用すると、オブジェクトは作られますがトラフィックはどこにも流れません — apply は成功するのに外部から応答が来ない形で事故になります。

頭の中の絵は次のように置くと楽です。

Ingress の 2 層
[ 外部クライアント ]
[ クラウド LB ]  ←── Ingress Controller が公開する 1 つの Service(LoadBalancer)
[ Ingress Controller Pod ]  ←── nginx / Traefik / ALB など
       │  Ingress オブジェクトのルーティング規則を読んで分岐
       ├──────────┬──────────┐
       ▼          ▼          ▼
   [Service A] [Service B] [Service C]
       │          │          │
     Pods       Pods       Pods

要点は — 外部クラウド LB は 1 つ であり、その後ろに立つ Ingress Controller がすべての Ingress オブジェクトの規則を合わせて実際のルーティングを行う点です。クラスタに Ingress オブジェクトを 100 個書いてもクラウド LB は通常 1 つそのままです。

Ingress Controller の種類 #

Ingress オブジェクトのマニフェスト形式は K8s が標準として定めていますが、それをどう解釈してルーティングに解くかはコントローラ実装ごとに異なります。運用でよく出会うコントローラを 1 つの表にまとめると次のとおりです。

コントローラどこでよく見るか備考
ingress-nginxもっとも一般的。オンプレミス・ローカル・マネージドどこでもK8s コミュニティが管理。nginx をルーティングエンジンとして使用
Traefikコンテナ親和的な環境、自動証明書統合が強み設定がアノテーション・CRD で豊富
HAProxy Ingress高性能・きめ細かなチューニングが必要な環境HAProxy ベース
AWS Load Balancer ControllerEKS で ALB・NLB として公開するときALB が直接ルーティング。クラスタ内の nginx Pod は別途なし
GKE IngressGKE 標準提供Google Cloud Load Balancer がルーティング
AKS Application Gateway Ingress ControllerAKS で Application Gateway としてAzure がルーティング
CiliumeBPF ベースのネットワーキング、Gateway API に強みCNI 兼用

大きく 2 つに分けて見ると理解が容易です。

  • クラスタ内 Pod がルーティング — ingress-nginx、Traefik、HAProxy のようなコントローラは自分の nginx・Traefik Pod をクラスタに立てて、その Pod がトラフィックを受けて処理します。クラウド LB はその Pod の前に単純な L4 ディストリビュータとして立つ形です。
  • クラウドリソースがルーティング — AWS ALB Controller、GKE Ingress、AKS AGIC はクラウドのマネージド LB(ALB・CLB・Application Gateway)自体がホスト・パスルーティングをします。クラスタ内には小さなコントローラ Pod があって Ingress オブジェクトをクラウド LB のルールに翻訳しておくだけです。

同じ Ingress マニフェストでも、どのコントローラが処理するかでアノテーションのキーや動作が変わります。そのためマニフェストにコントローラ固有のアノテーションを書くときは、どのコントローラを使っているのかから確認しなければなりません。

Ingress Controller のインストール #

運用クラスタでは通常 1 種類のコントローラを 1 度インストールしておき、すべての Ingress がそれを通過するようにします。環境別のインストールの形を短く押さえておきます。

minikube #

addons コマンド 1 行で ingress-nginx がインストールされます。

minikube に ingress-nginx を有効化
minikube addons enable ingress
確認
kubectl get pods -n ingress-nginx
NAME                                       READY   STATUS    RESTARTS   AGE
ingress-nginx-controller-6d4b7f6c8-abc12   1/1     Running   0          30s

kind #

kind は ingress-nginx を別マニフェストで適用します。

kind に ingress-nginx を適用
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml

加えて kind クラスタを作るときに 80/443 ポートをホストにマッピングしておく設定が一緒に必要です。ingress-nginx の公式ガイドに従えばよいです。

EKS / GKE / AKS #

マネージドクラスタではコントローラを Helm でインストールするパターンが標準です。

ingress-nginx の Helm インストール — 環境非依存
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm install ingress-nginx ingress-nginx/ingress-nginx \
  --namespace ingress-nginx --create-namespace

EKS で AWS ALB Controller を使う場合は別途 IAM・サービスアカウントの設定が伴います。

AWS Load Balancer Controller インストール — 抜粋
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  --namespace kube-system \
  --set clusterName=my-cluster \
  --set serviceAccount.create=false \
  --set serviceAccount.name=aws-load-balancer-controller

GKE は Google が管理する GKE Ingress がデフォルトで有効化されているので、別途インストールなしに Ingress マニフェストを適用すれば GCLB が自動で作られる体験が可能です。AKS にも同様のマネージドオプションがあります。

インストールしたコントローラは通常自分の namespace(ingress-nginxkube-system など)に Pod・Service・Deployment・ConfigMap の 1 セットとして立っています。クラスタ 1 台にコントローラ 1 種類だけインストールされていれば通常十分です。

最初の Ingress マニフェスト — 単純なドメインルーティング #

もっとも単純な形から始めます。example.com に入ってくるすべてのトラフィックを web Service の 80 ポートへ送る Ingress です。

まずバックエンド Service が立っていると仮定します。

web-deploy-svc.yaml — 抜粋
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  type: ClusterIP
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80

Service タイプが ClusterIP という点が重要です。Ingress の後ろの Service はクラスタ内部専用で十分 です。外部公開は Ingress Controller が自分の LoadBalancer Service 1 つで代わりに行うからです。ここの Service に type: LoadBalancer を書く理由はありません。

次に Ingress マニフェストです。

ingress-web.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

フィールドを 1 行ずつ押さえておきます。

  • apiVersion: networking.k8s.io/v1 — Ingress の安定バージョンです。1.19 で stable になり、以前の extensions/v1beta1networking.k8s.io/v1beta1 はもう使いません。
  • spec.ingressClassName: nginx — どの Ingress Controller がこのオブジェクトを処理するかを指します。1 つのクラスタにコントローラが 1 種類だけあり、それが default IngressClass であれば省略してもよいですが、明示しておく方が安全です。詳細は後の IngressClass 節で再び見ます。
  • spec.rules[].host: example.com — どのホストのトラフィックかを表現します。HTTP の Host ヘッダ、HTTPS の SNI を見てマッチします。
  • spec.rules[].http.paths[].path: / — マッチするパスです。/ はこのホストのすべてのパスを意味します。
  • spec.rules[].http.paths[].pathType: Prefix — パスマッチ方式です。もっともよく使われる値です。
  • spec.rules[].http.paths[].backend.service — マッチしたトラフィックを流す Service 名とポートです。

このマニフェストを適用した後の状態を見ると次のような形です。

Ingress 適用と確認
kubectl apply -f ingress-web.yaml
kubectl get ingress
出力例
NAME   CLASS   HOSTS         ADDRESS          PORTS   AGE
web    nginx   example.com   34.120.10.20     80      30s

ADDRESS 列に外部入口の IP やホスト名が満たされます。この IP が Ingress Controller を公開する LoadBalancer Service の EXTERNAL-IP と同じです。クラスタ内に Ingress オブジェクトが 100 個あっても通常この ADDRESS は同じ 1 つの IP です。

DNS マッピング #

運用で example.com が本当に上の ADDRESS を指すようにするには、外部 DNS に A レコード(または CNAME)をその IP で設定しておかなければなりません。K8s 内で自動で起こることではありません。ExternalDNS のようなツールを使うと Ingress オブジェクトの host フィールドを見てクラウド DNS にレコードを自動で作ってくれる運用パターンもあります。

path ベースのルーティング #

同じホストのパスごとに別の Service へ流したい場合です。example.com/apibackend-api Service、example.com/staticcdn Service へ行く形です。

ingress-paths.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  ingressClassName: nginx
  rules:
    - host: example.com
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: backend-api
                port:
                  number: 8080
          - path: /static
            pathType: Prefix
            backend:
              service:
                name: cdn
                port:
                  number: 80
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

このマニフェストの動作は次のとおりです。

  • example.com/api/usersbackend-api:8080
  • example.com/static/logo.pngcdn:80
  • example.com/ または example.com/aboutweb:80

paths は上から下へ評価されるのではなく マッチがより長いパスが優先 です。/api/ より長くマッチするので /api/users リクエストは backend-api へ行きます。この優先順位ルールはコントローラ実装ごとに微妙に異なる場合があるので、運用では可能な限りマニフェスト内でパスが重ならないように書く方が安全です。

pathType の 3 つの値 #

pathType はパスマッチの方式を定めます。3 つあります。

意味
Prefixパスをスラッシュ単位で区切った prefix マッチ。/api/api/api//api/users にマッチ。/api2 にはマッチしない
Exactパスが正確に一致するときのみマッチ
ImplementationSpecificコントローラ実装が自分の方式で解釈。ingress-nginx は正規表現まで受け付ける

運用でもっともよく使われる値は Prefix です。Exact は単一エンドポイント 1 つだけを公開したいとき、ImplementationSpecific はコントローラ固有機能(例: ingress-nginx の regex)を使いたいときに選択します。マニフェストの移植性を考えるなら Prefix で統一しておく方が無難です。

Prefix のスラッシュ単位マッチが微妙な部分なので短く押さえておくと — /api と書いたとき /api/users はマッチしますが /api2 はマッチしません。K8s が Prefix を「ディレクトリ prefix」の意味で解釈するためです。この違いがセキュリティに関わるときがあります — 意図しないパスが同じバックエンドへ流れる事故を防いでくれます。

host + path の組み合わせ #

異なるドメインを 1 つの Ingress で一緒に処理する形です。api.example.comapp.example.com を分けるよくある構成です。

ingress-multi-host.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi
spec:
  ingressClassName: nginx
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: backend-api
                port:
                  number: 8080
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

rules 配列に host が異なる項目を 2 つ入れればよいです。1 つの Ingress が複数の host を一緒に持ってもよいし、host ごとに別々の Ingress オブジェクトを作ってもよいです。運用ではドメイングループ単位で Ingress を分けるパターンがよくあります — namespace ごとに 1 つ、チームごとに 1 つのように責任が分離するときオブジェクトも一緒に分離する形です。

ホストはワイルドカードもサポートします。*.example.com と書くと foo.example.combar.example.com のような 1 段階のサブドメインがすべてマッチします。ただし *.example.comfoo.bar.example.com のような 2 段階はマッチしません — DNS ワイルドカードのその規則をそのまま踏襲します。

TLS 終端 — Ingress + Secret #

運用で外部入口はほぼ常に HTTPS です。Ingress の tls フィールドと K8s Secret を組み合わせれば、証明書の終端を 1 か所で処理できます。

まず証明書・キーを格納した Secret が必要です。

TLS Secret を作る — 直接発行した証明書
kubectl create secret tls example-com-tls \
  --cert=fullchain.pem \
  --key=privkey.pem

Secret のタイプは kubernetes.io/tls で、中には tls.crt(証明書チェーン)と tls.key(秘密鍵)の 2 つのキーが入っています。マニフェストで同じ形を作ることもできますが、キーファイルを base64 エンコードした値をマニフェストに入れることになるので、通常は上のようにコマンドで作る方が綺麗です。

この Secret を Ingress に接続します。

ingress-tls.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - example.com
      secretName: example-com-tls
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

spec.tls[].hosts に書いたドメインのトラフィックは Ingress Controller が受けるときに TLS を終端し、内側の Service には平文 HTTP で流します。この形のおかげで Service と Pod 側のマニフェストは HTTPS を気にしなくてよく、証明書の更新は Secret を入れ替えるだけで済みます。

cert-manager — 自動発行・更新 #

Let’s Encrypt のような無料 CA から証明書を自動発行・更新する標準ツールが cert-manager です。cert-manager をクラスタにインストールして ClusterIssuer オブジェクトを 1 度作っておけば、Ingress マニフェストにアノテーション 1 行を書くだけで証明書発行が自動で進行します。

ingress-tls-cert-manager.yaml — 抜粋
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - example.com
      secretName: example-com-tls
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80

cert-manager.io/cluster-issuer アノテーションを見て cert-manager が次のサイクルを自動で進行します。

  1. ACME チャレンジ(HTTP-01 または DNS-01)を通じてドメイン所有検証。
  2. Let’s Encrypt から証明書発行。
  3. 証明書・キーを secretName に書かれた Secret として作っておく。
  4. 有効期限 30 日前頃に自動更新。

cert-manager 自体のインストールと ClusterIssuer 設定は分量が少なくないので、この記事では形だけ押さえて詳細は K8s 実戦トラックに譲ります。運用で cert-manager が事実上の標準になっているので名前と位置だけ覚えておけば十分です。

IngressClass — コントローラが 2 つ以上あるとき #

ほとんどのクラスタはコントローラを 1 種類だけ置きますが、同じクラスタに 2 種類が一緒にあるべき場合もあります。たとえば 公開トラフィックは ingress-nginx、内部管理トラフィックは AWS ALB Controller へ送りたい形です。このときどの Ingress オブジェクトがどのコントローラで処理されるべきかを表現するオブジェクトが IngressClass です。

IngressClass オブジェクト — 抜粋
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: nginx
  annotations:
    ingressclass.kubernetes.io/is-default-class: "true"
spec:
  controller: k8s.io/ingress-nginx

主要フィールドは 2 つです。

  • spec.controller — どのコントローラ実装がこの IngressClass を処理するかを指す識別子です。ingress-nginx は k8s.io/ingress-nginx、AWS ALB Controller は ingress.k8s.aws/alb のように実装ごとに決まっています。
  • ingressclass.kubernetes.io/is-default-class: "true" アノテーション — この IngressClass をクラスタのデフォルトとして示します。Ingress マニフェストに ingressClassName を書かないと default IngressClass のコントローラが処理します。

Ingress マニフェストでは spec.ingressClassName でどのクラスに属するかを書きます。

ingress-class-pick.yaml — 抜粋
spec:
  ingressClassName: alb   # AWS ALB Controller が処理
  rules:
    - host: admin.example.com
      ...

同じクラスタの別の Ingress が ingressClassName: nginx であれば、それは ingress-nginx が処理します。2 つのコントローラが同じオブジェクトをめぐって競合することはありません。

現在のクラスタの IngressClass
kubectl get ingressclass
出力例
NAME            CONTROLLER             PARAMETERS   AGE
nginx (default) k8s.io/ingress-nginx   <none>       30d
alb             ingress.k8s.aws/alb    <none>       10d

(default) 表示が付いたクラスが default です。クラスタに default IngressClass は 1 つだけ にするのが標準です。2 つが default で表示されると新しい Ingress オブジェクトがどちらで処理されるかが曖昧になります。

Gateway API — Ingress の後継標準 #

最後に 1 行押さえておきます。Ingress オブジェクトは単純なホスト・パスルーティングには十分ですが、より表現力のあるルーティング(ヘッダベース、クエリパラメータベース、重み付けトラフィック分配など)を扱うにはアノテーションに依存することになり、コントローラごとに異なってしまう限界があります。SIG-Network がその限界を解こうと作った後継標準が Gateway API です。

Gateway API はオブジェクトを 3 つに分けます。

オブジェクト役割
GatewayClassどのコントローラが処理するか (Ingress の IngressClass に対応)
Gateway外部入口そのもの (LoadBalancer のようなリソースに対応)
HTTPRoute / TCPRoute / TLSRouteルーティング規則 (Ingress の rules に対応するがより表現力がある)

ingress-nginx、Traefik、Cilium、Istio など多くのコントローラが Gateway API をサポートしており、新しいクラスタを始める運用者なら Gateway API を検討する段階です。ただし Ingress が依然としてもっとも広く使われる標準 で、既存クラスタで運用者が出会うオブジェクトはほとんどが Ingress です。Gateway API の深いモデルは K8s 上級トラックに譲っておき、この記事では名前と位置だけ押さえる程度にしておきます。

運用パターン — LoadBalancer 1 つ + Ingress 多数 #

この記事の頭の中の絵を 1 行で固めて行きます。運用クラスタの外部入口は通常クラウド LoadBalancer 1 つに集まります。 その LoadBalancer は Ingress Controller が自分の公開用に立てた 1 つの Service(type: LoadBalancer)に紐づいており、すべての外部トラフィックがその 1 つの LB を通過します。

運用のよくある入口の形
[ クラウド LoadBalancer ]   ←── 1 つ。コストも 1 か所
[ Ingress Controller (nginx Pod 群) ]   ←── ingress-nginx namespace
            │  Ingress オブジェクトたちのルーティング規則
            ├──────────┬──────────┬──────────┐
            ▼          ▼          ▼          ▼
       [web]      [api]       [admin]    [static]   ←── それぞれ ClusterIP Service

この構造の効果を 1 行ずつまとめると次のとおりです。

  • クラウド LB コストが 1 か所 — Service 数が増えても LB はそのまま 1 つ。
  • TLS 終端が 1 か所 — 証明書・cert-manager 設定も 1 か所に集まる。
  • ドメイン・パスルーティングがマニフェストで表現 — 新しい Service の公開は Ingress オブジェクト 1 行を追加すること。
  • DNS レコードがシンプル*.example.com を LB の IP/名前に 1 度設定しておけば、すべてのホストがその LB に入ってきます。

Service 数とは無関係にクラウド LB は通常 1 つですが、トラフィック分離が必要な場合(公開 vs 内部など)にはコントローラを 2 セット立てて LB 2 つを持つパターンもよくあります。上の IngressClass 節の形がその運用パターンの例です。

Ingress Controller 自体の可用性 #

この構造の 1 つのリスクは — Ingress Controller が単一障害点になりうる 点です。すべての外部トラフィックがそのコントローラを通過するので、コントローラ Pod が同時に障害になるとすべての外部トラフィックが切れます。運用では次を備えるのが標準です。

  • コントローラ Pod の多重化 — Deployment の replicas を 2 以上に。ノード障害時にも 1 つの Pod は生きているように PodDisruptionBudget・anti-affinity で分散。
  • リソースの余裕 — コントローラ Pod の CPU・メモリ limits を十分に取っておく。次の #4 で扱うテーマです。
  • モニタリング — コントローラが公開する Prometheus メトリクス(リクエスト数、5xx 率、応答時間)をアラームで。

まとめ #

この記事で押さえた流れをまとめます。

  • Service ごとの LoadBalancer の限界 — 外部公開 Service が増えるとクラウド LB コスト・管理負担が比例。ホスト・パスルーティングと TLS 終端も 1 か所に集める必要が出てきます。
  • Ingress の 2 層 — Ingress オブジェクト(マニフェスト、意図)と Ingress Controller(ランタイム)。コントローラなしにオブジェクトだけ書いても無動作。
  • コントローラの種類 — ingress-nginx(もっとも一般的)、Traefik、HAProxy、AWS ALB Controller、GKE Ingress、Cilium。クラスタ内 Pod がルーティングする系統とクラウドリソースがルーティングする系統に分かれる。
  • ホストルーティングspec.rules[].host でホスト分岐。ワイルドカード(*.example.com)もサポート。
  • パスルーティングと pathTypePrefix(もっとも一般的、スラッシュ単位 prefix)、Exact(正確マッチ)、ImplementationSpecific(コントローラ別)。
  • TLS 終端spec.tls にホストと Secret を接続します。Secret タイプは kubernetes.io/tls です。cert-manager で Let’s Encrypt 自動発行・更新をするのが標準パターンです。
  • IngressClass — 同じクラスタにコントローラが 2 つ以上あるとき Ingress オブジェクトがどのコントローラに属するかを表現。default 表示は 1 つだけ。
  • Gateway API — Ingress の後継標準です。表現力がより強い。Ingress が依然として標準ですが、新しいクラスタでは検討段階です。
  • 運用パターン — クラウド LB 1 つ → Ingress Controller 1 セット → Ingress オブジェクト別ルーティング → ClusterIP Service たち。LB コスト・TLS・ルーティングが 1 か所に集まる。コントローラ自体の可用性とリソースの余裕が運用の次の関心事。

このモデルまで手に入れば、会社のクラスタのマニフェストディレクトリで Ingress オブジェクトに出会ったときに、どのコントローラがそれを処理しているのか、外部 LB とどうつながっているのかを 1 行で読めます。

次 — resources.requests / limits #

この記事で外部入口の形を押さえながら最後に短く触れた 1 つが次回の出発点です — Ingress Controller Pod のリソースの余裕 です。コントローラがすべての外部トラフィックを処理するので、その Pod に CPU・メモリが不足するとトラフィック自体が詰まります。ところが K8s で Pod が自分に必要なリソースをどう表現するか、その表現がスケジューラの決定とノードの OOM 動作にどう影響を与えるかはまだ扱っていません。

#4 resources.requests / limits — Pod のリソース要求と上限 では Pod マニフェストの resources.requestsresources.limits 2 つのフィールドのモデル、CPU とメモリ 2 つのリソースの動作の違い(CPU は throttling、メモリは OOMKill)、QoS クラス(Guaranteed / Burstable / BestEffort)、LimitRange で namespace のデフォルトを強制する運用パターンまで 1 サイクルでまとめます。

X