Get logs from all pods in namespace using xargs - shell

Is there anyway to get all logs from pods in a specific namespace running a dynamic command like a combination of awk and xargs?
kubectl get pods | grep Running | awk '{print $1}' | xargs kubectl logs | grep value
I have tried the command above but it's failing like kubectl logs is missing pod name:
error: expected 'logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER]'.
POD or TYPE/NAME is a required argument for the logs command
See 'kubectl logs -h' for help and examples
Do you have any suggestion about how get all logs from Running pods?

Think about what your pipeline is doing:
The kubectl logs command takes as an argument a single pod name, but through your use of xargs you're passing it multiple pod names. Make liberal use of the echo command to debug your pipelines; if I have these pods in my current namespace:
$ kubectl get pods -o custom-columns=name:.metadata.name
name
c069609c6193930cd1182e1936d8f0aebf72bc22265099c6a4af791cd2zkt8r
catalog-operator-6b8c45596c-262w9
olm-operator-56cf65dbf9-qwkjh
operatorhubio-catalog-48kgv
packageserver-54878d5cbb-flv2z
packageserver-54878d5cbb-t9tgr
Then running this command:
kubectl get pods | grep Running | awk '{print $1}' | xargs echo kubectl logs
Produces:
kubectl logs catalog-operator-6b8c45596c-262w9 olm-operator-56cf65dbf9-qwkjh operatorhubio-catalog-48kgv packageserver-54878d5cbb-flv2z packageserver-54878d5cbb-t9tgr
To do what you want, you need to arrange to call kubectl logs multiple times with a single argument. You can do that by adding -n1 to your xargs command line. Keeping the echo command, running this:
kubectl get pods | grep Running | awk '{print $1}' | xargs -n1 echo kubectl logs
Gets us:
kubectl logs catalog-operator-6b8c45596c-262w9
kubectl logs olm-operator-56cf65dbf9-qwkjh
kubectl logs operatorhubio-catalog-48kgv
kubectl logs packageserver-54878d5cbb-flv2z
kubectl logs packageserver-54878d5cbb-t9tgr
That looks more reasonable. If we drop the echo and run:
kubectl get pods | grep Running | awk '{print $1}' | xargs -n1 kubectl logs | grep value
Then you will get the result you want. You may want to add the --prefix argument to kubectl logs so that you know which pod generated the match:
kubectl get pods | grep Running | awk '{print $1}' | xargs -n1 kubectl logs --prefix | grep value
Not directly related to your question, but you can lose that grep:
kubectl get pods | awk '/Running/ {print $1}' | xargs -n1 kubectl logs --prefix | grep value
And even lose the awk:
kubectl get pods --field-selector=status.phase==Running -o name | xargs -n1 kubectl logs --prefix | grep value

Related

grep for pods and select each result and pass a command in loop

I have few pods running in my kubernetes cluster. I am developing a shell script and I want to grep for few pods and want to select each pod from the grep result to execute a command.
Lets say I grep few pods by command :
kubectl get pods | grep test
the results are:
Test-0
Test-1
Test-2
From the result, I want to select each pod and execute a command for it in a loop.
for example:
for first pod:
kubectl exec -it Test-0 -- mysqldump.......
after finishing the first pod, it has to process the second pod and so on
for pod in $(kubectl get pod -oname |grep -i Test ); do
kubectl exec "$pod" -- ls -ltr ;
done
Replace ls -ltr with mysqldump .....
Get pods name and then use "for" to execute command in each pod
#!/bin/bash
pods=$(kubectl get pods | awk '{print $2}' | grep -i test)
for i in $pods
do
kubectl exec -it $i -- echo "test"
done
Select your target pods using labels is less error prone and can do multiple matching:
kubectl get pods --selector <key>=<value>,<key>=<value> --namespace <name> -oname | xargs -I{} kubectl exec -it {} --namespace <name> -- mysqldump ...

unable to use watch with kubectl and xargs

