Implementing Kubernetes pod exec in ruby
March 13, 2025
Recently I submitted a PR which just got merged, for k8s-ruby, a ruby client for the Kubernetes API, to implement the Pod#Create Connect Exec endpoint, which allows to execute arbitrary commands inside a pod container, including opening a shell session.
Eventually It wasn’t that hard to make it work but there were some interesting learnings along the way:
For example, it took me a while to figure out why I wasn’t receiving any response after sending commands through the WebSocket connections and even had to take a look at the kubectl
source code to learn why. It turns out that messages required to prepend a specific byte value as the stream identifier to make it work.
Testing was also a bit tricky as had to to handle the stdin and the EventMachine keyboard input.
Eventually, I had to tweak the terminal settings with termios
to make tty work as expected (thanks StackOverflow)
Using it would be a easy as calling the new K8s::ResourceClient#exec
with something like this:
require 'k8s-ruby'
client = K8s::Client.config(K8s::Config.load_file('~/.kube/config'))
test_pod = K8s::Resource.new(
apiVersion: 'v1',
kind: 'Pod',
metadata: {
name: 'test-pod',
namespace: 'default'
},
spec: {
containers: [
{
name: 'shell',
image: 'busybox',
command: [ 'sleep', 'infinity' ]
}
]
}
)
begin
client.get_resource(test_pod)
rescue K8s::Error::NotFound
client.create_resource(test_pod)
end
client.api('v1').resource('pods', namespace: 'default').exec(
name: "test-pod",
container: "shell",
command: ["ls", "-la"]
)