はじめに
EKS Auto ModeでKubernetesハンズオンを進めていたところ、MySQLのPodがPending状態のまま起動しなくなりました。
調査してみると、原因は1つではなく3つが同時に重なっていました。
- ノードのTaintでPodがスケジュールできない
- OIDCプロバイダー未登録でEBSボリュームが作れない
- StorageClassのProvisionerがEKS Auto Modeに対応していない
備忘録として対応した内容を残しておきます。
環境
- Amazon EKS (Auto Mode)
- Kubernetes 1.31
- リージョン: ap-northeast-1
やったこと
PodがPendingのまま起動しないときは、まず kubectl describe pod でEvents欄を確認します。
kubectl describe pod <Pod名>
出力の末尾にあるEvents欄に、原因を示すメッセージが表示されます。
Events:
Type Reason Message
---- ------ -------
Warning FailedScheduling 0/2 nodes are available: 2 node(s) had untolerated taint(s).
このメッセージを手がかりに原因を切り分けます。
今回出てたメッセージは下記です。
| Events欄のメッセージ | 原因 |
|---|---|
node(s) had untolerated taint(s) |
ノードのTaintでスケジュール拒否されている |
InvalidIdentityToken: No OpenIDConnect provider found |
OIDCプロバイダーが未登録 |
| PVCがPendingのまま(Eventsに目立ったエラーなし) | StorageClassのProvisionerが合っていない |
describe pod で情報が足りない場合は、kubectl get events でクラスタ全体のイベントも確認してみてください。
kubectl get events --sort-by=.metadata.creationTimestamp
原因1: ノードのTaintでスケジュールできない
エラーメッセージ
Warning FailedScheduling 0/2 nodes are available:
2 node(s) had untolerated taint(s).
preemption: 0/2 nodes are available:
2 Preemption is not helpful for scheduling.
原因
Kubernetesの Taint は、ノードに「条件を満たさないPodを拒否する」設定を付与する仕組みです。
EKS Auto Modeでは、ノードに CriticalAddonsOnly:NoSchedule というTaintが付いていることがあります。これは「システム系のPodだけ動かす」という制限で、通常のアプリケーションPodはスケジュールされません。
ノードのTaintは以下のコマンドで確認できます。
kubectl get node -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taints
解決方法
2つの方法があります。
方法A: Taintを削除する(検証環境向け)
kubectl taint nodes <ノード名> CriticalAddonsOnly:NoSchedule-
末尾の - がTaintの削除を意味します。手軽ですが、ノードの保護がなくなるため本番環境には向きません。
方法B: PodにTolerationを追加する(本番環境向け)
spec:
tolerations:
- key: "CriticalAddonsOnly"
operator: "Exists"
effect: "NoSchedule"
Taintが「立入禁止の張り紙」だとすると、Tolerationは「入室許可証」にあたります。
ノードの保護を維持しつつ、特定のPodだけ許可できます。
原因2: OIDCプロバイダー未登録でEBSが作れない
エラーメッセージ
EBS CSI DriverのPodログに以下のエラーが出ます。
kubectl logs <ebs-csi-controller Pod名> -n kube-system
InvalidIdentityToken: No OpenIDConnect provider found in your account for
https://oidc.eks.ap-northeast-1.amazonaws.com/id/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
原因
EKSでPodからAWSリソース(EBSなど)にアクセスするには、IRSA(IAM Roles for Service Accounts) という仕組みを使います。流れは以下の通りです。
- Pod内のServiceAccountがトークンを持っている
- そのトークンをAWS STSに提示して、一時的な認証情報を取得する
- AWS側はOIDCプロバイダーを通じてトークンの発行元を検証する
このとき、EKSクラスタのOIDCプロバイダーがAWSアカウントのIAMに登録されていないと、3の検証が失敗してEBSボリュームを作成できません。
登録状況は以下のコマンドで確認できます。
# クラスタのOIDC URLを確認
aws eks describe-cluster --name <クラスタ名> --region ap-northeast-1 \
--query "cluster.identity.oidc.issuer" --output text
# AWSアカウントに登録されているOIDCプロバイダー一覧
aws iam list-open-id-connect-providers
解決方法
AWSコンソールからOIDCプロバイダーを登録します。
- IAM > IDプロバイダー > プロバイダーを追加
- プロバイダーの種類: OpenID Connect
- プロバイダーURL:
https://oidc.eks.ap-northeast-1.amazonaws.com/id/XXXXXXXX...(上記コマンドで確認した値) - 対象者(Audience):
sts.amazonaws.com
対象者に sts.amazonaws.com を指定するのは、EBS CSI DriverがAWS STSを使って一時的な認証情報を取得するためです。
原因3: StorageClassのProvisionerが合っていない
エラーメッセージ
この問題はわかりにくく、describe pod ではTaintやOIDCのような明確なエラーが出ません。PVCのステータスがPendingのまま止まります。
kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
gvol-1 Pending gp2 5m
原因
StorageClassに設定された Provisioner(ボリュームを実際に作成するドライバー)が、EKS Auto Modeに対応していないことが原因です。
EKSには3種類のProvisionerがあり、EKS Auto Modeで動くのは専用のものだけです。
| Provisioner | 種別 | EKS Auto Mode |
|---|---|---|
kubernetes.io/aws-ebs |
in-tree(旧式) | 非対応 |
ebs.csi.aws.com |
CSI Driver(汎用) | 非対応 |
ebs.csi.eks.amazonaws.com |
CSI Driver(Auto Mode専用) | 対応 |
クラスタで利用可能なCSI Driverは以下で確認できます。
kubectl get csidriver
解決方法
EKS Auto Mode専用のStorageClassを作成します。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-auto
provisioner: ebs.csi.eks.amazonaws.com
volumeBindingMode: WaitForFirstConsumer
parameters:
type: gp3
PVC側も修正します。storageClassName を新しいStorageClassに変更し、accessModes を ReadWriteOnce にします。EBSはブロックストレージなので、複数ノードからの同時マウント(ReadWriteMany)はできません。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gvol-1
spec:
storageClassName: ebs-auto
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 12Gi
なお、PVCを適用した直後はStatusがPendingのままですが、volumeBindingMode: WaitForFirstConsumer を指定している場合はこれが正常です。Podがノードにスケジュールされたタイミングで、同じAZにEBSボリュームが作成されます。
まとめ
PodがPendingになったら、まず kubectl describe pod のEvents欄を確認。
1つ解決してもPodが起動しない場合は、焦らず1つずつ可能性を潰していくのが近道です。