Skip to content

Persistent volumes get lost in Kubernetes on Docker Desktop for Windows/WSL2 #7023

Closed
@hbel

Description

@hbel
    • I have tried with the latest version of my channel (Stable or Edge)
    • I have uploaded Diagnostics
    • Diagnostics ID: 2FBDD8C2-1DBB-45C8-A4C8-1FC5E25BD030/20200602184256

Expected behavior

  1. When creating a new persistent volume and new persistent volume claim that gets used in a pod, I expect to find the contents created by the pod in the given file path.

  2. Data stored in the persistent volume is still available after a reboot, since it should be stored in wsl2's file system.

Actual behavior

  1. I am not able to find the according path at all in my wsl2 file system.
  2. All data stored in the persistent volume is lost.

Information

  • Windows Version: Windows 10 Pro 2004
  • Docker Desktop Version: 2.3.03, running in WSL2
  • I could only test this on one machine because Kubernetes is not working on any other of my Windows machines yet.
  1. Which part of the file system gets accessed by Kubernetes when running in WSL2
  2. Where can I find my persistent volumes in the file systems (obviously there are not located under /var/k8s. BTW, there is also no /var/lib/docker as far as I can see)
  3. Why are these volumes not persistent and get deleted when shutting down WSL2 or Windows?

Steps to reproduce the behavior

Create a persistent volume and claim

apiVersion: v1
kind: PersistentVolume
metadata:
  name: neo4j-pv-volume
  namespace: persistence
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/var/k8s/data/neo4j"

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: neo4j-pv-claim
  namespace: persistence
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

Ruin a deployment using the persistent volume claim

apiVersion: apps/v1
kind: Deployment
metadata:
  name: neo4j
  namespace: persistence
spec:
  selector:
    matchLabels:
      db: neo4j
  template:
    metadata:
      labels:
        db: neo4j
    spec:
      volumes:
        - name: neo4j-pv-storage
          persistentVolumeClaim:
            claimName: neo4j-pv-claim
      containers:
      - name: neo4j
        image: neo4j:4.0.4
        ports:
          - containerPort: 7474
          - containerPort: 7687
        volumeMounts:
          - mountPath: "/data"
            name: neo4j-pv-storage
        env:
          - name: NEO4J_AUTH
            value: neo4j/neo4j

Activity

zhuyumi

zhuyumi commented on Jun 7, 2020

@zhuyumi

I had the similar issue with you, but it's a slight bit different, I was trying to mount as hostPath.
After some time on Google, I found this workaround works for me:
#5325 (comment)

If you feeling unclear about the above post, here is my working example:
In my k8s deployment yaml file, it's trying to mount a config.js file as a volume.
It's not 100% meet your Persistent volumes need, but I hope it can give you some reference.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ExampleProject
  labels:
    app: ExampleProject
spec:
      volumes:
        - name: example-volume
          hostPath:
            # path: 'E:\ExampleProject\config.js' THIS commented line was working in old DockerDesktopForWindows before I move to WSL2. It mounts my Windows file to the K8S pod. But failed after enabling WSL2.
            path: '/run/desktop/mnt/host/wsl/k8s-mount/ExampleProject/config.js'
            type: File
      containers:
        - image: example-image
          name: example-name
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: example-volume
              mountPath: "/usr/share/nginx/html/config.js"

Here I use Ubuntu-18.04 as WSL integration.
See, instead of trying to mount the file from my Windwos OS, I put the actual config.js file inside of the Ubuntu, the path is /mnt/wsl/k8s-ount/ExampleProject/config.js
Plus, when I mount it in k8s YAML file, I need to hacky and use /run/desktop/mnt/host/wsl/k8s-mount/ExampleProject/config.js instead.
Then, I go back to Windows and apply the YAML, the config.js file is mounted fine.
image

hbel

hbel commented on Jun 8, 2020

@hbel
Author

Actually, it does help. Although this makes things unnecessary complicated for the developers (I intended to provide them with a consistent deployment over all OS choices for their development systems), it helped to get that at least running under WSL2. One thing though, if storing the files in a cross-mounted directory not located on a windows drive, the mount seems to be a tmpfs - so if you really need persistent data, better not store it in a freshly created directory but on /run/desktop/mn/host/c or something similar.

Still, this is just a workaround, not a real solution. At least this behaviour should be documented officially somewhere. Which doesn't seem to be the case right now.

zhuyumi

zhuyumi commented on Jun 8, 2020

@zhuyumi

I totally agree.
According to the 'best practice' of using WSL2, we should copy over our codebase to WSL to gain the best performance.
Given this issue and other difficulties I had so far with WSL2, I'm considering if I should go back to HyperV......

zssng

zssng commented on Jun 10, 2020

@zssng

I have same issue. I mount host folder /C/Users/xx/k8s/test .But nothing shows under the folder
Here is a test config.

