Navendu Pottekkat
Navendu Pottekkat

Reputation: 335

Kubernetes go-client to list out pod details similar to `kubectl get pods`

I'm trying to use the Kubernetes client-go to access pod details in a cluster.

I want to use it to get the details of pods running in one particular namespace, similar to kubectl get pods -n <my namespace>.

The details I want are the name, status, ready, restarts and age of the pod.

How can I get those data?

Upvotes: 4

Views: 3901

Answers (2)

John Huynh
John Huynh

Reputation: 429

Adding on to Navendu's excellent answer, sometimes there is a difference in the "STATUS" column when you run kubectl get pods vs. the podStatus.Phase.

As described here: How to use the kubernetes go-client to get the same Pod status info that kubectl gives. Sometimes you want the actual reason why a specific container in a pod is not booting up or if it's initializing.

To get the reason, update Navendu's code to be:

// List all the pods similar to kubectl get pods -n <my namespace>
            for _, pod := range podList.Items {
                // Calculate the age of the pod
                podCreationTime := pod.GetCreationTimestamp()
                age := time.Since(podCreationTime.Time).Round(time.Second)

                // Get the status of each of the pods
                podStatus := pod.Status

                var containerRestarts int32
                var containerReady int
                var totalContainers int
                var containerReasonNotReady string

                // If a pod has multiple containers, get the status from all
                for container := range pod.Spec.Containers {
                    // Updated code to grab actual reason instead of showing just the podStatus
                    if !podStatus.ContainerStatuses[container].Ready {
                      if ok := podStatus.ContainerStatuses[container].State.Waiting; ok != nil {
                        containerReasonNotReady += podStatus.ContainerStatuses[container].State.Waiting.Reason
                      }
                      if ok := podStatus.ContainerStatuses[container].State.Terminated; ok != nil {
                        containerReasonNotReady += podStatus.ContainerStatuses[container].State.Terminated.Reason
                      }
                    }

                    containerRestarts += podStatus.ContainerStatuses[container].RestartCount
                    if podStatus.ContainerStatuses[container].Ready {
                        containerReady++
                    }
                    totalContainers++
                }

                // Get the values from the pod status
                name := pod.GetName()
                ready := fmt.Sprintf("%v/%v", containerReady, totalContainers)
                // Updated code to grab actualStatus
                var actualStatus string
                if len(containerReasonNotReady) > 0 {
                  actualStatus = containerReasonNotReady
                } else {
                  actualStatus = fmt.Sprintf("%v", podStatus.Phase)
                }

                restarts := fmt.Sprintf("%v", containerRestarts)
                ageS := age.String()

                // Append this to data to be printed in a table
                data = append(data, []string{name, ready, actualStatus, restarts, ageS})
            }

Note that this is a more direct method of doing the same thing as the source code: https://github.com/kubernetes/kubectl/blob/81cffe129f76292f24be1d05435c8d35e975f765/pkg/describe/describe.go#L2013

It seems like kubectl is abstracting the end result to a writer, and it also looks like the writer is encapsulating data about the terminationCode, times, and more.

You can update your code to be more or less the same, but the Waiting.Reason/Terminating.Reason is enough for me.

Upvotes: 1

Navendu Pottekkat
Navendu Pottekkat

Reputation: 335

So, I wrote a function that takes in a Kubernetes client (refer the client-go for details on making one) and a namespace and returns all the pods available-

func GetPods(client *meshkitkube.Client, namespace string) (*v1core.PodList, error) {
    // Create a pod interface for the given namespace
    podInterface := client.KubeClient.CoreV1().Pods(namespace)

    // List the pods in the given namespace
    podList, err := podInterface.List(context.TODO(), v1.ListOptions{})

    if err != nil {
        return nil, err
    }
    return podList, nil
}

After getting all the pods, I used a loop to run through all the pods and containers within each pod and manually got all the data I required-

// List all the pods similar to kubectl get pods -n <my namespace>
            for _, pod := range podList.Items {
                // Calculate the age of the pod
                podCreationTime := pod.GetCreationTimestamp()
                age := time.Since(podCreationTime.Time).Round(time.Second)

                // Get the status of each of the pods
                podStatus := pod.Status

                var containerRestarts int32
                var containerReady int
                var totalContainers int

                // If a pod has multiple containers, get the status from all
                for container := range pod.Spec.Containers {
                    containerRestarts += podStatus.ContainerStatuses[container].RestartCount
                    if podStatus.ContainerStatuses[container].Ready {
                        containerReady++
                    }
                    totalContainers++
                }

                // Get the values from the pod status
                name := pod.GetName()
                ready := fmt.Sprintf("%v/%v", containerReady, totalContainers)
                status := fmt.Sprintf("%v", podStatus.Phase)
                restarts := fmt.Sprintf("%v", containerRestarts)
                ageS := age.String()

                // Append this to data to be printed in a table
                data = append(data, []string{name, ready, status, restarts, ageS})
            }

This will result in the exact same data as you would get when running kubectl get pods -n <my namespace>.

Upvotes: 4

Related Questions