Graphic showing the Kubernetes logo

Containers running in Kubernetes Pods are meant to be self-contained compute units that you don’t need to manually interact with. Sometimes you might have to copy files to or from a Pod’s filesystem though, perhaps because you’re debugging a problem and want to archive logs, config files, or caches stored in a container.

Here’s how to move files between your machine and containers in a Pod, using Kubectl’s built-in transfer feature or a manual alternative.

Copying To or From Your Machine

The kubectl cp command is the simplest way to copy to or from a container filesystem. It works similarly to the docker cp you may already be familiar with from local container development.

kubectl cp requires source and destination arguments. One of the source or destination must be a Pod reference. This is formatted as the Pod name, followed by a colon and the in-container filesystem path.

kubectl cp example-pod:/tmp/example-dir ./example-dir

This example copies the contents of /tmp/example-dir from example-pod to example-dir on your local filesystem. Reversing the arguments would copy your machine’s example-dir back to the Pod.

Command Arguments

As a single Pod can hold multiple containers, it’s important to bear this in mind when using cp. Kubernetes will default to copying to or from the first container instance within the Pod. You can target a specific container instead by adding the -c flag:

kubectl cp example-pod:/tmp/example-dir ./example-dir -c second-container

Like all other kubectl commands, cp runs against the cluster connection defined by your KUBECONFIG environment variable. This defaults to ~/.kube/conf.

There are two options when you’re referencing namespaced Pods. You can either add the standard --namespace example-namespace flag or use a full Pod path in your filesystem reference:

kubectl cp example-namespace/example-pod:/tmp/example-dir ./example-dir

File attributes are preserved by default. Add the --no-preserve flag to your cp command to strip ownership and permissions data from the copied files left at the destination. Unlike regular Unix cp, Kubectl’s implementation is always recursive so referencing a directory will include its contents too.

When Kubectl Cp Won’t Work

kubectl cp comes with one big caveat: internally, it’s a simple wrapper around tar. The command will compress the source path, copy the archive to the destination, and then extract its content. Your container image must include the tar binary in its path for this to work.

This means kubectl cp may not always be an option when you’re following Docker best practices to keep images small. Although popular minimal bases such as alpine do include tar, it may not feature in every image and won’t be present if you’re assembling them from scratch.

The use of tar also limits what kubectl cp can copy. You can’t resolve symlinks or use wildcards like /tmp/*.log. You’ll have to use a different approach when this functionality is needed.

One option is to combine kubectl exec, the cat command, and shell redirection to stream a file’s content out of the cluster and into a local file:

kubectl exec 
    --namespace example-namespace 
    example-pod -c second-container 
    -- cat /tmp/example-file > local-file

The kubectl exec command starts a shell session in the Pod. Everything after the -- is run inside the container. The output of calling cat on the file will be emitted to your terminal where it can be redirected into a local file.

This technique is suitable when you’re copying a handful of relatively small files. It would quickly become tedious if you needed to retrieve a large directory. Unfortunately there’s no better alternative without adding additional software to your container.

If you’re feeling daring, you could install SSH in your container and use scp to access its filesystem from your host. This would give you a complete copying experience at the expense of running an extra daemon and creating a potential security issue. It should only be considered on properly protected clusters.

Adding tar to your container images is a much safer option. This lets you use kubectl cp and unlocks more advanced manual copying via kubectl exec when you need extra functionality. If you run into limitations with the cp syntax, invoke tar directly via kubectl exec to add extra flags to the command:

kubectl exec 
    --namespace example-namespace 
    example-pod -c second-container 
    -- tar -cf /tmp/example-dir | tar xf - -C ./extracted-dir

This runs tar -cF inside your container and pipes the result to the tar xf extraction command on your local machine. The - instructs tar to extract the data fed to it via the standard input stream. -C is used to specify a destination directory.

Summary

The kubectl cp command lets you copy files between Kubernetes Pods and your machine. It works in either direction but can’t be used to move files from Pod to Pod. If you need to do that, it’s best to use a two-stage procedure, copying first from Pod A to your machine, then onward to Pod B.

As cp relies on tar under-the-hood, you need to make sure your container image includes it. You’ll see a No such file or directory tar error if you try to run cp against a Pod without tar. In this situation, either add tar to the container or use a combination of kubectl exec and cat if you only need to retrieve a few files.

Profile Photo for James Walker James Walker
James Walker is a contributor to How-To Geek DevOps. He is the founder of Heron Web, a UK-based digital agency providing bespoke software development services to SMEs. He has experience managing complete end-to-end web development workflows, using technologies including Linux, GitLab, Docker, and Kubernetes.
Read Full Bio »