10日で覚えるKubernetesDay 10: 本番環境への準備とベストプラクティス

Day 10: 本番環境への準備とベストプラクティス

今日学ぶこと

  • Namespaceによるリソース分離
  • RBACによるアクセス制御
  • ResourceQuotaとLimitRange
  • モニタリングとロギング
  • 本番運用のベストプラクティス

Namespace によるリソース分離

Day 2でNamespaceの基本を学びました。本番環境では、Namespaceを使って環境やチームごとにリソースを分離します。

flowchart TB
    subgraph Cluster["Kubernetes Cluster"]
        subgraph Dev["dev namespace"]
            D1["App Pod"]
            D2["DB Pod"]
        end
        subgraph Staging["staging namespace"]
            S1["App Pod"]
            S2["DB Pod"]
        end
        subgraph Prod["production namespace"]
            P1["App Pod x3"]
            P2["DB Pod"]
        end
    end
    style Dev fill:#22c55e,color:#fff
    style Staging fill:#f59e0b,color:#fff
    style Prod fill:#3b82f6,color:#fff
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    environment: production
# Namespace作成
kubectl create namespace production
kubectl create namespace staging

# Namespace内にリソース作成
kubectl apply -f deployment.yaml -n production

# デフォルトNamespaceの設定
kubectl config set-context --current --namespace=production

RBAC(Role-Based Access Control)

RBACは誰が何をできるかを制御する仕組みです。

flowchart LR
    USER["User / ServiceAccount"] --> RB["RoleBinding"]
    RB --> ROLE["Role"]
    ROLE --> RES["Resources\n(Pods, Services...)"]
    style ROLE fill:#3b82f6,color:#fff
    style RB fill:#8b5cf6,color:#fff

Role と ClusterRole

リソース スコープ 用途
Role Namespace内 特定Namespaceのリソースへのアクセス
ClusterRole クラスタ全体 全Namespaceまたはクラスタリソースへのアクセス
# developer-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
  namespace: production
rules:
  - apiGroups: [""]
    resources: ["pods", "services", "configmaps"]
    verbs: ["get", "list", "watch", "create", "update", "delete"]
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch", "create", "update"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get", "list"]  # Secretは閲覧のみ

RoleBinding

# developer-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: developer-binding
  namespace: production
subjects:
  - kind: User
    name: alice
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

ServiceAccount

PodがKubernetes APIにアクセスするための認証情報です。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-service-account
  namespace: production
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: production
spec:
  template:
    spec:
      serviceAccountName: app-service-account
      containers:
        - name: web
          image: nginx:1.27

ResourceQuota と LimitRange

ResourceQuota

Namespaceごとのリソース使用量の上限を設定します。

apiVersion: v1
kind: ResourceQuota
metadata:
  name: production-quota
  namespace: production
spec:
  hard:
    requests.cpu: "10"
    requests.memory: "20Gi"
    limits.cpu: "20"
    limits.memory: "40Gi"
    pods: "50"
    services: "20"
    persistentvolumeclaims: "10"

LimitRange

個々のPodやコンテナのリソースのデフォルト値と上限を設定します。

apiVersion: v1
kind: LimitRange
metadata:
  name: production-limits
  namespace: production
spec:
  limits:
    - type: Container
      default:
        cpu: "250m"
        memory: "256Mi"
      defaultRequest:
        cpu: "100m"
        memory: "128Mi"
      max:
        cpu: "2"
        memory: "4Gi"
      min:
        cpu: "50m"
        memory: "64Mi"
# 確認
kubectl describe resourcequota production-quota -n production
kubectl describe limitrange production-limits -n production

NetworkPolicy

Pod間のネットワーク通信を制御します。Docker書籍のネットワーク分離の発展版です。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-network-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
    - Ingress
    - Egress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 8080
  egress:
    - to:
        - podSelector:
            matchLabels:
              app: postgres
      ports:
        - protocol: TCP
          port: 5432
flowchart LR
    FE["frontend"] -->|"許可: 8080"| API["api"]
    API -->|"許可: 5432"| DB["postgres"]
    OTHER["other pods"] -->|"拒否"| API
    style API fill:#3b82f6,color:#fff
    style OTHER fill:#ef4444,color:#fff

モニタリングとロギング

Metrics Server

# ノードのリソース使用量
kubectl top nodes

# Podのリソース使用量
kubectl top pods -n production
kubectl top pods --sort-by=cpu
kubectl top pods --sort-by=memory

ログの管理

# Podのログ
kubectl logs deployment/web-app -n production
kubectl logs deployment/web-app -n production -f --tail=100

# 全コンテナのログ
kubectl logs deployment/web-app -n production --all-containers

# ラベルセレクターでログ取得
kubectl logs -l app=web -n production

Prometheus + Grafana(概要)

本格的なモニタリングにはPrometheusとGrafanaを使います。

flowchart LR
    PODS["Pods\n(/metrics)"] --> PROM["Prometheus\n(メトリクス収集)"]
    PROM --> GRAF["Grafana\n(可視化)"]
    PROM --> ALERT["AlertManager\n(アラート)"]
    style PROM fill:#ef4444,color:#fff
    style GRAF fill:#f59e0b,color:#fff
    style ALERT fill:#8b5cf6,color:#fff
# Helm でインストール
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack -n monitoring --create-namespace

本番環境チェックリスト

セキュリティ

