Amazon EKS(AWS が提供するマネージド Kubernetes サービス)を本番導入したあと、想定外のコスト増や可用性トラブルに直面するケースがあります。この記事は、EKS 導入を検討中、または導入済みでノード構成やネットワーク設計に不安がある方に向けて書いています。判断基準と確認手順の参考になれば幸いです。
何が起きるか:コンピュート選択ミスによる過剰コストと運用負荷
EKS は control plane(API server・etcd・scheduler などクラスタの頭脳部分)を AWS が管理してくれます。可用性 SLA(サービス品質保証)は99.95%です。
ただし data plane(実際に Pod が動くノード群)は利用者側の責任範囲です。ここの設計を誤ると、2つの問題が典型的に起きます。
1つ目はコストの膨張です。たとえば AWS Fargate(サーバーレスで Pod 単位の実行環境を提供する仕組み)を全ワークロードに適用すると、vCPU あたりの単価が EC2 ベースより高くなりやすく、常時稼働するバッチ処理などでは月額が想定の数倍に膨らむことがあります。
2つ目はスケーリング遅延です。Managed Node Group(AWS が管理する EC2 の Auto Scaling Group)だけに頼ると、新規ノードの起動に数分かかり、急激なトラフィック増加に追従できません。結果としてPodがPending状態(スケジュール待ち)のまま滞留します。
なぜ起きるか:コンピュートモデルの特性を理解せずに選定しているため
原因を段階的に分解すると、まず「EKS には複数のコンピュートモデルがあり、それぞれ適用範囲が違う」という前提が共有されていないことが挙げられます。
Managed Node Groupは、EC2インスタンスをAuto Scaling Groupで管理し、Amazon Linux 2023やBottlerocket(コンテナ専用の軽量OS)のAMIを使います。汎用ワークロード向けですが、インスタンスタイプやスケール設定は利用者が自分で決める必要があります。
FargateはPodごとに隔離された実行環境を提供し、ノード管理そのものが不要になります。一方でDaemonSet(全ノードに1つずつPodを配置する仕組み)やGPUが使えず、断続的・短時間のワークロードに向いています。
Karpenter(Pending状態のPodを検知して最適なインスタンスを自動選択・起動するオートスケーラー)は、CPU・メモリ要求に応じて数秒でノードを立ち上げ、使われていないノードは自動で整理(consolidation)します。コスト効率とSpotインスタンス活用に向いていますが、NodePoolやEC2NodeClassという専用リソースの設定が必要です。
つまり、どのモデルを選ぶかは「ワークロードの性質」と「運用コストの許容度」のトレードオフであり、1つのモデルで全てをまかなおうとすると、どこかで無理が生じる構造になっています。
ネットワーク面でも同様の落とし穴があります。EKSはAmazon VPC CNI(Container Network Interface)というプラグインにより、PodにオーバーレイなしでVPCの実IPを直接割り当てます。これはオーバーレイネットワーク(Calicoなどで使われる仮想ネットワーク層)を使う一般的なKubernetesクラスタと異なる設計です。VPCのIPアドレス枯渇やサブネット設計を考慮せずにノード数を増やすと、新規Podがスケジュールされない事態につながります。
自分のプロジェクトが該当するか確認する方法
既存クラスタがどのコンピュートモデルを使っているかは、以下のコマンドで確認できます。
# ノードグループの一覧とタイプを確認
aws eks list-nodegroups --cluster-name <クラスタ名>
# Fargateプロファイルの有無を確認
aws eks list-fargate-profiles --cluster-name <クラスタ名>
# Karpenterが導入済みかをNodePoolリソースで確認
kubectl get nodepools.karpenter.shPendingのまま残っているPodがないかは、次のコマンドで確認します。
kubectl get pods --all-namespaces --field-selector=status.phase=PendingVPCのIPアドレス余力は、VPCのサブネット設定画面、またはCLIで確認できます。
aws ec2 describe-subnets --subnet-ids <サブネットID> \
--query 'Subnets[].AvailableIpAddressCount'この値がノード増加予定数×Pod数に対して十分かどうかが、ネットワーク面のボトルネックになるかどうかの判断材料になります。
対策の手順
対策は、ワークロードの棚卸しからコンピュートモデルの使い分けへと段階的に進めます。
- 常時稼働のAPIサーバーやステートフルなサービスは、Managed Node GroupかKarpenterで管理する
- 断続的なバッチ処理やテスト環境はFargate Profile(namespaceやlabelで対象Podを指定する設定)を使い、常時稼働コストを避ける
- トラフィック変動が大きいサービスはKarpenterのNodePoolを設定し、Spotインスタンスの活用も検討する
- VPCのサブネットは、ノード増加計画に対してIPアドレスの余力を事前に試算しておく
- add-on(VPC CNI、CoreDNS、kube-proxy、EBS CSI Driverなど)のバージョンは
aws eks describe-addonで定期的に確認し、EKSのKubernetesバージョンアップ時に互換性を確認する
Karpenterを新規導入する場合は、NodePoolとEC2NodeClassという2種類のカスタムリソースをマニフェストで定義します。既存のManaged Node Groupと併用する場合は、同じワークロードが二重にスケジュールされないよう、ノードのラベルやtaintで役割分担を明確にしておくと混乱を避けやすくなります。
コスト面では、AWS Cost Explorerでノードグループ別・Fargateプロファイル別の使用状況を分けて確認し、想定より高い項目がないかを月次で見直す運用が現実的です。
まとめ
EKSのcontrol plane自体はAWSが管理し高可用性ですが、data plane側のコンピュートモデル選定は設計判断そのものであり、誤ると過剰コストやスケーリング遅延という形で表面化します。
まず aws eks list-nodegroups と list-fargate-profiles で現状のコンピュート構成を棚卸しし、Pending Podの有無とサブネットのIP余力を確認してください。
そのうえで、常時稼働workloadとスポット的workloadを分離し、Karpenterの導入や既存Node Groupとの役割分担を検討する流れが、コストと可用性のバランスを取るための現実的な一歩になります。