2026年8月18日

2026年8月18日

KubernetesのIngressでHTTPルーティングを設定する|ホスト名・パス振り分け・TLSと404/503の調べ方

KubernetesのIngressは、外から来たHTTP/HTTPSのリクエストを、ホスト名やURLのパスに応じてクラスター内のServiceへ振り分ける設定です。ただしIngressはルールを書くだけのリソースで、実際に通信を受けるのは別途インストールする「Ingressコントローラー」です。この記事では、コントローラーとIngressClassの関係、ホスト名とパスでの振り分け、TLSの設定、WordPressをIngressの後ろに置くときの注意、つながらないときの調べ方を説明します。

あわせて、Ingressを取り巻く状況の変化にも触れます。後半の「コントローラー選びの現状」は、新しく構築する方は先に読んでおいてください。

Ingressが動く仕組み

通信は次の順に流れます。

  1. クライアントがIngressコントローラー(クラウドのロードバランサーやNodePort経由)に接続する。
  2. コントローラーが、Ingressに書かれたホスト名とパスのルールを見て、転送先のServiceを決める。
  3. Serviceの裏にある、準備完了(Ready)のPodへ転送される。

このため、Ingressを作ってもコントローラーが入っていなければ何も起きません。また、どのコントローラーがそのIngressを担当するかは、IngressClassで決まります。

kubectl get ingressclass

ここに表示される名前(例:nginx、traefik など)を、Ingressの spec.ingressClassName に書きます。何も表示されない場合は、コントローラーが入っていません。minikubeなら minikube addons enable ingress、k3sなら標準でTraefikが入るなど、環境ごとに用意の仕方が異なります。

転送先のServiceを用意する

Ingressの転送先はPodではなくServiceです。まず2つのアプリ(web と api)にServiceがある状態を作ります。

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080

port はService自身のポート、targetPort はPodのコンテナが待ち受けているポートです。ここを取り違えると、後で502や503の原因になります。api も同じ形で作ります。

ホスト名とパスで振り分ける

1つのドメインで、/api 以下を api に、それ以外を web に送る例です。

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

ingressClassName: nginx は例です。kubectl get ingressclass で確認した自分の環境の名前に置き換えてください。

pathType には3種類あります。

  • Prefix:パスの前方一致です。ただし文字列ではなく / で区切った単位で比べるため、/api は /api と /api/users には一致しますが、/apiv2 には一致しません。
  • Exact:パス全体が同じ場合だけ一致します。末尾の / の有無も区別します。
  • ImplementationSpecific:一致の仕方をコントローラーに任せます。コントローラーを変えると動きが変わる可能性があるので、特別な理由がなければ Prefix か Exact を使います。

複数のルールに一致する場合は、より長いパスが優先され、同じ長さなら Exact が Prefix より優先されます。書く順番では決まらない点に注意してください。

ホスト名ごとに別のサービスへ振り分けるなら、rules にホストを並べます。host を省略したルールは、すべてのホスト名に対して使われます。

HTTPSにする(TLS)

証明書と秘密鍵をTLS用のSecretとして登録し、Ingressの tls で指定します。

kubectl create secret tls app-example-tls --cert=fullchain.pem --key=privkey.pem
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - app.example.com
      secretName: app-example-tls
  rules:
    - host: app.example.com
      # ...(上と同じ)

SecretはIngressと同じ名前空間に置きます。tls.hosts と rules.host のホスト名、証明書に含まれるホスト名がそろっていないと、コントローラーの仮の証明書が返され、ブラウザで証明書エラーになります。証明書の取得と更新を自動にするなら、cert-managerを組み合わせるのが一般的です。

HTTPからHTTPSへのリダイレクト、URLの書き換え(リライト)、アップロードの最大サイズ、タイムアウトなどは、Ingressの標準の項目にはなく、コントローラーごとのアノテーションや設定で指定します。名前も書き方もコントローラーによって異なるため、使っているコントローラーのドキュメントで確認してください。

WordPressをIngressの後ろに置くときの注意