Team, I am trying to run the below every 5seconds but no luck.
watch -n 5 kubectl get pods -n testes-asdf-234-asdf | grep -v Comple | xargs -l1 -- sh -c 'kubectl logs $1 -n testes-asdf-234-asdf main --tail=15' --
output:
does nothing
tried using quotes and command execution is messed up not yielding right output. my command works perfectly when used without watch and quotes
watch "kubectl get pods --no-headers -n testes-asdf-234-asdf | grep -v Comple | xargs -l1 -- sh -c 'kubectl logs $1 -n testes-asdf-234-asdf main --tail=15' --"
Every 2.0s: kubectl get pods --no-headers -n testes-asdf-234-asdf | grep -v Comple | xargs -l1 -- sh -c 'kubectl logs -n testes... Wed Dec 4 10:10:18 2019
Error from server (NotFound): pods "main" not found
Error from server (NotFound): pods "main" not found
Error from server (NotFound): pods "main" not found
Error from server (NotFound): pods "main" not found
Error from server (NotFound): pods "main" not found
Without WATCH runs fine
└─ $ ▶ kubectl get pods --no-headers -n testes-asdf-234-asdf | grep -v Comple | xargs -l1 -- sh -c 'kubectl logs $1 -n testes-asdf-234-asdf main --tail=15' --
**** Stack trace ****
/roadrunner/roadrunner: dw::core::Exception::Exception(dwStatus, char const*)+0xa1 [0xcdfc31]
/roadrunner/roadrunner: dw::roadcast::RoadCastServerEngine::checkMessageEnabledStatus(dwRoadCastMessageType, char const*)+0x3a [0x1c0e1ea]
/roadrunner/roadrunner() [0x1bc2f2a]
/roadrunner/roadrunner: dwRoadCastServer_sendImage()+0x72 [0x1bc4302]
/roadrunner/roadrunner: roadrunner::castData(dwImageObject*, char const*, long, long, unsigned long)+0x66 [0xd03726]
/roadrunner/roadrunner: roadrunner::RRMainPipeline::getCameraEventFrames(roadrunner::CameraFrame**, unsigned int&, roadrunner::RRMainPipeline::CameraFrameList&, dwSensorEvent const*)+0x75c [0xb2c91c]
/roadrunner/roadrunner: roadrunner::RRMainPipeline::getCameraFrames(roadrunner::RRMainPipeline::CameraFrameList*&, roadrunner::CameraFrame**, unsigned int&)+0x3b9 [0xb31039]
/roadrunner/roadrunner: roadrunner::RRMainPipeline::cameraThreadLoop()+0x634 [0xb44b64]
/usr/lib/x86_64-linux-gnu/libstdc++.so.6: ()+0xbd8f0 [0x7f8fe0a6f8f0]
/lib/x86_64-linux-gnu/libpthread.so.0: ()+0x76ba [0x7f90050eb6ba]
/lib/x86_64-linux-gnu/libc.so.6: clone()+0x6d [0x7f8fdff9e41d]
Unless you put your command in quotes, bash will try to pass the output of watch ... kubectl ... to the first grep, but watch will never exit.
So try this:
watch -n 5 "kubectl get pods -n test | grep -v Comple | xargs -l1 -- sh -c 'kubectl logs \$1 -n test main --tail=15' --"
EDIT:
Didn't notice you had a $1 in there. You need to escape the $, as it's now enclosed in double quotes and it will just be expanded to an empty string (as per the output you've shown).
I edited the command above to reflect that.

Command run via xargs fails but runs manually

I'm trying to create a command that will automatically attach to my existing python docker container, and trying to chain a bunch of commands together.
docker ps | grep "mypythoncontainer" | awk '{print $1}' | xargs docker attach
If I run
docker ps | grep "mypythoncontainer" | awk '{print $1}' | xargs echo
I get back a docker id string, as expected. And if I do docker attach {id string} (copied from the return of the statement right above this), it works. But when I run the full command at top, I get an error (the input device is not a TTY).
So docker ps | grep "mypythoncontainer" | awk '{print $1}' | xargs echo would echo out abc, but docker ps | grep "mypythoncontainer" | awk '{print $1}' | xargs docker attach would fail, while docker attach abc works. Not sure what about xargs I don't understand.
Try:
docker attach $(docker ps | grep "mypythoncontainer" | awk '{print $1}')
or simplier:
docker attach $(docker ps | awk '/mypythoncontainer/{print $1}')
Not sure what about xargs I don't understand.
Running: ...| ... docker ... will redirect docker's standard input to ... the ouput of awk, wich was already read by xargs. So docker abc will r
un with a broken (already closed) STDIN, then fail.

Kubernetes: Display Pods by age in ascending order

I use below command to sort the pods by age
kubectl get pods --sort-by={metadata.creationTimestamp}
It shows up pods in descending order. How can we select sorting order like ascending?
Not supported by kubectl or the kube-apiserver as of this writing (AFAIK), but a workaround would be:
$ kubectl get pods --sort-by=.metadata.creationTimestamp | tail -n +2 | tac
or if tac is not available (MacOS X):
$ kubectl get pods --sort-by=.metadata.creationTimestamp | tail -n +2 | tail -r
If you want the header:
$ echo 'NAME READY STATUS RESTARTS AGE' | \
kubectl get pods --sort-by=.metadata.creationTimestamp | tail -n +2 | tac
You might just have to adjust the tabs on the header accordingly. Or if you don't want to use tail -n +2 you can use --no-headers. For example:
$ kubectl get pods --sort-by=.metadata.creationTimestamp --no-headers | tac
It Is Quite EASY: Once you have used --no-headers option, the HEADER will not be part of output (ascending ordered-listing of pods) and you can simply reverse sort the outcome of the command.
Here's the complete command to get exactly what is expected:
kubectl get po --sort-by={metadata.creationTimestamp} --no-headers | tac
Sorted kubectl output and awk provide the table view with a header. Installation of extra tools is not needed.
# kubectl get pods --sort-by=.status.startTime | awk 'NR == 1; NR > 1 {print $0 | "tac"}'
An approach with JSON processor offered by paulogrell works also but could require more effort: for some Linux distributions you'll need to download and compile jq from source code. As for the jq command line I'd suggest to add the "name" to the map parameters and sort by "timestamp":
# kubectl get pods -o json | jq '.items | group_by(.metadata.creationTimestamp) | map({"name": .[0].metadata.name, "timestamp": .[0].metadata.creationTimestamp, "count": length}) | sort_by(.timestamp)'
I believe the Kubernetes API doesnt support this option yet, but as a workaround you can use a JSON processor (jq) to adjust its output.
Ascending
kubectl get pods -o json | jq '.items | group_by(.metadata.creationTimestamp) | map({"timestamp": .[0].metadata.creationTimestamp, "count": length}) | sort_by(.count)'
Descending
kubectl get pods -o json | jq '.items | group_by(.metadata.creationTimestamp) | map({"timestamp": .[0].metadata.creationTimestamp, "count": length}) | sort_by(.count) | reverse'
Hope this helps
A simpler version that works on MacOS and retains arbitrary headers:
kubectl get node --sort-by=.metadata.creationTimestamp | { read -r headers; echo "$headers"; tail -r; }
If you are looking for a way to find the latest pod, try:
kubectl get pod --selector='app=my-app-name' \
--sort-by='.metadata.creationTimestamp' \
-o=jsonpath='{.items[-1].metadata.name}'

Bash grep IP from command output

I'm working with fleetctl and kubectl and would like to extract an IP from kubectl get pod app-etcd:
POD IP CONTAINER(S) IMAGE(S) HOST LABELS STATUS CREATED MESSAGE
app-etcd 10.10.0.1 k8s-socius-node-1/100.100.100.100 name=app-etcd Running 3 days
app-etcd xyz/etcd-discovery Running 3 days
The closest I got to get the IP address is:
kubectl get pod app-etcd | grep -Eo '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
But this gives me both IP addresses (10.10.0.1 and 100.100.100.100); I only want/need the first one to run sed over a config file afterwards.
How do I get only the first address to store it in a variable for further processing?
What if you use awk to get the second column output like
kubectl get pod app-etcd | awk '{print $2}'
kubectl offers json output with --output / -o:
kubectl get -o json pod app-etcd | jsawk 'return this.status.podIP'

Resources