項目 説明
RBAC設定 最小権限の原則でアクセス制御
NetworkPolicy Pod間の不要な通信を制限
Pod Security 非rootユーザーでコンテナを実行
Secret管理 外部シークレット管理ツールの利用
イメージスキャン 脆弱性スキャンを実施

Pod Security の設定

spec:
  template:
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 2000
      containers:
        - name: app
          image: myapp:1.0
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL

信頼性

項目 設定
レプリカ数 最低2以上
PodDisruptionBudget 最小稼働Pod数を保証
Probe設定 liveness、readiness、startupProbeを設定
リソース制限 requests/limitsを必ず設定
Affinity/Anti-Affinity Podを異なるノードに分散

PodDisruptionBudget

ノードメンテナンス時などに最低限のPod数を維持します。

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: web

Pod Anti-Affinity

Podを異なるノードに分散させます。

spec:
  template:
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: web
                topologyKey: kubernetes.io/hostname

本番環境の完全な構成例

apiVersion: v1
kind: Namespace
metadata:
  name: production
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota
  namespace: production
spec:
  hard:
    requests.cpu: "10"
    requests.memory: "20Gi"
    pods: "50"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: web
    spec:
      serviceAccountName: web-sa
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: web
                topologyKey: kubernetes.io/hostname
      containers:
        - name: web
          image: myapp:1.0
          ports:
            - containerPort: 3000
          resources:
            requests:
              cpu: "200m"
              memory: "256Mi"
            limits:
              cpu: "500m"
              memory: "512Mi"
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 10
            periodSeconds: 15
          readinessProbe:
            httpGet:
              path: /ready
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 5
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
          envFrom:
            - configMapRef:
                name: app-config
            - secretRef:
                name: app-secret
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
  namespace: production
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 3000
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-app
  minReplicas: 3
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
  namespace: production
spec:
  minAvailable: 2
  selector:
    matchLabels:
      app: web

kubectlコマンドリファレンス

この書籍で学んだ主要コマンドの一覧です。

カテゴリ コマンド 説明
情報取得 kubectl get <resource> リソース一覧
kubectl describe <resource> <name> リソース詳細
kubectl logs <pod> ログ表示
kubectl top <nodes/pods> リソース使用量
作成・更新 kubectl apply -f <file> 宣言的に作成/更新
kubectl create <resource> リソース作成
kubectl scale deployment <name> --replicas=N スケーリング
kubectl set image deployment/<name> イメージ更新
削除 kubectl delete -f <file> ファイルのリソース削除
kubectl delete <resource> <name> 指定リソース削除
デバッグ kubectl exec -it <pod> -- /bin/sh コンテナ内でコマンド実行
kubectl port-forward <pod> <local>:<remote> ポートフォワード
kubectl cp <pod>:<path> <local-path> ファイルコピー
ロールアウト kubectl rollout status deployment/<name> 更新状況確認
kubectl rollout undo deployment/<name> ロールバック
kubectl rollout history deployment/<name> 履歴確認

Docker から Kubernetes への対応表

Docker コマンド Kubernetes コマンド
docker run kubectl run / kubectl apply
docker ps kubectl get pods
docker logs kubectl logs
docker exec kubectl exec
docker stop kubectl delete pod
docker-compose up kubectl apply -f
docker-compose down kubectl delete -f
docker volume kubectl get pv/pvc
docker network kubectl get svc/ingress

まとめ

概念 説明
Namespace リソースの論理的分離
RBAC ロールベースのアクセス制御
ResourceQuota Namespaceごとのリソース上限
NetworkPolicy Pod間のネットワークアクセス制御
PodDisruptionBudget メンテナンス時の最小Pod数保証
Pod Security 非rootユーザー、読み取り専用ファイルシステム等

重要ポイント

  1. 本番環境ではNamespace、RBAC、ResourceQuotaで適切にリソースを管理・分離する
  2. セキュリティは多層防御。Pod Security、NetworkPolicy、RBACを組み合わせる
  3. 信頼性のためにProbe、PDB、Anti-Affinity、HPAを設定する

練習問題

問題1: Namespace設計

開発(dev)、ステージング(staging)、本番(production)の3つのNamespaceを作成し、それぞれにResourceQuotaを設定してください。

問題2: RBAC

developmentチームが開発Namespaceの全リソースにアクセスでき、本番NamespaceではPodの参照のみ可能なRBAC設定を作成してください。

チャレンジ問題

本番環境の完全な構成例を参考に、Webアプリ + API + データベースの3層アーキテクチャを構築してください。Namespace、RBAC、NetworkPolicy、HPA、PDBを全て設定しましょう。


参考リンク


おわりに

10日間を通じて、Docker書籍で学んだコンテナ技術をKubernetesで本格的に運用するための知識を習得しました。

Day 学んだこと
1 Kubernetesの概要とアーキテクチャ
2 クラスタ構築とkubectl
3 Podの詳細とヘルスチェック
4 ReplicaSetとDeployment
5 Serviceによるネットワーキング
6 ストレージとデータ永続化
7 ConfigMapとSecret
8 Ingressと外部公開
9 スケーリングとアップデート戦略
10 本番環境への準備

Dockerでコンテナの基礎を学び、Kubernetesでオーケストレーションを学んだことで、現代のクラウドネイティブアプリケーションを構築・運用するための基盤が整いました。次のステップとして、Helm、GitOps(ArgoCD)、サービスメッシュ(Istio)などの発展的なトピックにも挑戦してみてください。