【図解】Nginx Ingress Controller の仕組みと設定方法


【図解】Nginx Ingress Controller の仕組みと設定方法

Kubernetes上でアプリケーションを公開する際、その入り口となるコンポーネントは非常に重要です。単にトラフィックを受け付けるだけでなく、高度なルーティング、TLS終端、負荷分散など、様々な機能が求められます。この記事では、Kubernetesのエコシステムでデファクトスタンダードとして広く利用されている「Nginx Ingress Controller」に焦点を当て、その仕組みからインストール方法、そして実践的な設定方法までを詳細に解説します。約5000語にわたる解説を通じて、Nginx Ingress Controllerを深く理解し、自信を持って運用できるようになることを目指します。

はじめに:Kubernetesにおけるサービス公開の課題とIngressの必要性

Kubernetesでデプロイされたアプリケーション(Pod)は、通常、ClusterIP Serviceによってクラスタ内部でのみアクセス可能になります。これらのアプリケーションをインターネットやクラスタ外部から公開するには、いくつかの方法があります。

  1. NodePort: 各Podが稼働しているノードの特定のポートを介してサービスを公開します。外部から ノードIP:NodePort でアクセスできます。

    • 課題: 利用できるポート範囲が限られている(通常30000-32767)。複数のサービスを公開するとポート管理が煩雑になる。ノード障害時にアクセスできなくなる可能性がある。単なるポート転送であり、高度な機能(ホストベースルーティング、TLS終端など)を提供しない。
  2. LoadBalancer: クラウドプロバイダーが提供するロードバランサーを自動的にプロビジョニングし、そのIPアドレスでサービスを公開します。

    • 課題: クラウドプロバイダーに依存する(オンプレミスでは利用できないことが多い)。サービスごとにロードバランサーが必要になる場合があり、コストがかさむ。高度なルーティング設定はロードバランサー側で別途行う必要がある。

これらの基本的な公開方法では、プロダクションレベルのWebサービスに必要な多くの機能(例: 複数のドメイン/パスへの対応、SSL/TLS証明書の管理、レート制限、認証など)を単体で実現することは困難です。

そこで登場するのが Ingress です。

IngressはKubernetes APIの一種で、外部からクラスタ内のサービスへのHTTP/HTTPSトラフィックのルーティングルールを定義します。Ingressリソース自体はルーティングルールを記述した「設定」に過ぎず、実際にそのルールを読み取ってトラフィックを処理するコンポーネントが必要です。これが Ingress Controller です。

Ingress Controllerは、Ingressリソースの変更を常に監視し、その設定に基づいて自身が持つロードバランサー/リバースプロキシの設定を動的に更新します。外部からのトラフィックはこのIngress Controllerを経由して、適切なクラスタ内のServiceへ転送されます。

Ingress Controllerとは

Ingress Controllerは、Kubernetesクラスタ内で動作する特殊なコントローラーです。その主な役割は以下の通りです。

  1. Ingressリソースの監視: Kubernetes APIサーバーを介して、クラスタ内のIngress、Service、Endpoint、Secretなどのリソースの作成、更新、削除イベントを監視します。
  2. 設定の生成: 監視しているリソースの情報(特にIngressリソースで定義されたルーティングルール)をもとに、自身が使用するロードバランサー/リバースプロキシ(例えばNginxやHAProxy)の設定ファイルを動的に生成します。
  3. 設定の反映: 生成した設定ファイルをロードバランサー/リバースプロキシに反映させます。多くの場合、設定をリロードすることでサービス無停止での反映を実現します。
  4. トラフィックの処理: 外部からのトラフィックを受け付け、生成された設定に基づいて適切なServiceのPodへトラフィックを転送します。

様々な種類のIngress Controllerが存在します。代表的なものとして、

  • Nginx Ingress Controller: Nginxをバックエンドとして利用。最も広く使われており、機能も豊富。
  • HAProxy Ingress Controller: HAProxyをバックエンドとして利用。
  • Traefik: 設定の動的な反映に特化したクラウドネイティブなエッジルーター。
  • クラウドプロバイダー提供: AWS ALB Ingress Controller, GCP Load Balancing Ingress Controller, Azure Application Gateway Ingress Controllerなど。

これらのIngress Controllerの中から、要件や環境に合わせて選択することになります。その中でもNginx Ingress Controllerは、その実績、豊富な機能、柔軟な設定オプションから、多くの環境で採用されています。

なぜNginx Ingress Controllerが選ばれるのか

