Introduction
If kubectl cp is unavailable or unreliable in your environment, you can still copy files into a pod by streaming bytes through kubectl exec. The usual alternatives are simple shell redirection for single files or tar streaming for directories and richer copies.
These approaches are not hacks so much as manual versions of what kubectl cp effectively does. The important part is to choose a method that matches the tools available inside the target container.
Single-File Copy With cat
For one file, the simplest pattern is to stream the file into the container and redirect it to a destination path.
1LOCAL_FILE="./config.yaml"
2NAMESPACE="default"
3POD="my-app-7f9b6d4c9b-abcde"
4CONTAINER="app"
5DEST_FILE="/app/config/config.yaml"
6
7cat "$LOCAL_FILE" \
8| kubectl exec -i -n "$NAMESPACE" "$POD" -c "$CONTAINER" -- sh -c "cat > $DEST_FILE" kubectl exec -n "$NAMESPACE" "$POD" -c "$CONTAINER" -- ls -lah "$DEST_FILE" ``` This works well when the container has a shell and `cat`, which is common even in fairly small images. ## Directory Copy With `tar` For directories or more complex file sets, `tar` streaming is usually better. ```bash LOCAL_DIR="./assets" NAMESPACE="default" POD="my-app-7f9b6d4c9b-abcde" CONTAINER="app" DEST_DIR="/app" tar -C "$LOCAL_DIR" -cf - . \ | kubectl exec -i -n "$NAMESPACE" "$POD" -c "$CONTAINER" -- tar -C "$DEST_DIR" -xf - ``` This preserves nested structure naturally and avoids manually copying files one by one. The main requirement is that `tar` must exist both locally and inside the container. ## Minimal-Tool Containers Some very small images do not include `tar`. In that case, you can still move small files with base64 if the container has the matching tools. ```bash LOCAL_FILE="./settings.json" DEST_FILE="/tmp/settings.json" base64 "$LOCAL_FILE" \ | kubectl exec -i -n "$NAMESPACE" "$POD" -c "$CONTAINER" -- sh -c "base64 -d > $DEST_FILE" ``` This is fine for small files, but it is not the first choice for larger transfers because it adds overhead and depends on `base64` being present in the container. ## Pick the Correct Pod and Container In multi-container pods, always specify the target container with `-c`. Also remember that pod names are ephemeral, so scripts often resolve pods by label rather than hardcoding the current name. ```bash NAMESPACE="default" APP_LABEL="app=my-app" CONTAINER="app" POD=$(kubectl get pod -n "$NAMESPACE" -l "$APP_LABEL" -o jsonpath='{.items[0].metadata.name}') echo "$POD" ``` That reduces mistakes during rollouts and restarts. ## Treat the Pod Filesystem as Ephemeral Copying a file into a running container usually changes only that pod instance. If the pod restarts, the file is often lost unless it was written to a persistent volume. This matters operationally. Ad hoc file injection is fine for debugging, incident response, or temporary config changes, but it is not a substitute for rebuilding the image or using proper configuration management when the change should persist. ## Common Pitfalls A common mistake is writing to a path that is read-only in the container filesystem. Many hardened images do not allow arbitrary writes everywhere. Another issue is forgetting the container name in multi-container pods. The command succeeds, but the file lands in the wrong container. Developers also sometimes assume the copied file will survive pod restarts. Unless the destination is backed by a persistent volume, that assumption is usually wrong. Finally, always verify the transfer. A successful shell pipeline does not guarantee the application can actually read or use the resulting file. ## Summary - '`kubectl exec` can replace `kubectl cp` by streaming file contents into the container.' - Use `cat` redirection for single files and `tar` streaming for directories. - Choose a method that matches the tools available inside the container. - Target the correct pod and container, ideally by label rather than hardcoded pod name. - Remember that copied files are usually ephemeral unless written to persistent storage.