Ingressコントローラーでの暗号化を終えて、Podへは平文のHTTPで転送する構成では、WordPressは自分がHTTPで呼ばれていると判断します。その結果、管理画面へのリダイレクトが繰り返される、CSSが http:// で読み込まれて表示が崩れる、といった症状が出ます。

コントローラーは通常、元の通信がHTTPSだったことを X-Forwarded-Proto ヘッダーで伝えます。wp-config.php の require_once ABSPATH . 'wp-settings.php'; より前に、次を書きます。

if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && 'https' === $_SERVER['HTTP_X_FORWARDED_PROTO'] ) {
    $_SERVER['HTTPS'] = 'on';
}

このヘッダーはクライアントが偽装できるため、PodにIngressコントローラー経由でしか到達できない構成(ServiceをClusterIPにする、NetworkPolicyで制限するなど)であることが前提です。メディアのアップロードで413エラーが出る場合は、前述のアップロード上限をコントローラー側で引き上げます。編集前には wp-config.php のバックアップを取ってください。

つながらないときの調べ方

まずIngressの状態を確認します。

kubectl get ingress app
kubectl describe ingress app

そのうえで、症状ごとに起きやすい原因を順に確認します。

  1. **ADDRESS が空のまま**:担当するコントローラーがいません。ingressClassName が kubectl get ingressclass の名前と一致しているか、コントローラーのPodが動いているかを確認します。
  2. 404が返る:コントローラーまでは届いているが、ルールに一致していません。ホスト名の打ち間違いが多い原因です。DNSを設定する前に試すなら、curl -H "Host: app.example.com" http://<コントローラーのIP>/ のようにHostヘッダーを付けて送ります。
  3. 503が返る:転送先のServiceに準備完了のPodがありません。次のコマンドで、Serviceに紐づくPodのIPが並んでいるかを見ます。

``bash kubectl get endpointslices -l kubernetes.io/service-name=web

空なら、Serviceの selector とPodのラベルが一致していないか、PodのreadinessProbeが通っていません。

  1. 502が返る:Podには届いているが応答が得られていません。Serviceの targetPort とコンテナの実際の待ち受けポートが合っているかを確認します。

これでも分からない場合は、コントローラーのPodのログ(kubectl logs -n <コントローラーの名前空間> <Pod名>)を見ると、どのServiceに転送しようとして失敗したかが記録されています。

コントローラー選びの現状

Ingressの利用者が最も多かったコミュニティ版のコントローラー「Ingress NGINX(kubernetes/ingress-nginx)」は、Kubernetesプロジェクトが2025年11月に開発終了を発表し、2026年3月までで保守を終える方針が示されました(2026年10月現在)。既存の環境がすぐ止まるわけではありませんが、セキュリティ修正が提供されなくなるため、移行の計画が必要です。名前が似ているF5社のNGINX Ingress Controllerは別のプロジェクトなので、混同しないよう注意してください。

Ingressのリソース自体はKubernetesの正式なAPIとして残っており、Traefikなど他のコントローラーで使い続けられます。一方で、Kubernetesプロジェクトは後継としてGateway API(Gateway と HTTPRoute などのリソース)を推しており、ヘッダーによる振り分けや重み付けなど、Ingressでは各コントローラーのアノテーションに頼っていた機能を標準の項目で書けます。新しく構築するなら、使うコントローラーがGateway APIに対応しているかを確認し、選択肢に入れておくとよいでしょう。

まとめ

  • Ingressはルールで、通信を受けるのはIngressコントローラー。ingressClassName で担当を指定する。
  • pathType は Prefix(/ 区切りの前方一致)か Exact を使い、長いパスが優先される。
  • TLSは同じ名前空間のTLS用Secretを tls.secretName に指定する。リダイレクトや上限値はコントローラーごとの設定。
  • WordPressは X-Forwarded-Proto を見て $_SERVER['HTTPS'] を設定する。経路を限定したうえで使う。
  • つながらないときは、ADDRESS空→コントローラー、404→ルール、503→EndpointSlice、502→targetPort の順に見る。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