LESSON 40分

「Kubernetes のネットワークは難しいと言われるが、基本原則はシンプルだ。全てのPodは直接通信できる。Service がロードバランサーとして機能する。Ingress が外部からのアクセスポイントになる。この3層を理解すれば十分だ」と佐藤CTOが整理した。

推定読了時間: 40分


Kubernetes ネットワークモデル

基本原則

原則説明
Pod 間通信全てのPodはNATなしで直接通信できる
Node-Pod 通信全てのNodeは全てのPodと直接通信できる
Pod の IP各PodはユニークなIPアドレスを持つ
graph TB
    subgraph NodeA["Node A"]
        PodA(["Pod A<br/>10.0.1"]):::pod
        PodB(["Pod B<br/>10.0.2"]):::pod
        VethA["veth pairs"]:::veth
        CbrA[("cbr0")]:::bridge
        PodA --- VethA
        PodB --- VethA
        VethA --- CbrA
    end

    subgraph NodeB["Node B"]
        PodC(["Pod C<br/>10.0.3"]):::pod
        PodD(["Pod D<br/>10.0.4"]):::pod
        VethB["veth pairs"]:::veth
        CbrB[("cbr0")]:::bridge
        PodC --- VethB
        PodD --- VethB
        VethB --- CbrB
    end

    CbrA === CNI{{"CNI Network"}}
    CbrB === CNI

    classDef pod fill:#0f3460,stroke:#4a90d9,color:#ffffff,stroke-width:2px
    classDef veth fill:#1a1a2e,stroke:#533483,color:#e2e2e2
    classDef bridge fill:#16213e,stroke:#0f3460,color:#e2e2e2,stroke-width:2px
    classDef default fill:#1e3a5f,stroke:#4a90d9,color:#e2e2e2

Service タイプ

ClusterIP(デフォルト)

apiVersion: v1
kind: Service
metadata:
  name: api-server
spec:
  type: ClusterIP  # クラスタ内部のみ
  selector:
    app: api-server
  ports:
    - name: http
      port: 80         # Serviceのポート
      targetPort: 3000  # Podのポート
      protocol: TCP

NodePort

apiVersion: v1
kind: Service
metadata:
  name: api-server-nodeport
spec:
  type: NodePort
  selector:
    app: api-server
  ports:
    - port: 80
      targetPort: 3000
      nodePort: 30080  # 全ノードの30080番ポートで公開

LoadBalancer

apiVersion: v1
kind: Service
metadata:
  name: api-server-lb
  annotations:
    # AWS NLB を使用
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-scheme: "internet-facing"
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
  type: LoadBalancer
  selector:
    app: api-server
  ports:
    - port: 443
      targetPort: 3000
      protocol: TCP

ExternalName

# 外部サービスをクラスタ内のDNS名で参照
apiVersion: v1
kind: Service
metadata:
  name: external-db
spec:
  type: ExternalName
  externalName: prod-db.xxx.rds.amazonaws.com

Ingress Controller

Nginx Ingress Controller

# Ingress リソース
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: main-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/rate-limit-rps: "100"
    nginx.ingress.kubernetes.io/proxy-body-size: "10m"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - api.example.com
        - web.example.com
      secretName: example-tls
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /v1
            pathType: Prefix
            backend:
              service:
                name: api-server-v1
                port:
                  number: 80
          - path: /v2
            pathType: Prefix
            backend:
              service:
                name: api-server-v2
                port:
                  number: 80
    - host: web.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web-frontend
                port:
                  number: 80

Traefik

# Traefik IngressRoute (CRD)
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: api-route
spec:
  entryPoints:
    - websecure
  routes:
    - match: Host(`api.example.com`) && PathPrefix(`/v1`)
      kind: Rule
      services:
        - name: api-server-v1
          port: 80
      middlewares:
        - name: rate-limit
        - name: compress
    - match: Host(`api.example.com`) && PathPrefix(`/v2`)
      kind: Rule
      services:
        - name: api-server-v2
          port: 80
  tls:
    certResolver: letsencrypt
---
# Middleware
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: rate-limit
spec:
  rateLimit:
    average: 100
    burst: 200

