【図解】Nginx Ingress Controller の仕組みと設定方法
Kubernetes上でアプリケーションを公開する際、その入り口となるコンポーネントは非常に重要です。単にトラフィックを受け付けるだけでなく、高度なルーティング、TLS終端、負荷分散など、様々な機能が求められます。この記事では、Kubernetesのエコシステムでデファクトスタンダードとして広く利用されている「Nginx Ingress Controller」に焦点を当て、その仕組みからインストール方法、そして実践的な設定方法までを詳細に解説します。約5000語にわたる解説を通じて、Nginx Ingress Controllerを深く理解し、自信を持って運用できるようになることを目指します。
はじめに:Kubernetesにおけるサービス公開の課題とIngressの必要性
Kubernetesでデプロイされたアプリケーション(Pod)は、通常、ClusterIP Serviceによってクラスタ内部でのみアクセス可能になります。これらのアプリケーションをインターネットやクラスタ外部から公開するには、いくつかの方法があります。
-
NodePort: 各Podが稼働しているノードの特定のポートを介してサービスを公開します。外部から
ノードIP:NodePort
でアクセスできます。- 課題: 利用できるポート範囲が限られている(通常30000-32767)。複数のサービスを公開するとポート管理が煩雑になる。ノード障害時にアクセスできなくなる可能性がある。単なるポート転送であり、高度な機能(ホストベースルーティング、TLS終端など)を提供しない。
-
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クラスタ内で動作する特殊なコントローラーです。その主な役割は以下の通りです。
- Ingressリソースの監視: Kubernetes APIサーバーを介して、クラスタ内のIngress、Service、Endpoint、Secretなどのリソースの作成、更新、削除イベントを監視します。
- 設定の生成: 監視しているリソースの情報(特にIngressリソースで定義されたルーティングルール)をもとに、自身が使用するロードバランサー/リバースプロキシ(例えばNginxやHAProxy)の設定ファイルを動的に生成します。
- 設定の反映: 生成した設定ファイルをロードバランサー/リバースプロキシに反映させます。多くの場合、設定をリロードすることでサービス無停止での反映を実現します。
- トラフィックの処理: 外部からのトラフィックを受け付け、生成された設定に基づいて適切な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) |
+---------------------+
-
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のホットリロード機能を利用することで、新しい設定を適用しても既存の接続を維持できます。
- 内部的には、Ingress ControllerはGo言語で書かれており、
-
Nginx (Proxy) Pod: 実際のエッジプロキシ/ロードバランサーとして機能するNginxプロセスが実行されるPodです。外部からのトラフィックを受け付け、Ingress Controllerによって生成・反映された設定に基づいて、適切なServiceのClusterIPとポートへ転送します。
- Nginx Ingress Controllerの多くのデプロイメントでは、ControllerとNginxプロセスは同じPod内の異なるコンテナとして実行されます(マルチコンテナPod)。これにより、Controllerが生成した設定ファイルをNginxコンテナから容易に参照できます。外部からのトラフィックは、このPodの特定のポート(通常80/443)にルーティングされます。
-
Service: Nginx Ingress Controller Podへのアクセスポイントを提供します。外部からのトラフィックはこのServiceを経由してController Podに到達します。このServiceの
type
によって、Controllerがどのように外部に公開されるかが決まります。LoadBalancer
: クラウド環境で利用する場合、クラウドプロバイダーのロードバランサーが自動的にプロビジョニングされ、外部IPアドレスが割り当てられます。これが最も一般的なプロダクションでの公開方法です。NodePort
: 各ノードの特定のポートに公開されます。開発やテスト環境、または別のロードバランサー(例: 外部のL4 LB)と組み合わせて使用する場合に利用されることがあります。ClusterIP
: クラスタ内部からのみアクセス可能です。内部Ingressや、DaemonSetなどで各ノードにIngress Controllerをデプロイし、その手前にL4 LBを置く構成などで利用されます。
-
ConfigMap: Nginx Ingress Controller全体の挙動や、標準のNginx設定(例:
nginx.conf
のhttp
ブロック内の設定)をカスタマイズするために使用されます。Ingressリソースのアノテーションよりも広範な設定や、Ingressリソースでは指定できない設定を行う場合に利用します。- Controller PodはこのConfigMapも監視しており、変更があるとNginx設定の再生成とリロードを行います。
-
Secret: TLS終端のための証明書と秘密鍵を保存するために使用されます。Ingressリソースの
tls
セクションで指定されたSecretをIngress Controllerが読み込み、NginxにTLS証明書として設定します。
トラフィックの流れの概要:
- 外部からNginx Ingress ControllerのService(
LoadBalancer
やNodePort
)のIP/ポートにトラフィックが到達。 - トラフィックはNginx Ingress Controller Pod内のNginxプロセスに転送される。
- Nginxプロセスは、Controllerによって動的に生成された設定(
nginx.conf
)に基づいて、リクエストのホスト名やパスを解析する。 - 解析結果に基づき、Ingressリソースで定義されたバックエンドServiceのClusterIPとポートを特定する。
- Nginxプロセスは、Kubernetesクラスタ内のkube-proxyを経由して、そのServiceに対応するPodへトラフィックを転送する。
- 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.yaml
や service-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
オプションを使ったりすることで、デプロイ設定を柔軟かつ管理しやすく変更できます。
手順:
-
Helmリポジトリの追加:
公式のingress-nginx
Chartは、コミュニティ管理のリポジトリに含まれています。bash
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update -
Chartの設定確認:
インストール前に、Chartが持つ設定オプション(values)を確認しておくと良いでしょう。“`bash
helm show values ingress-nginx/ingress-nginx > values.yamlvalues.yaml をエディタで開いて内容を確認・編集する
``
values.yaml` には、レプリカ数、リソース制限、Serviceタイプ、アノテーション、ConfigMap設定など、多岐にわたる設定項目があります。 -
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リソースの検証に利用)。セキュリティと安定性のために有効を推奨。
-
デプロイメントの確認:
インストールが完了したら、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つの方法で行います。
- Ingressリソースのアノテーション: 特定のIngressリソースに適用されるNginx設定をカスタマイズする場合に使用します。
nginx.ingress.kubernetes.io/...
の形式で指定します。最も一般的な設定方法です。 - ConfigMap: Nginx Ingress Controller全体、または特定のIngressリソースに依存しないグローバルなNginx設定(例: httpブロックやserverブロックの一部)をカスタマイズする場合に使用します。Helm Chartでインストールした場合、通常は
ingress-nginx
Namespaceにあるingress-nginx-controller
という名前のConfigMap(名前はインストール時に変更可能)を使用します。Helmのvalues.yaml
のcontroller.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.yaml
のcontroller.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のexternalTrafficPolicy
をLocal
に設定する必要があります。これにより、Nginx Ingress ControllerやバックエンドPodのログで正しいクライアントIPを記録できるようになります。
allow-snippet-from-anywhere: "true"
とセキュリティ:
server-snippet
やconfiguration-snippet
アノテーションは非常に強力で、任意のNginx設定ディレクティブを挿入できてしまいます。これは便利な反面、悪意のあるユーザーがこれらのアノテーションを持つIngressリソースを作成できる場合、Nginxの設定を不正に変更し、セキュリティホールを生み出す可能性があります。そのため、デフォルトでは無効になっています。これらのアノテーションを使用したい場合は、ConfigMapで allow-snippet-from-anywhere: "true"
を設定する必要がありますが、Kubernetesクラスタへの書き込み権限を持つユーザーを信頼できる場合に限定して使用すべきです。
トラブルシューティング
Nginx Ingress Controllerが期待通りに動作しない場合、以下の手順で原因を特定できます。
-
Ingress Controller Podのログを確認する:
Ingressリソースの変更がControllerに認識されているか、設定生成やリロードにエラーがないかなどを確認します。
bash
kubectl logs <ingress-controller-pod-name> --namespace ingress-nginx
# Pod名を特定: kubectl get pods --namespace ingress-nginx -
IngressリソースのEventsを確認する:
Ingressリソースが作成/更新された際に、Ingress Controllerがそのリソースを処理したか、処理中にエラーが発生したかなどがEventsとして記録されます。
bash
kubectl describe ingress <your-ingress-name> --namespace <your-ingress-namespace>
Events
セクションにAddedOrUpdatedIngress
,ConfigurationReloaded
などの正常を示すイベントや、エラーイベントが表示されます。 -
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-nginxNginxコンテナにシェルで入る (Podに複数のコンテナがある場合は -c
を指定) kubectl exec -it
–namespace ingress-nginx — /bin/bash Nginx設定ファイルを確認
cat /etc/nginx/nginx.conf
cat /etc/nginx/conf.d/default.conf
exit # シェルから出る
“`
生成された設定が、意図したルーティングルールやアノテーションによる設定を反映しているかを確認します。 -
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> -
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リソースの
host
やpath
がリクエストにマッチしていない。 pathType
の指定が間違っている(Exact
を指定しているがPrefix
でアクセスしているなど)。ingressClassName
が正しく指定されていない、またはIngress Controllerがそのクラス名のリソースを処理していない。- デフォルトバックエンドが設定されていない。
- Ingressリソースの
- 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
セクションが設定されていない、またはホスト名が指定されていない。
- Ingressリソースで指定した
運用上の考慮事項
プロダクション環境でNginx Ingress Controllerを運用する際には、以下の点を考慮する必要があります。
- 可用性 (High Availability):
- Controller Podのレプリカ数を2以上に設定し、複数のノードで稼働するようにします(Helmの
controller.replicaCount
)。 - Node Affinity/Anti-AffinityやPod Anti-Affinityを設定して、Podが同じノードやゾーンに偏らないようにします。
- LoadBalancer Serviceを使用する場合、クラウドプロバイダーのロードバランサー自体の可用性も考慮が必要です。
- Controller Podのレプリカ数を2以上に設定し、複数のノードで稼働するようにします(Helmの
- スケーリング:
- トラフィックの増加に応じて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 Ingress ControllerはPrometheus形式のメトリクスを公開するエンドポイントを持っています(通常
- ログ管理:
- 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アドレスによる制限を行います。
- TLSv1.2以降の使用を強制するなど、安全なTLS設定を行います(ConfigMapで
- アップデート戦略:
- セキュリティパッチや新機能を取り込むために、定期的に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環境でのアプリケーション公開と運用の一助となれば幸いです。詳細な設定や特定のアノテーションについては、常に公式ドキュメントを参照することをお勧めします。