Nginx Ingress Controllerが広く普及している主な理由は以下の通りです。

  • 実績と信頼性: NginxはWebサーバーおよびリバースプロキシとして長年の実績があり、高いパフォーマンスと安定性を持っています。
  • 豊富な機能: HTTP/HTTPSルーティング、TLS終端、Basic認証、レート制限、IPアドレス制限、リライト、カスタムヘッダー、セッションアフィニティ、WebSocketなど、プロダクションで必要とされる多くの機能をサポートしています。
  • 柔軟な設定: Ingressリソースの標準的な設定に加え、アノテーションやConfigMapを介してNginxの機能を詳細にカスタマイズできます。
  • 活発なコミュニティ: 利用者が多く、情報や事例が豊富です。問題発生時にも解決策を見つけやすいでしょう。
  • デファクトスタンダード: 多くのツールや環境がNginx Ingress Controllerとの連携を前提としています。

Nginx Ingress Controllerのアーキテクチャと仕組み

Nginx Ingress Controllerは、主に以下のコンポーネントで構成されます。

+---------------------+ +---------------------+ +---------------------+
| Kubernetes API | <---> | Ingress Controller | ----> | Nginx (Proxy) Pod |
| (etcd) | | (Controller logic) | | |
+---------------------+ +---------------------+ | +-----------------+ |
^ | | | Nginx Worker | |
| Watch Ingress, Services, | Configure Nginx | | Processes | |
| Endpoints, Secrets | | +-----------------+ |
| | | ^ |
| | | | |
+---------------------+ +---------------------+ | | Forward |
| ConfigMap (Global | <---> | Ingress Controller | | | Traffic |
| Settings) | | | | | |
+---------------------+ +---------------------+ | | |
| | |
| +-----------------+ |
| | kube-proxy | |
| +-----------------+ |
| | |
| v |
+---------------------+
|
v
+---------------------+
| Service Endpoints |
| (Application Pods) |
+---------------------+

  1. Ingress Controller Pod: これがNginx Ingress Controllerの核となるコンポーネントです。Kubernetes APIを監視し、Ingressリソース、Service、Endpointなどの変更を検知します。変更があると、その情報をもとにNginxの設定ファイル(nginx.conf)を動的に生成します。そして、同じPod内で実行されているNginxプロセスに対して、生成した設定をリロードするシグナルを送ります。

    • 内部的には、Ingress ControllerはGo言語で書かれており、kubernetes/client-go ライブラリを使ってAPIと通信します。Nginxの設定生成には、Ingressリソースやアノテーションで指定されたルールを解釈し、Nginxの設定ディレクティブに変換するロジックが含まれています。生成された設定は、多くの場合、ファイルシステム上に書き出され、Nginxプロセスから読み込まれます。Nginxのホットリロード機能を利用することで、新しい設定を適用しても既存の接続を維持できます。
  2. Nginx (Proxy) Pod: 実際のエッジプロキシ/ロードバランサーとして機能するNginxプロセスが実行されるPodです。外部からのトラフィックを受け付け、Ingress Controllerによって生成・反映された設定に基づいて、適切なServiceのClusterIPとポートへ転送します。

    • Nginx Ingress Controllerの多くのデプロイメントでは、ControllerとNginxプロセスは同じPod内の異なるコンテナとして実行されます(マルチコンテナPod)。これにより、Controllerが生成した設定ファイルをNginxコンテナから容易に参照できます。外部からのトラフィックは、このPodの特定のポート(通常80/443)にルーティングされます。
  3. Service: Nginx Ingress Controller Podへのアクセスポイントを提供します。外部からのトラフィックはこのServiceを経由してController Podに到達します。このServiceのtypeによって、Controllerがどのように外部に公開されるかが決まります。

    • LoadBalancer: クラウド環境で利用する場合、クラウドプロバイダーのロードバランサーが自動的にプロビジョニングされ、外部IPアドレスが割り当てられます。これが最も一般的なプロダクションでの公開方法です。
    • NodePort: 各ノードの特定のポートに公開されます。開発やテスト環境、または別のロードバランサー(例: 外部のL4 LB)と組み合わせて使用する場合に利用されることがあります。
    • ClusterIP: クラスタ内部からのみアクセス可能です。内部Ingressや、DaemonSetなどで各ノードにIngress Controllerをデプロイし、その手前にL4 LBを置く構成などで利用されます。
  4. ConfigMap: Nginx Ingress Controller全体の挙動や、標準のNginx設定(例: nginx.confhttpブロック内の設定)をカスタマイズするために使用されます。Ingressリソースのアノテーションよりも広範な設定や、Ingressリソースでは指定できない設定を行う場合に利用します。

    • Controller PodはこのConfigMapも監視しており、変更があるとNginx設定の再生成とリロードを行います。
  5. Secret: TLS終端のための証明書と秘密鍵を保存するために使用されます。Ingressリソースのtlsセクションで指定されたSecretをIngress Controllerが読み込み、NginxにTLS証明書として設定します。

