Kubernetesのルーティング地獄からの脱却:ClusterIPからIngressまでの完全解剖と実務ベストプラクティス
こんにちは。テックリードの私だ。
開発チームから「新しく作ったマイクロサービスを外部公開したいんだけど、なぜかアクセスできない」「ALBとIngressのパスルーティングの挙動が噛み合わない」といった悲鳴めいた相談を受けることはないだろうか。
Kubernetes(K8s)におけるトラフィックルーティングは、概念自体はシンプルに見えて、実務で触るとL4とL7の抽象化レイヤーの壁に阻まれ、多くのエンジニアが迷子になりやすい領域だ。
今回は、ClusterIPからNodePort、LoadBalancer、そしてIngressへと至るルーティングの全貌をレイヤーごとに解体し、「明日から即座にチームの生産性を爆上げする実践的設定とプロの知見」を叩き込む。
—
1. Kubernetes内部ネットワークの深淵:kube-proxyとパケットの行方
まず、K8sのネットワークモデルの根本を理解しよう。K8sクラスタ内では、すべてのPodにユニークなIPアドレスが割り振られ、NATなしで直接通信できる(IP-per-Podモデル)。しかし、Podはエフェメラル(儚い)であり、オートスケーリングやデプロイによってIPアドレスは常に変動する。
この「変わり続けるPodの集合」に対して安定した単一のアクセスポイントを提供するのが Service であり、その裏側でルーティングを支えているのが kube-proxy だ。
kube-proxyのモード:iptables vs IPVS
本番環境を構築する際、kube-proxyのモード選定はパフォーマンスを左右するクリティカルな選択だ。
- iptablesモード(デフォルト):
ルール数が増えると(サービスやPod数が増大すると)、パケット処理の線形探索によりCPU負荷が跳ね上がり、レイテンシが悪化する。小規模なら問題ないが、数百サービスを超える本番環境では地雷となる。
- IPVSモード(推奨):
LinuxカーネルのIPVS(IP Virtual Server)を利用する。ハッシュテーブルを使用するため、数千のサービスが存在してもO(1)の計算量でルーティングが行われ、圧倒的なスケーラビリティを誇る。本番環境では必ずIPVSモードを選択せよ。
—
2. サービスタイプの違いと「使い所」の境界線
サービスタイプ(`ClusterIP`, `NodePort`, `LoadBalancer`)の本質は、「トラフィックをどこからどこへ引き受けるか」のスコープの違いに他ならない。
[Client]
│
├─ (社内/VPC内) ──> ClusterIP (クラスタ内のみ)
│
├─ (NodeのIP:Port) ─> NodePort (全ノードのポートを専有)
│
└─ (クラウドLB) ──> LoadBalancer (外部からの直接受付 / コスト高)
比較と実務的アンチパターン
| タイプ | スコープ | メリット | デメリット・実務でのリスク |
| :— | :— | :— | :— |
| ClusterIP | クラスタ内部のみ | 最もセキュア。余計なポートを開けない。 | 外部から直接アクセス不可(プロキシ必須)。 |
| NodePort | クラスタの全ノードの特定ポート | 外部LBなしで手軽に外部公開できる。 | ポート枯渇問題、セキュリティグループの管理が煩雑。本番での直接利用は厳禁。 |
| LoadBalancer | クラウドプロバイダのLB | プロバイダのマネージドLBが即座に連動。 | サービスごとにLBが作られ、クラウド費用が爆発する。SSL終端や高度なパスルーティングが面倒。 |
> プロの知見:
> 本番環境において、サービスタイプとして `LoadBalancer` や `NodePort` を直接アプリケーションごとに乱立させるのはアンチパターンだ。クラウドのコストが破綻するし、セキュリティホールの温床になる。
> 「基本はすべて ClusterIP で統一し、外部からの入り口は Ingress(またはGateway API)に集約する」。これがモダンなK8sインフラの黄金律である。
—
3. Ingressコントローラーの導入と実践的ルーティング設定
L4(トランスポート層)のサービス群の限界を突破し、HTTP/HTTPSのL7(アプリケーション層)でドメイン名やURLパスに基づいた高度なルーティングを提供するのが Ingress だ。
Ingress単体はただの「定義書(リソース)」にすぎず、実体としてトラフィックを裁くのは Ingress Controller(Nginx, Traefik, AWS ALB Ingress Controllerなど)である。ここではデファクトスタンダードである Ingress-NGINX Controller をベースに解説する。
実用的な設定ファイル(YAML)ベストプラクティス
マルチテナントや複数チームが同居する開発クラスタを想定し、TLS終端とパスベースのルーティングを美しく記述したマニフェストの模範解答を提示する。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: api-gateway-ingress
namespace: production
annotations:
# NGINXコントローラーを指定
kubernetes.io/ingress.class: “nginx”
# クライアントのリアルIPをバックエンドPodに伝えるための設定
nginx.ingress.kubernetes.io/use-forwarded-headers: “true”
# バックエンドへの接続タイムアウトを調整(マイクロサービスの遅延対策)
nginx.ingress.kubernetes.io/proxy-connect-timeout: “60”
nginx.ingress.kubernetes.io/proxy-read-timeout: “600”
# レートリミット(DDoS対策・API保護): 1秒間に10リクエストまで
nginx.ingress.kubernetes.io/limit-rps: “10”
spec:
# TLS/SSL設定(次章で詳解)
tls:
- hosts:
- api.example.com
secretName: api-tls-cert
rules:
- host: api.example.com
http:
paths:
# ユーザー認証サービスへのルーティング
- path: /api/v1/auth
pathType: Prefix
backend:
service:
name: auth-service
port:
number: 8080
# コアビジネスロジック(注文サービス)へのルーティング
- path: /api/v1/orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 3000
—
4. TLS/SSL証明書の導入手順:cert-managerによる完全自動化
手動でSSL証明書を発行し、Secretに手動でぶち込むような運用は、証明書切れによる障害を引き起こす「現代の技術的負債」だ。
Let’s Encryptと `cert-manager` を組み合わせ、証明書のライフサイクルを完全に自動化せよ。
1. cert-managerの導入(Helmを使用)
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
–namespace cert-manager \
–create-namespace \
–set installCRDs=true
2. ClusterIssuerの定義(Let’s Encrypt連携)
ACMEプロトコルを用いて証明書を自動発行・自動更新するグローバル設定(`ClusterIssuer`)を投入する。
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
# Let’s Encryptの本番サーバーURL
server: https://acme-v02.api.letsencrypt.org/directory
# 期限切れやトラブル時の通知用メールアドレス
email: admin@example.com
# KubernetesのSecretにACMEアカウントの秘密鍵を保存
privateKeySecretRef:
name: letsencrypt-prod-account-key
# HTTP-01チャレンジを用いたドメイン所有権の検証を指定
solvers:
- http01:
ingress:
class: nginx
3. Ingressとcert-managerの統合
前章のIngressマニフェストに以下のたった1行のアノテーションを追加するだけで、`cert-manager` が裏側で自動的に証明書を要求し、上記の `tls.secretName` に格納してくれる。
metadata:
annotations:
cert-manager.io/cluster-issuer: “letsencrypt-prod”
—
🚀 現場の生産性を爆上げする!プロの実践テクニック
ここからは、日々のK8s運用のストレスを消し去り、開発スピードを加速させるための「秘伝の技」を伝授する。
1. 開発スピードを高めるキーボードショートカット & エイリアス
毎回 `kubectl describe ingress` や `kubectl get pods -n production` を手打ちしているエンジニアは今日で卒業しよう。`.zshrc` や `.bashrc` に以下のエイリアスを即座に仕込め。
エイリアスの設定
alias k=”kubectl”
alias kgp=”kubectl get pods”
alias kgs=”kubectl get svc”
alias kgi=”kubectl get ingress”
alias klogs=”kubectl logs -f”
【神コマンド】クラスタ内のすべてのIngressと紐づくバックエンドを俯瞰する
alias k-routes=”kubectl get ingress -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,HOST:.spec.rules[].host,PATH:.spec.rules[].http.paths[].path,SERVICE:.spec.rules[].http.paths[].backend.service.name”
さらに、IDE(VS Code)を使っているなら、「Kubernetes (ms-kubernetes-tools)」 拡張機能に加え、「YAML (redhat.vscode-yaml)」 拡張機能を入れ、カスタムリソース定義(CRD)のスキーマ補完を有効化すること。これにより、YAMLのインデント地獄やタイポによるデプロイ失敗がゼロになる。
2. チーム開発で役立つ設定の共有化ルール
- マニフェストは純粋なYAMLで管理するな(Kustomize or Helm)
環境(dev/staging/production)ごとに異なるドメイン名やレプリカ数をベタ書きしたYAMLをコピペするのは絶対悪だ。Kustomize を用いて、ベースとなるマニフェストに対し、環境差分(patches)のみをオーバレイする構造を強制せよ。
- GitOps(Argo CD / Flux)の導入
`kubectl apply` を人間の手で叩く文化を今すぐ捨てろ。Gitリポジトリ(Config repository)の変更が自動的にクラスタに同期されるGitOpsフローを構築することこそが、インフラ変更の監査性と安全性を担保する唯一の道だ。
—
結びにかえて
Kubernetesのルーティングは、背後の仕組み(kube-proxy, L4/L7の分離)を正しく理解し、適切なレイヤー(Ingress + cert-manager + Kustomize)で設計さえすれば、これほど強力で拡張性の高いインフラストラクチャはない。
「なんとなく動く」から脱却し、予測可能で堅牢なネットワーク基盤を構築すること。それがチーム全体の開発スピードを真の意味で加速させる鍵となる。
さあ、今すぐあなたのクラスタのIngress設定を見直し、無駄なLoadBalancerを掃除しに行こう。