kubectl cp

Copy files and directories to and from containers in pods. Uses tar internally to transfer data.

kubectl cp [SOURCE] [DEST] [flags]

Common Flags

FlagShortDescription
--container-cContainer name to copy to/from in multi-container pods
--namespace-nNamespace of the pod
--no-preserveDo not preserve the ownership and permissions of the copied files
--retriesNumber of retries to copy (default 0)

Examples

Copy a file from local to a pod

kubectl cp ./config.yaml my-pod:/etc/app/config.yaml

Copy a file from a pod to local

kubectl cp my-pod:/var/log/app.log ./app.log

Copy a directory to a pod

kubectl cp ./configs/ my-pod:/etc/app/configs/

Copy from a specific container

kubectl cp my-pod:/data/export.csv ./export.csv -c app

Copy from a pod in a specific namespace

kubectl cp production/my-pod:/var/log/app.log ./app.log

Copy without preserving permissions

kubectl cp ./script.sh my-pod:/tmp/script.sh --no-preserve

When to Use kubectl cp

kubectl cp copies files between your local filesystem and containers running in pods. It is primarily used for debugging tasks: extracting log files, copying diagnostic tools into containers, or retrieving data exports from running applications.

Basic File Operations

Copy files in both directions using the pod:path syntax:

# Copy a local file into a pod
kubectl cp ./config.yaml my-pod:/etc/app/config.yaml

# Copy a file from a pod to local
kubectl cp my-pod:/var/log/app.log ./app.log

# Copy an entire directory
kubectl cp ./scripts/ my-pod:/tmp/scripts/

# Copy a directory from a pod
kubectl cp my-pod:/var/log/ ./pod-logs/

Namespace-Qualified Paths

When working with pods in non-default namespaces, prefix the pod name with the namespace:

# Copy from a pod in the production namespace
kubectl cp production/my-pod:/data/report.csv ./report.csv

# Copy to a pod in staging
kubectl cp ./fix.sh staging/my-pod:/tmp/fix.sh

# You can also use the -n flag
kubectl cp my-pod:/data/report.csv ./report.csv -n production

Multi-Container Pods

Specify the container with the -c flag:

# Copy from the application container
kubectl cp my-pod:/app/logs/error.log ./error.log -c app

# Copy a debug tool into the sidecar
kubectl cp ./tcpdump my-pod:/tmp/tcpdump -c debug

How It Works Internally

kubectl cp uses tar to package and transfer files. When you copy a file to a pod, kubectl:

  1. Creates a tar archive of the local file.
  2. Streams it through the API server.
  3. Executes tar -xf inside the container to extract the file.

When copying from a pod:

  1. Executes tar -cf inside the container to create an archive.
  2. Streams it back through the API server.
  3. Extracts it locally.

This means the container must have tar installed. Many minimal and distroless images do not include tar.

Working Without tar

When the container lacks tar, use alternative approaches:

# Copy a file from a container using exec and cat
kubectl exec my-pod -- cat /var/log/app.log > app.log

# Copy binary data using base64
kubectl exec my-pod -- base64 /data/file.bin > file.b64
base64 -d file.b64 > file.bin

# Copy a file into a container using exec
kubectl exec -i my-pod -- sh -c 'cat > /tmp/script.sh' < script.sh

# Make it executable
kubectl exec my-pod -- chmod +x /tmp/script.sh

Common Debugging Workflows

# Extract a heap dump from a Java application
kubectl cp my-pod:/tmp/heapdump.hprof ./heapdump.hprof -c app

# Copy diagnostic tools into a minimal container
kubectl cp ./strace my-pod:/tmp/strace
kubectl exec my-pod -- chmod +x /tmp/strace

# Retrieve a database export
kubectl cp my-pod:/tmp/db-backup.sql ./db-backup.sql -c postgres

# Copy configuration for inspection
kubectl cp my-pod:/etc/nginx/nginx.conf ./nginx-live.conf

# Compare live config with expected config
diff nginx-expected.conf nginx-live.conf

Large File Considerations

kubectl cp is not designed for large file transfers. The data streams through the API server, which has request size limits and timeout constraints:

# For large files, use a shared volume instead
# 1. Create a PVC
# 2. Mount it to a pod with tools installed
# 3. Use the tool pod to transfer data to/from external storage

# Or use exec with compression for moderate-sized files
kubectl exec my-pod -- tar czf - /data/large-dir | gzip -d > large-dir.tar

Security Notes

Files copied into containers are not persisted across restarts. Any file copied via kubectl cp exists only in the container's writable layer and is lost when the pod is recreated. For permanent configuration changes, update the container image, ConfigMap, or Secret.

Be cautious about copying files from untrusted containers. The tar extraction can potentially overwrite files outside the intended directory through path traversal attacks in crafted tar archives.

Best Practices

Use kubectl cp for one-off debugging tasks only. For regular data exchange, use ConfigMaps, Secrets, or PersistentVolumes. For large data, use object storage like S3 with init containers or sidecar uploaders. Always verify that tar is available in the target container before relying on cp. Prefer kubectl exec with pipe redirections for containers without tar.

Interview Questions About This Command

How does kubectl cp work internally?
kubectl cp uses tar to archive the files, streams the tar data through the API server, and extracts it on the destination. This means tar must be available in the container for cp to work.
What are the limitations of kubectl cp?
It requires tar in the container, does not support symlink-safe operations, cannot copy to init containers that have exited, and is not suitable for large file transfers in production.
How do you copy files when the container does not have tar installed?
Use kubectl exec with shell redirection: kubectl exec my-pod -- sh -c 'cat /path/to/file' > local-file. Or use kubectl debug to attach a container with tar.

Common Mistakes

  • Trying to use kubectl cp with a container that does not have tar installed, which causes the copy to fail silently or with an error.
  • Using kubectl cp for large data transfers instead of proper volume-based solutions like PersistentVolumes or S3.
  • Forgetting the namespace prefix format (namespace/pod:/path) when copying from pods in non-default namespaces.

Related Commands