List pods per namespace in kubernetes - kubernetes

I have several namespaces in my cluster and would like a log like:
NAMESPACE NAME PODS
MY_NAMESPACE my_ns6446f67599-25g7f 10

You can also try this one liner:
kubectl get pods --all-namespaces | awk '{print $1}' | sort | uniq -c | sort -k1 -n -r
Which will yield:
136 some-ns
133 kube-system
119 other-ns
Explaining a bit:
kubectl get pods --all-namespaces will list all pods with namespace in the first column.
awk { print $1 } will "filter out" the first column which is the namespace
sort will sort the name of namespaces alphabetically
uniq -c will count how many times each namespace appeared and aggregate with a count as the first column (e.g. 136 some-ns means that some-ns appeared 136 times).
sort -k1 -n -r this one will sort from the namespace which appeared the most (i.e. had most pods) to the one that appeared the least. -k1 means that I am using the first column to sort, -n I am using numeric comparison and -r and I am doing a reverse ordering.

You can use --all-namespaces flag to get pods.
kubectl get pods --all-namespaces
From your output, it looks like you are trying to print the replicasets as there is a PODs count column in the output.
kubectl get replicaset --all-namespaces
If you want to limit the resulting columns, we can use the --0 custom-columns= parameter as below.
$ kubectl get replicaset --all-namespaces -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,PODS:.status.replicas
NAMESPACE NAME PODS
MY_NAMESPACE my_ns6446f67599-25g7f 10

This solution combines the json output of kubectl get pods and kubectl get namespaces in order to also display the namespaces where no pods are deployed.
kubectl get pods -o json --all-namespaces | jq --argjson ns "$(kubectl get namespaces -o json)" '.items | group_by(.metadata.namespace) | map({namespace: .[].metadata.namespace, count: . | length}) | . += ($ns.items | map({namespace: .metadata.name, count: 0})) | unique_by(.namespace) | sort_by(.count)'
The solution provides an array of json objects sorted by number of pods in ascending order and can be easily extended to obtain the desired output.
The "magic" happens when we add the contents of the $ns variable -which contains the namespaces- to the end of the array with count=0. These entries will be discarded by unique_by if the namespace was already found before -which means it contains pods-.
Note: the solution relies on jq's unique_by function to discard the second appearance of an object with the same key value, which as for the documentation it is not granted but it happens to be implemented in this way.

Related

Kubectl Namespace script to filter only name

I'm trying to use Kubectl get namespaces command it is fetching the data.
kubectl get namespace
NAME STATUS AGE
default Active 1d
kube-node-lease Active 1d
kube-public Active 1d
kube-system Active 1d
but I want to filter it with name only. So when u run the script it should show like this.
kubectl get namespace
NAME
default
kube-node-lease
kube-public
kube-system
I've tried some powershell command but it is not working out for me.
Try any one of the command
kubectl get namespace --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}'
kubectl get namespace | awk '{print $1}'
kubectl get namespace --no-headers -o custom-columns=":metadata.name"
kubectl get namespace -o=name | sed "s/^.\{10\}//"
I presume the output of kubectrl is pure text so to manipulate it you will need to either do text parsing (error-prone and not fun) or you need to get the data into a PowerShell object.
ConvertFrom-SourceTable
This will allow you to read and parse the text/string data into a PowerShell object. Then you can simply Select-Object name to get the Name column only.
The second option is to use text/string parsing but for that, you will have to use length detections to extract the columns. An example of that can be found here.
This code works for me:
kubectl get ns | awk '{print $1}'

How to exclude taint nodes from outputs in kubectl get nodes?

I try to check how many nodes are ready (not including nodes tainted NoSchedule) and write the number to text file output.txt.
Could you give me any advice?
I believe that kubectl get nodes doesn't show taints, so you can't just filter with grep. In that case you can set the output as json and use jq (or yaml and use yq) to process it:
kubectl get nodes -o json | jq -c '.items[].spec.taints' | grep -v NoSchedule | wc -l > output.txt
-c option in jq is to output each element in a single line, instead of pretty printing it, in case you have multiple taints. The rest has already been explained in Abdennour TOUMI's answer
kubectl get nodes | grep Ready | grep -v NotReady | grep -v NoSchedule \
| wc -l > output.txt
This single command will do the job for you:
Notes:
While grep includes lines, grep -v excludes lines
wc -l counts the number of lines.
number of output's lines is the same number of nodes with criteria you described
Full proof Query to get nodes except node has taint effect NoSchedule on it
kubectl get node -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.taints[*].effect}{"\n"}{end}' | grep -v NoSchedule | wc -l
The following command can be used without jq or where jq is not installed.
kubectl get nodes --selector='!node-role.kubernetes.io/master' --no-headers | grep -v SchedulingDisabled | wc -l > output.txt

How to delete multiple Kubernetes pods having the same name expression except the latest one?

I have multiple pods running as below. I want to delete them all except the one having minimum age. How to do it?
Something like this? Perhaps also add -l app=value to filter for a specific app
kubectl get pods --sort-by=.metadata.creationTimestamp -o name | head -n -1 | xargs echo kubectl delete
(Remove echo to do it for realz)
You could just use PowerShell and pipe the output to the Foreach-Object, which then loops over each line:
kubectl get pods -n default -o name | ForEach-Object { kubectl delete $_ }

Comma in kubectl used as a pipe

Have you seen a comma in a kubectl command?
Like the following command:
kubectl get deployments,ing -n my-system
Is it like a pipe grap or?
It is just a separator between k8s resources, that you would like to do something with (get/describe/etc...). Your command will output the list of Ingress resources next to the list of Deployments

What kubectl command can I use to get events sorted by specific fields and print only specific details of events?

I need to print only specific fields of Kubernetes Events, sorted by a specific field.
This is to help me gather telemetry and analytics about my namespace
How could I do that?
kubectl get events --sort-by='.lastTimestamp'
Following command does it.
It prints the events sorted by timestamp of creation.
It also users go-template to filter out specific fields of the kubernetes-event object.
kubectl get events --sort-by='.metadata.creationTimestamp' -o 'go-template={{range .items}}{{.involvedObject.name}}{{"\t"}}{{.involvedObject.kind}}{{"\t"}}{{.message}}{{"\t"}}{{.reason}}{{"\t"}}{{.type}}{{"\t"}}{{.firstTimestamp}}{{"\n"}}{{end}}'
I am using the following command to sort it after timestamp
kubectl get event --all-namespaces --sort-by='.metadata.managedFields[0].time'
For filtering out the information you can of course combine it with the go-template described by #suryakrupa or with jq described by #Chris Stryczynski
If you don't mind seeing the output as JSON:
kubectl get event -o json | jq '.items |= sort_by(.lastTimestamp)'
This requires jq.
Here's the Bash function I use:
function kubectl-events {
{
echo $'TIME\tNAMESPACE\tTYPE\tREASON\tOBJECT\tSOURCE\tMESSAGE';
kubectl get events -o json "$#" \
| jq -r '.items | map(. + {t: (.eventTime//.lastTimestamp)}) | sort_by(.t)[] | [.t, .metadata.namespace, .type, .reason, .involvedObject.kind + "/" + .involvedObject.name, .source.component + "," + (.source.host//"-"), .message] | #tsv';
} \
| column -s $'\t' -t \
| less -S
}
You can use it like: kubectl-events -A, kubectl-events -n foo, etc.