発展LESSON 08

この教材で学ぶこと クラスタ内外の通信経路とIngressを設計します。

K8s ネットワークと Ingress

前提知識: Pod・Service・Deployment。本教材ではトラフィックフローとIngress設計を扱います。


1. K8s ネットワークの仕組み

K8s のネットワークモデル(基本原則):
  1. すべての Pod は固有の IP を持つ
  2. Pod 間通信は NAT なしで直接可能
  3. Node から Pod へも NAT なしで通信可能

実装(クラスター構築時に選ぶ CNI プラグイン):
  Calico   → 高機能(NetworkPolicy が強力)、EKS で推奨
  Flannel  → シンプル・軽量
  Cilium   → eBPF ベース・高パフォーマンス・可視化機能付き(最近人気)
  
EKS のデフォルト: AWS VPC CNI
  → Pod に VPC の IP アドレスが直接割り当てられる
  → Pod から VPC 内のリソース(RDS 等)に直接通信可能

2. Service の種類

# ClusterIP(デフォルト)— クラスター内部のみ
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  selector:
    app: myapp
  ports:
    - port: 80
      targetPort: 8080
  type: ClusterIP  # クラスター内の DNS で myapp-service.default.svc.cluster.local

---
# NodePort — 各ノードのポートを開放(開発・テスト向け)
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 30080  # 30000-32767 の範囲

---
# LoadBalancer — クラウドの LB を自動プロビジョニング
# EKS では AWS NLB/ALB が作られる
spec:
  type: LoadBalancer
  # EKS で ALB を使う場合は Ingress を使う方が推奨(後述)

3. Ingress — L7 ルーティングのベストプラクティス

Service type=LoadBalancer の問題:
  サービスごとに AWS NLB が1台作られる → コスト増

Ingress の利点:
  1台の ALB でパス・ホストベースの振り分けが可能
# EKS で AWS Load Balancer Controller を使った Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    # EKS: AWS Load Balancer Controller が ALB を自動作成
    kubernetes.io/ingress.class: "alb"
    alb.ingress.kubernetes.io/scheme: "internet-facing"
    alb.ingress.kubernetes.io/target-type: "ip"
    alb.ingress.kubernetes.io/certificate-arn: "arn:aws:acm:ap-northeast-1:xxx:certificate/yyy"
    alb.ingress.kubernetes.io/ssl-redirect: "443"
    # WAF と連携
    alb.ingress.kubernetes.io/wafv2-acl-arn: "arn:aws:wafv2:..."
spec:
  rules:
    - host: api.myapp.com
      http:
        paths:
          - path: /api/v1
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 80
          - path: /api/v2
            pathType: Prefix
            backend:
              service:
                name: api-v2-service
                port:
                  number: 80
    - host: admin.myapp.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: admin-service
                port:
                  number: 80

4. NetworkPolicy — Pod 間の通信制限

# デフォルト: 全ての Pod 間通信が許可(セキュリティリスク)
# NetworkPolicy でホワイトリスト方式に変更

# まず全ての Ingress を拒否
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}  # 全 Pod に適用
  policyTypes:
    - Ingress
    - Egress

---
# API Pod への接続を Front Pod からのみ許可
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-api
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080

---
# DB への接続を API からのみ許可
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-to-db
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: database
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: api
      ports:
        - port: 5432

5. DNS と Service Discovery

# K8s 内の DNS 解決(CoreDNS)
# Service 名で別の Pod から接続できる

# 同じ Namespace
curl http://myapp-service/api/health

# 別の Namespace
curl http://myapp-service.production.svc.cluster.local/api/health

# 外部 DNS への解決
# Pod から RDS エンドポイントへ → VPC DNS で解決

# DNS の動作確認
kubectl run test-pod --image=nicolaka/netshoot -it --rm -- bash
# Pod 内から:
nslookup myapp-service.production.svc.cluster.local
curl http://myapp-service.production/health

6. トラブルシューティング

# Pod の通信テスト
kubectl exec -it mypod -- curl http://other-service/health

# NetworkPolicy が原因で繋がらない場合
# Cilium Hubble(可視化)やシンプルなデバッグ Pod で確認
kubectl run netshoot --image=nicolaka/netshoot --rm -it -- bash
# → tcpdump, curl, nslookup 等が使える

# Service のエンドポイントが正しいか確認
kubectl get endpoints myapp-service
# → Pods の IP が表示されなければ selector のラベルが合っていない

# Ingress の状態確認
kubectl describe ingress myapp-ingress
# → Events 欄にエラーがあれば ALB Controller の設定問題
kubectl logs -n kube-system deployment/aws-load-balancer-controller

🔗 次のステップ