guest: pre-create nested mount points under read-only mounts - #2848
guest: pre-create nested mount points under read-only mounts#2848Jie Chen (jiechen0826) wants to merge 1 commit into
Conversation
|
Which type of parent mounts are targeted here? |
b9d2137 to
1445e2b
Compare
Good catch, thanks. This only targets read-only bind mounts whose source is a writable directory (the CRI volume mounts like emptyDir/configMap). For a read-only SCSI VHD the source is itself a read-only filesystem, so there's nothing to pre-create and runc would fail the same way regardless. I've added a guard that skips any parent whose source isn't writable, so read-only SCSI VHD and dm-verity parents are skipped up front. Does that cover your concern? |
runc applies the OCI mounts in spec order and remounts a bind mount read-only as soon as it processes it. When it then processes a child mount whose destination is nested inside that read-only mount and the mount point does not already exist, runc must create it under the now read-only parent and fails with EROFS. This breaks valid configurations where a read-only volume has another volume mounted into a subdirectory of it, for example a read-only /etc/coredns configMap with a custom config volume at /etc/coredns/custom. On a regular Kubernetes node the kubelet creates these subdirectories on the host before handing the spec to the runtime. Inside an LCOW UVM the guest owns the mount setup, so do the equivalent: for each nested mount, create the mount point inside the writable source of its read-only parent before the spec is handed to runc, so it already exists once the parent is made read-only. This is best effort; if a mount point cannot be pre-created it is logged and skipped so runc's own error still surfaces. Signed-off-by: Jie Chen <jiechen3@microsoft.com>
1445e2b to
7d408a1
Compare
Problem
Containers fail to start with
read-only file system(EROFS) when a volume is mounted into a subdirectory of another volume that is mounted read-only. For example:emptyDirat/mnt/data(readOnly) plus another volume at/mnt/data/subdirconfigMapat/etc/corednsplus a custom config volume at/etc/coredns/customRoot cause
runc applies
spec.Mountsin order and remounts a bind mount read-only as soon as it processes it. When it then processes a child mount nested under it, runc must create the child's mount point under the now read-only parent, which fails with EROFS.On a normal Kubernetes node the kubelet pre-creates these subdirectories on the host before handing the spec to the runtime. Inside an LCOW UVM the guest (GCS) owns the mount setup, so runc creates the mount point at
runc createtime and hits the read-only parent.Reordering the mounts does not help: mounting the child before the parent makes the parent bind mount shadow the child.
Fix
ensureNestedMountTargets(newinternal/guest/runtime/hcsv2/mount.go), called fromHost.CreateContainerjust before the spec is written for runc. For each mount whose destination is nested under a read-only bind mount, it pre-creates the mount point inside that parent's writable source (a directory, or an empty file when the child source is a file), so it already exists once runc makes the parent read-only. This mirrors what the kubelet does on a host node.It is best effort: if a mount point cannot be pre-created it logs and continues, so runc's own error still surfaces and unaffected containers are unchanged.
Testing