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"]
)