Search code examples
shellkuberneteskubectl

Get logs from all pods in namespace using xargs


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?


Solution

  • 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