Host Directory Mounting
In this tutorial you will share a directory from your host machine with pods running inside a kinder cluster. Because kinder nodes are Docker (or Podman) containers, a host directory cannot reach a pod in a single step — it travels through two hops: the host directory is mounted into the node container via extraMounts, and from there a Kubernetes hostPath PersistentVolume exposes it to pods. By the end of this guide you will have a running pod that reads a file written on your host.
Prerequisites
Section titled “Prerequisites”- kinder installed
- Docker (or Podman) installed and running
kubectlinstalled and on PATH- A host directory you want to share with the cluster
Step 1: Create a host directory
Section titled “Step 1: Create a host directory”Create the directory and add a test file so you can verify the mount end-to-end:
mkdir -p ~/shared-dataecho "hello from the host" > ~/shared-data/hello.txtStep 2: Create the cluster with extraMounts
Section titled “Step 2: Create the cluster with extraMounts”Save the following as cluster-config.yaml. The extraMounts field tells kinder (and the underlying kind cluster) to bind-mount ~/shared-data from your host into each node container at /mnt/host-data:
kind: ClusterapiVersion: kind.x-k8s.io/v1alpha4nodes: - role: control-plane extraMounts: - hostPath: /Users/you/shared-data containerPath: /mnt/host-dataReplace /Users/you/shared-data with the absolute path of the directory you created in Step 1 (use echo ~/shared-data to resolve the tilde).
Create the cluster:
kinder create cluster --config cluster-config.yamlStep 3: Create a PersistentVolume and PersistentVolumeClaim
Section titled “Step 3: Create a PersistentVolume and PersistentVolumeClaim”Now that the directory is available inside every node container at /mnt/host-data, create a Kubernetes hostPath PersistentVolume that points to that containerPath. Save the following as pv-pvc.yaml:
apiVersion: v1kind: PersistentVolumemetadata: name: host-data-pvspec: capacity: storage: 1Gi accessModes: - ReadWriteOnce storageClassName: manual hostPath: path: /mnt/host-data---apiVersion: v1kind: PersistentVolumeClaimmetadata: name: host-data-pvcspec: accessModes: - ReadWriteOnce storageClassName: manual resources: requests: storage: 1GiApply it:
kubectl apply -f pv-pvc.yamlVerify the PV is bound:
kubectl get pv host-data-pvExpected output:
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS AGEhost-data-pv 1Gi RWO Retain Bound default/host-data-pvc manual 10sStep 4: Deploy a pod that consumes the PVC
Section titled “Step 4: Deploy a pod that consumes the PVC”Save the following as reader-pod.yaml. The pod mounts the PVC at /data and reads hello.txt:
apiVersion: v1kind: Podmetadata: name: host-data-readerspec: containers: - name: reader image: busybox:1.37.0 command: ["sh", "-c", "cat /data/hello.txt && sleep 3600"] volumeMounts: - name: host-data mountPath: /data volumes: - name: host-data persistentVolumeClaim: claimName: host-data-pvcApply it:
kubectl apply -f reader-pod.yamlWait for the pod to be running:
kubectl get pod host-data-readerExpected output:
NAME READY STATUS RESTARTS AGEhost-data-reader 1/1 Running 0 15sStep 5: Verify the mount
Section titled “Step 5: Verify the mount”Read the logs from the pod to confirm it can see the file from your host:
kubectl logs host-data-readerExpected output:
hello from the hostThe pod read hello.txt directly from your host machine through the two-hop mount chain.
How it works
Section titled “How it works”Data travels through two hops to reach the pod:
Host machine Node container Pod~/shared-data ---> /mnt/host-data ---> /data(extraMounts) (hostPath PV) (volumeMount)- Hop 1 —
extraMounts: kinder passes thehostPath/containerPathpair to the container runtime (Docker or Podman) when it creates the node container. The host directory appears atcontainerPathinside the node. - Hop 2 —
hostPathPV: Kubernetes creates a PersistentVolume backed byhostPath: /mnt/host-data. Because this path already exists in the node’s filesystem (from Hop 1), the volume is immediately available. The PVC binds to the PV and the pod mounts it.
Platform notes
Section titled “Platform notes”macOS (Docker Desktop)
Section titled “macOS (Docker Desktop)”On macOS, Docker Desktop runs a Linux VM. For a host directory to reach a kinder node container, Docker Desktop must be configured to share it with that VM first.
File sharing: Open Docker Desktop → Settings → Resources → File sharing. Add the parent directory of your hostPath (e.g., /Users/you) if it is not already listed. The default shared paths are /Users, /Volumes, /private, /tmp, and /var/folders. Paths outside these directories will not be accessible.
Mount propagation: The propagation field in extraMounts controls whether sub-mounts created at runtime are visible across the host/node boundary. On macOS, propagation modes other than None are not supported for paths that originate on the macOS host (outside the Docker Desktop VM). Set propagation: None (the default) unless you are mounting a path that exists only inside the Docker Desktop Linux VM.
Windows (Docker Desktop with WSL 2)
Section titled “Windows (Docker Desktop with WSL 2)”Windows paths must use forward slashes and be expressed as WSL paths (e.g., /mnt/c/Users/you/shared-data rather than C:\Users\you\shared-data). Ensure the directory is within a WSL 2 filesystem or is exposed via Docker Desktop’s drive sharing.
On Linux, Docker (or Podman) runs natively and there is no intermediate VM. All host paths are directly accessible. Mount propagation modes (HostToContainer, Bidirectional) work as expected.
Troubleshooting
Section titled “Troubleshooting”Clean up
Section titled “Clean up”Delete the pod and Kubernetes objects:
kubectl delete pod host-data-readerkubectl delete pvc host-data-pvckubectl delete pv host-data-pvDelete the cluster:
kinder delete clusterOptionally remove the host directory:
rm -rf ~/shared-data