kubectl cp: Copying Files to and From Kubernetes Pods

Deploying apps on Kubernetes (K8) can feel like walking a tightrope. One wrong step and boom. Your app doesn’t work, your pod crashes, or your team’s stuck debugging for hours.

If this sounds familiar, you’re not alone. A 2023 CNCF report found that 66% of consumers were using Kubernetes for production, and a majority of them were dealing with K8s’ complexities. But many errors are preventable if you know what to look for.

Discover the most common deployment mistakes, what causes them, and how to fix or avoid them.

Coming Up Next

  • Prerequisites and Context
  • Basic Syntax of kubectl cp
  • Common Use Cases
  • Copying Directories and Recursive Transfers
  • Working With Multicontainer Pods
  • Copying Across Namespaces and Contexts
  • Dealing With Symlinks, Permissions, and Preserved Metadata
  • Troubleshooting kubectl cp Errors
  • Performance Tips and Alternatives
  • Security Considerations
  • Automating File Copy in CI/CD Pipelines
  • Wrap-Up: Keep It Simple, Ship It Smooth

Prerequisites and Context

Before we dive in, let’s make sure you’re set up. You don’t need to be a Kubernetes expert, but a few basics will help you follow along. Here’s what you should have ready:

  • A Kubernetes cluster (local or cloud-based)
  • kubectl installed on your machine
  • Basic understanding of YAML files (just the idea that they describe how things work in Kubernetes)
  • An app to deploy — even a simple “Hello World” one works
  • A bit of command-line comfort

That’s it, and you’re good to go.

Basic Syntax of kubectl cp

The kubectl cp command lets you copy files and folders between your local machine and your Kubernetes pods. It’s like using a USB stick, but for containers.

Under the hood, it uses the tar command to package and transfer files between your system and the container. This means both your machine and the container need to support basic tar operations for it to work smoothly.

Source and Destination Patterns

The basic pattern looks like this: kubectl cp

But here’s the catch: When you’re copying to or from a pod, you need to include: /:

Examples:

  • Copy a file from your local machine to a pod: kubectl cp ./myfile.txt default/mypod:/app/myfile.txt
  • Copy a file from a pod to your machine: kubectl cp default/mypod:/app/log.txt ./log.txt

Important Flags (-c, -n, –retries, –no-preserve)

Here are the most useful flags for kubectl cp:

Common Use Cases

Let’s look at some everyday ways developers use kubectl cp. Whether you’re moving a config file into a pod, grabbing logs from one, or copying data between pods, this command can save time and headaches.

Copying Local Files to a Pod

Use this command if you want to send a file from your laptop into a pod: kubectl cp ./myfile.txt default/mypod:/app/myfile.txt

With this command, we’re telling Kubernetes: “Hey, take this file on my computer and put it inside the pod at this path.”

This is helpful when:

  • You’re updating config files
  • You need to drop in a script or binary
  • You want to test something quickly

Copying Files From a Pod to Local

If you need to download something from a pod, just flip the order: kubectl cp default/mypod:/app/log.txt ./log.txt

This is great for:

  • Saving logs for debugging
  • Grabbing output files
  • Backing up config files

Pod-to-Pod Copy via Local Hop

Kubernetes doesn’t support direct pod-to-pod copy. But here’s a trick:

  1. Copy the file from Pod A to your local machine: kubectl cp default/pod-a:/data/file.txt ./file.txt
  2. Then copy it from your local machine to Pod B: kubectl cp ./file.txt default/pod-b:/data/file.txt

It’s a two-step process, but it works like a charm when:

  • You’re migrating data between services
  • You need to sync the setup files or logs

Copying Directories and Recursive Transfers

Sometimes, you need to move a bunch of files, not just one. And luckily, kubectl cp can handle directories, too. Here’s what you need to do:

  • Point it to the folder you want to copy: kubectl cp ./myfolder default/mypod:/app/myfolder
  • Or copy from the pod back to your machine: kubectl cp default/mypod:/app/myfolder ./myfolder

Handling Large Directories Efficiently

Big directories can slow things down or cause timeouts. Here are a few tips to keep things smooth:

This method reduces the number of file transfers and speeds up the whole process and works especially well when:

  • You’re moving lots of small files.
  • You need to upload full project folders.
  • You want to avoid transfer timeouts.

Working With Multicontainer Pods

