1
16
17 package kubelet
18
19 import (
20 "fmt"
21 "os"
22 "path/filepath"
23 "syscall"
24
25 v1 "k8s.io/api/core/v1"
26 "k8s.io/apimachinery/pkg/types"
27 utilerrors "k8s.io/apimachinery/pkg/util/errors"
28 "k8s.io/apimachinery/pkg/util/sets"
29 "k8s.io/klog/v2"
30 kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
31 "k8s.io/kubernetes/pkg/kubelet/metrics"
32 "k8s.io/kubernetes/pkg/util/removeall"
33 "k8s.io/kubernetes/pkg/volume"
34 volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
35 )
36
37
38
39 func (kl *Kubelet) ListVolumesForPod(podUID types.UID) (map[string]volume.Volume, bool) {
40 volumesToReturn := make(map[string]volume.Volume)
41 podVolumes := kl.volumeManager.GetMountedVolumesForPod(
42 volumetypes.UniquePodName(podUID))
43 for outerVolumeSpecName, volume := range podVolumes {
44
45
46
47 if volume.Mounter == nil {
48 continue
49 }
50 volumesToReturn[outerVolumeSpecName] = volume.Mounter
51 }
52
53 return volumesToReturn, len(volumesToReturn) > 0
54 }
55
56
57
58
59 func (kl *Kubelet) ListBlockVolumesForPod(podUID types.UID) (map[string]volume.BlockVolume, bool) {
60 volumesToReturn := make(map[string]volume.BlockVolume)
61 podVolumes := kl.volumeManager.GetMountedVolumesForPod(
62 volumetypes.UniquePodName(podUID))
63 for outerVolumeSpecName, volume := range podVolumes {
64
65
66
67 if volume.BlockVolumeMapper == nil {
68 continue
69 }
70 volumesToReturn[outerVolumeSpecName] = volume.BlockVolumeMapper
71 }
72
73 return volumesToReturn, len(volumesToReturn) > 0
74 }
75
76
77
78 func (kl *Kubelet) podVolumesExist(podUID types.UID) bool {
79 if mountedVolumes :=
80 kl.volumeManager.GetPossiblyMountedVolumesForPod(
81 volumetypes.UniquePodName(podUID)); len(mountedVolumes) > 0 {
82 return true
83 }
84
85
86
87 volumePaths, err := kl.getMountedVolumePathListFromDisk(podUID)
88 if err != nil {
89 klog.ErrorS(err, "Pod found, but error occurred during checking mounted volumes from disk", "podUID", podUID)
90 return true
91 }
92 if len(volumePaths) > 0 {
93 klog.V(4).InfoS("Pod found, but volumes are still mounted on disk", "podUID", podUID, "paths", volumePaths)
94 return true
95 }
96
97 return false
98 }
99
100
101
102
103 func (kl *Kubelet) newVolumeMounterFromPlugins(spec *volume.Spec, pod *v1.Pod, opts volume.VolumeOptions) (volume.Mounter, error) {
104 plugin, err := kl.volumePluginMgr.FindPluginBySpec(spec)
105 if err != nil {
106 return nil, fmt.Errorf("can't use volume plugins for %s: %v", spec.Name(), err)
107 }
108 physicalMounter, err := plugin.NewMounter(spec, pod, opts)
109 if err != nil {
110 return nil, fmt.Errorf("failed to instantiate mounter for volume: %s using plugin: %s with a root cause: %v", spec.Name(), plugin.GetPluginName(), err)
111 }
112 klog.V(10).InfoS("Using volume plugin for mount", "volumePluginName", plugin.GetPluginName(), "volumeName", spec.Name())
113 return physicalMounter, nil
114 }
115
116
117
118
119
120
121 func (kl *Kubelet) removeOrphanedPodVolumeDirs(uid types.UID) []error {
122 orphanVolumeErrors := []error{}
123
124
125 volumePaths, err := kl.getPodVolumePathListFromDisk(uid)
126 if err != nil {
127 orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but error occurred during reading volume dir from disk: %v", uid, err))
128 return orphanVolumeErrors
129 }
130 if len(volumePaths) > 0 {
131 for _, volumePath := range volumePaths {
132 if err := syscall.Rmdir(volumePath); err != nil {
133 orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but failed to rmdir() volume at path %v: %v", uid, volumePath, err))
134 } else {
135 klog.InfoS("Cleaned up orphaned volume from pod", "podUID", uid, "path", volumePath)
136 }
137 }
138 }
139
140
141 subpathVolumePaths, err := kl.getPodVolumeSubpathListFromDisk(uid)
142 if err != nil {
143 orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but error occurred during reading of volume-subpaths dir from disk: %v", uid, err))
144 return orphanVolumeErrors
145 }
146 if len(subpathVolumePaths) > 0 {
147 for _, subpathVolumePath := range subpathVolumePaths {
148
149 if err := os.Remove(subpathVolumePath); err != nil {
150 orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but failed to rmdir() subpath at path %v: %v", uid, subpathVolumePath, err))
151 } else {
152 klog.InfoS("Cleaned up orphaned volume subpath from pod", "podUID", uid, "path", subpathVolumePath)
153 }
154 }
155 }
156
157
158
159 podVolDir := kl.getPodVolumesDir(uid)
160 if err := removeall.RemoveDirsOneFilesystem(kl.mounter, podVolDir); err != nil {
161 orphanVolumeErrors = append(orphanVolumeErrors, fmt.Errorf("orphaned pod %q found, but error occurred when trying to remove the volumes dir: %v", uid, err))
162 } else {
163 klog.InfoS("Cleaned up orphaned pod volumes dir", "podUID", uid, "path", podVolDir)
164 }
165
166 return orphanVolumeErrors
167 }
168
169
170
171 func (kl *Kubelet) cleanupOrphanedPodDirs(pods []*v1.Pod, runningPods []*kubecontainer.Pod) error {
172 allPods := sets.NewString()
173 for _, pod := range pods {
174 allPods.Insert(string(pod.UID))
175 }
176 for _, pod := range runningPods {
177 allPods.Insert(string(pod.ID))
178 }
179
180 found, err := kl.listPodsFromDisk()
181 if err != nil {
182 return err
183 }
184
185 orphanRemovalErrors := []error{}
186 orphanVolumeErrors := []error{}
187 var totalPods, errorPods int
188
189 for _, uid := range found {
190 if allPods.Has(string(uid)) {
191 continue
192 }
193
194 totalPods++
195
196
197
198
199
200 if podVolumesExist := kl.podVolumesExist(uid); podVolumesExist {
201 errorPods++
202 klog.V(3).InfoS("Orphaned pod found, but volumes are not cleaned up", "podUID", uid)
203 continue
204 }
205
206
207 podVolumeErrors := kl.removeOrphanedPodVolumeDirs(uid)
208 if len(podVolumeErrors) > 0 {
209 errorPods++
210 orphanVolumeErrors = append(orphanVolumeErrors, podVolumeErrors...)
211
212
213
214
215
216 continue
217 }
218
219
220 podDir := kl.getPodDir(uid)
221 podSubdirs, err := os.ReadDir(podDir)
222 if err != nil {
223 errorPods++
224 klog.ErrorS(err, "Could not read directory", "path", podDir)
225 orphanRemovalErrors = append(orphanRemovalErrors, fmt.Errorf("orphaned pod %q found, but error occurred during reading the pod dir from disk: %v", uid, err))
226 continue
227 }
228
229 var cleanupFailed bool
230 for _, podSubdir := range podSubdirs {
231 podSubdirName := podSubdir.Name()
232 podSubdirPath := filepath.Join(podDir, podSubdirName)
233
234
235
236 if podSubdirName == "volumes" {
237 cleanupFailed = true
238 err := fmt.Errorf("volumes subdir was found after it was removed")
239 klog.ErrorS(err, "Orphaned pod found, but failed to remove volumes subdir", "podUID", uid, "path", podSubdirPath)
240 continue
241 }
242 if err := removeall.RemoveAllOneFilesystem(kl.mounter, podSubdirPath); err != nil {
243 cleanupFailed = true
244 klog.ErrorS(err, "Failed to remove orphaned pod subdir", "podUID", uid, "path", podSubdirPath)
245 orphanRemovalErrors = append(orphanRemovalErrors, fmt.Errorf("orphaned pod %q found, but error occurred when trying to remove subdir %q: %v", uid, podSubdirPath, err))
246 }
247 }
248
249
250 klog.V(3).InfoS("Orphaned pod found, removing", "podUID", uid)
251 if err := syscall.Rmdir(podDir); err != nil {
252 cleanupFailed = true
253 klog.ErrorS(err, "Failed to remove orphaned pod dir", "podUID", uid)
254 orphanRemovalErrors = append(orphanRemovalErrors, fmt.Errorf("orphaned pod %q found, but error occurred when trying to remove the pod directory: %v", uid, err))
255 }
256 if cleanupFailed {
257 errorPods++
258 }
259 }
260
261 logSpew := func(errs []error) {
262 if len(errs) > 0 {
263 klog.ErrorS(errs[0], "There were many similar errors. Turn up verbosity to see them.", "numErrs", len(errs))
264 for _, err := range errs {
265 klog.V(5).InfoS("Orphan pod", "err", err)
266 }
267 }
268 }
269 logSpew(orphanVolumeErrors)
270 logSpew(orphanRemovalErrors)
271 metrics.OrphanPodCleanedVolumes.Set(float64(totalPods))
272 metrics.OrphanPodCleanedVolumesErrors.Set(float64(errorPods))
273 return utilerrors.NewAggregate(orphanRemovalErrors)
274 }
275
View as plain text