Get pods in Kubernetes where all containers are "ready" in one line using kubectl

2/16/2022

We have cluster with Istio and also Jenkins job to get "stable" pods, which uses this kubectl query:

kubectl get po -o=jsonpath="{range .items[?(@.status.containerStatuses[-1].ready==true)]}{.spec.containers[0].image}{'\\n'}{end}"
registry/my-proj/admin:2.0.0.000123
registry/my-proj/foo:2.0.0.000123
registry/my-proj/bar:2.0.0.000123

This query fetches pods where last container (application) is ready, because we also have Istio sidecar containers. But here is tricky thing, it looks like array is built using alphabet, so if Istio container will be last - it fetches it as ready pod, because last container is ready.

I've tried to use go-template also, but the best thing I've managed to do

kubectl get po -o go-template='{{range .items}}{{range .status.containerStatuses}}{{if eq .ready true }}{{end}}{{end}}{{.metadata.name}}{{println}}{{end}}
registry/my-proj/admin:2.0.0.000123
registry/my-proj/admin:2.0.0.000123
registry/my-proj/foo:2.0.0.000123
registry/my-proj/foo:2.0.0.000123
registry/my-proj/bar:2.0.0.000123

It fetches 2 times pods where 2 containers are ready and only 1 if 1 container is ready.

TL;DR;

I am looking for ultimate query which can fetch pods where all containers are ready, thanks

-- orlovw
kubectl
kubernetes

3 Answers

2/16/2022

What about something like this?

kubectl get po -o go-template='{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}{{range .items}}{{$pod := .}}{{range .status.containerStatuses}}{{if eq .ready false}}{{$pod.metadata.name}}{{"\n"}}{{end}}{{end}}{{end}}' | sort | uniq -u

What's happening here:

  1. We are getting all existing pod names, delimited by newline
  2. Appending all pod names, which have at least one not ready container, delimited by newline
  3. Sorting output alphabetically
  4. Getting unique lines, while excluding duplicate ones.

The trick is that -u key excludes all duplicate entries, so all that is left is running pods. {{ $pod := .}} is used to save outer scope to print pod name inside inner loop. "Get all pods" is coming after "get not ready pods" to reduce risk of possible race condition, when some pods may have become ready by the time we did a "get all pods" query.

I do believe that something like this can easily be achieved with jsonpath too, but I don't think that you'll be able to do it with kubectl only, without the usage of sort and uniq.

-- Andrew
Source: StackOverflow

2/16/2022

If you are ok with grep, you can use the following command:

kubectl get pod |grep -Po '^([^ ]+)(?=\s+((\d+)\/\3))'

Example:

kubectl get pod
NAME    READY   STATUS     RESTARTS        AGE
bar     2/2     Running    0               5m12s
foo     1/3     NotReady   6               6m9s
mypod   1/1     Running    2 (9m58s ago)   21h

kubectl get pod |grep -Po '^([^ ]+)(?=\s+((\d+)\/\3))'
bar
mypod
ps@controller:~$
-- P....
Source: StackOverflow

2/17/2022

Get all ready pods:

kubectl get po -o go-template='{{ $readyFlag := true}}{{range .items}}{{range .status.containerStatuses}}{{ if not .ready}}{{ $readyFlag = false}}{{end}}{{end}}{{if $readyFlag }}{{.metadata.name}}{{"\n"}}{{end}}{{end}}'

Get all not ready pods:

kubectl get po -o go-template='{{ $readyFlag := true}}{{range .items}}{{range .status.containerStatuses}}{{ if not .ready}}{{ $readyFlag = false}}{{end}}{{end}}{{if not $readyFlag }}{{.metadata.name}}{{"\n"}}{{end}}{{end}}'

Implementation details: 1. We define variable $readyFlag with initial value true 2. We loop over all containers statuses and if its field ".ready" is not true - update our flag value to false 3. In the end we just check if $readyFlag has value false - then at least one of checked containers had status not ready. If value true - then all containers was ready

-- AndyMrk
Source: StackOverflow