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
Name | Required | Description |
---|---|---|
KUBE_CONFIG_DATA | yes | A base64 encoded Kubeconfig file. |
K8S_EXEC_COMMAND | no | The command that will be used to execute the script from stdin. |
K8S_EXEC_RESOURCE | no | The name of the kubernetes resource: POD or TYPE/NAME. Must be used only when K8S_EXEC_COMMAND is set. |
K8S_EXEC_CONTAINER | no | The name of the container, it will follow the kubectl exec default behavior if this option isn't set. |
NAMESPACE | no | The 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.
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>