7

I have a use case where my pod is run as non-rootuser and its running a python app. Now I want to copy file from master node to running pod. But when I try to run

kubectl cp app.py 103000-pras-dev/simplehttp-777fd86759-w79pn:/tmp

This command hungs up but when i run pod as root user and then run the same command it executes successfully. I was going through the code of kubectl cp where it internally uses tar command.

Tar command has got multiple flags like --overwrite --no-same-owner, --no-preserve and few others. Now from kubectl cp we can't pass all those flag to tar. Is there any way by which I can copy file using kubectl exec command or any other way.

kubectl exec simplehttp-777fd86759-w79pn -- cp app.py /tmp/ **flags**
prashant
  • 2,808
  • 5
  • 26
  • 41
  • is it the same physical node? if yes, did you tried using hostPath volume? – Prateek Jain Apr 29 '19 at 09:12
  • same physical node... umm what does that mean? – prashant Apr 29 '19 at 09:15
  • they are on different node, master on one and pod on other. – prashant Apr 29 '19 at 09:25
  • 1
    So long as it's a text file, `master-node$ cat app.py | kubectl exec simplehttpetcetc -- tee /tmp/app.py >/dev/null` will do what you want (possibly with some `-i` and/or `-t` flags sprinkled to `exec`, as I never can remember which is required for which kinds of commands – mdaniel Apr 30 '19 at 05:34

5 Answers5

4

If the source file is a simple text file, here's my trick:

#!/usr/bin/env bash

function copy_text_to_pod() {
  namespace=$1
  pod_name=$2
  src_filename=$3
  dest_filename=$4

  base64_text=`cat $src_filename | base64`
  kubectl exec -n $namespace $pod_name -- bash -c "echo \"$base64_text\" | base64 -d > $dest_filename"
}

copy_text_to_pod my-namespace my-pod-name /path/of/source/file /path/of/target/file

Maybe base64 is not necessary. I put it here in case there is some special character in the source file.

Trent Zhou
  • 41
  • 2
0

Meanwhile I found a hack, disclaimer this is not the exact kubectl cp just a workaround.

I have written a go program where I have created a goroutine to read file and attached that to stdin and ran kubectl exec tar command with proper flags. Here is what I did

reader, writer := io.Pipe()
copy := exec.CommandContext(ctx, "kubectl", "exec", pod.Name, "--namespace", pod.Namespace, "-c", container.Name, "-i",
    "--", "tar", "xmf", "-", "-C", "/", "--no-same-owner") // pass all the flags you want to
copy.Stdin = reader
go func() {
    defer writer.Close()

    if err := util.CreateMappedTar(writer, "/", files); err != nil {
        logrus.Errorln("Error creating tar archive:", err)
    }
}()

Helper function definition

func CreateMappedTar(w io.Writer, root string, pathMap map[string]string) error {
    tw := tar.NewWriter(w)
    defer tw.Close()

    for src, dst := range pathMap {
        if err := addFileToTar(root, src, dst, tw); err != nil {
            return err
        }

    }

    return nil
}

Obviously, this thing doesn't work because of permission issue but *I was able to pass tar flags

prashant
  • 2,808
  • 5
  • 26
  • 41
0

If it is only a text file it can be also "copied" via netcat.

1) You have to be logged on both nodes

$ kubectl exec -ti <pod_name> bash

2) Make sure to have netcat, if not install them

$ apt-get update
$ apt-get install netcat-openbsd

3) Go to the folder with permissions i.e.

/tmp

4) Inside the container where you have python file write

$ cat app.py | nc -l <random_port>

Example

$ cat app.py | nc -l 1234

It will start listening on provided port.

5) Inside the container where you want have the file

$ nc <PodIP_where_you_have_py_file> > app.py 

Example

$ nc 10.36.18.9 1234 > app.py

It must be POD IP, it will not recognize pod name. To get ip use kubectl get pods -o wide

It will copy content of app.py file to the other container file. Unfortunately, you will need to add permissions manual or you can use script like (sleep is required due to speed of "copying"):

#!/bin/sh
nc 10.36.18.9 1234 > app.py | sleep 2 |chmod 770 app.py;
PjoterS
  • 12,841
  • 1
  • 22
  • 54
0

Copy a file into kubernetes pod without using kubectl cp

kubectl cp is bit of a pain to work with. For example:

  • installing kubectl and configuring it (might need it on multiple machines). In our company, most people only have a restrictive kubectl access from rancher web GUI. No CLI access is provided for most people.
  • network restrictions in enterprises
  • Large file downloads/uploads may stop or freeze sometimes probably because traffic goes through k8s API server.
  • weird tar related errors keep popping up etc..

One of the reasons for lack of support to copy the files from a pod(or other way around) is because k8s pods were never meant to be used like a VM.. They are meant to be ephemeral. So, the expectation is to not store/create any files on the pod/container disk.

But sometimes we are forced to do this, especially while debugging issues or using external volumes..

Below is the solution we found effective. This might not be right for you/your team.

We now instead use azure blob storage as a mediator to exchange files between a kubernetes pod and any other location. The container image is modified to include azcopy utility (Dockerfile RUN instruction below will install azcopy in your container).

 RUN /bin/bash -c 'wget https://azcopyvnext.azureedge.net/release20220511/azcopy_linux_amd64_10.15.0.tar.gz && \
  tar -xvzf azcopy_linux_amd64_10.15.0.tar.gz && \
  cp ./azcopy_linux_amd64_*/azcopy /usr/bin/ && \
  chmod 775 /usr/bin/azcopy && \
  rm azcopy_linux_amd64_10.15.0.tar.gz && \
  rm -rf azcopy_linux_amd64_*'

Checkout this SO question for more on azcopy installation.

When we need to download a file,

  1. we simply use azcopy to copy the file from within the pod to azure blob storage. This can be done either programmatically or manually.
  2. Then we download the file to local machine from azure blob storage explorer. Or some job/script can pick up this file from blob container.

Similar thing is done for upload as well. The file is first placed in blob storage container. This can be done manually using blob storage explorer or can be done programmatically. Next, from within the pod azcopy can pull the file from blob storage and place it inside the pod.

The same can be done with AWS (S3) or GCP or using any other cloud provider. Probably even SCP, SFTP, RSYNC can be used.

ns15
  • 5,604
  • 47
  • 51
0

This works for me:

tar -cf - .  | kubectl exec --stdin <podname> -- /bin/bash -c "cat > /path/out.tar" 
Martin
  • 1
  • 1