mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-02 00:07:50 +00:00
Merge pull request #65837 from clandry94/pvc_describe_claimed_by
Automatic merge from submit-queue (batch tested with PRs 65838, 65837). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. output which pods are a pvc in use when kubectl describe pvc is run **What this PR does / why we need it**: This PR implements a feature request to display the pods mounted to a PVC when `kubectl describe pvc` is ran. We need it since the only way to see which pods are bound to a PVC is by checking the volume mounts of each individual pod in the namespace. Example Output: ``` $ kubectl get pods,pvc NAME READY STATUS RESTARTS AGE test-pod 1/1 Running 0 2h NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE test-pvc Bound pvc-718681dd-70cc-11e7-aa14-42010af00029 100Gi RWO us-east1-b 345d ``` ``` $ kubectl describe pvc Name: elasticsearch-data-elasticsearch-data-us-east1-b-0 Namespace: partners-production StorageClass: us-east1-b Status: Bound Volume: pvc-718681dd-70cc-11e7-aa14-42010af00029 Labels: <none> Annotations: <none> Finalizers: [kubernetes.io/pvc-protection] Capacity: 1Gi Access Modes: RWO Events: <none> Mounted By: test-pod ``` Pods using the PVC are shown with the `Mounted By` field **Which issue(s) this PR fixes**: Closes #65233 **Special notes for your reviewer**: **Release note**: ```release-note Running `kubectl describe pvc` now shows which pods are mounted to the pvc being described with the `Mounted By` field ```
This commit is contained in:
commit
54db2273eb
@ -1291,12 +1291,52 @@ func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, descri
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pc := d.Core().Pods(namespace)
|
||||||
|
|
||||||
|
mountPods, err := getMountPods(pc, pvc.Name)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
events, _ := d.Core().Events(namespace).Search(legacyscheme.Scheme, pvc)
|
events, _ := d.Core().Events(namespace).Search(legacyscheme.Scheme, pvc)
|
||||||
|
|
||||||
return describePersistentVolumeClaim(pvc, events)
|
return describePersistentVolumeClaim(pvc, events, mountPods)
|
||||||
}
|
}
|
||||||
|
|
||||||
func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.EventList) (string, error) {
|
func getMountPods(c coreclient.PodInterface, pvcName string) ([]api.Pod, error) {
|
||||||
|
nsPods, err := c.List(metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return []api.Pod{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var pods []api.Pod
|
||||||
|
|
||||||
|
for _, pod := range nsPods.Items {
|
||||||
|
pvcs := getPvcs(pod.Spec.Volumes)
|
||||||
|
|
||||||
|
for _, pvc := range pvcs {
|
||||||
|
if pvc.PersistentVolumeClaim.ClaimName == pvcName {
|
||||||
|
pods = append(pods, pod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pods, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPvcs(volumes []api.Volume) []api.Volume {
|
||||||
|
var pvcs []api.Volume
|
||||||
|
|
||||||
|
for _, volume := range volumes {
|
||||||
|
if volume.VolumeSource.PersistentVolumeClaim != nil {
|
||||||
|
pvcs = append(pvcs, volume)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pvcs
|
||||||
|
}
|
||||||
|
|
||||||
|
func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.EventList, mountPods []api.Pod) (string, error) {
|
||||||
return tabbedString(func(out io.Writer) error {
|
return tabbedString(func(out io.Writer) error {
|
||||||
w := NewPrefixWriter(out)
|
w := NewPrefixWriter(out)
|
||||||
w.Write(LEVEL_0, "Name:\t%s\n", pvc.Name)
|
w.Write(LEVEL_0, "Name:\t%s\n", pvc.Name)
|
||||||
@ -1342,6 +1382,8 @@ func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.E
|
|||||||
DescribeEvents(events, w)
|
DescribeEvents(events, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printPodsMultiline(w, "Mounted By", mountPods)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -3867,6 +3909,37 @@ func printTaintsMultilineWithIndent(w PrefixWriter, initialIndent, title, innerI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printPodsMultiline prints multiple pods with a proper alignment.
|
||||||
|
func printPodsMultiline(w PrefixWriter, title string, pods []api.Pod) {
|
||||||
|
printPodsMultilineWithIndent(w, "", title, "\t", pods)
|
||||||
|
}
|
||||||
|
|
||||||
|
// printPodsMultilineWithIndent prints multiple pods with a user-defined alignment.
|
||||||
|
func printPodsMultilineWithIndent(w PrefixWriter, initialIndent, title, innerIndent string, pods []api.Pod) {
|
||||||
|
w.Write(LEVEL_0, "%s%s:%s", initialIndent, title, innerIndent)
|
||||||
|
|
||||||
|
if pods == nil || len(pods) == 0 {
|
||||||
|
w.WriteLine("<none>")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// to print pods in the sorted order
|
||||||
|
sort.Slice(pods, func(i, j int) bool {
|
||||||
|
cmpKey := func(pod api.Pod) string {
|
||||||
|
return pod.Name
|
||||||
|
}
|
||||||
|
return cmpKey(pods[i]) < cmpKey(pods[j])
|
||||||
|
})
|
||||||
|
|
||||||
|
for i, pod := range pods {
|
||||||
|
if i != 0 {
|
||||||
|
w.Write(LEVEL_0, "%s", initialIndent)
|
||||||
|
w.Write(LEVEL_0, "%s", innerIndent)
|
||||||
|
}
|
||||||
|
w.Write(LEVEL_0, "%s\n", pod.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// printPodTolerationsMultiline prints multiple tolerations with a proper alignment.
|
// printPodTolerationsMultiline prints multiple tolerations with a proper alignment.
|
||||||
func printPodTolerationsMultiline(w PrefixWriter, title string, tolerations []api.Toleration) {
|
func printPodTolerationsMultiline(w PrefixWriter, title string, tolerations []api.Toleration) {
|
||||||
printTolerationsMultilineWithIndent(w, "", title, "\t", tolerations)
|
printTolerationsMultilineWithIndent(w, "", title, "\t", tolerations)
|
||||||
|
Loading…
Reference in New Issue
Block a user