トラフィックの流れの概要:

  1. 外部からNginx Ingress ControllerのService(LoadBalancerNodePort)のIP/ポートにトラフィックが到達。
  2. トラフィックはNginx Ingress Controller Pod内のNginxプロセスに転送される。
  3. Nginxプロセスは、Controllerによって動的に生成された設定(nginx.conf)に基づいて、リクエストのホスト名やパスを解析する。
  4. 解析結果に基づき、Ingressリソースで定義されたバックエンドServiceのClusterIPとポートを特定する。
  5. Nginxプロセスは、Kubernetesクラスタ内のkube-proxyを経由して、そのServiceに対応するPodへトラフィックを転送する。
  6. Podがレスポンスを返し、同じ経路を逆に戻ってクライアントに届けられる。

この仕組みにより、ユーザーはアプリケーションPodやServiceの設定を変更することなく、Ingressリソースを更新するだけで外部からのアクセス方法やルーティングルールを変更できるようになります。

Nginx Ingress Controllerのインストール方法

Nginx Ingress Controllerのインストールにはいくつかの方法がありますが、Helmを利用する方法が最も一般的で推奨されています。ここではManifestファイルによる基本的なインストールと、Helmによる推奨インストール方法を解説します。

前提条件:

  • 稼働中のKubernetesクラスタ
  • kubectl コマンドラインツールが設定済み
  • (Helmを使用する場合)Helm 3がインストール済み

方法1: Manifestファイルによるインストール (基本的な理解のため)

公式が提供しているYAMLファイルを直接適用する方法です。GitHubリポジトリに各バージョンごとのManifestファイルが用意されています。

“`bash

インストールしたいバージョン(例: v1.8.1)のmanifestファイルを取得

stable版は非推奨となり、kubernetes/ingress-nginx リポジトリが公式です

最新の安定版は公式リポジトリの release ページで確認できます

例: https://github.com/kubernetes/ingress-nginx/releases/tag/controller-v1.8.1

RBACの設定など

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/mandatory.yaml

クラウド環境などでLoadBalancer Serviceを作成する場合

(GCE/AWS/Azureなどに対応)

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/cloud-generic.yaml

bare-metal環境などでNodePort Serviceを作成する場合

(cloud-generic.yamlの代わりにこちらを使用)

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/baremetal/service-nodeport.yaml

デプロイメントの確認

kubectl get pods –namespace ingress-nginx
kubectl get service –namespace ingress-nginx
“`

mandatory.yaml には、Namespace (ingress-nginx)、ServiceAccount、ClusterRole、ClusterRoleBinding、Role、RoleBinding、ConfigMap (デフォルト設定)、Deployment (Controller本体) など、Ingress Controllerが動作するために最低限必要なリソースが含まれています。

cloud-generic.yamlservice-nodeport.yaml は、外部からのアクセスを受けるためのServiceリソースを定義しています。多くの場合、cloud-generic.yaml を使用し、クラウドプロバイダーがLoadBalancerをプロビジョニングするのを待ちます。割り当てられた外部IPアドレス/ホスト名がIngress Controllerのエントリポイントとなります。

この方法はシンプルですが、設定のカスタマイズ(レプリカ数、リソース制限、Service Typeの変更など)がManifestファイルを直接編集する必要があり、管理が煩雑になりがちです。

方法2: Helmによるインストール (推奨)

HelmはKubernetesのパッケージマネージャーであり、Chartと呼ばれるパッケージ形式でアプリケーションのデプロイや管理を行います。Nginx Ingress Controllerも公式のHelm Chartが提供されており、こちらを利用するのが最も推奨される方法です。Helm Chartを使うと、values.yaml ファイルを編集したり、--set オプションを使ったりすることで、デプロイ設定を柔軟かつ管理しやすく変更できます。

