Search code examples
kubernetescontainers

Running a command on all kubernetes pods of a service


Hey I'm running a kubernetes cluster and I want to run a command on all pods that belong to a specific service.

As far as I know kubectl exec can only run on a pod and tracking all my pods is a ridiculous amount of work (which is one of the benefits of services).

Is there any way or tool that gives you the ability to "broadcast" to all pods in a service?

Thanks in advance for your help!


Solution

  • As Bal Chua wrote, kubectl has no way to do this, but you can use bash script to do this:

     #!/usr/bin/env bash
    
    PROGNAME=$(basename $0)
    
    function usage {
        echo "usage: $PROGNAME [-n NAMESPACE] [-m MAX-PODS] -s SERVICE -- COMMAND"
        echo "  -s SERVICE   K8s service, i.e. a pod selector (required)"
        echo "     COMMAND   Command to execute on the pods"
        echo "  -n NAMESPACE K8s namespace (optional)"
        echo "  -m MAX-PODS  Max number of pods to run on (optional; default=all)"
        echo "  -q           Quiet mode"
        echo "  -d           Dry run (don't actually exec)"
    }
    
    function header {
        if [ -z $QUIET ]; then
            >&2 echo "###"
            >&2 echo "### $PROGNAME $*"
            >&2 echo "###"
        fi
    }
    
    while getopts :n:s:m:qd opt; do
        case $opt in
            d)
                DRYRUN=true
                ;;
            q)
                QUIET=true
                ;;
            m)
                MAX_PODS=$OPTARG
                ;;
            n)
                NAMESPACE="-n $OPTARG"
                ;;
            s)
                SERVICE=$OPTARG
                ;;
            \?)
                usage
                exit 0
                ;;
        esac
    done
    
    if [ -z $SERVICE ]; then
        usage
        exit 1
    fi
    
    shift $(expr $OPTIND - 1)
    
    while test "$#" -gt 0; do
        if [ "$REST" == "" ]; then
            REST="$1"
        else
            REST="$REST $1"
        fi
    
        shift
    done
    
    if [ "$REST" == "" ]; then
        usage
        exit 1
    fi
    
    PODS=()
    
    for pod in $(kubectl $NAMESPACE get pods --output=jsonpath={.items..metadata.name}); do
        echo $pod | grep -qe "^$SERVICE" >/dev/null 2>&1
        if [ $? -eq 0 ]; then
            PODS+=($pod)
        fi
    done
    
    if [ ${#PODS[@]} -eq 0 ]; then
        echo "service not found in ${NAMESPACE:-default}: $SERVICE"
        exit 1
    fi
    
    if [ ! -z $MAX_PODS ]; then
        PODS=("${PODS[@]:0:$MAX_PODS}")
    fi
    
    header "{pods: ${#PODS[@]}, command: \"$REST\"}"
    
    for i in "${!PODS[@]}"; do
        pod=${PODS[$i]}
        header "{pod: \"$(($i + 1))/${#PODS[@]}\", name: \"$pod\"}"
    
        if [ "$DRYRUN" != "true" ]; then
            kubectl $NAMESPACE exec $pod -- $REST
        fi
    done