example of exec in k8s's pod by using go client

huangapple go评论82阅读模式
英文:

example of exec in k8s's pod by using go client

问题

我想使用k8s go客户端在一个Pod中执行命令。然而,我找不到任何关于这方面的示例。所以我阅读了kubectl exec的源代码,并编写了以下代码。然而,err = exec.Stream(sopt)总是返回一个没有任何消息的错误。有人可以告诉我如何调试这个问题,或者给我一个正确的示例吗?

config := &restclient.Config{
	Host:     "http://192.168.8.175:8080",
	Insecure: true,
}

config.ContentConfig.GroupVersion = &api.Unversioned
config.ContentConfig.NegotiatedSerializer = api.Codecs

restClient, err := restclient.RESTClientFor(config)
if err != nil {
	panic(err.Error())
}

req := restClient.Post().Resource("pods").Name("wordpress-mysql-213049546-29s7d").Namespace("default").SubResource("exec").Param("container", "mysql")
req.VersionedParams(&api.PodExecOptions{
	Container: "mysql",
	Command:   []string{"ls"},
	Stdin:     true,
	Stdout:    true,
}, api.ParameterCodec)

exec, err := remotecommand.NewExecutor(config, "POST", req.URL())
if err != nil {
	panic(err.Error())
}
sopt := remotecommand.StreamOptions{
	SupportedProtocols: remotecommandserver.SupportedStreamingProtocols,
	Stdin:              os.Stdin,
	Stdout:             os.Stdout,
	Stderr:             os.Stderr,
	Tty:                false,
}

err = exec.Stream(sopt)
if err != nil {
	panic(err.Error())
}
英文:

I want to use k8s go client to exec command in a pod. However I cannot find any example about this. So I read kubectl exec source code, and write code as below. And err = exec.Stream(sopt) always get an error without any message. Can anyone tell me how to debug this problem, or give me a correct example.

config := &restclient.Config{
	Host:     "http://192.168.8.175:8080",
	Insecure: true,
}

config.ContentConfig.GroupVersion = &api.Unversioned
config.ContentConfig.NegotiatedSerializer = api.Codecs

restClient, err := restclient.RESTClientFor(config)
if err != nil {
	panic(err.Error())
}

req := restClient.Post().Resource("pods").Name("wordpress-mysql-213049546-29s7d").Namespace("default").SubResource("exec").Param("container", "mysql")
req.VersionedParams(&api.PodExecOptions{
	Container: "mysql",
	Command:   []string{"ls"},
	Stdin:     true,
	Stdout:    true,
}, api.ParameterCodec)

exec, err := remotecommand.NewExecutor(config, "POST", req.URL())
if err != nil {
	panic(err.Error())
}
sopt := remotecommand.StreamOptions{
	SupportedProtocols: remotecommandserver.SupportedStreamingProtocols,
	Stdin:              os.Stdin,
	Stdout:             os.Stdout,
	Stderr:             os.Stderr,
	Tty:                false,
}

err = exec.Stream(sopt)
if err != nil {
	panic(err.Error())
}

答案1

得分: 14

package k8s

import (
"io"

v1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/remotecommand"

)

// ExecCmd exec command on specific pod and wait the command's output.
func ExecCmdExample(client kubernetes.Interface, config *restclient.Config, podName string,
command string, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
cmd := []string{
"sh",
"-c",
command,
}
req := client.CoreV1().RESTClient().Post().Resource("pods").Name(podName).
Namespace("default").SubResource("exec")
option := &v1.PodExecOptions{
Command: cmd,
Stdin: true,
Stdout: true,
Stderr: true,
TTY: true,
}
if stdin == nil {
option.Stdin = false
}
req.VersionedParams(
option,
scheme.ParameterCodec,
)
exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL())
if err != nil {
return err
}
err = exec.Stream(remotecommand.StreamOptions{
Stdin: stdin,
Stdout: stdout,
Stderr: stderr,
})
if err != nil {
return err
}

return nil

}

对我来说很有效。

英文:
package k8s
import (
"io"
v1 "k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/tools/remotecommand"
)
// ExecCmd exec command on specific pod and wait the command's output.
func ExecCmdExample(client kubernetes.Interface, config *restclient.Config, podName string,
command string, stdin io.Reader, stdout io.Writer, stderr io.Writer) error {
cmd := []string{
"sh",
"-c",
command,
}
req := client.CoreV1().RESTClient().Post().Resource("pods").Name(podName).
Namespace("default").SubResource("exec")
option := &v1.PodExecOptions{
Command: cmd,
Stdin:   true,
Stdout:  true,
Stderr:  true,
TTY:     true,
}
if stdin == nil {
option.Stdin = false
}
req.VersionedParams(
option,
scheme.ParameterCodec,
)
exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL())
if err != nil {
return err
}
err = exec.Stream(remotecommand.StreamOptions{
Stdin:  stdin,
Stdout: stdout,
Stderr: stderr,
})
if err != nil {
return err
}
return nil
}

It works to me.

答案2

得分: 2

命令: []string{"/bin/sh", "-c", "ls", "-ll", "."}

字符串数组应以/bin/sh(shell可执行文件的路径)开头。

然后,可以将-c标志添加为第二个元素,以指示后续字符串将被解释为要由shell执行的命令。

最后,可以将任何命令的附加参数作为数组中的后续元素添加。

英文:
Command: []string{"/bin/sh", "-c", "ls", "-ll", "."}

The array of strings should start with /bin/sh (the path to the shell executable).

Then -c flag can be added as the second element to indicate that the subsequent string will be interpreted as a command to be executed by the shell.

Finally, any additional arguments for the command can be added as subsequent elements in the array.

答案3

得分: 1

在创建请求时,你错过了.CoreV1()

英文:

you miss .CoreV1() when create request!

huangapple
  • 本文由 发表于 2017年4月10日 11:48:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/43314689.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定