Skip to main content

Kubernetes Exec

Execute commands inside a container in a Kubernetes Cluster, this type is useful when there's a necessity to change the state of a running system. It's possible to pass any kind of command to a container through Runops. The command can be run in two modes:

  • Script Mode

    This is the default mode - the script mode allows controlling which resource to target when running a script inside a container, it's useful when you need more flexibility to execute commands over several resources (deployments, statefulsets or pods) It must have the format: deploy/{deployment_name} {shell_command}, where shell_command will be executed inside one of the pods of deployment_name.

  • Stdin Mode

    The input of the script is passed directly to the container, this mode is useful when running full fledged scripts

Type: k8s-exec

Configuration#

NameRequiredDescription
KUBE_CONFIG_DATAyesA base64 encoded Kubeconfig file.
K8S_EXEC_COMMANDnoThe command that will be used to execute the script from stdin.
K8S_EXEC_RESOURCEnoThe name of the kubernetes resource: POD or TYPE/NAME. Must be used only when K8S_EXEC_COMMAND is set.
K8S_EXEC_CONTAINERnoThe name of the container, it will follow the kubectl exec default behavior if this option isn't set.
NAMESPACEnoThe name of the namespace, it will default to the namespace set in the KUBE_CONFIG_DATA.

Examples#

Script Mode#

runops tasks create --target k8s-exec-type --script 'deploy/rails-app rails runner "puts User.first.to_json"'
# execute find inside the container
runops tasks create --target k8s-exec-type --script 'deploy/rails-app find /tmp/ -type f -exec echo '{}' \;'

It's important to notest that using sub shell calls are not allowed, hence the example below will not work

runops tasks create -t k8s-exec-type --script 'deploy/myapp ls -l && echo foo'

Some trick examples

# this will work, but not the way you expected, the subshell here is being evaluated in your current bash
# thus the command will output the files of your local /tmp/ directory
runops tasks create -t k8s-exec-type --script 'deploy/myapp echo "$(ls -l /tmp/)"'

In order to use subshell, use a /bin/bash -c call

runops tasks create --target k8s-exec-type --script 'deploy/myapp /bin/bash -c "ls -l && echo FOO"'

Let's say you want to execute a command to dinamically call a python script, using kubectl this would be

kubectl exec deploy/myapp -- /bin/bash -c "python3 -c 'import os;print(os.environ)'"

However, with Runops cli things works differently, because of how the current shell interpret commands, to make this example to work the double quotes need to be escaped

runops tasks create -t k8s-exec-type --script "deploy/myapp /bin/bash -c \"python3 -c 'import os;print(os.environ)'\""

The next example things become more cumbersome, because of multiple quotes to escape

# this example won't work because of your local shell
runops tasks create -t k8s-exec --script "deploy/myapp /bin/bash -c \"python3 -c 'print(\"foo\")'\""
# this command needs to be passed down to a script and then executed in order to work properly
cat - > /tmp/task.sh <<EOF
deploy/myapp /bin/bash -c "python3 -c 'print(\"foo\")'"
EOF
runops tasks create -t k8s-exec --file /tmp/tasks.sh

Stdin Mode#

This mode solves the limitations explained above.

Executing commands directly from stdin is powerful because it allows creating targets that interact directly with the semantics of any commands available in the container.

info

To configure such behavior the K8S_EXEC_COMMAND and K8S_EXEC_RESOURCE are required.

  • K8S_EXEC_COMMAND=rails runner -
# print all environment variables on ruby
runops tasks create -t k8s-exec-rails --script 'pp ENV'
  • K8S_EXEC_COMMAND=doppler run -- rails runner -
# if you use doppler, get the project env variable
runops tasks create -t k8s-exec-rails -s 'print ENV["DOPPLER_PROJECT"]'
  • K8S_EXEC_COMMAND=python -
runops tasks create -t k8s-exec-python -s 'print("Hello World from Python Container")'

The only requirement is that the command support reading content from the stdin, otherwise it will fail, in practice this option is analogous to:

echo 'print("Hello World")' | kubectl exec -n <namespace> -i <k8s-exec-resource> -- <k8s-exec-command>