目次(もくじ)
1. はじめに:Kubernetes上級運用(じょうきゅううんよう)が重要(じゅうよう)な理由(りゆう)
Kubernetesを本番環境(ほんばんかんきょう)で運用(うんよう)すると、基本的(きほんてき)なデプロイだけでは解決(かいけつ)できない課題(かだい)が現(あらわ)れる。トラフィック急増時(きゅうぞうじ)にPodが十分(じゅうぶん)に速(はや)くスケールしなかったり、特定(とくてい)のノードにPodが集中(しゅうちゅう)して障害(しょうがい)が伝播(でんぱ)したり、リソース管理(かんり)が不適切(ふてきせつ)でコストが爆発的(ばくはつてき)に増加(ぞうか)する状況(じょうきょう)だ。
このガイドでは、Kubernetes上級運用の4つのコア領域(りょういき)をカバーする:
- オートスケーリング - HPA、VPA、KEDA、Karpenterでワークロードとインフラを自動拡張(じどうかくちょう)
- スケジューリング - Affinity、Taint、Priority、Topology SpreadでPod配置(はいち)を最適化(さいてきか)
- リソース管理 - QoS、LimitRange、ResourceQuota、PDBで安定性(あんていせい)を保証(ほしょう)
- マルチクラスター - 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 | 作成時(さくせいじ)のみ適用 | 安定したワークロード |
| Recreate | Pod再作成(さいさくせい)で適用 | 一般的な運用 |
| 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 Autoscaler | Karpenter |
|---|---|---|
| ノード選択(せんたく) | 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) |
| Burstable | requestsまたはlimitsの一方のみ設定 | 中間(ちゅうかん) |
| BestEffort | requests、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 | 中央管理クラスターからワーカークラスターを制御 | 基本マルチクラスター |
| Federation | KubeFedでリソースを複数クラスターに同期 | 同一アプリマルチリージョン |
| Service Mesh | Istio Multi-clusterでクラスター間通信 | 分散マイクロサービス |
| Virtual Kubelet | Admiralty、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/882)
Kubernetesを本番環境(ほんばんかんきょう)で運用(うんよう)すると、基本的(きほんてき)なデプロイだけでは解決(かいけつ)できない課題(かだい)が現(あらわ)れる。トラフィック急増時(きゅう...