EKS Nodeのアップグレード時に発生したPodEvictionFailureエラーに対処した話
概要
本記事では以下の条件での EKS アップグレード時に発生したエラーとそのトラブルシューティングについて書きます。
アップグレード方式 | EKS Version | CoreDNS Version |
---|---|---|
インプレース方式 | EKS1.27 -> EKS1.28 | v1.10.1-eksbuild.1 -> v1.10.1-eksbuild.4 |
発生したエラーと状況
クラスター側は問題なく EKS1.28 にアップグレードできたため、Node 側のアップグレードを行ったところ、下記エラーが発生。
ip-10-x-xxx-xx.ap-northeast-1.compute.internal:
PodEvictionFailure: Reached max retries while trying to evict pods from nodes in node group node-group
上記エラーの内容は、「Node から Pod を退去させようとしたが、最大再試行回数に達しても退去できなかった」というもので、このエラーで検索しても有効な解決策を見つけられませんでした。
調査
エラーが発生したNode(ip-10-x-xxx-xx.ap-northeast-1.compute.internal
)内の Pod を確認したところ、一部の Pod がエラー発生時から起動したままであることを発見しました。
このことからエラー文言通り、Node から Pod の退去に失敗しているということが分かりましたが、どの Pod が退去できないのかは特定できず・・・
そこで、詳しいエラー文言が取得できないか確認するために手動で Node から Pod を退去させることにしました。
以下、コマンドと出力結果。
$ kubectl drain --ignore-daemonsets ip-10-x-xxx-xx.ap-northeast-1.compute.internal --delete-emptydir-data
node/ip-10-x-xxx-xx.ap-northeast-1.compute.internal already cordoned
Warning: ignoring DaemonSet-managed Pods: kube-system/aws-node-r79f8, kube-system/kube-proxy-t8845, logging/fluent-bit-2gx9b, monitoring/datadog-nmk9s
evicting pod kube-system/coredns-57cb7cc4f9-jq6cn
evicting pod argocd/argocd-redis-ha-server-2
evicting pod argocd/argocd-application-controller-0
evicting pod argocd/argocd-dex-server-6bd5fff9f4-hr9z6
evicting pod external-secrets/external-secrets-cert-controller-6cf7d57d4f-hh5xz
evicting pod external-secrets/external-secrets-webhook-6f47fbd5cd-zwzdr
pod/external-secrets-cert-controller-6cf7d57d4f-hh5xz evicted
pod/argocd-dex-server-6bd5fff9f4-hr9z6 evicted
pod/argocd-application-controller-0 evicted
pod/external-secrets-webhook-6f47fbd5cd-zwzdr evicted
pod/argocd-redis-ha-server-2 evicted
There are pending pods in node "ip-10-x-xxx-xx.ap-northeast-1.compute.internal" when an error occurred: error when evicting pods/"coredns-57cb7cc4f9-jq6cn" -n "kube-system": This pod has more than one PodDisruptionBudget, which the eviction subresource does not support.
pod/coredns-57cb7cc4f9-jq6cn
error: unable to drain node "ip-10-x-xxx-xx.ap-northeast-1.compute.internal" due to error:error when evicting pods/"coredns-57cb7cc4f9-jq6cn" -n "kube-system": This pod has more than one PodDisruptionBudget, which the eviction subresource does not support., continuing command...
There are pending nodes to be drained:
ip-10-x-xxx-xx.ap-northeast-1.compute.internal
error when evicting pods/"coredns-57cb7cc4f9-jq6cn" -n "kube-system": This pod has more than one PodDisruptionBudget, which the eviction subresource does not support.
上記の出力結果の一部から、「CoreDNS の PodDisruptionBudget が重複している為 Pod の退去に失敗した」という内容が読み取れます。
error when evicting pods/"coredns-57cb7cc4f9-jq6cn" -n "kube-system": This pod has more than one PodDisruptionBudget, which the eviction subresource does not support.
そこで、CoreDNS の PodDisruptionBudget(以降PDB
と呼ぶ)が重複しているか実際に確認したところ、確かに coredns と coredns-pdb の2つが存在していました。
$ kubectl get pdb --all-namespaces
NAMESPACE NAME MIN AVAILABLE MAX UNAVAILABLE ALLOWED DISRUPTIONS AGE
account account-puma-pdb N/A 25% 1 280d
kube-system cluster-autoscaler-aws-cluster-autoscaler N/A 1 1 125d
kube-system coredns N/A 1 1 2d6h
kube-system coredns-pdb N/A 25% 1 280d
エラーの原因は PDB の重複で間違いなさそうです。
なぜCoreDNSのPDBが増えたのか
以前までは CoreDNS の PDB は自前で用意する必要があり、以下のように管理していました。
resource "kubernetes_pod_disruption_budget_v1" "coredns" {
metadata {
name = "coredns-pdb"
namespace = "kube-system"
}
spec {
max_unavailable = "25%"
selector {
match_labels = {
k8s-app = "kube-dns"
}
}
}
}
しかし、EKS add-on の CoreDNS の v1.9.3-eksbuild.5 以降および v1.10.1-eksbuild.2 では、PDB がデフォルトでデプロイされるようになる仕様変更があり、その影響で CoreDNS の PDB が重複して今回のエラーに繋がったようです。
公式ドキュメントにも、自前で CoreDNS の PDB を用意した状態で EKS add-on の CoreDNS を該当バージョンへのアップグレードに失敗する可能性があるとの記載がありました。
CoreDNS Deploymentの安定性と可用性を向上させるため、v1.9.3-eksbuild.5以降およびv1.10.1-eksbuild.2では、PodDisruptionBudgetがデプロイされます。既存のPodDisruptionBudgetをデプロイしている場合、これらのバージョンへのアップグレードに失敗する可能性があります。
ただ、今回の事例だと EKS Cluster のアップグレード時に行った CoreDNS のアップグレードは問題なく成功しており、その後の EKS Node アップグレード時に PDB 重複エラーが発生という形になりました。
CoreDNS のアップグレードは既に PDB が存在してもエラーが発生せず、その後の EKS Node アップグレード時に Pod 退去失敗エラーとなるパターンもあるようです。
CoreDNS アップグレード時にエラーが出てくれた方が調査しやすかったと思いますが、どちらにしろドキュメントはよく読んだ方が良いですね...
EKS add-onの提供するPDBの設定が自前のPDB設定と異なる
EKS add-on の CoreDNS が提供する PDB
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
labels:
eks.amazonaws.com/component: coredns
k8s-app: kube-dns
name: coredns
namespace: kube-system
spec:
maxUnavailable: 1
selector:
matchLabels:
eks.amazonaws.com/component: coredns
k8s-app: kube-dns
今まで自前で用意していた PDB
resource "kubernetes_pod_disruption_budget_v1" "coredns" {
metadata {
name = "coredns-pdb"
namespace = "kube-system"
}
spec {
max_unavailable = "25%"
selector {
match_labels = {
k8s-app = "kube-dns"
}
}
}
}
となっており、EKS add-onの提供する PDB の設定が自前の PDB 設定とは異なる内容となっていました。
既存の構成に影響を与えたくないため、EKS add-on側の設定も自前の設定と揃えたいです。
EKS add-onの提供するPDB設定を自前のPDB設定と同じにする方法
EKS add-on の CoreDNS 設定を Terraform で管理している場合
Resource: aws_eks_addon.configuration_valuesを設定することで PDB の設定を調整することができました。
実際の差分は以下になります。
resource "aws_eks_addon" "coredns" {
addon_name = "coredns"
addon_version = data.aws_eks_addon_version.coredns.version
cluster_name = var.eks_cluster_name
resolve_conflicts_on_create = "OVERWRITE"
resolve_conflicts_on_update = "OVERWRITE"
preserve = true
+ configuration_values = jsonencode({
+ "podDisruptionBudget": {
+ "enabled": true,
+ "maxUnavailable": "25%"
+ "selector" = {
+ "match_labels" = {
+ "k8s-app" = "kube-dns"
+ }
+ }
+ }
+ })
}
EKS add-on の CoreDNS 設定を AWSコンソールから管理している場合
EKS > クラスター > アドオン > CoreDNS > アドオンの編集 > オプションの設定 > 設定値
で、YAML か JSON による設定が可能です。
Discussion