Day 8: Ingressと外部公開
今日学ぶこと
- Ingressの仕組みとServiceとの違い
- Ingress Controllerの導入
- パスベースとホストベースのルーティング
- TLS/SSLの設定
なぜIngressが必要なのか
Day 5でServiceのNodePortやLoadBalancerを使って外部公開する方法を学びました。しかし、複数のサービスを外部公開する場合、それぞれにLoadBalancerを割り当てるとコストがかかります。
flowchart TB
subgraph Without["Ingressなし"]
LB1["LoadBalancer 1\n$$$"]
LB2["LoadBalancer 2\n$$$"]
LB3["LoadBalancer 3\n$$$"]
end
subgraph With["Ingressあり"]
ING["Ingress\n(1つのLB)"]
end
LB1 --> S1A["frontend"]
LB2 --> S2A["api"]
LB3 --> S3A["admin"]
ING -->|"/api"| S1B["api"]
ING -->|"/admin"| S2B["admin"]
ING -->|"/"| S3B["frontend"]
style Without fill:#ef4444,color:#fff
style With fill:#22c55e,color:#fff
| 方式 | メリット | デメリット |
|---|---|---|
| Service (LoadBalancer) | シンプル | サービスごとにLBが必要(高コスト) |
| Service (NodePort) | 無料 | ポート番号の管理が煩雑 |
| Ingress | 1つのLBで複数サービスをルーティング | Ingress Controllerの導入が必要 |
Ingressの仕組み
Ingressは、クラスタ外からのHTTP/HTTPSトラフィックを、URLのパスやホスト名に基づいてServiceにルーティングするリソースです。
flowchart LR
CLIENT["クライアント"] -->|"HTTPS"| IC["Ingress Controller\n(nginx等)"]
IC -->|"app.example.com/"| WEB["web-service"]
IC -->|"app.example.com/api"| API["api-service"]
IC -->|"admin.example.com"| ADMIN["admin-service"]
style IC fill:#3b82f6,color:#fff
Ingressの2つの要素
| 要素 | 説明 |
|---|---|
| Ingress リソース | ルーティングルールを定義するYAMLマニフェスト |
| Ingress Controller | ルールを実行するソフトウェア(nginx、Traefik等) |
重要: IngressリソースだけではIngress Controllerが必要です。Kubernetesにはデフォルトで含まれていないため、別途インストールが必要です。
Ingress Controllerの導入
NGINX Ingress Controller
最も広く使われているIngress Controllerです。
# Helmを使ったインストール
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install ingress-nginx ingress-nginx/ingress-nginx
# またはマニフェストから直接インストール
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.12.0/deploy/static/provider/cloud/deploy.yaml
# Docker Desktop / Minikubeの場合
# Minikube
minikube addons enable ingress
# インストール確認
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
パスベースルーティング
URLのパスに基づいて異なるServiceにルーティングします。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- path: /admin
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 80
pathType
| タイプ | 説明 | 例 |
|---|---|---|
| Prefix | パスのプレフィックスでマッチ | /apiは/api/usersにもマッチ |
| Exact | 完全一致でマッチ | /apiは/apiのみマッチ |
| ImplementationSpecific | Ingress Controller依存 | - |
ホストベースルーティング
ホスト名(ドメイン)に基づいてルーティングします。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-host-ingress
spec:
ingressClassName: nginx
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 80
flowchart TB
IC["Ingress Controller"]
IC -->|"app.example.com"| APP["app-service"]
IC -->|"api.example.com"| API["api-service"]
IC -->|"admin.example.com"| ADMIN["admin-service"]
style IC fill:#3b82f6,color:#fff
style APP fill:#22c55e,color:#fff
style API fill:#8b5cf6,color:#fff
style ADMIN fill:#f59e0b,color:#fff
TLS/SSL設定
IngressでHTTPSを設定する方法です。
1. TLS Secretの作成
# 自己署名証明書を作成(テスト用)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key -out tls.crt \
-subj "/CN=app.example.com"
# Secretとして登録
kubectl create secret tls app-tls-secret \
--cert=tls.crt \
--key=tls.key
2. IngressにTLSを設定
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: secure-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls-secret
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 80
実践: 完全な構成例
フロントエンドとAPIを1つのIngressで公開する構成です。
# deployments.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: nginx:1.27
ports:
- containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: httpd:2.4
ports:
- containerPort: 80
---
# services.yaml
apiVersion: v1
kind: Service
metadata:
name: frontend-service
spec:
selector:
app: frontend
ports:
- port: 80
---
apiVersion: v1
kind: Service
metadata:
name: api-service
spec:
selector:
app: api
ports:
- port: 80
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
ingressClassName: nginx
rules:
- host: myapp.local
http:
paths:
- path: /(.*)
pathType: ImplementationSpecific
backend:
service:
name: frontend-service
port:
number: 80
- path: /api/(.*)
pathType: ImplementationSpecific
backend:
service:
name: api-service
port:
number: 80
ローカルでテスト
# リソースを作成
kubectl apply -f deployments.yaml
kubectl apply -f services.yaml
kubectl apply -f ingress.yaml
# Ingressの確認
kubectl get ingress
# NAME CLASS HOSTS ADDRESS PORTS AGE
# app-ingress nginx myapp.local localhost 80 30s
# /etc/hostsに追加(ローカルテスト用)
echo "127.0.0.1 myapp.local" | sudo tee -a /etc/hosts
# テスト
curl http://myapp.local/
curl http://myapp.local/api/
よく使うAnnotation
| Annotation | 説明 |
|---|---|
nginx.ingress.kubernetes.io/rewrite-target |
パスの書き換え |
nginx.ingress.kubernetes.io/ssl-redirect |
HTTPSへのリダイレクト |
nginx.ingress.kubernetes.io/proxy-body-size |
リクエストボディのサイズ制限 |
nginx.ingress.kubernetes.io/cors-allow-origin |
CORS設定 |
nginx.ingress.kubernetes.io/rate-limit |
レート制限 |
まとめ
| 概念 | 説明 |
|---|---|
| Ingress | HTTP/HTTPSのルーティングルールを定義するリソース |
| Ingress Controller | ルールを実行するソフトウェア(nginx等) |
| パスベースルーティング | URLパスでServiceを振り分け |
| ホストベースルーティング | ドメイン名でServiceを振り分け |
| TLS | HTTPS通信の設定 |
重要ポイント
- Ingressを使えば1つのエントリポイントで複数のServiceを公開できる
- Ingress Controllerのインストールが別途必要
- パスベースとホストベースのルーティングを組み合わせて柔軟なルーティングが可能
練習問題
問題1: 基本
3つのサービス(frontend、api、docs)をパスベースルーティングで公開するIngressを作成してください。
問題2: ホストベース
app.example.comとapi.example.comでそれぞれ異なるServiceにルーティングするIngressを作成してください。
チャレンジ問題
TLS Secretを作成し、HTTPSでアクセスできるIngressを構成してください。HTTPからHTTPSへの自動リダイレクトも設定しましょう。
参考リンク
次回予告: Day 9では「スケーリングとアップデート戦略」について学びます。Horizontal Pod Autoscalerによる自動スケーリングや、Blue/Green・Canaryデプロイメントなどの高度なアップデート戦略を習得しましょう。