手順:

  1. Helmリポジトリの追加:
    公式のingress-nginx Chartは、コミュニティ管理のリポジトリに含まれています。

    bash
    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm repo update

  2. Chartの設定確認:
    インストール前に、Chartが持つ設定オプション(values)を確認しておくと良いでしょう。

    “`bash
    helm show values ingress-nginx/ingress-nginx > values.yaml

    values.yaml をエディタで開いて内容を確認・編集する

    ``values.yaml` には、レプリカ数、リソース制限、Serviceタイプ、アノテーション、ConfigMap設定など、多岐にわたる設定項目があります。

  3. Helm Chartのインストール:
    helm install コマンドでインストールを実行します。リリース名(例: my-nginx-ingress)、Namespace(例: ingress-nginx)、使用するChart名 (ingress-nginx/ingress-nginx) を指定します。カスタマイズした values.yaml を使う場合は -f values.yaml オプションを追加します。

    “`bash

    新しいNamespaceを作成する場合 (任意)

    kubectl create namespace ingress-nginx

    Helmインストール

    デフォルト設定でインストールする場合 (LoadBalancer Service)

    helm install my-nginx-ingress ingress-nginx/ingress-nginx –namespace ingress-nginx

    カスタマイズした values.yaml を使ってインストールする場合

    helm install my-nginx-ingress ingress-nginx/ingress-nginx –namespace ingress-nginx -f values.yaml

    “`

    よく使う設定値 (values.yaml もしくは –set で指定):

    • controller.replicaCount: Controller Podのレプリカ数(高可用性のために2以上を推奨)。
    • controller.service.type: 公開Serviceのタイプ (LoadBalancer, NodePort, ClusterIPなど)。
    • controller.service.loadBalancerIP: クラウドプロバイダーで静的なロードバランサーIPを割り当てる場合。
    • controller.nodeSelector, controller.tolerations: 特定のノードにController Podを配置したい場合。
    • controller.resources: Controller Podのリソース要求・制限。
    • controller.config: ConfigMapによる全体設定(YAML形式で記述)。
    • controller.ingressClassResource.enabled: IngressClassリソースを作成するかどうか。Kubernetes 1.18+で推奨される方法。
    • controller.ingressClassResource.name: IngressClassの名前。
    • controller.ingressClassResource.default: このControllerをデフォルトのIngressClassにするか。
    • controller.admissionWebhooks.enabled: ValidatingWebhookConfigurationを有効にするか(Ingressリソースの検証に利用)。セキュリティと安定性のために有効を推奨。
  4. デプロイメントの確認:
    インストールが完了したら、PodとServiceが作成されたことを確認します。

    bash
    kubectl get pods --namespace ingress-nginx
    kubectl get service --namespace ingress-nginx

    kubectl get service --namespace ingress-nginx の出力で、ServiceのEXTERNAL-IPがPendingからIPアドレスに変わるのを待ちます(LoadBalancer Serviceの場合)。このIPアドレスが、外部からアプリケーションにアクセスするためのエントリポイントとなります。

Helmによるインストールは、設定の変更やアップグレード、ロールバックが容易であるため、プロダクション環境では強く推奨されます。

Ingressリソースの設定方法

Nginx Ingress Controllerのインストールが完了したら、次にIngressリソースを作成してルーティングルールを定義します。Ingressリソースは標準的なKubernetes APIオブジェクトです。

基本的なIngressリソースの構造:

yaml
apiVersion: networking.k8s.io/v1 # または extensions/v1beta1 (古いバージョン)
kind: Ingress
metadata:
name: my-app-ingress
namespace: default # Ingress Controllerと同じNamespaceである必要はない
annotations:
# ここにNginx Ingress Controller固有の設定を記述
# 例: nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx # 使用するIngress Controllerのクラス名を指定
defaultBackend: # いずれのルールにもマッチしない場合に使われるバックエンド (任意)
service:
name: default-http-backend # デフォルトバックエンドServiceの名前
port:
number: 80
rules:
- host: example.com # ホスト名ベースのルーティング
http:
paths:
- path: /app1 # パスベースのルーティング
pathType: Prefix # マッチング方法 (Prefix, Exact, ImplementationSpecific)
backend:
service:
name: app1-service # 転送先のService名
port:
number: 80 # 転送先のServiceポート
- path: /app2
pathType: Exact
backend:
service:
name: app2-service
port:
number: 8080
- host: api.example.com # 別のホスト名
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: api-service-v1
port:
number: 5000
tls: # TLS終端設定 (HTTPS)
- hosts:
- example.com
- api.example.com
secretName: example-tls-secret # TLS証明書を含むSecretの名前

主要フィールド解説:

  • apiVersion, kind, metadata: 標準的なKubernetesオブジェクトのフィールド。
  • metadata.annotations: Nginx Ingress Controllerの機能の大部分は、Ingressリソースのannotationsフィールドを使って設定します。 nginx.ingress.kubernetes.io/... の形式で様々なアノテーションが提供されています。これについては後述の「高度な機能」で詳しく解説します。
  • spec.ingressClassName: Kubernetes 1.18+で導入されたフィールド。どのIngress ControllerがこのIngressリソースを処理するかを指定します。Nginx Ingress ControllerをHelmでインストールした場合、デフォルトのクラス名は nginx です。以前は kubernetes.io/ingress.class アノテーションで指定していましたが、ingressClassName が推奨されます。
  • spec.defaultBackend: 定義されたどのrulesにもマッチしないリクエストが来た場合に、トラフィックを転送するデフォルトのバックエンドServiceを指定します。設定しない場合、通常はNginx Ingress Controllerが提供するデフォルトの404ページが表示されます。
  • spec.rules: ルーティングルールのリスト。各ルールはホスト名 (host) とHTTPパス (http.paths) の組み合わせで定義されます。
    • host: リクエストヘッダーのHostフィールドとマッチさせます。指定しない場合、すべてのホスト名にマッチします(ワイルドカード)。
    • http.paths: パスベースのルーティング規則のリスト。
      • path: リクエストURLのパス部分とマッチさせます。
      • pathType: パスのマッチング方法。
        • Prefix: 指定したパスで始まるすべてのパスにマッチします (例: /app/app, /app/, /app/users にマッチ)。パスの階層を考慮したマッチングになります。
        • Exact: 指定したパスと完全に一致する場合にのみマッチします (例: /app/app にのみマッチ)。
        • ImplementationSpecific: Ingress Controllerの実装に依存するマッチング方法。Nginx Ingress Controllerの場合、これは正規表現によるマッチングに使用されることが多いですが、特定の用途に限定して使用することが推奨されます(正規表現はパフォーマンスに影響する可能性があるため)。標準的なルーティングにはPrefixまたはExactを使用すべきです。
      • backend: マッチした場合にトラフィックを転送するServiceとポートを指定します。
  • spec.tls: HTTPSを有効にするための設定。
    • hosts: TLS終端を行うホスト名のリスト。
    • secretName: TLS証明書(tls.crt)と秘密鍵(tls.key)を含むKubernetes Secretの名前を指定します。このSecretはkubernetes.io/tlsタイプのSecretとして事前に作成しておく必要があります。

