@@ -27,6 +27,7 @@ import (
2727 "k8c.io/kubeone/pkg/fail"
2828
2929 corev1 "k8s.io/api/core/v1"
30+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3031 "k8s.io/apimachinery/pkg/util/wait"
3132 "k8s.io/client-go/kubernetes"
3233 "k8s.io/client-go/rest"
@@ -45,13 +46,25 @@ const (
4546
4647var VolumeResources = []string {"persistentvolumes" , "persistentvolumeclaims" }
4748
49+ // PodResources is the list of resources blocked by the Pod creation-preventing webhook.
50+ var PodResources = []string {"pods" }
51+
4852func CleanupUnretainedVolumes (ctx context.Context , logger logrus.FieldLogger , c client.Client , restConfig * rest.Config ) error {
4953 // We disable the PV & PVC creation so nothing creates new PV's while we delete them
5054 logger .Infoln ("Creating ValidatingWebhookConfiguration to disable future PV & PVC creation..." )
5155 if err := disablePVCreation (ctx , c ); err != nil {
5256 return fail .KubeClient (err , "disabling future PV & PVC creation." )
5357 }
5458
59+ // We also disable Pod creation so workload controllers (Deployments, StatefulSets, ...) can't
60+ // recreate the Pods we delete below. A recreated Pod would re-mount the PVC and keep the
61+ // kubernetes.io/pvc-protection finalizer, leaving the PVC stuck in Terminating. The webhook
62+ // excludes kube-system so the CSI controllers keep running to actually delete the cloud volumes.
63+ logger .Infoln ("Creating ValidatingWebhookConfiguration to disable future Pod creation..." )
64+ if err := disablePodCreation (ctx , c ); err != nil {
65+ return fail .KubeClient (err , "disabling future Pod creation." )
66+ }
67+
5568 pvcList , pvList , err := getDynamicallyProvisionedUnretainedPvs (ctx , c )
5669 if err != nil {
5770 return err
@@ -91,7 +104,24 @@ func CleanupUnretainedVolumes(ctx context.Context, logger logrus.FieldLogger, c
91104
92105func disablePVCreation (ctx context.Context , c client.Client ) error {
93106 // Prevent re-creation of PVs and PVCs by using an intentionally defunct admissionWebhook
94- return creationPreventingWebhook (ctx , c , "" , VolumeResources )
107+ return creationPreventingWebhook (ctx , c , "" , VolumeResources , nil )
108+ }
109+
110+ func disablePodCreation (ctx context.Context , c client.Client ) error {
111+ // Prevent re-creation of Pods by using an intentionally defunct admissionWebhook. kube-system is
112+ // excluded so the CSI controllers (and other system components) keep running to delete the cloud
113+ // volumes backing the PVCs we remove.
114+ namespaceSelector := & metav1.LabelSelector {
115+ MatchExpressions : []metav1.LabelSelectorRequirement {
116+ {
117+ Key : corev1 .LabelMetadataName ,
118+ Operator : metav1 .LabelSelectorOpNotIn ,
119+ Values : []string {metav1 .NamespaceSystem },
120+ },
121+ },
122+ }
123+
124+ return creationPreventingWebhook (ctx , c , "" , PodResources , namespaceSelector )
95125}
96126
97127func cleanupPVCUsingPods (ctx context.Context , c client.Client , log logrus.FieldLogger , kubeClient * kubernetes.Clientset ) error {
@@ -100,11 +130,11 @@ func cleanupPVCUsingPods(ctx context.Context, c client.Client, log logrus.FieldL
100130 return fail .KubeClient (err , "listing Pods from user cluster." )
101131 }
102132
103- var pvUsingPods []* corev1.Pod
133+ var pvUsingPods []corev1.Pod
104134 for idx := range podList .Items {
105135 pod := & podList .Items [idx ]
106136 if podUsesPV (pod ) {
107- pvUsingPods = append (pvUsingPods , pod )
137+ pvUsingPods = append (pvUsingPods , * pod )
108138 }
109139 }
110140
@@ -119,6 +149,10 @@ func cleanupPVCUsingPods(ctx context.Context, c client.Client, log logrus.FieldL
119149 // ReplicaSet)
120150 Force : true ,
121151 DeleteEmptyDirData : true ,
152+ // DisableEviction makes drain delete pods directly instead of using the
153+ // eviction API. The cluster is being torn down, so PodDisruptionBudgets
154+ // must not be allowed to block (and indefinitely fail) the deletion.
155+ DisableEviction : true ,
122156 GracePeriodSeconds : - 1 ,
123157 Out : os .Stdout ,
124158 ErrOut : os .Stdout ,
@@ -135,16 +169,9 @@ func cleanupPVCUsingPods(ctx context.Context, c client.Client, log logrus.FieldL
135169 log .Infof ("pod %s/%s is %s" , pod .GetNamespace (), pod .GetName (), evicted )
136170 },
137171 }
138- evictionGroupVersion , err := drain .CheckEvictionSupport (kubeClient )
139- if err != nil {
140- return err
141- }
142172
143- for _ , pod := range pvUsingPods {
144- err := helper .EvictPod (* pod , evictionGroupVersion )
145- if err != nil {
146- return fail .KubeClient (err , "deleting the pod." )
147- }
173+ if err := helper .DeleteOrEvictPods (pvUsingPods ); err != nil {
174+ return fail .KubeClient (err , "deleting the pods using PVs." )
148175 }
149176
150177 return nil
0 commit comments