Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
2 tasks done
hbel opened this issue Jun 2, 2020 · 22 comments
Closed
2 tasks done

Comments

@hbel
Copy link

hbel commented Jun 2, 2020

  • 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
@zhuyumi
Copy link

zhuyumi commented Jun 7, 2020

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
Copy link
Author

hbel commented Jun 8, 2020

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
Copy link

zhuyumi commented Jun 8, 2020

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
Copy link

zssng commented Jun 10, 2020

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
Copy link

zhuyumi commented Jun 10, 2020

@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
Copy link

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

This makes Persistent Volumes unusable and broken.

@fornous
Copy link

fornous commented Sep 9, 2020

The same here volume data lost ...

@zhleonix
Copy link

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
Copy link

snekcz commented Nov 25, 2020

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
Copy link

+1

@ivorscott
Copy link

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

@wanderrful
Copy link

wanderrful commented Jan 2, 2021

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
Copy link

jm-ra commented Feb 3, 2021

@wanderrful Which part of that is the workaround?

@wanderrful
Copy link

@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
Copy link

TBBle commented Feb 8, 2021

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.

@docker-robott
Copy link
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
Copy link

/remove-lifecycle stale

@docker-robott
Copy link
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
Copy link

/remove-lifecycle stale

@TBBle
Copy link

TBBle commented Aug 7, 2021

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
Copy link
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
Copy link
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

@docker docker locked and limited conversation to collaborators Jan 4, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests