💥

EKS Nodeのアップグレード時に発生したPodEvictionFailureエラーに対処した話

2024/03/12に公開

概要

本記事では以下の条件での 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 による設定が可能です。

まとめ

  • EKS add-on の CoreDNS の v1.9.3-eksbuild.5 以降および v1.10.1-eksbuild.2 では、PDB がデフォルトでデプロイされるようになる(詳細は公式ドキュメント参照)
  • 自前で PDB を用意していた場合、 CoreDNS のアップグレード時か EKS Node のアップグレード時にエラーが発生する
  • CoreDNS を該当バージョンにアップグレードする際は自前の PDB を削除して、 EKS add-on 側でPDB 設定の調整を行わなければならない
SocialPLUS Tech Blog

Discussion