Some pods have more than one container inside — kind of like a lunchbox with multiple compartments. By default, kubectl cp doesn’t know which one you want to copy to or from. So, you need to tell it.

Selecting the Right Container

Use the -c flag to name the container you want to work with.

Example: kubectl cp -c my-container ./file.txt default/mypod:/app/

This tells Kubernetes: “Hey, copy this file into the my-container inside mypod.”

You’ll usually need this when:

  • You’re working with sidecar containers, like one for logs and one for the app.
  • You only want to target one specific container in the pod.
  • Your kubectl cp command is failing without it.

Copying Across Namespaces and Contexts

Kubernetes clusters often have multiple namespaces (like folders) and multiple contexts (like environments). If you don’t specify the right one, your command won’t find the pod.

Here are a few ways to deal with it:

  • Use -n to pick the right namespace: kubectl cp -n custom-namespace ./file.txt mypod:/app/
  • Use –context if you’re working in a different cluster: kubectl –context=my-cluster cp ./file.txt default/mypod:/app/
  • Check your current context and namespace:
    • kubectl config get-contexts
    • kubectl config view –minify | grep namespace

These small flags make a big difference when you’re juggling dev, staging, and production setups.

Dealing With Symlinks, Permissions, and Preserved Metadata

The kubectl cp command tries to copy things as-is, but there are a few things that can cause problems if you’re not careful.

Here’s what to look out for:

  • Symlinks may break: Symlinks (shortcut files) might not work as expected after copying. If you’re relying on them, double-check their paths inside the pod.
  • Permissions might not match: File permissions, such as who can read/write, may change after copying. Use kubectl exec and chmod inside the pod if needed.
  • Timestamps are preserved by default: The file keeps its original “created” and “modified” times. To turn this off, use the –no-preserve flag:
    • kubectl cp –no-preserve ./file.txt default/mypod:/app/
  • Executable files might lose permissions: If your script or binary isn’t working inside the pod, check if it’s still marked as executable:
    • kubectl exec -it mypod — chmod +x /app/myscript.sh

Copying files sounds simple, but the details matter, especially when you’re troubleshooting strange behavior.

Troubleshooting kubectl cp Errors

Sometimes, kubectl cp doesn’t work the way you expect. Let’s break down some of the most common errors and exactly how to fix them.

Permission Denied and Read-Only File System

The error:

  • tar: ./file.txt: Cannot open: Permission denied
  • tar: Exiting with failure status due to previous errors

What it means:

  • You’re trying to copy a file into a folder where the container doesn’t have write access.
  • The container’s file system might be read-only, or your user inside the pod lacks permission.

To fix it:

  • Try copying to a different folder, like /tmp, which is usually writable: kubectl cp ./file.txt default/mypod:/tmp/
  • Or, exec into the pod and change permissions (if allowed): kubectl exec -it mypod — chmod 777 /target/folder

Heads-up: In production pods, changing permissions may not be allowed, and that’s by design for security.

No Such File or Directory

The error:

  • error: one of src or dest must be a local file specification
  • Or: tar: /app/file.txt: No such file or directory

What it means:

  • The file or folder path doesn’t exist — either on your machine or inside the pod.
  • Or, you misspelled the pod name, container name, or namespace.

To fix it:

  • Double-check your source and destination paths. Use kubectl exec to inspect the pod: kubectl exec -it mypod — ls /app/
  • Make sure you’re targeting the right namespace: kubectl cp -n my-namespace ./file.txt mypod:/app/
  • Use kubectl get pods to confirm the pod name.

Unexpected Tar Format Errors

The error: unexpected tar header error

What it means: The kubectl cp command relies on tar under the hood. If tar isn’t installed in the container — or if the version is too different — things break.

To fix it:

  1. Check if tar exists inside the pod: kubectl exec -it mypod — which
  2. If tar is missing, you won’t be able to use kubectl cp. You have two options:
    1. Install tar, if possible and safe to do so.
    2. Use an alternative like the tar + exec combo (explained below!)

Performance Tips and Alternatives

If you’re moving large files or lots of files, kubectl cp can be slow. Or flaky. Here are a couple of tips that offer faster, more reliable alternatives.

Using Tar Over kubectl exec for Big Files

Instead of kubectl cp, try creating a tar archive yourself and pushing it using kubectl exec. This avoids many of the bugs tied to kubectl cp.

