In this post we will present a short example of executing a command on a kubernetes pod using the kubernetes client-go library. The client-go library is great for usage, but specifically for the exec command, it is not strait-forward, so I believe an example is a good start for anyone who wishes to use the exec command.
To use the client-go library, wee first need to create a client. This is explained in more details in the post Access Kubernetes API from GoLang.
type K8s struct {
client *kubernetes.Clientset restConfig *rest.Config }
func Produce(insideK8sCluster bool) *K8s {
var err error var restConfig *rest.Config if insideK8sCluster {
restConfig, err = rest.InClusterConfig()
if err != nil {
panic(err)
}
} else {
configPath := filepath.Join(os.Getenv("HOME"), ".kube", "config")
restConfig, err = clientcmd.BuildConfigFromFlags("", configPath)
if err != nil {
panic(err)
}
}
client, err := kubernetes.NewForConfig(restConfig)
if err != nil {
panic(err)
}
return &K8s{
client: client,
restConfig: restConfig,
}
}
Once we have the client ready, we can use it to execute the command.
Notice that the command execution is actually implemented as a streaming HTTP request.
func (k *K8s) Exec(namespace string, pod string, container string, command []string) string {
attachOptions := &k8sApiCore.PodExecOptions{
Stdin: false,
Stdout: true,
Stderr: true,
TTY: false,
Container: container,
Command: command,
}
request := k.client.CoreV1().RESTClient().Post().
Resource("pods").
Name(pod).
Namespace(namespace).
SubResource("exec").
VersionedParams(attachOptions, scheme.ParameterCodec)
stdout := new(bytes.Buffer)
stderr := new(bytes.Buffer)
streamOptions := remotecommand.StreamOptions{
Stdout: stdout,
Stderr: stderr,
}
exec, err := remotecommand.NewSPDYExecutor(k.restConfig, "POST", request.URL())
if err != nil {
panic(err)
}
err = exec.Stream(streamOptions)
if err != nil {
result := strings.TrimSpace(stdout.String()) + "\n" + strings.TrimSpace(stderr.String())
result = strings.TrimSpace(result)
panic(err)
}
result := strings.TrimSpace(stdout.String()) + "\n" + strings.TrimSpace(stderr.String())
result = strings.TrimSpace(result)
return result}
Final Notes
It is not clear why did the kubernetes go-client group did not create a simplified version of the exec, as it is commonly used, but anyways, you can get your need here.
BTW:
Make sure to have the same dependency version for the k8s API and the k8s client-go in your go.mod file. Otherwise, you will get compilation and/or runtime errors.
module k8s
go 1.14
require (
k8s.io/api v0.18.6 k8s.io/client-go v0.18.6 )