TLS Secretの作成例:

OpenSSLなどで証明書と秘密鍵ファイル(例: tls.crt, tls.key)を準備した後、以下のコマンドでSecretを作成します。

bash
kubectl create secret tls example-tls-secret \
--cert tls.crt \
--key tls.key \
--namespace default # Secretを作成するNamespace

このSecretをIngressリソースのspec.tls.secretNameで参照することで、Nginx Ingress Controllerが証明書を読み込み、指定されたホスト名でHTTPS通信を提供します。Let’s Encryptなどと連携して証明書を自動管理したい場合は、cert-managerなどのツールと組み合わせるのが一般的です。cert-managerはCertificateリソースとIssuer/ClusterIssuerリソースを監視し、CAと連携して証明書を発行・更新し、kubernetes.io/tlsタイプのSecretとして保存してくれます。Nginx Ingress ControllerはそのSecretを利用する形になります。

Nginx Ingress Controllerの高度な機能と設定 (アノテーションとConfigMap)

Nginx Ingress Controllerの強みは、Ingressリソースの標準的な設定に加え、Nginx固有の詳細設定を柔軟に行える点です。これは主に以下の2つの方法で行います。

  1. Ingressリソースのアノテーション: 特定のIngressリソースに適用されるNginx設定をカスタマイズする場合に使用します。nginx.ingress.kubernetes.io/... の形式で指定します。最も一般的な設定方法です。
  2. ConfigMap: Nginx Ingress Controller全体、または特定のIngressリソースに依存しないグローバルなNginx設定(例: httpブロックやserverブロックの一部)をカスタマイズする場合に使用します。Helm Chartでインストールした場合、通常はingress-nginx Namespaceにあるingress-nginx-controllerという名前のConfigMap(名前はインストール時に変更可能)を使用します。Helmのvalues.yamlcontroller.configフィールドで設定できます。

主要なアノテーションの例

ここではよく利用されるアノテーションをいくつか紹介します。全てのアノテーションは公式ドキュメントを参照してください。

アノテーション 説明
nginx.ingress.kubernetes.io/rewrite-target パスを書き換えてバックエンドに転送します。 / (/appへのリクエストを/としてバックエンドに転送)
nginx.ingress.kubernetes.io/proxy-connect-timeout バックエンドへの接続タイムアウト(秒)。 60
nginx.ingress.kubernetes.io/proxy-send-timeout バックエンドへのリクエスト送信タイムアウト(秒)。 60
nginx.ingress.kubernetes.kubernetes.io/proxy-read-timeout バックエンドからのレスポンス読み取りタイムアウト(秒)。 60
nginx.ingress.kubernetes.io/client-max-body-size クライアントから送信されるリクエストボディの最大サイズ。ファイルアップロードなどに。 100m (100MB)
nginx.ingress.kubernetes.io/server-snippet serverブロック内にカスタムNginx設定を挿入します。高度なカスタマイズ。 location /status { return 200; }
nginx.ingress.kubernetes.io/configuration-snippet locationブロック内にカスタムNginx設定を挿入します。 add_header X-Frame-Options DENY;
nginx.ingress.kubernetes.io/auth-type 認証タイプ。basicなど。 basic
nginx.ingress.kubernetes.io/auth-secret ベーシック認証のユーザー名/パスワードを含むSecret名。 basic-auth-users
nginx.ingress.kubernetes.io/auth-realm ベーシック認証のダイアログに表示されるRealm名。 "Authentication Required"
nginx.ingress.kubernetes.io/limit-rpm 1分あたりのリクエスト数制限。 100 (IPアドレスごと)
nginx.ingress.kubernetes.io/limit-rps 1秒あたりのリクエスト数制限。 5 (IPアドレスごと)
nginx.ingress.kubernetes.io/limit-connections 同時接続数制限。 10 (IPアドレスごと)
nginx.ingress.kubernetes.io/enable-cors CORS (Cross-Origin Resource Sharing) を有効にします。 true
nginx.ingress.kubernetes.io/affinity セッションアフィニティ。cookieまたはip cookie
nginx.ingress.kubernetes.io/ssl-redirect HTTPリクエストをHTTPSにリダイレクトするかどうか。デフォルトtrue false
nginx.ingress.kubernetes.io/from-to-www-redirect non-www から www またはその逆にリダイレクトするかどうか。 true (example.com -> www.example.com など)
nginx.ingress.kubernetes.io/whitelist-source-range アクセスを許可する送信元IPアドレス範囲 (CIDR)。 10.0.0.0/8,192.168.1.0/24

