Skip to content

Mount Kubernetes PVs locally using SSHFS/NFS

License

Notifications You must be signed in to change notification settings

fenio/pv-mounter

pv-mounter

build test Go Report Card Latest GitHub release GitHub license GitHub stars GitHub issues GitHub all releases Docker Pulls Docker Pulls OpenSSF Scorecard OpenSSF Best Practices codecov

A tool to locally mount Kubernetes Persistent Volumes (PVs) using SSHFS or NFS.

This tool can also be used as a kubectl plugin.

Rationale

I often need to copy some files from my homelab which is running on Kubernetes. Having the ability to work on these files locally greatly simplifies this task. Thus, pv-mounter was born to automate that process.

What exactly does it do?

pv-mounter

pv-mounter supports two backends: SSH (default) and NFS (--backend nfs). Both work the same way depending on the volume's access mode.

For RWX (ReadWriteMany) volumes or unmounted RWO (ReadWriteOnce) volumes:

  • Spawns a standalone Pod with the chosen backend (SSH daemon or NFS-Ganesha) and binds it to the existing PVC.
  • Creates a port-forward to make it locally accessible.
  • Mounts the volume locally using SSHFS or NFSv4.

For already mounted RWO volumes:

  • Creates an ephemeral container with the chosen backend within the Pod that currently mounts the volume.
  • Creates a port-forward directly to the workload Pod to make it locally accessible.
  • Mounts the volume locally using SSHFS or NFSv4.

Prerequisites

  • SSH backend (default): You need a working SSHFS setup.
  • NFS backend (--backend nfs): You need an NFS client.
    • macOS: Built-in, no installation needed.
    • Linux: sudo apt install nfs-common (Debian/Ubuntu) or sudo dnf install nfs-utils (RHEL/Fedora).

Quick Start / Usage

kubectl krew install pv-mounter

kubectl pv-mounter mount [--backend ssh|nfs] [--needs-root] [--debug] [--image] [--image-secret] <namespace> <pvc-name> <local-mount-point>
kubectl pv-mounter clean [--backend ssh|nfs] <namespace> <pvc-name> <local-mount-point>

Obviously, you need to have working krew installation first.

Or you can simply grab binaries from releases.

Security

I spent quite some time making the solution as secure as possible.

SSH backend

  • SSH keys used for connections between various components are generated every time from scratch and once you wipe the environment clean, you won't be able to connect back into it using the same credentials.
  • Containers / Pods are using minimal possible privileges:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsUser = XYZ
runAsGroup = XYZ
runAsNonRoot = true

sshd_config is also limited as much as possible:

PermitRootLogin no
PasswordAuthentication no

Above, it's not true if you're using the --needs-root option or the NEEDS_ROOT environment variable, but well, you've asked for it.

NFS backend

  • NFS-Ganesha requires more capabilities than SSH (SYS_ADMIN, DAC_READ_SEARCH, DAC_OVERRIDE, SYS_RESOURCE, CHOWN, FOWNER, SETUID, SETGID) and runs with seccompProfile: Unconfined.
  • Standalone NFS pods run as root. Ephemeral NFS containers run as the workload pod's UID.
  • NFS exports use No_Root_Squash and SecType = sys (AUTH_SYS) — this is acceptable since traffic stays within the kubectl port-forward tunnel (localhost only).

Limitations

The tool has a "clean" option that does its best to clean up all the resources it created for mounting the volume locally. However, ephemeral containers can't be removed or deleted. That's the way Kubernetes works. As part of the cleanup, this tool kills the process that keeps its ephemeral container alive. I confirmed it also kills other processes that were running in that container, but the container itself remains in a limbo state.

Windows

Since I can't test Windows binaries, they are not included. However, since there seems to exist a working Windows implementation of SSHFS, in theory it should work.

Demos

Created with VHS tool.

The demo GIFs are automatically regenerated when code or tape files change.

SSH

RWX or unmounted RWO volume

ssh-rwx

Mounted RWO volume

ssh-rwo

NFS

RWX or unmounted RWO volume

nfs-rwx

Mounted RWO volume

nfs-rwo

FAQ

Ask more questions, if you like ;)

I need to run the mounter pod as root, but my Pod Security Admission blocks the creation. What needs to be done?

You can add a label to the namespace you want the pod to be spawned in, to create an exception.

kubectl label namespace NAMESPACE-NAME pod-security.kubernetes.io/enforce=privileged

Star History

Star History Chart