Execute command on Kubernetes POD(multiple containers) using Python client library
Table of contents
Take note of this problem that takes two hours to Google the web.
Environment setup
I run on Ubuntu 22.04, so I assume you also run on Linux.
# install Kubernetes Python client library
pip3 install kubernetes
Check Github for how to execute commands in POD.
Main program
First, we load the default configuration and create CoreV1Api which will be used to invoke API.
#!/usr/bin/python3
from kubernetes import config
from kubernetes.client import Configuration
from kubernetes.client.api import core_v1_api
from kubernetes.client.rest import ApiException
from kubernetes.stream import stream
def main():
# I put my K8s config under /home/cylee/.kube/config
config.load_kube_config("/home/cylee/.kube/config")
try:
c = Configuration().get_default_copy()
except AttributeError:
c = Configuration()
c.assert_hostname = False
Configuration.set_default(c)
core_v1 = core_v1_api.CoreV1Api()
Helper function
Second, let's write execute command part. We use 'stream' and 'connect_get_namespaced_pod_exec' to execute commands.
def exec_commands(api_instance, pod_name, namespace_name):
exec_command = [
'/bin/sh',
'-c',
'echo This to stderr; echo This goes to stdout']
resp = stream(api_instance.connect_get_namespaced_pod_exec,
pod_name,
namespace_name,
command=exec_command,
stderr=True, stdin=False,
stdout=True, tty=False)
while resp.is_open():
resp.update(timeout=1)
if resp.peek_stdout():
print("STDOUT: {}".format(resp.read_stdout()))
if resp.peek_stderr():
print("STDERR: {}".format(resp.read_stderr()))
Put invoke statement in the 'main' section.
exec_commands(core_v1, 'my_pod_name', 'default')
Save it and run your program. You will find error messages like others encounter before.
Handshake status 400 Bad Request
How to fix it
Remember our POD contains multiple containers?
The correct fix way is by adding the extra 'container' parameter to explicitly specify the container name in the stream function call.
resp = stream(api_instance.connect_get_namespaced_pod_exec,
pod_name,
namespace_name,
command=exec_command,
stderr=True, stdin=False,
stdout=True, tty=False,
container="target_container_name",
_preload_content=True)
That's all I have and thanks ctheisingfl for sharing the solution.