アノテーション使用例 (リライト):

例えば、/app へのリクエストをバックエンドServiceでは / として処理させたい場合。

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress-rewrite
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # ★ ここでパスを書き換える
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /app # ★ このパスにマッチしたリクエストのパス部分が...
pathType: Prefix
backend:
service:
name: app1-service
port:
number: 80

外部から http://example.com/app/users にアクセスすると、Nginx Ingress Controllerは app1-service/users パスにトラフィックを転送します。rewrite-target: / とすることで、/app に続くパス (/users) のみがバックエンドに送られます。より複雑な正規表現を使ったリライトも可能ですが、設定ミスが起きやすいため注意が必要です。

アノテーション使用例 (ベーシック認証):

特定のパスへのアクセスにベーシック認証をかけたい場合。ユーザー名とパスワードはSecretに保存しておきます。Secretのデータは auth というキーで ユーザー名:ハッシュ化されたパスワード の形式で保存します(htpasswd コマンドなどで生成)。

“`yaml

ベーシック認証情報を格納するSecretを作成 (例: user:pass を htpasswd で生成)

echo $(htpasswd -nb user pass) | kubectl create secret generic basic-auth-users –from-literal=auth=”user:{ hashed_password }” -n default

“`

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress-auth
annotations:
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth-users # ★ 先ほど作成したSecret名
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required for Admin Area' # ★ 認証ダイアログのメッセージ
spec:
ingressClassName: nginx
rules:
- host: example.com
http:
paths:
- path: /admin # ★ このパスへのアクセスに認証をかける
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 80

ConfigMapによる全体設定

Nginx Ingress Controllerのインストール時に作成されるConfigMapを編集することで、すべてまたは一部のIngressリソースに影響するグローバルな設定や、アノテーションでは設定できない項目を制御できます。Helmインストールの場合、values.yamlcontroller.configセクションで設定できます。

ConfigMapのデータはキーと値のペアで構成されます。キーは設定名、値は設定値です。

“`yaml

例: ConfigMap を直接編集する場合 (非推奨、Helm valuesでの管理を推奨)

kubectl edit configmap ingress-nginx-controller –namespace ingress-nginx
“`

“`yaml

ConfigMapの一部 (Helm values.yaml の controller.config に対応)

data:
allow-snippet-from-anywhere: “true” # server-snippet, configuration-snippet を許可するか (デフォルト false)
use-forwarded-headers: “true” # X-Forwarded-* ヘッダーを信頼するか (LB利用時に重要)
proxy-body-size: “1m” # 全体の最大リクエストボディサイズ (アノテーションで上書き可能)
worker-processes: “auto” # Nginxワーカープロセスの数
error-log-level: “warn” # Nginxエラーログのレベル
# … その他の設定 …
“`

use-forwarded-headers: "true" の重要性:

Nginx Ingress Controller ServiceとしてLoadBalancerを使用している場合、クライアントからの実際のIPアドレスはLoadBalancerによってNginx Ingress Controller Podに転送される際に、X-Forwarded-Forヘッダーなどに格納されます。Nginx Ingress Controllerがこれらのヘッダーを信頼してクライアントIPとして認識するためには、use-forwarded-headers: "true" をConfigMapで設定し、さらにServiceのexternalTrafficPolicyLocalに設定する必要があります。これにより、Nginx Ingress ControllerやバックエンドPodのログで正しいクライアントIPを記録できるようになります。

allow-snippet-from-anywhere: "true" とセキュリティ:

server-snippetconfiguration-snippetアノテーションは非常に強力で、任意のNginx設定ディレクティブを挿入できてしまいます。これは便利な反面、悪意のあるユーザーがこれらのアノテーションを持つIngressリソースを作成できる場合、Nginxの設定を不正に変更し、セキュリティホールを生み出す可能性があります。そのため、デフォルトでは無効になっています。これらのアノテーションを使用したい場合は、ConfigMapで allow-snippet-from-anywhere: "true" を設定する必要がありますが、Kubernetesクラスタへの書き込み権限を持つユーザーを信頼できる場合に限定して使用すべきです。

