Executing multiple commands( or from a shell script) in a kubernetes pod - kubernetes

I'm writing a shell script which needs to login into the pod and execute a series of commands in a kubernetes pod.
Below is my sample_script.sh:
kubectl exec octavia-api-worker-pod-test -c octavia-api bash
unset http_proxy https_proxy
mv /usr/local/etc/octavia/octavia.conf /usr/local/etc/octavia/octavia.conf-orig
/usr/local/bin/octavia-db-manage --config-file /usr/local/etc/octavia/octavia.conf upgrade head
After running this script, I'm not getting any output.
Any help will be greatly appreciated

Are you running all these commands as a single line command? First of all, there's no ; or && between those commands. So if you paste it as a multi-line script to your terminal, likely it will get executed locally.
Second, to tell bash to execute something, you need: bash -c "command".
Try running this:
$ kubectl exec POD_NAME -- bash -c "date && echo 1"
Wed Apr 19 19:29:25 UTC 2017
1
You can make it multiline like this:
$ kubectl exec POD_NAME -- bash -c "date && \
echo 1 && \
echo 2"

The following should work
kubectl -it exec podname -- bash -c "ls && ls"
bin dev etc home proc root run sys tmp usr var bin
dev etc home proc root run sys tmp usr var
If above command doesn't work then try too replace bash with one of the following /bin/bash, sh or /bin/sh

-t
can solve your task
For example, I run here few cmd:
kubectl get pods |grep nginx|cut -f1 -d\ |\
while read pod; \
do echo "$pod writing:";\
kubectl exec -t $pod -- bash -c \
"dd if=/dev/zero of=/feeds/test.bin bs=260K count=4 2>&1|\
grep copi |cut -d, -f4; \
a=$SECONDS; echo -ne 'reading:'; cat /feeds/test.bin >/dev/null ; \
let a=SECONDS-a ; \
echo $a sec"
done
p.s. your example will be:
kubectl exec -t octavia-api-worker-pod-test -c octavia-api -- bash -c "unset http_proxy https_proxy ; mv /usr/local/etc/octavia/octavia.conf /usr/local/etc/octavia/octavia.conf-orig ; /usr/local/bin/octavia-db-manage --config-file /usr/local/etc/octavia/octavia.conf ; upgrade ; head"

Posting here because google search still brings you to this post...
I'd like to throw out using a HEREDOC as an additional possibility.
kubectl exec -i --tty-false PODNAME -- bash << EOF
echo "insert all your commands here."
echo "this subprocess will even pickup any variables you have in"
echo "the shell script that is calling this"
EOF

Related

K8S How to add quotes when on parameters provided for `kubectl exec -c`

I am using K8S
I want to calculate a string that that is a result of kubectl exec -it ... -c
after the -c option there is a string.
How can I pass a string with double quotes inside.
The following example doesn't work properly.
x="$(kubectl exec -it mysql-pod -- /bin/sh -c \"mysql -uroot -p12345
-e 'show databases'\" 2>/dev/null)"
echo $x
Thanks.
when only a command needs to be executed on a pod , -it option is not required as it stands for attaching an interactive teminal
when mysql is itself an executable command , no need to use /bin/sh -c
no need to encapsulate whole command in " "
So try following
x=$(kubectl exec mysql-pod -- mysql -uroot -p12345 -e 'show databases ;' 2>/dev/null)
echo $x

lxc option "--" when calling lxc-start / lxc-create

What is the significance of -- in the command line of commands like lxc-create or lxc-start.
I tried to use Google in order to get an answer but without success.
// Example 1
lxc-create -t download -n u1 -- -d ubuntu -r DISTRO-SHORT-CODENAME -a amd64
// Example 1
application="/root/app.out"
start="/root/lxc-app/lxc-start"
$start -n LXC_app -d -f /etc/lxc/lxc-app/lxc-app.conf -- $application &
As explained in the references provided in the comments, the "--" indicates the end of the options passed to the command. The following parameters/options will be eventually used by a sub-command called by the command.
In your example:
lxc-create -t download -n u1 -- -d ubuntu -r DISTRO-SHORT-CODENAME -a amd64
lxc-create command will interpret "-t download -n u1" and the remaining "-d ubuntu -r DISTRO-SHORT-CODENAME -a amd64" will be passed to the template script which will configure/populate the container.
In this specific example, the "-t download" makes lxc-create run a template script named something like "/usr/share/lxc/templates/lxc-download" to which it will pass "-d ubuntu -r DISTRO-SHORT-CODENAME -a amd64".

kubectl exec: Permission denied

Try to append some new entries to /etc/hosts in pods, but failed:
$ ips=$(cat ips.txt); kubectl exec -u root myspark-master-5d6656bd84-5zf2h echo "$ips" >> /etc/hosts
-sh: /etc/hosts: Permission denied
How to fix this?
Thanks
UPDATE
$ ips=$(cat ips.txt); kubectl exec myspark-worker-5976b685b4-8bcbl -- sh -c "echo $ips >> /etc/hosts"
sh: 2: 10.233.88.5: not found
sh: 3: 10.233.96.2: not found
sh: 4: 10.233.86.5: not found
10.233.88.4 myspark-master-5d6656bd84-dxhxc
command terminated with exit code 127
I think you mean to write to the file inside the container, but bash is parsing that on your workstation and try to apply the redirect locally. Use kubectl exec ... -- sh -c “...” instead.
There is indeed a parsing problem because $ips contain new lines.
Try with
$ ips=$(cat ips.txt); kubectl exec myspark-worker-5976b685b4-8bcbl -- sh -c "echo \"$ips\" >> /etc/hosts"

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!
Here's a simple example with kubectl pipe to xargs, printing env of each pod:
k get pod \
-l {your label selectors} \
--field-selector=status.phase=Running \
-o custom-columns=name:metadata.name --no-headers \
| xargs -I{} kubectl exec {} env
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
Here:
kubectl -n alex get pods -l app=alex-admin-api -o name | xargs -I{} kubectl -n alex exec {} -- cat alexAdminApi.log >> alex-admin-api_pods.logs
I have written a simple kubectl plugin that "boardcast"s commands to all pods, using Tmux. Assuming that all your pods in the service should share the same labels in their spec, app=foobar for instance, you can use the command below,
kubectl tmux-exec -l app=foobar bash
The plugin is available on Github: predatorray/kubectl-tmux-exec. Hope it will help you!
there is also a kubectl plugin called kubectl-exec-all https://github.com/jpdasma/kubectl-exec-all that is doing a good job.
Can't work with krew index but you can save the content of https://raw.githubusercontent.com/jpdasma/kubectl-exec-all/master/unix/exec-all.sh to /usr/local/bin/kubectl-exec_all and don't forget to make it executable by running
chmod +x /usr/local/bin/kubectl-exec_all
then it work like this:
kubectl plugin exec-all daemonset docker-daemon -- docker system prune -a -f

Kubectl exec command to write contents to a file in the pod

I am trying below command
kubectl exec -it sss-pod-four echo "hi" >> /mnt/sss/testnew.txt
But it throws error
-bash: /mnt/sss/testnew.txt: No such file or directory
What is the best way to achieve this
Found a similar question here and below command works now
kubectl exec -it sss-pod-four -- bash -c "echo hi > /mnt/sss/testnew.txt"