Kyr*_*roy 2 go kubernetes client-go
我想使用https://github.com/kubernetes/client-go将文件从我的文件系统复制到容器,反之亦然。
kubectl cp <file-spec-src> <file-spec-dest> -c <specific-container>
Run Code Online (Sandbox Code Playgroud)
go 客户端中是否有封装调用的函数?或者我可以使用类似RESTClient的东西吗?
小智 9
有代码使用client-go实现将文件复制到容器,也可以从容器复制文件。
\nhttps://github.com/ica10888/client-go-helper/blob/master/pkg/kubectl/cp.go
\n\xe2\x94\x9c\xe2\x94\x80kubectl\n \xe2\x94\x82 client.go\n \xe2\x94\x82 cp.go\n \xe2\x94\x94\xe2\x94\x80 stub.s\n\nRun Code Online (Sandbox Code Playgroud)\n客户
\npackage kubectl \n\nimport (\n corev1client "k8s.io/client-go/kubernetes/typed/core/v1"\n "k8s.io/client-go/rest"\n "k8s.io/client-go/tools/clientcmd"\n)\n\n\nfunc InitRestClient() (*rest.Config, error, *corev1client.CoreV1Client) {\n // Instantiate loader for kubeconfig file.\n kubeconfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(\n clientcmd.NewDefaultClientConfigLoadingRules(),\n &clientcmd.ConfigOverrides{},\n )\n // Get a rest.Config from the kubeconfig file. This will be passed into all\n // the client objects we create.\n restconfig, err := kubeconfig.ClientConfig()\n if err != nil {\n panic(err)\n }\n // Create a Kubernetes core/v1 client.\n coreclient, err := corev1client.NewForConfig(restconfig)\n if err != nil {\n panic(err)\n }\n return restconfig, err, coreclient\n}\nRun Code Online (Sandbox Code Playgroud)\ncopyToPod 和 copyFromPod
\npackage kubectl\n\nimport (\n "archive/tar"\n "fmt"\n "io"\n corev1 "k8s.io/api/core/v1"\n "k8s.io/client-go/kubernetes/scheme"\n "k8s.io/client-go/tools/remotecommand"\n _ "k8s.io/kubectl/pkg/cmd/cp"\n cmdutil "k8s.io/kubectl/pkg/cmd/util"\n "log"\n "os"\n "path"\n "path/filepath"\n "strings"\n _ "unsafe"\n)\n\nfunc (i *pod) copyToPod(srcPath string, destPath string) error {\n restconfig, err, coreclient := InitRestClient()\n\n reader, writer := io.Pipe()\n if destPath != "/" && strings.HasSuffix(string(destPath[len(destPath)-1]), "/") {\n destPath = destPath[:len(destPath)-1]\n }\n if err := checkDestinationIsDir(i, destPath); err == nil {\n destPath = destPath + "/" + path.Base(srcPath)\n }\n go func() {\n defer writer.Close()\n err := cpMakeTar(srcPath, destPath, writer)\n cmdutil.CheckErr(err)\n }()\n var cmdArr []string\n\n cmdArr = []string{"tar", "-xf", "-"}\n destDir := path.Dir(destPath)\n if len(destDir) > 0 {\n cmdArr = append(cmdArr, "-C", destDir)\n }\n //remote shell.\n req := coreclient.RESTClient().\n Post().\n Namespace(i.Namespace).\n Resource("pods").\n Name(i.Name).\n SubResource("exec").\n VersionedParams(&corev1.PodExecOptions{\n Container: i.ContainerName,\n Command: cmdArr,\n Stdin: true,\n Stdout: true,\n Stderr: true,\n TTY: false,\n }, scheme.ParameterCodec)\n\n exec, err := remotecommand.NewSPDYExecutor(restconfig, "POST", req.URL())\n if err != nil {\n log.Fatalf("error %s\\n", err)\n return err\n }\n err = exec.Stream(remotecommand.StreamOptions{\n Stdin: reader,\n Stdout: os.Stdout,\n Stderr: os.Stderr,\n Tty: false,\n })\n if err != nil {\n log.Fatalf("error %s\\n", err)\n return err\n }\n return nil\n}\n\nfunc checkDestinationIsDir(i *pod, destPath string) error {\n return i.Exec([]string{"test", "-d", destPath})\n}\n\n//go:linkname cpMakeTar k8s.io/kubectl/pkg/cmd/cp.makeTar\nfunc cpMakeTar(srcPath, destPath string, writer io.Writer) error\n\nfunc (i *pod) copyFromPod(srcPath string, destPath string) error {\n restconfig, err, coreclient := InitRestClient()\n reader, outStream := io.Pipe()\n //todo some containers failed : tar: Refusing to write archive contents to terminal (missing -f option?) when execute `tar cf -` in container\n cmdArr := []string{"tar", "cf", "-", srcPath}\n req := coreclient.RESTClient().\n Get().\n Namespace(i.Namespace).\n Resource("pods").\n Name(i.Name).\n SubResource("exec").\n VersionedParams(&corev1.PodExecOptions{\n Container: i.ContainerName,\n Command: cmdArr,\n Stdin: true,\n Stdout: true,\n Stderr: true,\n TTY: false,\n }, scheme.ParameterCodec)\n\n exec, err := remotecommand.NewSPDYExecutor(restconfig, "POST", req.URL())\n if err != nil {\n log.Fatalf("error %s\\n", err)\n return err\n }\n go func() {\n defer outStream.Close()\n err = exec.Stream(remotecommand.StreamOptions{\n Stdin: os.Stdin,\n Stdout: outStream,\n Stderr: os.Stderr,\n Tty: false,\n })\n cmdutil.CheckErr(err)\n }()\n prefix := getPrefix(srcPath)\n prefix = path.Clean(prefix)\n prefix = cpStripPathShortcuts(prefix)\n destPath = path.Join(destPath, path.Base(prefix))\n err = untarAll(reader, destPath, prefix)\n return err\n}\n\nfunc untarAll(reader io.Reader, destDir, prefix string) error {\n tarReader := tar.NewReader(reader)\n for {\n header, err := tarReader.Next()\n if err != nil {\n if err != io.EOF {\n return err\n }\n break\n }\n\n if !strings.HasPrefix(header.Name, prefix) {\n return fmt.Errorf("tar contents corrupted")\n }\n\n mode := header.FileInfo().Mode()\n destFileName := filepath.Join(destDir, header.Name[len(prefix):])\n\n baseName := filepath.Dir(destFileName)\n if err := os.MkdirAll(baseName, 0755); err != nil {\n return err\n }\n if header.FileInfo().IsDir() {\n if err := os.MkdirAll(destFileName, 0755); err != nil {\n return err\n }\n continue\n }\n\n evaledPath, err := filepath.EvalSymlinks(baseName)\n if err != nil {\n return err\n }\n\n if mode&os.ModeSymlink != 0 {\n linkname := header.Linkname\n\n if !filepath.IsAbs(linkname) {\n _ = filepath.Join(evaledPath, linkname)\n }\n\n if err := os.Symlink(linkname, destFileName); err != nil {\n return err\n }\n } else {\n outFile, err := os.Create(destFileName)\n if err != nil {\n return err\n }\n defer outFile.Close()\n if _, err := io.Copy(outFile, tarReader); err != nil {\n return err\n }\n if err := outFile.Close(); err != nil {\n return err\n }\n }\n }\n\n return nil\n}\n\nfunc getPrefix(file string) string {\n return strings.TrimLeft(file, "/")\n}\n\n//go:linkname cpStripPathShortcuts k8s.io/kubectl/pkg/cmd/cp.stripPathShortcuts \nfunc cpStripPathShortcuts(p string) string\n\n\nRun Code Online (Sandbox Code Playgroud)\n触摸存根
\n\nRun Code Online (Sandbox Code Playgroud)\n
由于这个问题的答案已经很老了,所以我是这样做的:
package main
import (
"bytes"
"fmt"
"io"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"k8s.io/kubectl/pkg/cmd/cp"
"k8s.io/kubectl/pkg/cmd/exec"
"log"
"os"
)
type PodExec struct {
RestConfig *rest.Config
*kubernetes.Clientset
}
func NewPodExec(config rest.Config, clientset *kubernetes.Clientset) *PodExec {
config.APIPath = "/api" // Make sure we target /api and not just /
config.GroupVersion = &schema.GroupVersion{Version: "v1"} // this targets the core api groups so the url path will be /api/v1
config.NegotiatedSerializer = serializer.WithoutConversionCodecFactory{CodecFactory: scheme.Codecs}
return &PodExec{
RestConfig: &config,
Clientset: clientset,
}
}
func (p *PodExec) PodCopyFile(src string, dst string, containername string) (*bytes.Buffer, *bytes.Buffer, *bytes.Buffer, error) {
ioStreams, in, out, errOut := genericclioptions.NewTestIOStreams()
copyOptions := cp.NewCopyOptions(ioStreams)
copyOptions.Clientset = p.Clientset
copyOptions.ClientConfig = p.RestConfig
copyOptions.Container = containername
err := copyOptions.Run([]string{src, dst})
if err != nil {
return nil, nil, nil, fmt.Errorf("Could not run copy operation: %v", err)
}
return in, out, errOut, nil
}
Run Code Online (Sandbox Code Playgroud)
然后您可以像 kubectl cp 一样使用 PodCopyFile
podExec := podexec.NewPodExec(*restconfig, clientset) // Here, you need to get your restconfig and clientset from either ~/.kube/config or built-in pod config.
_, out, _, err := podExec.PodCopyFile("/srcfile", "/dstfile", "containername")
if err != nil {
fmt.Printf("%v\n", err)
}
fmt.Println("out:")
fmt.Printf("%s", out.String())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7350 次 |
| 最近记录: |