EKS Automodeのカスタムノードプールを作成するときはノードクラスの作成を忘れずに(組み込みノードプール無効化の場合)
結論
EKS Automode有効・組み込みノードプール無効で、クラスターを作成するとノードクラスやアクセスエントリは自動的に作成されません。
ノードクラスやアクセスエントリの設定を忘れずに行いましょう。
EKS Automodeのノードプール・ノードクラス
本ブログでは、ノードプール や ノードクラス といった概念が登場します。
聞き慣れない方は、以下をご確認ください。
前提
本ブログの環境では、Terraform経由でKubernetesとAWSリソースを管理しています。
EKS ClusterとKubernetesリソースで、Statefileを分割しています。
ディレクトリ構成は以下の形をとっています。
cluster/
main.tf
outputs.tf
providers.tf
variables.tf
terraform.tfvars
kube/
main.tf
outputs.tf
providers.tf
variables.tf
terraform.tfvars
カスタムノードプールのみ使うため、組み込みノードプールは無効にしていました。
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.34.0"
# 省略
cluster_compute_config = {
enabled = true
node_pools = []
}
# 省略
事象
ノードが起動せず、Podが作成できない事象が発生しました。
詳細
ノードプールを作成しました。
resource "kubernetes_manifest" "node_pool_general" {
manifest = yamldecode(file("${path.module}/files/manifest/nodepool_general.yaml"))
}
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: general
spec:
template:
spec:
nodeClassRef:
group: eks.amazonaws.com
kind: NodeClass
name: default
requirements:
- key: "karpenter.sh/capacity-type"
operator: In
values: ["spot", "on-demand"]
- key: "eks.amazonaws.com/instance-category"
operator: In
values: ["c", "m", "r"]
- key: "eks.amazonaws.com/instance-cpu"
operator: In
values: ["2", "4", "8"]
- key: "kubernetes.io/arch"
operator: In
values: ["amd64"]
metadata:
labels:
workload: general
動作確認用にPodの起動を試しました。
kubectl run test-pod --image=nginx --restart=Never
しかし、Podが起動しません。
kubectl get pods
NAME READY STATUS RESTARTS AGE
test-pod 0/1 Pending 0 6s
kubectl describe pods test-pod
Name: test-pod
Namespace: default
Priority: 0
Service Account: default
Node: <none>
Labels: run=test-pod
Annotations: <none>
Status: Pending
IP:
IPs: <none>
Containers:
test-pod:
Image: nginx
Port: <none>
Host Port: <none>
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9dl7m (ro)
Conditions:
Type Status
PodScheduled False
Volumes:
kube-api-access-9dl7m:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 3s (x6 over 28s) default-scheduler no nodes available to schedule pods
kubectl describe
コマンドで以下のメッセージが出ていました。
PodをスケジュールできるNodeが無いみたいです。
Warning FailedScheduling 3s (x6 over 28s) default-scheduler no nodes available to schedule pods
原因
ノードプールのステータスを確認したところ、ノードクラスが存在しない旨のメッセージがありました。
NodeClass not found on cluster
ノードクラスが存在せずノードプールが使えない状態になっており、結果ノードを作成できなかったようです。
組み込みノードプールを有効化して作成したときはノードクラスが自動的に作成されていたため、ノードクラスの作成を行っていませんでした。
どうやら組み込みノードプール無効化で作成すると、デフォルトのノードクラスは自動的に作成されないようです。
kubectl get nodepools.karpenter.sh
NAME NODECLASS NODES READY AGE
general default 0 False 8m2s
kubectl describe nodepools.karpenter.sh
Name: general
Namespace:
Labels: <none>
Annotations: karpenter.sh/nodepool-hash: 6272226517684250404
karpenter.sh/nodepool-hash-version: v3
API Version: karpenter.sh/v1
Kind: NodePool
Metadata:
Creation Timestamp: 2025-04-04T01:38:58Z
Generation: 1
Resource Version: 2313
UID: 86138198-83a8-44ee-8034-5733f17a7df6
Spec:
Disruption:
Budgets:
Nodes: 10%
Consolidate After: 0s
Consolidation Policy: WhenEmptyOrUnderutilized
Template:
Metadata:
Labels:
Workload: general
Spec:
Expire After: 336h
Node Class Ref:
Group: eks.amazonaws.com
Kind: NodeClass
Name: default
Requirements:
Key: karpenter.sh/capacity-type
Operator: In
Values:
spot
on-demand
Key: eks.amazonaws.com/instance-category
Operator: In
Values:
c
m
r
Key: eks.amazonaws.com/instance-cpu
Operator: In
Values:
2
4
8
Key: kubernetes.io/arch
Operator: In
Values:
amd64
Termination Grace Period: 24h
Status:
Conditions:
Last Transition Time: 2025-04-04T01:38:58Z
Message: NodeClass not found on cluster
Observed Generation: 1
Reason: NodeClassNotFound
Status: False
Type: NodeClassReady
Last Transition Time: 2025-04-04T01:38:59Z
Message:
Observed Generation: 1
Reason: ValidationSucceeded
Status: True
Type: ValidationSucceeded
Last Transition Time: 2025-04-04T01:38:58Z
Message: NodeClassReady=False
Observed Generation: 1
Reason: UnhealthyDependents
Status: False
Type: Ready
Resources:
Cpu: 0
Ephemeral - Storage: 0
Memory: 0
Nodes: 0
Pods: 0
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal NodeClassReady 5m22s karpenter Status condition transitioned, Type: NodeClassReady, Status: Unknown -> False, Reason: NodeClassNotFound, Message: NodeClass not found on cluster
Normal Ready 5m22s karpenter Status condition transitioned, Type: Ready, Status: Unknown -> False, Reason: UnhealthyDependents, Message: NodeClassReady=False, ValidationSucceeded=Unknown
Normal ValidationSucceeded 5m22s karpenter Status condition transitioned, Type: ValidationSucceeded, Status: Unknown -> True, Reason: ValidationSucceeded
Warning 5m16s karpenter Failed resolving NodeClass
Warning 78s (x2 over 3m18s) karpenter Failed resolving NodeClass
対応
ノードクラスを作成して、ノードを作成できるようにします。
以下を参考にTerraformを修正します。
Amazon EKS のノードクラスを作成する - アマゾン EKS
ノードクラス作成
組み込みノードクラスを有効にすると、default
という名前のノードクラスが作成されます。
前述の公式ドキュメント上に以下の記述があるため、独自に作成するノードクラス名をgeneral
としました。
独自に作成するノードクラスに default という名前を付けないでください。
# 追加
resource "kubernetes_manifest" "node_class" {
manifest = yamldecode(templatefile("${path.module}/templates/manifest/nodeclass.yaml", {
node_security_group_id = data.tfe_outputs.cluster.values.eks.node_security_group_id
node_role_name = data.tfe_outputs.cluster.values.eks.node_iam_role_name
}))
}
resource "kubernetes_manifest" "node_pool_general" {
manifest = yamldecode(file("${path.module}/files/manifest/nodepool_general.yaml"))
}
セキュリティグループやIAM RoleはTerraform EKS Moduleで自動作成されるリソースを指定します。
subnetSelectorTerms:
部分も置き換えが必要な場合があります。
今回はサブネット用のタグ(※1)で指定していますが、タグを設定していない場合はsubnet id
を指定する形で設定します。
apiVersion: eks.amazonaws.com/v1
kind: NodeClass
metadata:
name: general
spec:
# Required: Subnet selection for node placement
subnetSelectorTerms:
- tags:
kubernetes.io/role/internal-elb: "1"
# Alternative using direct subnet ID
# - id: "subnet-0123456789abcdef0"
# Required: Security group selection for nodes
securityGroupSelectorTerms:
- id: ${node_security_group_id}
# Alternative approaches:
# - id: "sg-0123456789abcdef0"
# - name: "eks-cluster-node-security-group"
# Optional: Configure SNAT policy (defaults to Random)
snatPolicy: Random # or Disabled
# Optional: Network policy configuration (defaults to DefaultAllow)
networkPolicy: DefaultAllow # or DefaultDeny
# Optional: Network policy event logging (defaults to Disabled)
networkPolicyEventLogs: Disabled # or Enabled
# Optional: Configure ephemeral storage (shown with default values)
ephemeralStorage:
size: "80Gi" # Range: 1-59000Gi or 1-64000G or 1-58Ti or 1-64T
iops: 3000 # Range: 3000-16000
throughput: 125 # Range: 125-1000
# Optional: Name of IAM role to use for EC2 instance role
# If unspecified, EKS creates a role
# If specified, you must create an access entry for this role as described above
role: ${node_role_name}
ノードプールの設定で、指定しているノードクラスを今回作成したノードクラスに変更します。(default
-> general
)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: general
spec:
template:
spec:
nodeClassRef:
group: eks.amazonaws.com
kind: NodeClass
# 作成したノードクラスを指定
name: general
requirements:
- key: "karpenter.sh/capacity-type"
operator: In
values: ["spot", "on-demand"]
- key: "eks.amazonaws.com/instance-category"
operator: In
values: ["c", "m", "r"]
- key: "eks.amazonaws.com/instance-cpu"
operator: In
values: ["2", "4", "8"]
- key: "kubernetes.io/arch"
operator: In
values: ["amd64"]
metadata:
labels:
workload: general
Terraformで設定を適用します。
terraform -chdir=kube apply
※1 EKS Auto Mode のサブネットにタグを付ける - アマゾン EKS
アクセスエントリ作成
組み込みノードプール無効化時は、アクセスエントリは自動で作成されません。
こちらも作成します。
resource "aws_eks_access_entry" "auto_mode" {
cluster_name = module.eks.cluster_name
principal_arn = module.eks.node_iam_role_arn
type = "EC2"
}
resource "aws_eks_access_policy_association" "auto_mode" {
cluster_name = module.eks.cluster_name
policy_arn = "arn:aws:eks::aws:cluster-access-policy/AmazonEKSAutoNodePolicy"
principal_arn = module.eks.node_iam_role_arn
access_scope {
type = "cluster"
}
}
terraform -chdir=cluster apply
動作確認
動作確認として、Podを起動してみます。
「出力例」のようにStatus
がRunning
になればOKです。
kubectl run test-pod --image=nginx --restart=Never
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
test-pod 1/1 Running 0 3m2s
おわりに
初歩的なところですが、忘れそうと思ったのでブログにしました。
組み込みノードグループを無効化する場合は、ノードクラスの設定を忘れずに設定しましょう。
以上、AWS事業本部の佐藤(@chari7311でした。)