22

I need to rsync a file tree to a specific pod in a kubernetes cluster. It seems it should be possible if only one can convince rsync that kubectl acts sort of like rsh. Something like:

rsync --rsh='kubectl exec -i podname -- ' -r foo x:/tmp

... except that this runs into problems with x since rsync assumes a hostname is needed:

exec: "x": executable file not found in $PATH

I can not seem to find a method to help rsync construct the rsh command. Is there a way to do this? Or some other method by which relatively efficient file transfer can be achieved over a pipe?

(I am aware of gcloud compute copy-files, but it can only be used onto the node?)

Bittrance
  • 2,970
  • 2
  • 21
  • 27

7 Answers7

47

To rsync to a pod I use the following helper:

pod=$1;shift;kubectl exec -i $pod -- "$@"

I put this in a file called "rsync-helper.sh" and then run the rsync like this:

rsync -av --progress --stats -e './rsync-helper.sh' source-dir/ thePodName:/tmp/dest-dir

If you'd like a simple script that wraps this all up save this as krsync:

#!/bin/bash

if [ -z "$KRSYNC_STARTED" ]; then
    export KRSYNC_STARTED=true
    exec rsync --blocking-io --rsh "$0" $@
fi

# Running as --rsh
namespace=''
pod=$1
shift

# If use uses pod@namespace rsync passes as: {us} -l pod namespace ...
if [ "X$pod" = "X-l" ]; then
    pod=$1
    shift
    namespace="-n $1"
    shift
fi

exec kubectl $namespace exec -i $pod -- "$@"

Then you can use krsync where you would normally rsync:

krsync -av --progress --stats src-dir/ pod:/dest-dir

Or you can set the namespace:

krsync -av --progress --stats src-dir/ pod@namespace:/dest-dir

NOTE: You must have rsync executable in the pod image for this to work.

Karl Bunch
  • 571
  • 4
  • 3
  • 1
    This script works perfectly! – omikron Feb 16 '19 at 15:23
  • 2
    Works perfectly indeed, the `--rsh` part is not trivial at all to understand. Downside is not using tar – Mugen Mar 26 '19 at 13:47
  • hats off to you, sir. This is a very elegant script. – Michael Niemand Mar 23 '20 at 20:45
  • Error on my Mac OS: rsync error: protocol incompatibility (code 2) at /BuildRoot/Library/Caches/com.apple.xbs/Sources/rsync/rsync-52/rsync/compat.c(61) [sender=2.6.9] command terminated with exit code 126 – Abdennour TOUMI Jul 05 '20 at 13:58
  • 1
    Thank you for the script. I am new to k8s and was trying to migrate my old server. Saved me a lot of time. – Chaitanya Bankanhal Feb 12 '21 at 12:33
  • Just helped me sync 21 gigs of data. I wrote a blog post describing how it can be used in disaster recovery with a link back here: https://vhs.codeberg.page/post/recover-files-kubernetes-persistent-volume/ – vhs Mar 06 '22 at 02:25
  • Thanks so much for the script which works very well. Could you please provide some explanation about how it works? It is not trivial to understand. – Fabrice Jammes Apr 20 '22 at 20:59
  • protocol incompatibility is an error raised by not having rsync binary on the pod – Federico Galli May 04 '22 at 18:04
3

In the end, I wrote a Python script to act as a receiver of tar files. You can do thus:

tar cf - . | kubectl exec shinken -i catcher -v /etc/shinken/custom_configs

Note that this only works if you cluster nodes are kubernetes 1.1 or later.

Bittrance
  • 2,970
  • 2
  • 21
  • 27
2

The answer from @karl-bunch was perfect. For those who prefer using tar this is how I use it:

tar -cvz -C /orig-dir . | kubectl exec -ti podname -- sh -c 'cd /var/www && tar -xzv'
Uwe Keim
  • 2,370
  • 4
  • 29
  • 46
leumasino
  • 21
  • 1
2

If the tar binary is available on the container, you can transfer files using the new cp command.

Though possibly not as efficient as rsync.

rcoup
  • 167
  • 1
  • 8
Chris Stryczynski
  • 1,176
  • 2
  • 15
  • 23
2

A one-liner, just edit to you names and paths:

p_user=$USER;p_name=$POD_NAME; rsync -avurP --blocking-io --rsync-path= --rsh="$(which kubectl) exec $p_name -i -- " /home/$USER/target_dir rsync:/home/$p_user/
Nico
  • 121
  • 1
1

I ran into the same problem today. I had to sync files from the pod to my local machine.

My solution for this was this rsync command

rsync -aOv --blocking-io --rsync-path="/some/path/on/pod" --rsh="kubectl exec somePod -c someContainer -i -- " rsync:"/some/path/on/pod /some/local/path
Dave M
  • 4,494
  • 21
  • 30
  • 30
Adam H.
  • 11
  • 1
0

It is not supported, but there is an issue for adding support which you can +1 or even contribute to: https://github.com/kubernetes/kubernetes/issues/18007#issuecomment-164797262

Eric Tune
  • 155
  • 5