apiVersion: v1
kind: Namespace
metadata:
  name: test-storage

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: test-pv-volume
  labels:
    type: local
  namespace: test-storage
spec:
  storageClassName: manual
  capacity:
    storage: 20Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/C/Users/xx/k8s/test" #host path to mount
    # type: Directory  # if uncomment this, get is not a directory error

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pv-claim
  namespace: test-storage
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: manual
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: alpine
  labels:
    app: test-storage
  namespace: test-storage
spec:
  selector:
    matchLabels:
      app: test-storage
  template:
    metadata:
      labels:
        app: test-storage
    spec:
      containers:
      - image: alpine
        name: test-storage
        volumeMounts:
        - name: test-persistent-storage
          mountPath: /testdata
        command: ["/bin/sh"]
        args: ["-c", "echo aa > /testdata/11.txt && ls -s testdata && ls /mnt"]
      volumes:
      - name: test-persistent-storage
        persistentVolumeClaim:
          claimName: test-pv-claim

This is the output

total 4
     4 11.txt

Host folder file not shown in the container mount path,and container directory file not shown in host path.

version: 2.3.0.3, older version (2.2.x) works fine.

And docker run --rm -v /C/Users/xx/k8s/test:/testdata alpine ls -s /testdata show the host file in contanier

zhuyumi

zhuyumi commented on Jun 10, 2020

@zhuyumi

@zssng Your problem is a little bit different here.
You were trying to mount your Windows host path, while hbel was trying to mount the Linux path inside of WSL2 itself.

But yeah, it would be good to have your case supported as well.

mentos1386

mentos1386 commented on Sep 8, 2020

@mentos1386

We are experiencing the same issues. Data stored using PersistentVolumeClaim gets lost after restarting docker.

This makes Persistent Volumes unusable and broken.

fornous

fornous commented on Sep 9, 2020

@fornous

The same here volume data lost ...

zhleonix

zhleonix commented on Sep 23, 2020

@zhleonix

Same here when using Docker Desktop for win 19.3.
I have created statefulSet on embedded K8s and docker.io/hostpath is used as provisioner of PVC.

Volumes can be successfully created under /C/Users/xx/.docker/volumes/, which is mapped in MobyVM under /host_mnt/c/....

However, in MobyVM path, I can see the files created by container, but in Windows, the directory is empty. After restarted Docker Desktop, all changes on the persistent volume are gone.

snekcz

snekcz commented on Nov 25, 2020

@snekcz

Hey Docker guys, can someone from you comment on this issue, please? It's been open for almost half a year without any reaction from your side. Thank you.

This issue makes the Deploy on Kubernetes feature unusable.

wanderrful

wanderrful commented on Nov 29, 2020

@wanderrful

+1

ivorscott

ivorscott commented on Jan 2, 2021

@ivorscott

For what its worth this happens on docker for mac as well and it's really annoying.

wanderrful

wanderrful commented on Jan 2, 2021

@wanderrful

I was able to find a workaround for Windows by using this type of path with the PersistentVolume resource (this example is setting a local volume for RabbitMQ):

apiVersion: v1
kind: PersistentVolume
metadata:
  name: rabbit-pv
  namespace: my-namespace
spec:
  capacity:
    storage: 512Mi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: rabbit-local-storage
  local:
    path: /run/desktop/mnt/host/c/myRabbitDrive
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - docker-desktop

The docker-desktop node is the one created by default.

jm-ra

jm-ra commented on Feb 3, 2021

@jm-ra

@wanderrful Which part of that is the workaround?

wanderrful

wanderrful commented on Feb 4, 2021

@wanderrful

@wanderrful Which part of that is the workaround?

At least in my case, local.path shows how we directly we reference the Windows folder so that we can connect the PersistentVolume locally on a Windows machine.

The nodeAffinity.required.nodeSelectorTerms[0][0].values[0] is what we get from checking the valid Kubernetes nodes on our k8s cluster. In my case, it was just a normal Docker Desktop.

I didn't include the corresponding PVC and Storage resource, but the PV I posted there was the critical piece of the puzzle. For me, at least.

TBBle

TBBle commented on Feb 8, 2021

@TBBle

Looking at the initial request, it appears the request is to have a hostPath mount from Docker Desktop-bundled k8s into a different WSL2 distribution?

Docker Desktop is not running in your current WSL2 distribution, it has its own, and runs inside mount namespaces under that, for isolation, so you can't access it from the same root, as the initial request was trying to do.

So I suspect the solution is the same as for mounting from the Windows host (above), except instead of /run/desktop/mnt/host/<DRIVE> it's probably going to be a path in /mnt/desktop/mnt/host/wsl.

To find out, become root in WSL while Docker Desktop is running, and run

ls -l /proc/$(pidof kubelet)/root/run/desktop/mnt/host/wsl

