Skip to content

Instantly share code, notes, and snippets.

@avoidik
Forked from tzing/kubectl-rsync
Last active November 13, 2025 16:01
Show Gist options
  • Select an option

  • Save avoidik/768b1ce51497a9f212ca7426e591baf9 to your computer and use it in GitHub Desktop.

Select an option

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:=}"
: "${REMOTE_BIN_PATH:=/usr/bin/rsync}"
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"
[[ -n "$REMOTE_BIN_PATH" ]] && echo >&2 "* Found \$REMOTE_BIN_PATH = $REMOTE_BIN_PATH"
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
;;
-p | --path)
REMOTE_BIN_PATH="$2"
shift 2
;;
--path=*)
REMOTE_BIN_PATH="${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 " -p, --path='' Set path to rsync on a remote side, by default /usr/bin/rsync"
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 REMOTE_BIN_PATH
exec rsync --rsync-path="$REMOTE_BIN_PATH" --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 Oct 3, 2025

exec rsync --rsync-path=/usr/bin/rsync --blocking-io --rsh="$0" "$@"

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