Skip to content

✍️ 필사 모드: Kubernetes上級運用ガイド2025:オートスケーリング、スケジューリング、リソース管理、マルチクラスター

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

目次(もくじ)

1. はじめに:Kubernetes上級運用(じょうきゅううんよう)が重要(じゅうよう)な理由(りゆう)

Kubernetesを本番環境(ほんばんかんきょう)で運用(うんよう)すると、基本的(きほんてき)なデプロイだけでは解決(かいけつ)できない課題(かだい)が現(あらわ)れる。トラフィック急増時(きゅうぞうじ)にPodが十分(じゅうぶん)に速(はや)くスケールしなかったり、特定(とくてい)のノードにPodが集中(しゅうちゅう)して障害(しょうがい)が伝播(でんぱ)したり、リソース管理(かんり)が不適切(ふてきせつ)でコストが爆発的(ばくはつてき)に増加(ぞうか)する状況(じょうきょう)だ。

このガイドでは、Kubernetes上級運用の4つのコア領域(りょういき)をカバーする:

  1. オートスケーリング - HPA、VPA、KEDA、Karpenterでワークロードとインフラを自動拡張(じどうかくちょう)
  2. スケジューリング - Affinity、Taint、Priority、Topology SpreadでPod配置(はいち)を最適化(さいてきか)
  3. リソース管理 - QoS、LimitRange、ResourceQuota、PDBで安定性(あんていせい)を保証(ほしょう)
  4. マルチクラスター - Cluster API、Fleetで複数(ふくすう)クラスターを統合管理(とうごうかんり)

2. オートスケーリング戦略(せんりゃく)

2.1 HPA(Horizontal Pod Autoscaler)深掘(ふかぼ)り

HPAはPod数(すう)を自動調整(じどうちょうせい)する最(もっと)も基本的なオートスケーラーだ。v2 APIではカスタムメトリクスと外部(がいぶ)メトリクスをサポートしている。

基本HPA設定(せってい)

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-server-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-server
  minReplicas: 3
  maxReplicas: 50
  metrics:
    # CPUベーススケーリング
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    # メモリベーススケーリング
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
        - type: Percent
          value: 100
          periodSeconds: 60
        - type: Pods
          value: 10
          periodSeconds: 60
      selectPolicy: Max
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 10
          periodSeconds: 60

カスタムメトリクスHPA

Prometheus Adapterを使用(しよう)すると、アプリケーション固有(こゆう)のカスタムメトリクスでスケーリングできる。

# Prometheus Adapter設定
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-adapter-config
  namespace: monitoring
data:
  config.yaml: |
    rules:
      - seriesQuery: 'http_requests_per_second{namespace!="",pod!=""}'
        resources:
          overrides:
            namespace:
              resource: namespace
            pod:
              resource: pod
        name:
          matches: "^(.*)$"
          as: "requests_per_second"
        metricsQuery: 'sum(rate(http_requests_total{<<.LabelMatchers>>}[2m])) by (<<.GroupBy>>)'
---
# カスタムメトリクスベースHPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-server-custom-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-server
  minReplicas: 3
  maxReplicas: 100
  metrics:
    - type: Pods
      pods:
        metric:
          name: requests_per_second
        target:
          type: AverageValue
          averageValue: "1000"

外部メトリクスHPA

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: queue-worker-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: queue-worker
  minReplicas: 1
  maxReplicas: 30
  metrics:
    - type: External
      external:
        metric:
          name: sqs_queue_depth
          selector:
            matchLabels:
              queue: "order-processing"
        target:
          type: AverageValue
          averageValue: "5"

2.2 VPA(Vertical Pod Autoscaler)

VPAはPodのCPU/メモリリクエスト量(りょう)を自動調整する。適切(てきせつ)なリソースリクエスト量が不明(ふめい)な初期段階(しょきだんかい)で特(とく)に有用(ゆうよう)だ。

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: api-server-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-server
  updatePolicy:
    updateMode: "Auto"  # Off, Initial, Recreate, Auto
  resourcePolicy:
    containerPolicies:
      - containerName: api-server
        minAllowed:
          cpu: 100m
          memory: 128Mi
        maxAllowed:
          cpu: 4
          memory: 8Gi
        controlledResources: ["cpu", "memory"]
        controlledValues: RequestsAndLimits

VPA動作(どうさ)モード比較(ひかく):

モード動作使用時期(しようじき)
Off推奨(すいしょう)のみ提供、適用(てきよう)なし初期分析段階
Initial作成時(さくせいじ)のみ適用安定したワークロード
RecreatePod再作成(さいさくせい)で適用一般的な運用
Auto可能(かのう)ならin-place、そうでなければ再作成最新K8s環境

注意(ちゅうい): HPAとVPAを同(おな)じメトリクス(CPU/メモリ)で同時に使用すると競合(きょうごう)が発生する。VPAはOffモードで推奨のみ取得し、HPAがスケーリングを担当するパターンを推奨する。

2.3 KEDA(Kubernetes Event-Driven Autoscaling)

KEDAは外部イベントソースに基(もと)づいてワークロードをスケーリングする。60以上のスケーラーをサポートしている。

# KEDAインストール
# helm repo add kedacore https://kedacore.github.io/charts
# helm install keda kedacore/keda --namespace keda-system --create-namespace

# ScaledObject例: Kafkaベーススケーリング
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: kafka-consumer-scaler
  namespace: production
spec:
  scaleTargetRef:
    name: kafka-consumer
  pollingInterval: 15
  cooldownPeriod: 300
  idleReplicaCount: 0
  minReplicaCount: 1
  maxReplicaCount: 50
  fallback:
    failureThreshold: 3
    replicas: 5
  triggers:
    - type: kafka
      metadata:
        bootstrapServers: kafka.production.svc:9092
        consumerGroup: order-processor
        topic: orders
        lagThreshold: "100"
        offsetResetPolicy: latest
---
# ScaledObject例: AWS SQSベーススケーリング
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: sqs-worker-scaler
spec:
  scaleTargetRef:
    name: sqs-worker
  pollingInterval: 10
  cooldownPeriod: 60
  minReplicaCount: 0
  maxReplicaCount: 100
  triggers:
    - type: aws-sqs-queue
      metadata:
        queueURL: https://sqs.ap-northeast-2.amazonaws.com/123456789012/order-queue
        queueLength: "5"
        awsRegion: ap-northeast-2
      authenticationRef:
        name: aws-credentials
---
# ScaledJob例: バッチジョブスケーリング
apiVersion: keda.sh/v1alpha1
kind: ScaledJob
metadata:
  name: image-processor
spec:
  jobTargetRef:
    template:
      spec:
        containers:
          - name: processor
            image: myapp/image-processor:latest
        restartPolicy: Never
  pollingInterval: 10
  maxReplicaCount: 20
  successfulJobsHistoryLimit: 10
  failedJobsHistoryLimit: 5
  triggers:
    - type: redis-lists
      metadata:
        address: redis.production.svc:6379
        listName: image-processing-queue
        listLength: "3"

2.4 Karpenter - 次世代(じせだい)ノードオートスケーラー

KarpenterはCluster Autoscalerの限界(げんかい)を克服(こくふく)したノードプロビジョニングエンジンだ。

# NodePool定義
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: general-purpose
spec:
  template:
    metadata:
      labels:
        team: platform
        tier: general
    spec:
      requirements:
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64", "arm64"]
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["on-demand", "spot"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["c", "m", "r"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["5"]
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
      expireAfter: 720h
  limits:
    cpu: "1000"
    memory: 2000Gi
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 30s
---
# EC2NodeClass定義
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: default
spec:
  amiSelectorTerms:
    - alias: al2023@latest
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-cluster
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-cluster
  role: KarpenterNodeRole-my-cluster
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 100Gi
        volumeType: gp3
        iops: 3000
        throughput: 125

Cluster Autoscaler vs Karpenter比較:

項目(こうもく)Cluster AutoscalerKarpenter
ノード選択(せんたく)Node Groupベースワークロード要件(ようけん)ベース
プロビジョニング速度(そくど)分単位(ふんたんい)秒単位(びょうたんい)
インスタンス多様性(たようせい)グループごとに固定(こてい)自動最適選択
Spot処理(しょり)手動設定(しゅどうせってい)自動価格/可用性最適化
統合(とうごう)(Consolidation)未対応(みたいおう)自動ノード統合
クラウドサポートすべてのクラウドAWS(Azureプレビュー)

3. スケジューリング深掘(ふかぼ)り

3.1 nodeSelector

最(もっと)もシンプルなノード選択方法(ほうほう)だ。

apiVersion: v1
kind: Pod
metadata:
  name: gpu-worker
spec:
  nodeSelector:
    accelerator: nvidia-tesla-v100
    topology.kubernetes.io/zone: ap-northeast-2a
  containers:
    - name: gpu-worker
      image: myapp/gpu-worker:latest
      resources:
        limits:
          nvidia.com/gpu: 1

3.2 Node AffinityとPod Affinity

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-frontend
spec:
  replicas: 6
  selector:
    matchLabels:
      app: web-frontend
  template:
    metadata:
      labels:
        app: web-frontend
    spec:
      affinity:
        # Node Affinity: 特定ノードに配置
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: node-type
                    operator: In
                    values:
                      - compute-optimized
                      - general-purpose
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 80
              preference:
                matchExpressions:
                  - key: topology.kubernetes.io/zone
                    operator: In
                    values:
                      - ap-northeast-2a
            - weight: 20
              preference:
                matchExpressions:
                  - key: topology.kubernetes.io/zone
                    operator: In
                    values:
                      - ap-northeast-2c
        # Pod Affinity: 特定Podと同じノード/ゾーンに配置
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: app
                    operator: In
                    values:
                      - redis-cache
              topologyKey: topology.kubernetes.io/zone
        # Pod Anti-Affinity: 同じアプリのPodを分散
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: app
                    operator: In
                    values:
                      - web-frontend
              topologyKey: kubernetes.io/hostname
      containers:
        - name: web-frontend
          image: myapp/web-frontend:latest

3.3 TaintsとTolerations

# ノードにTaintを追加
# kubectl taint nodes gpu-node-1 gpu=true:NoSchedule
# kubectl taint nodes spot-node-1 spot=true:PreferNoSchedule

# GPUワークロード: gpu Taintを許容
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ml-training
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ml-training
  template:
    metadata:
      labels:
        app: ml-training
    spec:
      tolerations:
        - key: "gpu"
          operator: "Equal"
          value: "true"
          effect: "NoSchedule"
        - key: "nvidia.com/gpu"
          operator: "Exists"
          effect: "NoSchedule"
      nodeSelector:
        accelerator: nvidia-tesla-v100
      containers:
        - name: trainer
          image: myapp/ml-trainer:latest
          resources:
            limits:
              nvidia.com/gpu: 4
---
# Spotインスタンスワークロード
apiVersion: apps/v1
kind: Deployment
metadata:
  name: batch-processor
spec:
  replicas: 10
  selector:
    matchLabels:
      app: batch-processor
  template:
    metadata:
      labels:
        app: batch-processor
    spec:
      tolerations:
        - key: "spot"
          operator: "Equal"
          value: "true"
          effect: "PreferNoSchedule"
        - key: "node.kubernetes.io/not-ready"
          operator: "Exists"
          effect: "NoExecute"
          tolerationSeconds: 60
      containers:
        - name: processor
          image: myapp/batch-processor:latest

3.4 PriorityとPreemption

# PriorityClass定義
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: critical-production
value: 1000000
globalDefault: false
preemptionPolicy: PreemptLowerPriority
description: "本番環境の重要サービス用"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: standard-production
value: 100000
globalDefault: true
preemptionPolicy: PreemptLowerPriority
description: "一般本番ワークロード用"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: batch-low
value: 1000
globalDefault: false
preemptionPolicy: Never
description: "バッチジョブ用。Preemptionなし"
---
# Priority使用
apiVersion: apps/v1
kind: Deployment
metadata:
  name: payment-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: payment-service
  template:
    metadata:
      labels:
        app: payment-service
    spec:
      priorityClassName: critical-production
      containers:
        - name: payment
          image: myapp/payment:latest

3.5 Topology Spread Constraints

Podを複数(ふくすう)のトポロジードメインに均等(きんとう)に分散(ぶんさん)する強力(きょうりょく)な機能(きのう)だ。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-gateway
spec:
  replicas: 12
  selector:
    matchLabels:
      app: api-gateway
  template:
    metadata:
      labels:
        app: api-gateway
    spec:
      topologySpreadConstraints:
        # AZ基準で分散
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: api-gateway
        # ノード基準で分散
        - maxSkew: 2
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: api-gateway
          nodeAffinityPolicy: Honor
          nodeTaintsPolicy: Honor
      containers:
        - name: api-gateway
          image: myapp/api-gateway:latest

4. リソース管理(かんり)

4.1 Requests vs Limitsの理解(りかい)

apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
    - name: app
      image: myapp/demo:latest
      resources:
        # スケジューリングに使用。この量のリソースが保証される
        requests:
          cpu: 500m
          memory: 512Mi
          ephemeral-storage: 1Gi
        # 使用上限。CPU超過時はスロットリング、メモリ超過時はOOMKill
        limits:
          cpu: "2"
          memory: 1Gi
          ephemeral-storage: 2Gi

4.2 QoSクラス

QoSクラス条件(じょうけん)OOM Kill優先順位(ゆうせんじゅんい)
Guaranteedすべてのコンテナでrequests = limits最低(さいてい)(最後にKill)
Burstablerequestsまたはlimitsの一方のみ設定中間(ちゅうかん)
BestEffortrequests、limitsともに未設定最高(さいこう)(最初にKill)
# Guaranteed QoS
apiVersion: v1
kind: Pod
metadata:
  name: guaranteed-pod
spec:
  containers:
    - name: app
      image: myapp/critical:latest
      resources:
        requests:
          cpu: "1"
          memory: 1Gi
        limits:
          cpu: "1"
          memory: 1Gi

4.3 LimitRangeとResourceQuota

# LimitRange: ネームスペース内の個別Pod/コンテナリソース制限
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: team-backend
spec:
  limits:
    - type: Container
      default:
        cpu: 500m
        memory: 512Mi
      defaultRequest:
        cpu: 100m
        memory: 128Mi
      max:
        cpu: "4"
        memory: 8Gi
      min:
        cpu: 50m
        memory: 64Mi
    - type: Pod
      max:
        cpu: "8"
        memory: 16Gi
    - type: PersistentVolumeClaim
      max:
        storage: 100Gi
      min:
        storage: 1Gi
---
# ResourceQuota: ネームスペース全体のリソース総量制限
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-backend-quota
  namespace: team-backend
spec:
  hard:
    requests.cpu: "20"
    requests.memory: 40Gi
    limits.cpu: "40"
    limits.memory: 80Gi
    pods: "100"
    services: "20"
    persistentvolumeclaims: "30"
    requests.storage: 500Gi
    count/deployments.apps: "30"
    count/configmaps: "50"
    count/secrets: "50"
  scopeSelector:
    matchExpressions:
      - scopeName: PriorityClass
        operator: In
        values:
          - standard-production
          - critical-production

4.4 PodDisruptionBudget(PDB)

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: api-server-pdb
  namespace: production
spec:
  minAvailable: "60%"
  selector:
    matchLabels:
      app: api-server
  unhealthyPodEvictionPolicy: IfHealthy
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: redis-pdb
  namespace: production
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app: redis-cluster

5. マルチクラスター運用(うんよう)

5.1 Cluster API

Cluster APIはKubernetesクラスターを宣言的(せんげんてき)に作成(さくせい)・管理するプロジェクトだ。

# Cluster定義
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: production-cluster
  namespace: clusters
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/16
    services:
      cidrBlocks:
        - 10.96.0.0/12
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: KubeadmControlPlane
    name: production-control-plane
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
    kind: AWSCluster
    name: production-cluster
---
# Control Plane定義
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
metadata:
  name: production-control-plane
  namespace: clusters
spec:
  replicas: 3
  version: v1.30.2
  machineTemplate:
    infrastructureRef:
      apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
      kind: AWSMachineTemplate
      name: production-control-plane
  kubeadmConfigSpec:
    clusterConfiguration:
      apiServer:
        extraArgs:
          audit-log-maxage: "30"
          audit-log-maxbackup: "10"
          enable-admission-plugins: "NodeRestriction,PodSecurityAdmission"
    initConfiguration:
      nodeRegistration:
        kubeletExtraArgs:
          cloud-provider: external

5.2 Fleet/Rancherマルチクラスター管理

# Fleet GitRepo: 複数クラスターへデプロイ
apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
  name: platform-apps
  namespace: fleet-default
spec:
  repo: https://github.com/myorg/platform-apps
  branch: main
  paths:
    - monitoring/
    - logging/
    - ingress/
  targets:
    - name: production
      clusterSelector:
        matchLabels:
          env: production
    - name: staging
      clusterSelector:
        matchLabels:
          env: staging
---
# Fleet Bundleカスタマイズ
apiVersion: fleet.cattle.io/v1alpha1
kind: GitRepo
metadata:
  name: app-deployments
  namespace: fleet-default
spec:
  repo: https://github.com/myorg/app-deployments
  branch: main
  targets:
    - name: us-east
      clusterSelector:
        matchLabels:
          region: us-east
      helm:
        values:
          replicaCount: 5
          ingress:
            host: api-us.mycompany.com
    - name: ap-northeast
      clusterSelector:
        matchLabels:
          region: ap-northeast
      helm:
        values:
          replicaCount: 3
          ingress:
            host: api-ap.mycompany.com

5.3 マルチクラスターアーキテクチャパターン

パターン説明(せつめい)使用時期
Hub-Spoke中央管理クラスターからワーカークラスターを制御基本マルチクラスター
FederationKubeFedでリソースを複数クラスターに同期同一アプリマルチリージョン
Service MeshIstio Multi-clusterでクラスター間通信分散マイクロサービス
Virtual KubeletAdmiralty、Liqoで仮想ノード接続バーストワークロード

6. クラスターアップグレード戦略

6.1 In-placeアップグレード

#!/bin/bash
# Control Planeアップグレード
echo "=== Control Planeアップグレード開始 ==="

# 1. 現在のバージョン確認
kubectl get nodes
kubectl version --short

# 2. kubeadmアップグレード
sudo apt-get update
sudo apt-get install -y kubeadm=1.30.2-1.1
sudo kubeadm upgrade plan
sudo kubeadm upgrade apply v1.30.2

# 3. kubelet、kubectlアップグレード
sudo apt-get install -y kubelet=1.30.2-1.1 kubectl=1.30.2-1.1
sudo systemctl daemon-reload
sudo systemctl restart kubelet

echo "=== Worker Node順次アップグレード ==="
NODES=$(kubectl get nodes -l node-role.kubernetes.io/worker -o jsonpath='{.items[*].metadata.name}')

for NODE in $NODES; do
  echo "--- $NODE アップグレード開始 ---"

  # Cordon: 新しいPodスケジューリングを阻止
  kubectl cordon "$NODE"

  # Drain: 既存Podを退避
  kubectl drain "$NODE" \
    --ignore-daemonsets \
    --delete-emptydir-data \
    --grace-period=120 \
    --timeout=300s

  # ノードでアップグレード実行(SSHまたは自動化ツール使用)
  echo "ノード $NODE でkubeadm、kubeletアップグレード実行"

  # Uncordon: スケジューリング再開
  kubectl uncordon "$NODE"

  # ノードReady状態確認
  kubectl wait --for=condition=Ready "node/$NODE" --timeout=300s

  echo "--- $NODE アップグレード完了 ---"
done

6.2 Blue-Greenクラスターアップグレード

# Cluster APIで新クラスターを作成
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: production-v130
  namespace: clusters
  labels:
    upgrade-group: production
    version: v1.30
spec:
  clusterNetwork:
    pods:
      cidrBlocks:
        - 192.168.0.0/16
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: KubeadmControlPlane
    name: production-v130-cp
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
    kind: AWSCluster
    name: production-v130

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

7.1 kubectl debugの活用(かつよう)

# 実行中のPodにデバッグコンテナを追加
kubectl debug -it pod/api-server-abc123 \
  --image=nicolaka/netshoot \
  --target=api-server \
  -- /bin/bash

# ノードデバッグ
kubectl debug node/worker-1 \
  -it --image=ubuntu:22.04 \
  -- /bin/bash

# 問題Podのコピーでデバッグ(イメージ変更)
kubectl debug pod/api-server-abc123 \
  -it --copy-to=debug-pod \
  --container=api-server \
  --image=myapp/api-server:debug \
  -- /bin/sh

7.2 一般的(いっぱんてき)な問題と解決(かいけつ)

Pending Pod問題:

# PodがPending状態の理由を確認
kubectl describe pod pending-pod-name

# 一般的な原因:
# 1. リソース不足 -> ノード追加またはリソース調整
kubectl get nodes -o custom-columns=\
NAME:.metadata.name,\
CPU_ALLOC:.status.allocatable.cpu,\
MEM_ALLOC:.status.allocatable.memory,\
CPU_REQ:.status.capacity.cpu

# 2. nodeSelector/affinity不一致 -> ラベル確認
kubectl get nodes --show-labels

# 3. Taintによるブロック -> Toleration追加
kubectl describe nodes | grep -A5 Taints

CrashLoopBackOff解決:

# ログ確認
kubectl logs pod/crashing-pod --previous
kubectl logs pod/crashing-pod -c init-container-name

# イベント確認
kubectl get events --sort-by=.lastTimestamp \
  --field-selector involvedObject.name=crashing-pod

# OOM Kill確認
kubectl describe pod crashing-pod | grep -A5 "Last State"
# OOMKilledが表示された場合、メモリlimitsの増加が必要

# デバッグモードで実行
kubectl debug pod/crashing-pod \
  -it --copy-to=debug-pod \
  --container=app \
  --image=busybox \
  -- /bin/sh

ネットワーク問題診断(しんだん):

# DNS確認
kubectl run dns-test --image=busybox:1.36 --rm -it --restart=Never \
  -- nslookup kubernetes.default.svc.cluster.local

# サービス接続テスト
kubectl run curl-test --image=curlimages/curl --rm -it --restart=Never \
  -- curl -v http://api-server.production.svc:8080/health

# ネットワークポリシー確認
kubectl get networkpolicy -A
kubectl describe networkpolicy -n production

8. コスト最適化(さいてきか)

8.1 Spotノードの活用

# Karpenter Spot NodePool
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: spot-workloads
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["c", "m", "r"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["5"]
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 30s
  limits:
    cpu: "500"
    memory: 1000Gi

8.2 Right-sizing自動化(じどうか)

#!/bin/bash
# VPA推奨値ベースのRight-sizingレポート

echo "=== ネームスペース別リソース使用率 ==="
for NS in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
  CPU_REQ=$(kubectl top pods -n "$NS" --no-headers 2>/dev/null | \
    awk '{sum += $2} END {print sum}')
  MEM_REQ=$(kubectl top pods -n "$NS" --no-headers 2>/dev/null | \
    awk '{sum += $3} END {print sum}')
  if [ -n "$CPU_REQ" ] && [ "$CPU_REQ" != "0" ]; then
    echo "Namespace: $NS | CPU: ${CPU_REQ}m | Memory: ${MEM_REQ}Mi"
  fi
done

echo ""
echo "=== VPA推奨値確認 ==="
for VPA in $(kubectl get vpa -A -o jsonpath='{range .items[*]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}'); do
  NS=$(echo "$VPA" | cut -d'/' -f1)
  NAME=$(echo "$VPA" | cut -d'/' -f2)
  echo "--- $VPA ---"
  kubectl get vpa "$NAME" -n "$NS" -o jsonpath='{.status.recommendation.containerRecommendations[*]}'
  echo ""
done

8.3 ネームスペース別コスト配分(はいぶん)

# KubecostまたはOpenCostの活用
# helm install kubecost kubecost/cost-analyzer \
#   --namespace kubecost --create-namespace \
#   --set prometheus.enabled=false \
#   --set prometheus.fqdn=http://prometheus-server.monitoring:80

# ネームスペースラベルによるコスト配分
apiVersion: v1
kind: Namespace
metadata:
  name: team-backend
  labels:
    cost-center: "backend-team"
    department: "engineering"
    project: "api-platform"
    environment: "production"

9. 実践(じっせん)クイズ

Q1: HPAがカスタムメトリクスでスケーリングするには、どのコンポーネントが必要か?

正解(せいかい): Prometheus Adapter(またはDatadog Cluster Agentなど)のようなカスタムメトリクスAPIサーバーが必要。

  • Prometheus AdapterはPrometheusメトリクスをKubernetes Custom Metrics API(custom.metrics.k8s.io)として公開する
  • HPAはこのAPIを通じてカスタムメトリクス値を取得し、スケーリング判断を行う
  • フロー: Prometheus収集 -> Adapter変換 -> HPA照会 -> スケーリング実行
Q2: Guaranteed QoS Classになるための条件は?

正解: Pod内のすべてのコンテナについて、CPUとメモリのrequestsとlimitsが設定され、それぞれ同じ値である必要がある。

  • requests.cpu = limits.cpu
  • requests.memory = limits.memory
  • すべてのコンテナ(initコンテナ含む)に適用
  • Guaranteed Podはノードメモリ圧迫時に最後にOOM Killされる
Q3: podAntiAffinityのrequiredDuringSchedulingIgnoredDuringExecutionとpreferredDuringSchedulingIgnoredDuringExecutionの違いは?

正解: requiredは条件を必ず満たす必要があり、満たすノードがなければPending状態になる。preferredは可能な限り条件を満たす場所に配置するが、不可能な場合は他のノードにも配置される。

  • required: 強制条件(ハードコンストレイント)
  • preferred: 優先条件(ソフトコンストレイント)、weightで優先度を調整
  • IgnoredDuringExecution: 既に実行中のPodは条件が変わっても退避されない
Q4: Karpenterのconsolidation機能はどのようにコストを削減するか?

正解: Karpenter consolidationはアイドルまたは低利用ノードのPodを他のノードに移動し、空のノードを削除するか、より小さい(安価な)インスタンスに置き換える。

  • WhenEmpty: Podがないノードのみ削除
  • WhenEmptyOrUnderutilized: 低利用ノードのPodも再配置後に削除
  • より安価なインスタンスタイプへの置き換えが可能(例: c5.2xlarge 2台をc5.4xlarge 1台に)
  • consolidateAfterで安定化待機時間を設定
Q5: PodDisruptionBudgetはクラスターアップグレードにどう影響するか?

正解: PDBは自発的中断(voluntary disruption)時に同時に中断できるPod数を制限する。

  • kubectl drain時にPDBを尊重してPodを順次退避
  • minAvailable: 最小可用Pod数/割合を保証
  • maxUnavailable: 最大中断Pod数/割合を制限
  • PDBが厳格すぎるとdrainがタイムアウトする可能性がある
  • unhealthyPodEvictionPolicy: IfHealthyで非正常Podに対してPDBを無視可能

10. 参考資料(さんこうしりょう)

  1. Kubernetes公式ドキュメント - HPA
  2. Kubernetes公式ドキュメント - VPA
  3. KEDA公式ドキュメント
  4. Karpenter公式ドキュメント
  5. Kubernetes Scheduling
  6. Topology Spread Constraints
  7. Resource Management
  8. Cluster API
  9. Fleet Manager
  10. Kubecost
  11. Kubernetes Best Practices - Google
  12. EKS Best Practices Guide
  13. Pod Priority and Preemption

현재 단락 (1/882)

Kubernetesを本番環境(ほんばんかんきょう)で運用(うんよう)すると、基本的(きほんてき)なデプロイだけでは解決(かいけつ)できない課題(かだい)が現(あらわ)れる。トラフィック急増時(きゅう...

작성 글자: 0원문 글자: 21,673작성 단락: 0/882