Skip to content

Instantly share code, notes, and snippets.

@avoidik
Forked from tzing/kubectl-rsync
Last active August 27, 2025 10:18
Show Gist options
  • Save avoidik/768b1ce51497a9f212ca7426e591baf9 to your computer and use it in GitHub Desktop.
Save avoidik/768b1ce51497a9f212ca7426e591baf9 to your computer and use it in GitHub Desktop.
rsync over kubectl
#! /bin/bash
# This script is inspired by following scripts:
# * https://serverfault.com/a/887402
# * https://github.com/dmrub/kube-utils/blob/master/kube-rsync
set -euo pipefail
: "${KUBECTL_RSYNC_RSH:=}"
: "${KUBE_CONTEXT:=}"
: "${POD_NAMESPACE:=}"
: "${POD_NAME:=}"
if [[ -z "$KUBECTL_RSYNC_RSH" ]]; then
[[ -n "$KUBE_CONTEXT" ]] && echo >&2 "* Found \$KUBE_CONTEXT = $KUBE_CONTEXT"
[[ -n "$POD_NAMESPACE" ]] && echo >&2 "* Found \$POD_NAMESPACE = $POD_NAMESPACE"
[[ -n "$POD_NAME" ]] && echo >&2 "* Found \$POD_NAME = $POD_NAME"
while [[ $# -gt 0 ]]; do
case "$1" in
--context)
KUBE_CONTEXT="$2"
shift 2
;;
--context=*)
KUBE_CONTEXT="${1#*=}"
shift
;;
-c | --container)
POD_CONTAINER="$2"
shift 2
;;
--container=*)
POD_CONTAINER="${1#*=}"
shift
;;
-n | --namespace)
POD_NAMESPACE="$2"
shift 2
;;
--namespace=*)
POD_NAMESPACE="${1#*=}"
shift
;;
-h | --help)
echo "Rsync file and directories from/to Kubernetes pod"
echo ""
echo "IMPORTANT:"
echo "'rsync' must be installed on both the local machine and the target container for this script to work."
echo ""
echo "Usage:"
echo " $(basename "$0") [options] [--] [rsync-options] SRC DST"
echo ""
echo "Options:"
echo " -n, --namespace='' Namespace of the pod"
echo " --context='' The name of the kubeconfig context to use."
echo " Has precedence over KUBE_CONTEXT variable."
echo " -c, --container='' Container name. If omitted, the first container in the pod will be chosen"
echo " --help Display this help and exit"
echo ""
exit
;;
--)
shift
break
;;
*)
break
;;
esac
done
export KUBECTL_RSYNC_RSH=1
export KUBE_CONTEXT POD_NAMESPACE POD_CONTAINER
exec rsync --blocking-io --rsh="$0" "$@"
fi
# Running under --rsh
# If user uses pod@namespace, rsync passes args as `-l pod namespace`
if [[ x"$1" == x"-l" ]]; then
POD_NAME="$2"
POD_NAMESPACE="$3"
shift 3
else
POD_NAMESPACE="$POD_NAMESPACE"
POD_NAME="$1"
shift
fi
export KUBE_CONTEXT POD_NAMESPACE POD_CONTAINER POD_NAME
echo >&2 "* Connect to pod $POD_NAME in ${POD_NAMESPACE:-current namespace}"
exec kubectl exec \
-i \
${KUBE_CONTEXT:+--context=${KUBE_CONTEXT}} \
${POD_NAMESPACE:+--namespace=${POD_NAMESPACE}} \
${POD_CONTAINER:+--container=${POD_CONTAINER}} \
"${POD_NAME}" \
-- \
"$@"
@avoidik
Copy link
Author

avoidik commented Aug 20, 2025

@avoidik
Copy link
Author

avoidik commented Aug 27, 2025

mkdir -p ~/.local/bin
curl -fsSL https://gist.github.com/avoidik/768b1ce51497a9f212ca7426e591baf9/raw/bd269311deff5afb8b68ca8c43dfe908f73c2b5f/kubectl-rsync -o ~/.local/bin/kubectl-rsync
chmod +x ~/.local/bin/kubectl-rsync
kubectl rsync --help
kubectl rsync -n default -c nginx -- -avzh --progress /tmp nginx:/opt

@avoidik
Copy link
Author

avoidik commented Aug 27, 2025

#!/bin/bash

# ./krsync.sh -avzh --progress --stats nginx:/etc/nginx/nginx.conf .

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

# Running as --rsh
namespace='default'
pod="$1"
container='nginx'
shift

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

exec kubectl -n "$namespace" exec -i -c "$container" "$pod" -- "$@"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment