10日で覚えるKubernetesDay 8: Ingressと外部公開
books.chapter 810日で覚えるKubernetes

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通信の設定

重要ポイント

  1. Ingressを使えば1つのエントリポイントで複数のServiceを公開できる
  2. Ingress Controllerのインストールが別途必要
  3. パスベースとホストベースのルーティングを組み合わせて柔軟なルーティングが可能

練習問題

問題1: 基本

3つのサービス(frontend、api、docs)をパスベースルーティングで公開するIngressを作成してください。

問題2: ホストベース

app.example.comapi.example.comでそれぞれ異なるServiceにルーティングするIngressを作成してください。

チャレンジ問題

TLS Secretを作成し、HTTPSでアクセスできるIngressを構成してください。HTTPからHTTPSへの自動リダイレクトも設定しましょう。


参考リンク


次回予告: Day 9では「スケーリングとアップデート戦略」について学びます。Horizontal Pod Autoscalerによる自動スケーリングや、Blue/Green・Canaryデプロイメントなどの高度なアップデート戦略を習得しましょう。