トラブルシューティング

Nginx Ingress Controllerが期待通りに動作しない場合、以下の手順で原因を特定できます。

  1. Ingress Controller Podのログを確認する:
    Ingressリソースの変更がControllerに認識されているか、設定生成やリロードにエラーがないかなどを確認します。
    bash
    kubectl logs <ingress-controller-pod-name> --namespace ingress-nginx
    # Pod名を特定: kubectl get pods --namespace ingress-nginx

  2. IngressリソースのEventsを確認する:
    Ingressリソースが作成/更新された際に、Ingress Controllerがそのリソースを処理したか、処理中にエラーが発生したかなどがEventsとして記録されます。
    bash
    kubectl describe ingress <your-ingress-name> --namespace <your-ingress-namespace>

    EventsセクションにAddedOrUpdatedIngress, ConfigurationReloadedなどの正常を示すイベントや、エラーイベントが表示されます。

  3. Nginx設定ファイルを確認する:
    Ingress Controllerが生成したNginx設定ファイル(nginx.conf)の内容を直接確認します。Controller Pod内で実行されているNginxコンテナにアクセスする必要があります。設定ファイルは通常 /etc/nginx/nginx.conf/etc/nginx/conf.d/*.conf に生成されます。
    “`bash
    # Controller Pod名を特定
    # kubectl get pods –namespace ingress-nginx

    Nginxコンテナにシェルで入る (Podに複数のコンテナがある場合は -c を指定)

    kubectl exec -it –namespace ingress-nginx — /bin/bash

    Nginx設定ファイルを確認

    cat /etc/nginx/nginx.conf

    cat /etc/nginx/conf.d/default.conf

    exit # シェルから出る

    “`
    生成された設定が、意図したルーティングルールやアノテーションによる設定を反映しているかを確認します。

  4. ServiceとEndpointの状態を確認する:
    Ingress Controllerが参照しているバックエンドServiceが存在し、そのServiceにEndpoint(つまり稼働中のPod)が紐づいているかを確認します。Podが存在しない、Readyになっていないなどの理由でEndpointがない場合、Nginxはバックエンドにトラフィックを転送できません(通常502 Bad Gatewayや503 Service Unavailableになる)。
    bash
    kubectl get service <your-backend-service-name> --namespace <your-service-namespace>
    kubectl get endpoints <your-backend-service-name> --namespace <your-service-namespace>

  5. Nginxの状態を確認する (Nginx Status Page):
    ConfigMapでallow-snippet-from-anywhere: "true"を設定している場合、server-snippetアノテーションなどを使ってNginxのStatus Page (ngx_http_stub_status_module) を有効にすると、Nginxの稼働状況(アクティブな接続数、処理されたリクエスト数など)を確認できます。より高度な情報が必要な場合は、ngx_http_vts_module などを使用するようにControllerをビルド・設定することも可能です。

よくある問題:

  • 404 Not Found:
    • Ingressリソースのhostpathがリクエストにマッチしていない。
    • pathTypeの指定が間違っている(Exactを指定しているがPrefixでアクセスしているなど)。
    • ingressClassNameが正しく指定されていない、またはIngress Controllerがそのクラス名のリソースを処理していない。
    • デフォルトバックエンドが設定されていない。
  • 502 Bad Gateway / 503 Service Unavailable:
    • バックエンドServiceに対応するPodが稼働していない、またはReadyになっていない(Endpointが存在しない)。
    • バックエンドServiceのポートが間違っている。
    • バックエンドPodがクラッシュしている、またはリクエストを正常に処理できていない。
    • Nginx Ingress ControllerからバックエンドPodへのネットワーク疎通がない(Serviceやkube-proxyの問題)。
  • TLSエラー (ブラウザでの証明書警告など):
    • Ingressリソースで指定したsecretNameのSecretが存在しない、またはタイプがkubernetes.io/tlsではない。
    • Secretに含まれる証明書/秘密鍵ファイル名がtls.crt/tls.keyではない。
    • 証明書が不正、有効期限切れ、またはIngressリソースのhostsフィールドに指定したホスト名と一致しない。
    • Ingressリソースのtlsセクションが設定されていない、またはホスト名が指定されていない。

運用上の考慮事項

プロダクション環境でNginx Ingress Controllerを運用する際には、以下の点を考慮する必要があります。

  • 可用性 (High Availability):
    • Controller Podのレプリカ数を2以上に設定し、複数のノードで稼働するようにします(Helmのcontroller.replicaCount)。
    • Node Affinity/Anti-AffinityやPod Anti-Affinityを設定して、Podが同じノードやゾーンに偏らないようにします。
    • LoadBalancer Serviceを使用する場合、クラウドプロバイダーのロードバランサー自体の可用性も考慮が必要です。
  • スケーリング:
    • トラフィックの増加に応じてController Podを自動的にスケーリングするために、Horizontal Pod Autoscaler (HPA) を設定します。CPU使用率やカスタムメトリクス(例: NginxのRequests per second)をトリガーにできます。
    • HPAの設定には、Controller Podのリソース要求(requests)を適切に設定することが重要です。
  • 監視とアラート:
    • Nginx Ingress ControllerはPrometheus形式のメトリクスを公開するエンドポイントを持っています(通常/metrics)。Prometheusなどでこれらのメトリクス(リクエスト数、レスポンスタイム、エラーレート、Nginxワーカーの状態など)を収集し、Grafanaなどで可視化します。
    • 重要なメトリクス(例: エラーレートの急増、レイテンシの増加)に対してアラートを設定します。
    • Controller PodのログやNginxのエラーログも監視対象とします。
  • ログ管理:
    • Nginxのアクセスログやエラーログを収集し、集中ログ管理システム(Fluentd, Elasticsearch, Kibanaなど)に転送します。
    • ログのフォーマットを調整し、トラブルシューティングやトラフィック分析に役立てられるようにします。
  • セキュリティ:
    • TLSv1.2以降の使用を強制するなど、安全なTLS設定を行います(ConfigMapでssl-protocolsなどを設定)。
    • 弱いSSLシファーの使用を禁止します(ConfigMapでssl-ciphersなどを設定)。
    • 不要なNginxモジュールや機能を無効にします。
    • WAF (Web Application Firewall) と組み合わせることで、SQLインジェクションやXSSなどのアプリケーション層の攻撃から保護できます。Nginx Ingress Controller自体には基本的なWAF機能はありませんが、ModSecurityモジュールを組み込んだカスタムビルドを使用したり、外部のWAFサービスと連携したりする方法があります。
    • Ingressリソースのwhitelist-source-rangeアノテーションやNginx設定で、アクセス元IPアドレスによる制限を行います。
  • アップデート戦略:
    • セキュリティパッチや新機能を取り込むために、定期的にNginx Ingress Controllerをアップデートします。
    • Helmを使用している場合、helm upgradeコマンドで比較的容易にアップデートできます。
    • アップデート前に、リリースノートを確認し、破壊的な変更がないか、必要な設定変更がないかを確認します。
    • 本番環境に適用する前に、ステージング環境などで十分にテストを行います。
  • ConfigMapとアノテーションの管理:
    • ConfigMapやIngressリソースはGitなどのバージョン管理システムで管理し、変更履歴を追えるようにします(GitOps)。
    • アノテーションは強力ですが、Ingressリソースごとに設定が分散するため、管理が複雑になる可能性があります。チーム内でアノテーションの利用ルールを定めることが望ましいです。

まとめ

この記事では、KubernetesにおけるNginx Ingress Controllerの役割、アーキテクチャ、インストール方法、そして実践的な設定方法について詳細に解説しました。

Nginx Ingress Controllerは、Kubernetesクラスタへの外部トラフィックの入り口として、HTTP/HTTPSルーティング、TLS終端、負荷分散、認証、レート制限など、多岐にわたる重要な機能を提供します。Ingressリソースという共通のAPIを通じて、これらの設定を宣言的に定義できるため、アプリケーションのデプロイと外部公開の設定を分離し、管理を容易にします。

特に、アノテーションやConfigMapによるNginxの詳細設定は、Nginx Ingress Controllerが他の多くのIngress Controllerと一線を画す強力な点です。これにより、ほぼ全てのNginxの機能をKubernetes環境で活用することが可能になります。

Helmを使ったインストールは、設定の管理と運用の効率化に不可欠であり、プロダクション環境では必須のアプローチと言えます。また、安定した運用のためには、高可用性の確保、適切な監視、ログ管理、セキュリティ対策、そして継続的なアップデートが重要となります。

Kubernetesのネットワークコンポーネントは進化しており、Ingressの次世代APIとしてGateway APIが登場しつつあります。Gateway APIはIngressよりも柔軟で表現力豊かなAPIを提供することを目指しており、Nginx Ingress ControllerもGateway APIへの対応を進めています。しかし、現時点ではIngressが引き続き広く利用されており、Nginx Ingress ControllerはKubernetesにおけるトラフィック管理のデファクトスタンダードであり続けています。

この記事を通じて、Nginx Ingress Controllerの仕組みと設定に関する理解が深まり、皆様のKubernetes環境でのアプリケーション公開と運用の一助となれば幸いです。詳細な設定や特定のアノテーションについては、常に公式ドキュメントを参照することをお勧めします。


コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール