How to invoke the Pod proxy verb using the Kubernetes Go client?

5/22/2019

The Kubernetes remote API allows HTTP access to arbitrary pod ports using the proxy verb, that is, using an API path of /api/v1/namespaces/{namespace}/pods/{name}/proxy.

The Python client offers corev1.connect_get_namespaced_pod_proxy_with_path() to invoke the above proxy verb.

Despite reading, browsing, and searching the Kubernetes client-go for some time, I'm still lost how to do the same with the goclient what I'm able to do with the python client. My other impression is that I may need to dive down into the rest client of the client changeset, if there's no ready-made API corev1 call available?

How do I correctly construct the GET call using the rest client and the path mentioned above?

-- TheDiveO
kubernetes
kubernetes-go-client
proxy

1 Answer

9/12/2019

As it turned out after an involved dive into the Kubernetes client sources, accessing the proxy verb is only possible when going down to the level of the RESTClient and then building the GET/... request by hand. The following code shows this in form of a fully working example:

package main

import (
    "fmt"

    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

func main() {
    clcfg, err := clientcmd.NewDefaultClientConfigLoadingRules().Load()
    if err != nil {
        panic(err.Error())
    }
    restcfg, err := clientcmd.NewNonInteractiveClientConfig(
        *clcfg, "", &clientcmd.ConfigOverrides{}, nil).ClientConfig()
    if err != nil {
        panic(err.Error())
    }
    clientset, err := kubernetes.NewForConfig(restcfg)
    res := clientset.CoreV1().RESTClient().Get().
        Namespace("default").
        Resource("pods").
        Name("hello-world:8000").
        SubResource("proxy").
        // The server URL path, without leading "/" goes here...
        Suffix("index.html").
        Do()
    if err != nil {
        panic(err.Error())
    }
    rawbody, err := res.Raw()
    if err != nil {
        panic(err.Error())
    }
    fmt.Print(string(rawbody))
}

You can test this, for instance, on a local kind cluster (Kubernetes in Docker). The following commands spin up a kind cluster, prime the only node with the required hello-world webserver, and then tell Kubernetes to start the pod with said hello-world webserver.

kind create cluster
docker pull crccheck/hello-world
docker tag crccheck/hello-world crccheck/hello-world:current
kind load docker-image crccheck/hello-world:current
kubectl run hello-world --image=crccheck/hello-world:current --port=8000 --restart=Never --image-pull-policy=Never

Now run the example:

export KUBECONFIG=~/.kube/kind-config-kind; go run .

It then should show this ASCII art:

<xmp>
Hello World


                                       ##         .
                                 ## ## ##        ==
                              ## ## ## ## ##    ===
                           /""""""""""""""""\___/ ===
                      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~ ~ /  ===- ~~~
                           \______ o          _,/
                            \      \       _,'
                             `'--.._\..--''
</xmp>
-- TheDiveO
Source: StackOverflow