I don't have any other WSL distributions installed, so all see there is Docker's own WSL distributions.

au1-wl-005:/tmp/docker-desktop-root/mnt/host/c/Users/paulh# ls -l /proc/$(pidof kubelet)/root/run/desktop/mnt/host/wsl
total 0
drwxr-xr-x    4 root     root           100 Feb  8 01:28 docker-desktop
drwxr-xr-x    6 root     root           120 Feb  8 01:28 docker-desktop-data

That said, those appear to be specific mounts, rather than just the root filesystem for those distributions, so I don't know whether other WSL2 distributions will appear there. I think this is a bind-mount of the crossMount=true mounts described in microsoft/WSL#4577, based on /etc/wsl.conf in the docker-desktop WSL2 distro:

[automount]
root = /mnt/host
crossDistro = true
options = "metadata"

However, per microsoft/WSL#4577 (comment) it's possible other distros won't auto-mount there, if crossDistro has been dropped. Per microsoft/WSL#5177 (comment) I believe you can expose your distro into /mnt/wsl (visible at /run/desktop/mnt/host/wsl for hostPath PV purposes) and other distros will then see whatever you chose to share, so that might be necessary to do what the original ticket wanted.

So the solution at #7023 (comment) is nearly correct, except before using a path under /run/desktop/mnt/host/wsl/ you need to bind-mount something into /mnt/wsl on the distro you want to persist to or expose data from. Otherwise, as noted in that solution, you are storing data in a tmpfs and it's lost on WSL shutdown.

Per microsoft/WSL#5177 (comment) and microsoft/WSL#5851, there's an issue that the mount points are lost on WSL shutdown, which is tricky to solve because it would require starting other distros before starting the docker desktop k8s stack.


For contrast, if you let the storage-provisioner service dynamically allocate a PV for your PVC, it's stored internally, e.g.,

au1-wl-005:/tmp/docker-desktop-root/mnt/host/c/Users/paulh# ls -l /proc/$(pidof storage-provisioner)/root/var/lib/k8s-pvs/
total 8
drwxr-xr-x    2 root     root          4096 Feb  8 05:29 some-stateful-set-0

I'm not sure where that actually lives physically, I suspect it's a virtual disk mounted from somewhere else as it shows up as /dev/sdc in a few other places.

2 remaining items

stefanloerwald

stefanloerwald commented on May 9, 2021

@stefanloerwald

/remove-lifecycle stale

docker-robott

docker-robott commented on Aug 7, 2021

@docker-robott
Collaborator

Issues go stale after 90 days of inactivity.
Mark the issue as fresh with /remove-lifecycle stale comment.
Stale issues will be closed after an additional 30 days of inactivity.

Prevent issues from auto-closing with an /lifecycle frozen comment.

If this issue is safe to close now please do so.

Send feedback to Docker Community Slack channels #docker-for-mac or #docker-for-windows.
/lifecycle stale

stefanloerwald

stefanloerwald commented on Aug 7, 2021

@stefanloerwald

/remove-lifecycle stale

TBBle

TBBle commented on Aug 7, 2021

@TBBle

I was thinking about this. It would be feasible (but not trivial) to write a CSI driver which could mount like hostPath but from other WSL2 distros than the current one (i.e the docker-desktop distro), which appeared to be what the original poster wanted.

It'd probably work a lot like the CSI Proxy system used to support CSI on Windows, except hopefully it would be able to launch the target WSL distro directly to host the back-end, rather than needing to be started externally, as the backend of the CSI Proxy requires.

That would avoid the use of magic /mnt/wsl-based symlinks and hence the ordering issues associated with them.

In theory such a thing would work not just in Docker Desktop for Windows's k8s implementation, but any other WSL2-hosted k8s environment too.

docker-robott

docker-robott commented on Nov 5, 2021

@docker-robott
Collaborator

Issues go stale after 90 days of inactivity.
Mark the issue as fresh with /remove-lifecycle stale comment.
Stale issues will be closed after an additional 30 days of inactivity.

Prevent issues from auto-closing with an /lifecycle frozen comment.

If this issue is safe to close now please do so.

Send feedback to Docker Community Slack channels #docker-for-mac or #docker-for-windows.
/lifecycle stale

docker-robott

docker-robott commented on Jan 4, 2022

@docker-robott
Collaborator

Closed issues are locked after 30 days of inactivity.
This helps our team focus on active issues.

If you have found a problem that seems similar to this, please open a new issue.

Send feedback to Docker Community Slack channels #docker-for-mac or #docker-for-windows.
/lifecycle locked

locked and limited conversation to collaborators on Jan 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @TBBle@wanderrful@zhleonix@ivorscott@mentos1386

        Issue actions

          Persistent volumes get lost in Kubernetes on Docker Desktop for Windows/WSL2 · Issue #7023 · docker/for-win