Karpenter
Karpenter 完全ガイド: Kubernetes ノードの自動プロビジョニング
目次
- はじめに
- Karpenter の概要と背景
- アーキテクチャの全体像
- コアコンセプト
- NodePool の設計と設定
- EC2NodeClass の詳細設定
- スケジューリングとプロビジョニングの仕組み
- Consolidation(統合)と最適化
- Drift Detection と自動更新
- Disruption(中断)管理
- スポットインスタンスの活用
- マルチアーキテクチャ対応(ARM/AMD)
- セキュリティとIAM設定
- モニタリングとオブザーバビリティ
- Cluster Autoscaler との比較
- 本番環境でのベストプラクティス
- トラブルシューティング
- 高度な設定パターン
- 移行ガイド
- まとめと今後の展望
1. はじめに
Kubernetes クラスターの運用において、ノードの管理は最も重要かつ複雑なタスクの一つである。ワークロードの需要に応じてノードを適切にスケーリングし、コストを最適化しながら高い可用性を維持することは、多くの運用チームにとって大きな課題となっている。
従来、AWS 上の Kubernetes クラスターでは Cluster Autoscaler (CA) がノードの自動スケーリングに使用されてきた。しかし、CA は Auto Scaling Group (ASG) に依存するアーキテクチャであるため、インスタンスタイプの柔軟な選択や迅速なスケーリングに制約があった。
Karpenter は、これらの課題を根本的に解決するために AWS が開発したオープンソースのノードプロビジョニングツールである。Kubernetes ネイティブな設計思想に基づき、Pod の要件に応じて最適なノードを直接プロビジョニングすることで、従来のアプローチでは実現できなかったレベルの柔軟性、効率性、および速度を提供する。
本記事では、Karpenter のアーキテクチャから具体的な設定例、本番環境でのベストプラクティスまで、包括的に解説する。
2. Karpenter の概要と背景
2.1 Karpenter とは
Karpenter は、Kubernetes クラスター向けのオープンソースノードプロビジョニングプロジェクトである。2021年に AWS によって開発が開始され、2023年に Cloud Native Computing Foundation (CNCF) のサンドボックスプロジェクトとして採択された。現在はCNCFインキュベーションプロジェクトとして活発に開発が進められている。
Karpenter の主な特徴は以下の通りである:
- 直接的なノードプロビジョニング: ASG を介さず、EC2 API を直接呼び出してインスタンスを起動する
- Group-less アーキテクチャ: ノードグループの概念を排除し、Pod の要件に基づいて個別にノードを最適化する
- 高速スケーリング: ASG の制約を受けないため、秒単位でのスケーリングが可能
- インテリジェントな統合: 使用率の低いノードを自動的に検出し、ワークロードを統合してコストを削減する
- Drift Detection: AMI やセキュリティグループなどの設定変更を自動的に検出し、ノードを更新する
2.2 開発の経緯
Karpenter の開発は、以下のような背景から始まった:
Phase 1: 問題認識(2020年以前)
- Cluster Autoscaler の ASG 依存によるスケーリング遅延
- ノードグループごとにインスタンスタイプを固定する必要がある柔軟性の欠如
- ビンパッキング効率の低さによるコスト増大
Phase 2: 設計と開発(2021年)
- AWS が Karpenter プロジェクトを公開
- Kubernetes のスケジューラーと連携する新しいアプローチの採用
- v0.1.0 のリリース
Phase 3: CNCF への移行(2023年)
- CNCF サンドボックスプロジェクトとして採択
- マルチクラウド対応の基盤設計
- API の安定化(v1beta1 → v1)
Phase 4: 成熟期(2024年〜現在)
- v1.0 のリリースとAPI の GA(General Availability)
- 本番環境での広範な採用
- エコシステムの拡大
2.3 プロジェクト構造
Karpenter は以下の2つの主要リポジトリで構成されている:
| リポジトリ | 説明 |
|---|---|
kubernetes-sigs/karpenter | クラウドプロバイダー非依存のコアロジック |
aws/karpenter-provider-aws | AWS 固有の実装(EC2NodeClass など) |
この分離により、将来的に Azure や GCP など他のクラウドプロバイダーへの対応が容易になっている。
2.4 バージョン体系
Karpenter のバージョンは以下の形式で管理されている:
- Core API:
v1(GA)- NodePool, NodeClaim - AWS Provider API:
v1(GA)- EC2NodeClass - Helm Chart: セマンティックバージョニングに従ったリリース(例:
1.1.0)
v1 API は後方互換性が保証されており、本番環境での使用に推奨される。
3. アーキテクチャの全体像
3.1 全体アーキテクチャ
Karpenter のアーキテクチャは、以下の主要コンポーネントで構成されている:
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes Control Plane │
│ ┌───────────────┐ ┌──────────────┐ ┌─────────────────────┐ │
│ │ kube-scheduler│ │ kube-apiserver│ │ etcd │ │
│ └───────┬───────┘ └──────┬───────┘ └─────────────────────┘ │
│ │ │ │
│ ┌───────┴──────────────────┴───────────────────────────────┐ │
│ │ Karpenter Controller │ │
│ │ ┌─────────────┐ ┌──────────────┐ ┌───────────────────┐ │ │
│ │ │ Provisioner │ │ Disruption │ │ Drift Detector │ │ │
│ │ │ Controller │ │ Controller │ │ │ │ │
│ │ └──────┬──────┘ └──────┬───────┘ └───────┬───────────┘ │ │
│ │ │ │ │ │ │
│ │ ┌──────┴──────────────┴──────────────────┴───────────┐ │ │
│ │ │ Cloud Provider Interface │ │ │
│ │ │ (AWS EC2 Fleet API / Launch API) │ │ │
│ │ └────────────────────────┬────────────────────────────┘ │ │
│ └───────────────────────────┼───────────────────────────────┘ │
└──────────────────────────────┼───────────────────────────────────┘
│
┌──────────┴──────────┐
│ AWS EC2 API │
│ ┌────────────────┐ │
│ │ CreateFleet │ │
│ │ RunInstances │ │
│ │ TerminateInst. │ │
│ └────────────────┘ │
└──────────┬──────────┘
│
┌────────────────┼────────────────┐
│ │ │
┌─────┴─────┐ ┌─────┴─────┐ ┌───────┴───────┐
│ Worker │ │ Worker │ │ Worker │
│ Node 1 │ │ Node 2 │ │ Node N │
│ (m5.xlarge)│ │ (c6g.2xl) │ │ (r5.large) │
└───────────┘ └───────────┘ └───────────────┘
3.2 コントローラーの詳細
Karpenter は、Kubernetes のコントローラーパターンに従って設計されており、複数のコントローラーが協調して動作する:
3.2.1 Provisioning Controller
プロビジョニングコントローラーは、Karpenter の中核を成すコンポーネントである。以下の処理フローで動作する:
- Pending Pod の監視: kube-scheduler がスケジュールできなかった Pod を検出
- 要件の分析: Pod のリソース要求、nodeSelector、tolerations、affinity などを分析
- シミュレーション: 仮想的なノードを作成し、Pod のスケジューリングをシミュレート
- インスタンスタイプの選択: 要件を満たす最も効率的なインスタンスタイプを選択
- ノードの起動: Cloud Provider API を呼び出してノードを起動
Pending Pod 検出 → 要件分析 → ビンパッキング → インスタンス選択 → ノード起動
↑ │
└──── Pod がスケジュールされるまで繰り返し ──────────────────────┘
3.2.2 Disruption Controller
Disruption Controller は、不要になったノードや最適化が可能なノードを管理する:
- Consolidation(統合): 使用率の低いノードを検出し、ワークロードを他のノードに移動
- Expiration(有効期限): 設定された期限を超えたノードを入れ替え
- Drift(ドリフト): 設定変更を検出し、ノードを最新の設定に更新
- Emptiness(空ノード): ワークロードが存在しないノードを削除
3.2.3 Cloud Provider Interface
クラウドプロバイダーインターフェースは、Karpenter のコアロジックと特定のクラウドプロバイダーの実装を分離する抽象化レイヤーである:
// Cloud Provider Interface(概念的な構造)
type CloudProvider interface {
Create(ctx context.Context, nodeClaim *v1.NodeClaim) (*v1.NodeClaim, error)
Delete(ctx context.Context, nodeClaim *v1.NodeClaim) error
Get(ctx context.Context, providerID string) (*v1.NodeClaim, error)
List(ctx context.Context) ([]*v1.NodeClaim, error)
GetInstanceTypes(ctx context.Context, nodePool *v1.NodePool) ([]*InstanceType, error)
}
3.3 データフロー
Karpenter のデータフローは以下のように進行する:
1. ユーザーが Deployment をデプロイ
↓
2. kube-scheduler が Pod をスケジュール試行
↓
3. スケジュール不可の場合、Pod は Pending 状態に
↓
4. Karpenter が Pending Pod を検出
↓
5. NodePool の制約に基づいてインスタンスタイプを決定
↓
6. EC2NodeClass の設定に基づいてインスタンスを構成
↓
7. EC2 Fleet API でインスタンスを起動
↓
8. NodeClaim リソースが作成される
↓
9. ノードが Ready になると Pod がスケジュールされる
↓
10. 継続的に Consolidation と Drift Detection が実行される
3.4 Kubernetes リソースモデル
Karpenter は以下のカスタムリソース(CRD)を定義する:
| リソース | API グループ | 説明 |
|---|---|---|
| NodePool | karpenter.sh/v1 | ノードプロビジョニングの制約とポリシー |
| NodeClaim | karpenter.sh/v1 | 個別のノードリクエストとライフサイクル |
| EC2NodeClass | karpenter.k8s.aws/v1 | AWS 固有のノード設定 |
これらのリソース間の関係は以下の通りである:
NodePool ──参照──→ EC2NodeClass
│
└──作成──→ NodeClaim ──対応──→ EC2 Instance ──対応──→ Kubernetes Node
4. コアコンセプト
4.1 NodePool
NodePool は、Karpenter がノードをプロビジョニングする際の制約とポリシーを定義するリソースである。以下の要素を含む:
- テンプレート: ノードのラベル、taints、要件(インスタンスタイプ、AZ、アーキテクチャなど)
- 制約: リソース制限、重みによる優先順位
- Disruption ポリシー: ノードの統合や有効期限の設定
基本的な NodePool の例:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: general-purpose
spec:
template:
metadata:
labels:
team: platform
environment: production
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- 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: ["4"]
limits:
cpu: "1000"
memory: 1000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
weight: 50
4.2 NodeClaim
NodeClaim は、Karpenter が作成する個別のノードリクエストを表すリソースである。NodePool のテンプレートに基づいて自動的に作成され、EC2 インスタンスのライフサイクルを管理する。
NodeClaim のステータスには以下の情報が含まれる:
- プロバイダーID(EC2 インスタンス ID)
- 割り当てられたインスタンスタイプ
- アベイラビリティゾーン
- キャパシティタイプ(On-Demand / Spot)
- リソースの割り当て量
# NodeClaim のステータス例(自動生成される)
apiVersion: karpenter.sh/v1
kind: NodeClaim
metadata:
name: general-purpose-abc123
labels:
karpenter.sh/nodepool: general-purpose
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: node.kubernetes.io/instance-type
operator: In
values: ["m5.xlarge"]
status:
providerID: "aws:///us-west-2a/i-0123456789abcdef0"
instanceType: m5.xlarge
zone: us-west-2a
capacity:
cpu: "4"
memory: "16Gi"
ephemeral-storage: "100Gi"
pods: "58"
allocatable:
cpu: "3920m"
memory: "15168Mi"
ephemeral-storage: "95Gi"
pods: "58"
conditions:
- type: Ready
status: "True"
4.3 EC2NodeClass
EC2NodeClass は、AWS EC2 インスタンスの具体的な設定を定義するリソースである。AMI、セキュリティグループ、サブネット、IAM ロールなどの AWS 固有の設定を含む。
4.4 Requirements(要件)
Requirements は、Karpenter がノードを選択する際の条件を定義する仕組みである。Kubernetes の Well-Known Labels と Karpenter 固有のラベルを使用して、詳細な条件を指定できる。
主要な Requirement キー:
| キー | 説明 | 例 |
|---|---|---|
kubernetes.io/arch | CPU アーキテクチャ | amd64, arm64 |
kubernetes.io/os | OS | linux |
node.kubernetes.io/instance-type | インスタンスタイプ | m5.xlarge |
topology.kubernetes.io/zone | AZ | us-west-2a |
karpenter.sh/capacity-type | キャパシティタイプ | on-demand, spot |
karpenter.k8s.aws/instance-category | インスタンスカテゴリ | c, m, r, t |
karpenter.k8s.aws/instance-family | インスタンスファミリー | m5, c6g, r6i |
karpenter.k8s.aws/instance-size | インスタンスサイズ | large, xlarge |
karpenter.k8s.aws/instance-generation | インスタンス世代 | 5, 6, 7 |
karpenter.k8s.aws/instance-cpu | vCPU 数 | 4, 8, 16 |
karpenter.k8s.aws/instance-memory | メモリ (MiB) | 8192, 16384 |
karpenter.k8s.aws/instance-gpu-count | GPU 数 | 1, 4 |
karpenter.k8s.aws/instance-gpu-manufacturer | GPU メーカー | nvidia |
4.5 ビンパッキングアルゴリズム
Karpenter のビンパッキングアルゴリズムは、Pending Pod をできるだけ少ないノードに効率的に配置することを目的としている。以下のステップで動作する:
- Pod のグループ化: 同じ要件を持つ Pod をグループ化
- 互換インスタンスタイプの列挙: 要件を満たすすべてのインスタンスタイプを列挙
- コスト最適化: 最小コストでPod を配置できる組み合わせを計算
- 制約の検証: NodePool の limits やその他の制約を検証
- 最終選択: 最適なインスタンスタイプとAZの組み合わせを決定
例: 4つの Pod(各 1 CPU, 2 GiB メモリ)が Pending の場合
方法A: 4つの m5.large(各 2 CPU, 8 GiB)→ コスト: $0.384/h
方法B: 1つの m5.xlarge(4 CPU, 16 GiB)→ コスト: $0.192/h ← Karpenter が選択
方法C: 1つの m5.2xlarge(8 CPU, 32 GiB)→ コスト: $0.384/h
Karpenter は方法B を選択(最小コストで全 Pod を配置可能)
5. NodePool の設計と設定
5.1 NodePool の構造
NodePool は Karpenter の最も重要な設定リソースである。以下に各フィールドの詳細な説明を行う。
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: <名前>
spec:
# ノードテンプレート
template:
metadata:
labels: {} # ノードに付与するラベル
annotations: {} # ノードに付与するアノテーション
spec:
nodeClassRef: # EC2NodeClass への参照
group: karpenter.k8s.aws
kind: EC2NodeClass
name: <名前>
requirements: [] # インスタンス要件
taints: [] # ノードに付与する Taint
startupTaints: [] # 起動時のみ付与する Taint
expireAfter: 720h # ノードの有効期限
terminationGracePeriod: 24h # 終了時の猶予期間
# リソース制限
limits:
cpu: "1000"
memory: 1000Gi
# Disruption ポリシー
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
budgets: [] # Disruption バジェット
# 優先度の重み(0-100)
weight: 50
5.2 マルチ NodePool 設計
本番環境では、ワークロードの種類に応じて複数の NodePool を設計することが推奨される:
パターン1: ワークロードタイプ別
# 一般ワークロード用 NodePool
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: general
spec:
template:
metadata:
labels:
workload-type: general
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["m"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["5"]
- key: karpenter.k8s.aws/instance-size
operator: In
values: ["large", "xlarge", "2xlarge", "4xlarge"]
limits:
cpu: "500"
memory: 500Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
weight: 50
---
# コンピュート集約型ワークロード用 NodePool
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: compute-intensive
spec:
template:
metadata:
labels:
workload-type: compute
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["5"]
taints:
- key: workload-type
value: compute
effect: NoSchedule
limits:
cpu: "200"
memory: 200Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 5m
weight: 30
---
# メモリ集約型ワークロード用 NodePool
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: memory-intensive
spec:
template:
metadata:
labels:
workload-type: memory
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: high-memory
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["5"]
taints:
- key: workload-type
value: memory
effect: NoSchedule
limits:
cpu: "200"
memory: 2000Gi
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 5m
weight: 30
パターン2: コスト最適化(On-Demand + Spot)
# Spot インスタンス優先 NodePool(高い weight)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: spot-preferred
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
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: ["4"]
limits:
cpu: "500"
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 30s
weight: 80 # 高い優先度
---
# On-Demand フォールバック NodePool(低い weight)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: on-demand-fallback
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["4"]
limits:
cpu: "200"
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
weight: 20 # 低い優先度(Spot が使えない場合のフォールバック)
5.3 Weight(重み)によるNodePool の優先順位
NodePool の weight フィールド(0-100)は、複数の NodePool が Pod の要件を満たす場合の優先順位を決定する。値が大きいほど優先度が高い。
Pod の要件を満たす NodePool:
- spot-preferred (weight: 80) → 最優先で使用
- on-demand-fallback (weight: 20) → Spot が不可の場合に使用
- general (weight: 50) → 中間の優先度
5.4 Limits(制限)
NodePool の limits は、その NodePool が管理するノードの合計リソースの上限を定義する。これにより、予期しないコスト増大を防止できる。
spec:
limits:
cpu: "1000" # 全ノードの合計 CPU が 1000 コアを超えない
memory: 1000Gi # 全ノードの合計メモリが 1000 GiB を超えない
注意事項:
limitsはノードのallocatableリソースの合計で計算される- 制限に達すると、新しいノードはプロビジョニングされない
- 制限に達した場合、Pod は Pending のままとなる
5.5 StartupTaints
startupTaints は、ノードの起動中にのみ付与される Taint であり、ノードの初期化が完了するまで Pod のスケジューリングを防ぐために使用される。
spec:
template:
spec:
startupTaints:
- key: node.kubernetes.io/not-ready
effect: NoSchedule
- key: custom-init/not-ready
effect: NoSchedule
典型的なユースケース:
- カスタム初期化スクリプトの完了待ち
- セキュリティエージェントのインストール完了待ち
- ネットワーク設定の完了待ち
DaemonSet やカスタムコントローラーが初期化完了後に Taint を除去する設計にする。
6. EC2NodeClass の詳細設定
6.1 EC2NodeClass の構造
EC2NodeClass は、AWS EC2 インスタンスの具体的な構成を定義する:
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
amiSelectorTerms:
- alias: al2023@latest
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
Type: private
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
role: KarpenterNodeRole-my-cluster
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 100Gi
volumeType: gp3
iops: 3000
throughput: 125
encrypted: true
deleteOnTermination: true
metadataOptions:
httpEndpoint: enabled
httpProtocolIPv6: disabled
httpPutResponseHopLimit: 2
httpTokens: required
userData: |
#!/bin/bash
echo "Custom initialization script"
yum install -y amazon-ssm-agent
systemctl enable amazon-ssm-agent
systemctl start amazon-ssm-agent
tags:
Environment: production
Team: platform
ManagedBy: karpenter
6.2 AMI の選択と管理
6.2.1 エイリアスによる選択(推奨)
spec:
amiSelectorTerms:
- alias: al2023@latest # Amazon Linux 2023 最新版
# - alias: al2@latest # Amazon Linux 2 最新版
# - alias: bottlerocket@latest # Bottlerocket 最新版
# - alias: windows2022@latest # Windows Server 2022 最新版
エイリアスのバージョン指定も可能:
spec:
amiSelectorTerms:
- alias: al2023@v20240312 # 特定バージョンを固定
6.2.2 タグによる選択
spec:
amiSelectorTerms:
- tags:
Environment: production
AMIType: eks-optimized
6.2.3 AMI ID による直接指定
spec:
amiSelectorTerms:
- id: ami-0123456789abcdef0
- id: ami-0987654321fedcba0
6.3 サブネット設定
# プライベートサブネットの選択
spec:
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
kubernetes.io/role/internal-elb: "1"
# 特定のサブネット ID を指定
spec:
subnetSelectorTerms:
- id: subnet-0123456789abcdef0
- id: subnet-0987654321fedcba0
6.4 ブロックデバイスマッピング
# 一般的なワークロード
spec:
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 100Gi
volumeType: gp3
iops: 3000
throughput: 125
encrypted: true
kmsKeyID: arn:aws:kms:us-west-2:111122223333:key/xxxx
deleteOnTermination: true
---
# I/O 集約型ワークロード
spec:
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 200Gi
volumeType: gp3
iops: 10000
throughput: 500
encrypted: true
deleteOnTermination: true
- deviceName: /dev/xvdb
ebs:
volumeSize: 500Gi
volumeType: io2
iops: 20000
encrypted: true
deleteOnTermination: true
6.5 メタデータオプション(IMDSv2)
spec:
metadataOptions:
httpEndpoint: enabled
httpProtocolIPv6: disabled
httpPutResponseHopLimit: 2 # コンテナからのアクセスには 2 が必要
httpTokens: required # IMDSv2 を必須に
6.6 ユーザーデータ
Amazon Linux 2023 向け
spec:
userData: |
#!/bin/bash
set -euo pipefail
yum install -y amazon-ssm-agent
systemctl enable amazon-ssm-agent
systemctl start amazon-ssm-agent
cat <<'SYSCTL' >> /etc/sysctl.d/99-custom.conf
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
vm.max_map_count = 262144
SYSCTL
sysctl --system
Bottlerocket 向け
spec:
amiSelectorTerms:
- alias: bottlerocket@latest
userData: |
[settings.kubernetes]
max-pods = 110
[settings.kernel.sysctl]
"net.core.somaxconn" = "65535"
"vm.max_map_count" = "262144"
7. スケジューリングとプロビジョニングの仕組み
7.1 プロビジョニングの詳細フロー
┌─────────────────────────────────────────────────────┐
│ プロビジョニングフロー │
├─────────────────────────────────────────────────────┤
│ 1. Pending Pod の収集 │
│ └→ kube-apiserver から Pending 状態の Pod を取得 │
│ 2. Pod のフィルタリング │
│ ├→ DaemonSet Pod を除外 │
│ └→ 既にノードが割り当てられた Pod を除外 │
│ 3. NodePool の評価 │
│ ├→ 各 NodePool の requirements と Pod の要件を照合│
│ ├→ limits に余裕があるか確認 │
│ └→ weight に基づいて NodePool を優先順位付け │
│ 4. インスタンスタイプの選択 │
│ ├→ requirements を満たすインスタンスタイプを列挙 │
│ ├→ 各インスタンスタイプの価格情報を取得 │
│ └→ ビンパッキングで最適な組み合わせを計算 │
│ 5. ノードの作成 │
│ ├→ NodeClaim リソースを作成 │
│ ├→ EC2 CreateFleet API を呼び出し │
│ └→ インスタンスの起動を待機 │
│ 6. ノードの初期化 │
│ ├→ kubelet がノードを登録 │
│ ├→ ノードが Ready になるまで待機 │
│ └→ startupTaints が除去される │
│ 7. Pod のスケジューリング │
│ └→ kube-scheduler が Pod をノードに配置 │
└─────────────────────────────────────────────────────┘
7.2 バッチング
Karpenter はプロビジョニングの効率を上げるため、短時間に発生する複数の Pending Pod をバッチ処理する:
時間軸:
0s - Pod A が Pending になる → バッチウィンドウ開始
0.5s - Pod B が Pending になる → バッチに追加
0.8s - Pod C が Pending になる → バッチに追加
1.0s - バッチウィンドウ終了 → Pod A, B, C をまとめてプロビジョニング
7.3 Pod Affinity/Anti-Affinity の処理
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["web-app"]
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx:latest
resources:
requests:
cpu: "500m"
memory: "512Mi"
この場合、Karpenter は3つの Pod それぞれに別のノードを作成する必要があることを理解し、3つのノードをプロビジョニングする。
7.4 Topology Spread Constraints の処理
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 6
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web-app
containers:
- name: web
image: nginx:latest
resources:
requests:
cpu: "500m"
memory: "512Mi"
結果:
us-west-2a: 2 Pod(ノード1つ)
us-west-2b: 2 Pod(ノード1つ)
us-west-2c: 2 Pod(ノード1つ)
7.5 DaemonSet の考慮
ノードに必要なリソース = Pod のリソース要求 + DaemonSet のリソース要求 + kubelet 予約
例:
Pod 要求: 2 CPU, 4 GiB
DaemonSet (kube-proxy): 0.1 CPU, 0.1 GiB
DaemonSet (aws-node): 0.025 CPU, 0.1 GiB
DaemonSet (datadog-agent): 0.2 CPU, 0.5 GiB
kubelet 予約: 0.08 CPU, 0.3 GiB
─────────────────────────────────
合計: 2.405 CPU, 5.0 GiB → m5.xlarge (4 CPU, 16 GiB) を選択
7.6 GPU ワークロードのプロビジョニング
# GPU NodePool
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-workloads
spec:
template:
metadata:
labels:
workload-type: gpu
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: gpu-nodeclass
requirements:
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["g", "p"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["4"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
taints:
- key: nvidia.com/gpu
value: "true"
effect: NoSchedule
limits:
cpu: "100"
memory: 500Gi
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 5m
8. Consolidation(統合)と最適化
8.1 Consolidation の概要
Consolidation は、Karpenter の最も強力な機能の一つである。クラスターのリソース使用効率を継続的に監視し、コストを削減するためにノードを統合する。
8.2 Consolidation ポリシー
WhenEmpty
spec:
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 30s
WhenEmptyOrUnderutilized(推奨)
spec:
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
8.3 Consolidation のアルゴリズム
1. 空ノード削除 (Empty Node Deletion)
└→ ワークロードがないノードを即座に削除
2. マルチノード統合 (Multi-Node Consolidation)
└→ 複数のノードのワークロードを他の既存ノードに移動し、元のノードを削除
3. シングルノード置換 (Single Node Replacement)
└→ 1つのノードを、より小さい(安い)インスタンスタイプに置き換える
具体例:
Before Consolidation:
Node A (m5.2xlarge - $0.384/h): CPU 使用率 20%
Node B (m5.2xlarge - $0.384/h): CPU 使用率 30%
Node C (m5.xlarge - $0.192/h): CPU 使用率 90%
After Consolidation:
Node A の Pod を Node B と Node C に移動 → Node A を削除
コスト削減: $0.384/h → 月間約 $280 の節約
8.4 Disruption Budgets
spec:
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 1m
budgets:
- nodes: "10%"
- nodes: "0"
schedule: "0 9 * * 1-5"
duration: 8h
- nodes: "0"
schedule: "0 0 25 12 *"
duration: 24h
8.5 コスト最適化の数値例
Consolidation なし(手動管理、ノードグループ固定):
合計: $4.376/h = $3,190/月
Karpenter + Consolidation:
合計: $1.744/h = $1,273/月
コスト削減: 約60%($1,917/月の節約)
9. Drift Detection と自動更新
9.1 Drift Detection の概要
Drift Detection は、ノードの現在の設定が NodePool や EC2NodeClass の定義と一致しているかを継続的に監視する機能である。
9.2 Drift が検出されるケース
| 変更項目 | 検出方法 |
|---|---|
| AMI の変更 | EC2NodeClass の amiSelectorTerms に新しい AMI が一致 |
| セキュリティグループの変更 | securityGroupSelectorTerms の結果が変更 |
| サブネットの変更 | subnetSelectorTerms の結果が変更 |
| NodePool の requirements 変更 | ノードの属性が新しい requirements に不一致 |
| ブロックデバイスの変更 | blockDeviceMappings の設定変更 |
| メタデータオプションの変更 | metadataOptions の設定変更 |
| ユーザーデータの変更 | userData の内容変更 |
9.3 AMI の自動更新フロー
1. AWS が新しい EKS Optimized AMI をリリース
↓
2. Karpenter が定期的に AMI を確認(約15分間隔)
↓
3. 新しい AMI が検出される
↓
4. 既存ノードに "Drifted" 条件が追加される
↓
5. Disruption Controller がドリフトしたノードを処理
↓
6. ワークロードを他のノードに移動(cordon → drain)
↓
7. 新しい AMI でノードを起動
↓
8. 古いノードを削除
9.4 ローリングアップデートの戦略
spec:
disruption:
budgets:
- nodes: "10%"
- nodes: "0"
schedule: "0 14 * * 1-5"
duration: 9h
- nodes: "25%"
schedule: "0 0 * * 6"
duration: 48h
10. Disruption(中断)管理
10.1 Disruption の種類
| 種類 | 優先順位 | 説明 |
|---|---|---|
| Expiration | 1 | expireAfter で設定した期限を超えたノード |
| Drift | 2 | 設定変更により現在の構成がスペックと不一致 |
| Consolidation (Empty) | 3 | ワークロードが存在しないノード |
| Consolidation (Underutilized) | 4 | リソース使用率が低いノード |
10.2 Disruption の防止
# Pod レベル
apiVersion: v1
kind: Pod
metadata:
annotations:
karpenter.sh/do-not-disrupt: "true"
# PodDisruptionBudget
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-app-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: web-app
10.3 terminationGracePeriod
spec:
template:
spec:
terminationGracePeriod: 48h
11. スポットインスタンスの活用
11.1 Spot インスタンスの設定
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: spot-workloads
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
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: ["4"]
- key: karpenter.k8s.aws/instance-size
operator: In
values: ["large", "xlarge", "2xlarge"]
limits:
cpu: "500"
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 30s
11.2 Spot 中断のハンドリング
1. AWS が Spot 中断通知を送信(2分前)
↓
2. Karpenter が通知を検出(SQS キュー経由)
↓
3. ノードを Cordon → Pod を Drain → 新しいノードをプロビジョニング
11.3 SQS キューの設定
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": ["events.amazonaws.com", "sqs.amazonaws.com"]
},
"Action": "sqs:SendMessage",
"Resource": "arn:aws:sqs:us-west-2:111122223333:karpenter-events"
}
]
}
11.4 Spot のベストプラクティス
- インスタンスタイプの多様化: 最低15種類以上のインスタンスタイプを許可する
- マルチ AZ: 複数の AZ にまたがってプロビジョニングする
- フォールバック戦略: On-Demand の NodePool をフォールバックとして用意する
- 適切なワークロードの選択: ステートレスで中断耐性のあるワークロードを配置する
12. マルチアーキテクチャ対応(ARM/AMD)
12.1 マルチアーキテクチャ NodePool
# ARM 優先 NodePool
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: arm-preferred
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: kubernetes.io/arch
operator: In
values: ["arm64"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["6"]
weight: 80
---
# x86 フォールバック NodePool
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: amd-fallback
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["5"]
weight: 20
12.2 コスト比較
4 vCPU, 16 GiB Memory:
m5.xlarge (x86): $0.192/h
m6g.xlarge (ARM): $0.154/h → 20% 削減
m7g.xlarge (ARM): $0.163/h → 15% 削減
ARM + Spot の組み合わせ: On-Demand x86 比で最大 73% 削減
13. セキュリティとIAM設定
13.1 IAM アーキテクチャ
1. Karpenter Controller Role
└→ IRSA で設定、EC2/SQS/SSM/EKS API へのアクセス
2. Karpenter Node Role
└→ EC2 インスタンスプロファイル、ECR/EKS API へのアクセス
13.2 Karpenter Controller IAM ポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEC2Operations",
"Effect": "Allow",
"Action": [
"ec2:CreateFleet",
"ec2:CreateLaunchTemplate",
"ec2:CreateTags",
"ec2:DeleteLaunchTemplate",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeImages",
"ec2:DescribeInstances",
"ec2:DescribeInstanceTypeOfferings",
"ec2:DescribeInstanceTypes",
"ec2:DescribeLaunchTemplates",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSpotPriceHistory",
"ec2:DescribeSubnets",
"ec2:RunInstances",
"ec2:TerminateInstances"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:RequestedRegion": "us-west-2"
}
}
},
{
"Sid": "AllowSQSOperations",
"Effect": "Allow",
"Action": [
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl",
"sqs:ReceiveMessage"
],
"Resource": "arn:aws:sqs:us-west-2:111122223333:karpenter-*"
},
{
"Sid": "AllowSSMOperations",
"Effect": "Allow",
"Action": ["ssm:GetParameter"],
"Resource": "arn:aws:ssm:us-west-2::parameter/aws/service/*"
},
{
"Sid": "AllowEKSOperations",
"Effect": "Allow",
"Action": ["eks:DescribeCluster"],
"Resource": "arn:aws:eks:us-west-2:111122223333:cluster/my-cluster"
},
{
"Sid": "AllowIAMPassRole",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::111122223333:role/KarpenterNodeRole-*",
"Condition": {
"StringEquals": {
"iam:PassedToService": "ec2.amazonaws.com"
}
}
},
{
"Sid": "AllowPricing",
"Effect": "Allow",
"Action": ["pricing:GetProducts"],
"Resource": "*"
}
]
}
13.3 セキュリティベストプラクティス
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: secure-nodes
spec:
amiSelectorTerms:
- alias: al2023@latest
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
Type: private
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: my-cluster
role: KarpenterNodeRole-my-cluster
metadataOptions:
httpEndpoint: enabled
httpProtocolIPv6: disabled
httpPutResponseHopLimit: 2
httpTokens: required
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 100Gi
volumeType: gp3
encrypted: true
kmsKeyID: arn:aws:kms:us-west-2:111122223333:key/mrk-xxx
deleteOnTermination: true
14. モニタリングとオブザーバビリティ
14.1 Prometheus メトリクス
| メトリクス | 説明 |
|---|---|
karpenter_nodeclaims_created_total | 作成された NodeClaim の総数 |
karpenter_nodeclaims_terminated_total | 終了された NodeClaim の総数 |
karpenter_nodes_total | Karpenter 管理ノードの総数 |
karpenter_nodes_allocatable | ノードの allocatable リソース |
karpenter_disruption_actions_performed_total | 実行された disruption アクションの数 |
karpenter_cloudprovider_duration_seconds | API 呼び出しの応答時間 |
karpenter_cloudprovider_errors_total | API エラーの総数 |
karpenter_cloudprovider_instance_type_price_estimate | インスタンスタイプの価格推定 |
14.2 Grafana ダッシュボード
# Karpenter 管理ノード数の推移
sum(karpenter_nodes_total) by (nodepool)
# インスタンスタイプ別のノード数
count(karpenter_nodes_total) by (instance_type)
# ノード作成のレイテンシ(P99)
histogram_quantile(0.99,
sum(rate(karpenter_provisioner_scheduling_duration_seconds_bucket[5m])) by (le)
)
# コスト推定
sum(karpenter_cloudprovider_instance_type_price_estimate) by (nodepool)
14.3 アラート設定例
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: karpenter-alerts
namespace: monitoring
spec:
groups:
- name: karpenter.rules
rules:
- alert: KarpenterNodePoolNearLimit
expr: |
sum by (nodepool) (karpenter_nodes_allocatable{resource_type="cpu"})
/
sum by (nodepool) (karpenter_nodepools_limit{resource_type="cpu"})
> 0.9
for: 5m
labels:
severity: warning
- alert: KarpenterHighErrorRate
expr: |
rate(karpenter_cloudprovider_errors_total[5m]) > 0.1
for: 10m
labels:
severity: critical
- alert: KarpenterPendingPods
expr: |
count(kube_pod_status_phase{phase="Pending"} == 1) > 0
for: 10m
labels:
severity: warning
15. Cluster Autoscaler との比較
15.1 詳細な比較表
| 機能 | Cluster Autoscaler | Karpenter |
|---|---|---|
| スケーリング速度 | 30秒〜数分 | 数秒〜30秒 |
| インスタンスタイプ選択 | ASG で固定 | Pod の要件に基づき動的選択 |
| ビンパッキング | 限定的 | 高度なアルゴリズム |
| Consolidation | なし | 自動統合 |
| Drift Detection | なし | 自動検出・更新 |
| Spot 対応 | ASG の Mixed Instances | ネイティブ対応 |
| GPU 対応 | ノードグループごとに設定 | 動的に選択 |
| マルチアーキテクチャ | ノードグループごとに分離 | 統合管理 |
| ノードの有効期限 | なし | expireAfter で設定可能 |
| 設定の複雑さ | 多数のノードグループが必要 | 少数の NodePool で管理 |
| クラウド対応 | マルチクラウド | AWS(他は開発中) |
| ノードグループ依存 | あり(ASG) | なし |
15.2 スケーリング速度の比較
シナリオ: 100 Pod を同時にデプロイ(各 1 CPU, 2 GiB)
Cluster Autoscaler: 約 2分10秒、m5.xlarge x 25ノード
Karpenter: 約 1分5秒、m5.4xlarge x 7ノード(自動選択)
15.3 コスト比較
月間コスト比較(同一ワークロード):
Cluster Autoscaler: $4,963/月(平均 CPU 使用率 45%)
Karpenter: $2,500/月(平均 CPU 使用率 75%)
削減額: ~$2,463/月(約50%削減)
16. 本番環境でのベストプラクティス
16.1 NodePool 設計
# 良い例: 幅広いインスタンスタイプを許可
spec:
template:
spec:
requirements:
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["4"]
- key: karpenter.k8s.aws/instance-size
operator: In
values: ["large", "xlarge", "2xlarge", "4xlarge"]
16.2 Helm チャートの設定
replicas: 2
controller:
resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"
env:
- name: CLUSTER_NAME
value: "my-cluster"
- name: INTERRUPTION_QUEUE
value: "my-cluster-karpenter"
- name: LOG_LEVEL
value: "info"
serviceAccount:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::111122223333:role/KarpenterControllerRole
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values: ["karpenter"]
topologyKey: kubernetes.io/hostname
podDisruptionBudget:
maxUnavailable: 1
17. トラブルシューティング
17.1 一般的な問題と解決策
問題1: Pod が Pending のまま
kubectl describe pod <pod-name>
kubectl logs -n kube-system -l app.kubernetes.io/name=karpenter -c controller
kubectl get nodepool -o yaml
よくある原因: NodePool の limits 到達、要件を満たすインスタンスタイプなし、IAM 権限不足
問題2: ノードが Ready にならない
kubectl get nodeclaim
kubectl describe nodeclaim <name>
aws ec2 describe-instances --instance-ids <instance-id>
よくある原因: ユーザーデータのスクリプトエラー、ネットワーク設定の問題、AMI の互換性
17.2 デバッグコマンド集
kubectl get nodepool
kubectl get nodeclaim -o wide
kubectl get ec2nodeclass
kubectl get nodes -l karpenter.sh/nodepool
kubectl top nodes -l karpenter.sh/nodepool
kubectl get events --field-selector source=karpenter --sort-by='.lastTimestamp'
17.3 ログのフィルタリング
# プロビジョニング関連
kubectl logs -n kube-system -l app.kubernetes.io/name=karpenter -c controller | \
jq 'select(.logger == "controller.provisioner")'
# エラーログのみ
kubectl logs -n kube-system -l app.kubernetes.io/name=karpenter -c controller | \
jq 'select(.level == "ERROR")'
18. 高度な設定パターン
18.1 テナント分離パターン
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: team-a
spec:
template:
metadata:
labels:
team: team-a
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: team-a-nodes
taints:
- key: team
value: team-a
effect: NoSchedule
limits:
cpu: "500"
memory: 500Gi
18.2 バッチジョブパターン
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: batch-jobs
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: batch-nodes
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot"]
- key: karpenter.k8s.aws/instance-size
operator: In
values: ["2xlarge", "4xlarge", "8xlarge"]
taints:
- key: workload-type
value: batch
effect: NoSchedule
expireAfter: 24h
limits:
cpu: "2000"
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 30s
18.3 機械学習ワークロードパターン
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: ml-training
spec:
template:
spec:
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: ml-nodeclass
requirements:
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["p", "g"]
- key: karpenter.k8s.aws/instance-family
operator: In
values: ["p4d", "p5", "g5", "g6"]
taints:
- key: nvidia.com/gpu
value: "true"
effect: NoSchedule
expireAfter: 168h
limits:
cpu: "200"
memory: 2000Gi
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 10m
19. 移行ガイド
19.1 Cluster Autoscaler からの移行
Phase 1: 並行運用(2-4週間)→ Phase 2: 段階的移行(2-4週間)→ Phase 3: 完全移行(1-2週間)
Karpenter のインストール
helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter \
--version "1.1.0" \
--namespace kube-system \
--set "settings.clusterName=my-cluster" \
--set "settings.interruptionQueue=my-cluster-karpenter" \
--set replicas=2 \
--wait
19.2 v1beta1 から v1 への API 移行
| v1beta1 | v1 | 変更内容 |
|---|---|---|
consolidationPolicy: WhenUnderutilized | consolidationPolicy: WhenEmptyOrUnderutilized | 名称変更 |
spec.template.spec.kubelet | 削除(EC2NodeClass に移動) | 設定場所の変更 |
spec.disruption.expireAfter | spec.template.spec.expireAfter | 設定場所の変更 |
| なし | spec.template.spec.terminationGracePeriod | 新規追加 |
19.3 Terraform / IaC による管理
resource "helm_release" "karpenter" {
namespace = "kube-system"
name = "karpenter"
repository = "oci://public.ecr.aws/karpenter"
chart = "karpenter"
version = "1.1.0"
set {
name = "settings.clusterName"
value = module.eks.cluster_name
}
set {
name = "settings.interruptionQueue"
value = aws_sqs_queue.karpenter.name
}
set {
name = "replicas"
value = "2"
}
set {
name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"
value = aws_iam_role.karpenter_controller.arn
}
}
20. まとめと今後の展望
20.1 まとめ
Karpenter は、Kubernetes クラスターのノード管理を根本的に変革するツールである:
- アーキテクチャ: Group-less アーキテクチャにより、ASG の制約を排除し、Pod の要件に基づいた柔軟なプロビジョニングを実現
- コアコンセプト: NodePool、NodeClaim、EC2NodeClass の3つのCRDにより、宣言的なノード管理を提供
- 最適化: ビンパッキング、Consolidation、Drift Detection により、継続的なコスト最適化と設定の一貫性を実現
- スポットインスタンス: ネイティブなSpot対応により、大幅なコスト削減が可能
- セキュリティ: IMDSv2、暗号化、IAM最小権限の原則を標準でサポート
- オブザーバビリティ: 豊富なPrometheusメトリクスとJSON形式のログにより、運用の透明性を確保
20.2 今後の展望
- マルチクラウド対応: Azure / GCP Provider の開発が進行中
- 機能強化: より高度な Consolidation アルゴリズム、GPU ネイティブサポート強化
- エコシステム: Terraform Provider 強化、ArgoCD/Flux 統合パターンの標準化
20.3 推奨事項
- 小規模な環境から開始: 開発環境で十分に検証する
- 段階的な移行: Cluster Autoscaler からの移行は段階的に実施する
- モニタリングの整備: Prometheus + Grafana でメトリクスを可視化する
- Disruption Budget の設定: 本番環境では適切な Disruption Budget を設定する
- 定期的な設定レビュー: NodePool と EC2NodeClass の設定を定期的に見直す
- コスト分析: Karpenter 導入前後のコスト比較を実施する
本記事は2026年4月時点の情報に基づいています。Karpenter は活発に開発が進められているプロジェクトであり、最新の情報は公式ドキュメント(https://karpenter.sh/)を参照してください。