Gateway API(次世代 Ingress)

Gateway API は Ingress の後継として設計された、より表現力の高いAPIです。

# GatewayClass(インフラ管理者が定義)
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: aws-alb
spec:
  controllerName: gateway.k8s.aws/alb
---
# Gateway(クラスタ管理者が定義)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: main-gateway
  namespace: gateway-system
spec:
  gatewayClassName: aws-alb
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: example-tls
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              gateway-access: "true"
---
# HTTPRoute(アプリ開発者が定義)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-routes
  namespace: production
spec:
  parentRefs:
    - name: main-gateway
      namespace: gateway-system
  hostnames:
    - api.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api/v1
      backendRefs:
        - name: api-server-v1
          port: 80
          weight: 90
        - name: api-server-v2
          port: 80
          weight: 10  # Canary: 10% のトラフィック
    - matches:
        - path:
            type: PathPrefix
            value: /api/v2
      backendRefs:
        - name: api-server-v2
          port: 80

Gateway API vs Ingress

機能IngressGateway API
トラフィック分割不可weight で可能
ヘッダーベースルーティングAnnotation 依存標準サポート
責任分離1つの IngressGatewayClass/Gateway/Route
プロトコルHTTP/HTTPSHTTP/HTTPS/TCP/UDP/gRPC
拡張性AnnotationPolicy Attachment

DNS と Service Discovery

CoreDNS

Service: my-service.my-namespace.svc.cluster.local
Pod:     10-0-1-5.my-namespace.pod.cluster.local
StatefulSet: pod-0.my-service.my-namespace.svc.cluster.local
# CoreDNS の設定(Corefile)
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
            lazystart
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            fallthrough in-addr.arpa ip6.arpa
        }
        forward . /etc/resolv.conf
        cache 30
        loop
        reload
        loadbalance
    }

ExternalDNS

# ExternalDNS: Kubernetes リソースから DNS レコードを自動作成
apiVersion: apps/v1
kind: Deployment
metadata:
  name: external-dns
  namespace: kube-system
spec:
  template:
    spec:
      containers:
        - name: external-dns
          image: registry.k8s.io/external-dns/external-dns:v0.14.0
          args:
            - --source=service
            - --source=ingress
            - --provider=aws
            - --aws-zone-type=public
            - --registry=txt
            - --txt-owner-id=my-cluster
            - --domain-filter=example.com

NetworkPolicy

# デフォルト拒否ポリシー
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
---
# API Server へのアクセスを制限
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-server-ingress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api-server
  policyTypes:
    - Ingress
  ingress:
    # Ingress Controller からのみ許可
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-system
          podSelector:
            matchLabels:
              app: nginx-ingress
      ports:
        - port: 3000
          protocol: TCP
Cilium の L7 NetworkPolicy
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: api-l7-policy
spec:
  endpointSelector:
    matchLabels:
      app: api-server
  ingress:
    - fromEndpoints:
        - matchLabels:
            app: api-gateway
      toPorts:
        - ports:
            - port: "3000"
              protocol: TCP
          rules:
            http:
              - method: GET
                path: "/api/v1/users.*"
              - method: POST
                path: "/api/v1/orders"

まとめ

コンポーネント役割選定基準
ClusterIPクラスタ内通信内部サービス間
NodePortノードポート公開テスト/開発環境
LoadBalancer外部公開単一サービス公開
IngressL7 ルーティング複数サービスのHTTPルーティング
Gateway API次世代 Ingressトラフィック分割、gRPC 対応
NetworkPolicyネットワーク制御Zero Trust ネットワーク

チェックリスト

  • Service の各タイプ(ClusterIP/NodePort/LoadBalancer)を理解している
  • Ingress Controller(Nginx/Traefik)の設定ができる
  • Gateway API の概念と Ingress との違いを理解している
  • CoreDNS による Service Discovery を理解している
  • NetworkPolicy でトラフィックを制限できる
  • ExternalDNS による DNS レコードの自動管理を理解している

次のステップへ

次のレッスンでは、Kubernetes のセキュリティ(RBAC、Pod Security Standards、Secrets 管理)を学びます。