Example: Copying to a pod

  1. Compress your files: tar -czf files.tar.gz myfolder/
  2. Copy the archive: kubectl cp ./files.tar.gz default/mypod:/tmp/
  3. Unpack it inside the pod: kubectl exec -it mypod — tar -xzf /tmp/files.tar.gz -C /app/

This method works better because it:

  • Has fewer files, which means faster transfers
  • Offers more control over how things are unpacked
  • Works even if kubectl cp is flaky

Leveraging rsync via kubectl port-forward

If you want blazing-fast file sync, try rsync — a powerful file transfer tool. It’s not built into Kubernetes, but you can port-forward to a container running rsync, and then push files directly.

Here’s how you can do it:

  1. Run rsync inside a container, either install it or use a custom image that has it.
  2. Port-forward to expose rsync: kubectl port-forward pod/mypod 8730:873
  3. Use rsync from your machine to push files: rsync -av ./myfolder rsync://localhost:8730/app/

This method works well because it:

  • Is fast and efficient for lots of files
  • Only transfers what’s changed, which saves time
  • Is great for syncing folders during dev

That said, you’ll need a container with rsync installed, and security rules that allow port-forwarding.

Security Considerations

Copying files in and out of pods might seem harmless, but it can open doors to risks if you’re not careful. Let’s look at two key areas: Permissions and data safety.

RBAC Rules for Copy Operations

Kubernetes uses role-based access control (RBAC) to decide who can do what. Copying files with kubectl cp involves actions like:

  • Reading from a pod
  • Writing to a pod
  • Executing commands inside the container (via tar)

So, to use kubectl cp, you must have permission to get, list, and exec pods in the right namespace.

If you see access denied errors, it’s likely your user or service account doesn’t have these rights. An admin can fix this by updating the Role or ClusterRole bindings.

Example Role:

Pro tip: Always follow least privilege, i.e., give only the access that’s needed and nothing more.

Avoiding Sensitive Data Leakage

Copying files can accidentally expose secrets if you’re not paying attention. Here’s how to stay safe:

  • Never copy files into a pod’s /etc, /secrets, or system directories unless you know what you’re doing.
  • Don’t copy secrets out of pods, like TLS certificates, config files, or .env
  • Review file contents before copying, especially when using wildcard commands or whole directories.
  • Audit who has access to kubectl cp, and make sure devs aren’t copying sensitive files into shared or production pods.

Pro tip: If you’re working with sensitive files (like keys, certs, or passwords), use Kubernetes Secrets instead. They’re made for that.

Automating File Copy in CI/CD Pipelines

In a CI/CD pipeline, manual steps are the enemy. You want everything, including file transfers, to run automatically and reliably.

Using kubectl cp in your pipeline works for basic tasks, but there are a few things to keep in mind to make it safe and stable.

For instance, you need to know when to automate file copy. You might want to copy files during:

  • Pre-deployment steps, such as injecting config files into a pod.
  • Post-deployment tests, like pulling logs or results from a test container.
  • Data migration between app versions.

Sample command in a pipeline script:

You can drop this into a CI/CD job step — in GitHub Actions, GitLab CI, or Jenkins.

And here are a few things to keep in mind when automating file copy:

  • Always set the namespace with -n so the command doesn’t rely on local configs: kubectl cp -n staging ./file.txt mypod:/app/
  • Set KUBECONFIG in your CI environment to point to the right cluster.
  • Add retries or checks in case the pod isn’t ready yet: kubectl wait –for=condition=Ready pod/mypod
  • Use tar + exec instead of kubectl cp if your container doesn’t have tar, or if kubectl cp is flaky in your setup.

Remember to ensure that your CI runner only has access to what it needs. Don’t give it full admin rights just to copy files. Use a service account with the bare minimum permissions instead.

Wrapping Up: Keep It Simple, Ship It Smooth

Copying files in Kubernetes can be tricky, but with the right approach — using the correct flags, understanding pod/container setups, avoiding common errors, and optimizing for performance — it becomes a smooth part of your workflow. Whether you’re working in dev, CI/CD, or production, knowing how to handle file transfers gives you more control and fewer headaches.

If you’re ready to automate even more of your Kubernetes tasks, check out our guide on how to run Kubernetes commands in Go. We talk about how to programmatically handle file operations, deployments, and more using Go.

Primary sources:


Group Created with Sketch.


Continue Reading