Maison > développement back-end > Golang > le corps du texte

Comment copier des fichiers locaux vers le conteneur pod dans le cluster minikube à l'aide du client Go ?

PHPz
Libérer: 2024-02-06 08:06:14
avant
1058 Les gens l'ont consulté

如何使用 Go 客户端将本地文件复制到 minikube 集群中的 pod 容器?

Contenu de la question

Ma requête est presque la même que le titre, j'ai un fichier local file.txt ,我想将其复制到 pod1 的容器 container1 dedans.

Si j'utilise kubectl pour ce faire, la commande appropriée est :

kubectl cp file.txt pod1:file.txt -c container1

Mais comment y parvenir en utilisant le client go de kubectl ?

J'ai essayé deux méthodes mais aucune n'a fonctionné :

import (
    "fmt"
    "context"
    "log"
    "os"
    "path/filepath"

    g "github.com/sdslabs/katana/configs"
    v1 "k8s.io/api/core/v1"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/apimachinery/pkg/labels"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/rest"
    "k8s.io/client-go/tools/clientcmd"
    //"k8s.io/kubectl/pkg/cmd/exec"
)

func copyintopod(namespace string, podname string, containername string, srcpath string, dstpath string) {
    // create a kubernetes client
    config, err := getkubeconfig()
    if err != nil {
        log.fatal(err)
    }

    client, err := kubernetes.newforconfig(config)
    if err != nil {
        log.fatal(err)
    }

    // build the command to execute
    cmd := []string{"cp", srcpath, dstpath}

    // use the podexecoptions struct to specify the options for the exec request
    options := v1.podexecoptions{
        container: containername,
        command:   cmd,
        stdin:     false,
        stdout:    true,
        stderr:    true,
        tty:       false,
    }
    log.println("options set!")

    // use the corev1api.exec method to execute the command inside the container
    req := client.corev1().restclient().post().
        namespace(namespace).
        name(podname).
        resource("pods").
        subresource("exec").
        versionedparams(&options, metav1.parametercodec)
    log.println("request generated")
    
    exec, err := req.stream(context.todo())
    if err != nil {
        log.fatal(err)
    }
    defer exec.close()

    // read the response from the exec command
    var result []byte
    if _, err := exec.read(result); err != nil {
        log.fatal(err)
    }

    fmt.println("file copied successfully!")
}
Copier après la connexion

Cela m'a donné le message d'erreur : 

no 类型已在方案“pkg/runtime/scheme.go:100” Inscrit pour le type v1.podexecoptions

Je n'arrivais pas à comprendre, alors j'ai essayé une autre méthode :

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, podNamespace 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
    copyOptions.Namespace = podNamespace
    err := copyOptions.Run()
    if err != nil {
        return nil, nil, nil, fmt.Errorf("could not run copy operation: %v", err)
    }
    return in, out, errOut, nil
}
Copier après la connexion

Cependant, copyoptions.run()命令存在一些问题,它尝试在copyoptions内查找o.args[0]和o.args[0],但on'est pas importé et ne peut donc pas être importé pour modification.

Contexte : https://pkg.go.dev/k8s.io/kubectl/pkg/cmd/cp#copyoptions.run

Donc, maintenant je suis vraiment perdu et confus. Toute aide serait grandement appréciée. Merci.

EDIT : J'ai pensé à une méthode de travail où nous pourrions simplement appeler la commande cmd.exec() 并直接运行 kubectl cp directement, mais cela semble un peu galvaudé et je ne suis pas sûr que cela fonctionnera, des idées ?


Bonne réponse


Voici comment j'ai finalement réussi à le faire :

package main

import (
    "context"
    "fmt"
    "os"
    "path/filepath"

    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/kubernetes/scheme"
    corev1 "k8s.io/api/core/v1"
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/util/homedir"
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/tools/remotecommand"
)

func CopyIntoPod(podName string, namespace string, containerName string, srcPath string, dstPath string) {
    // Get the default kubeconfig file
    kubeConfig := filepath.Join(homedir.HomeDir(), ".kube", "config")

    // Create a config object using the kubeconfig file
    config, err := clientcmd.BuildConfigFromFlags("", kubeConfig)
    if err != nil {
        fmt.Printf("Error creating config: %s\n", err)
        return
    }

    // Create a Kubernetes client
    client, err := kubernetes.NewForConfig(config)
    if err != nil {
        fmt.Printf("Error creating client: %s\n", err)
        return
    }

    // Open the file to copy
    localFile, err := os.Open(srcPath)
    if err != nil {
        fmt.Printf("Error opening local file: %s\n", err)
        return
    }
    defer localFile.Close()

    pod, err := client.CoreV1().Pods(namespace).Get(context.TODO(), podName, metav1.GetOptions{})
    if err != nil {
        fmt.Printf("Error getting pod: %s\n", err)
        return
    }

    // Find the container in the pod
    var container *corev1.Container
    for _, c := range pod.Spec.Containers {
        if c.Name == containerName {
            container = &c
            break
        }
    }

    if container == nil {
        fmt.Printf("Container not found in pod\n")
        return
    }

    // Create a stream to the container
    req := client.CoreV1().RESTClient().Post().
        Resource("pods").
        Name(podName).
        Namespace(namespace).
        SubResource("exec").
        Param("container", containerName)   

    req.VersionedParams(&corev1.PodExecOptions{
        Container: containerName,
        Command:   []string{"bash", "-c", "cat > " + dstPath},
        Stdin:     true,
        Stdout:    true,
        Stderr:    true,
    }, scheme.ParameterCodec)

    exec, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL())
    if err != nil {
        fmt.Printf("Error creating executor: %s\n", err)
        return
    }

    // Create a stream to the container
    err = exec.StreamWithContext(context.TODO(), remotecommand.StreamOptions{
        Stdin:  localFile,
        Stdout: os.Stdout,
        Stderr: os.Stderr,
        Tty:    false,
    })
    if err != nil {
        fmt.Printf("Error streaming: %s\n", err)
        return
    }

    fmt.Println("File copied successfully")
}
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal