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

Correctly handle named pipe host mounts for Windows #69484

Merged
merged 5 commits into from
Oct 30, 2018
Merged

Correctly handle named pipe host mounts for Windows #69484

merged 5 commits into from
Oct 30, 2018

Conversation

ddebroy
Copy link
Member

@ddebroy ddebroy commented Oct 5, 2018

What this PR does / why we need it:
Windows named pipes in host mounts were not being correctly handled and passed through to the container runtime. This PR adds support to detect named pipes in Windows and skip the processing associated with regular file system based host mount paths in Windows.

Which issue(s) this PR fixes (optional, in fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when PR gets merged):
Fixes # #67147

Special notes for your reviewer:
Tested the following spec spawns up the pod container on Windows with the mount paths to \\.\pipe\docker_pipe correctly configured:

apiVersion: v1
kind: Pod
metadata:
  name: docker-pipe-windows
spec:
  nodeSelector:
    beta.kubernetes.io/os: windows
  containers:
    - name: main
      image: microsoft/windowsservercore:1803
      command:
        - powershell
        - Start-Sleep
        - "-s 3600"
      volumeMounts:
        - mountPath: \\.\pipe\docker-engine
          name: docker-pipe
  volumes:
    - name: docker-pipe
      hostPath: 
        path: \\.\pipe\docker-engine
        type: null
  restartPolicy: Never

docker inspect output for above container:

...
        "Mounts": [
            {
                "Type": "npipe",
                "Source": "\\\\.\\pipe\\docker-engine",
                "Destination": "\\\\.\\pipe\\docker-engine",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "bind",
                "Source": "c:\\var\\lib\\kubelet\\pods\\1e664368-c8f7-11e8-97bc-000d3a35a802\\volumes\\kubernetes.io~secret\\default-token-5kttv",
                "Destination": "c:\\var\\run\\secrets\\kubernetes.io\\serviceaccount",
                "Mode": "",
                "RW": false,
                "Propagation": ""
            }
        ],
...

Release note:

Handle Windows named pipes in host mounts.

Signed-off-by: Deep Debroy <ddebroy@docker.com>
@k8s-ci-robot k8s-ci-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-kind Indicates a PR lacks a `kind/foo` label and requires one. needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. labels Oct 5, 2018
@ddebroy
Copy link
Member Author

ddebroy commented Oct 5, 2018

/sig storage

@k8s-ci-robot k8s-ci-robot added sig/storage Categorizes an issue or PR as relevant to SIG Storage. and removed needs-sig Indicates an issue or PR lacks a `sig/foo` label and requires one. labels Oct 5, 2018
@k8s-ci-robot k8s-ci-robot added area/kubelet sig/node Categorizes an issue or PR as relevant to SIG Node. labels Oct 5, 2018
@ddebroy
Copy link
Member Author

ddebroy commented Oct 5, 2018

/assign @dchen1107

@ddebroy
Copy link
Member Author

ddebroy commented Oct 5, 2018

cc @feiskyer @andyzhangx

@ddebroy
Copy link
Member Author

ddebroy commented Oct 6, 2018

/kind bug

@k8s-ci-robot k8s-ci-robot added kind/bug Categorizes issue or PR as related to a bug. and removed needs-kind Indicates a PR lacks a `kind/foo` label and requires one. labels Oct 6, 2018
@ddebroy
Copy link
Member Author

ddebroy commented Oct 6, 2018

/test pull-kubernetes-verify

@ddebroy
Copy link
Member Author

ddebroy commented Oct 6, 2018

/test pull-kubernetes-local-e2e-containerized

Copy link
Member

@feiskyer feiskyer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@PatrickLang Would you like also take a look?

@feiskyer
Copy link
Member

feiskyer commented Oct 6, 2018

/retest

@@ -945,6 +945,13 @@ func CheckPersistentVolumeClaimModeBlock(pvc *v1.PersistentVolumeClaim) bool {
return utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == v1.PersistentVolumeBlock
}

func IsWindowsNamedPipe(goos, path string) bool {
if goos == "windows" && strings.HasPrefix(path, `\\.\pipe\`) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PatrickLang @atomaras Does named pipe also starts with \\.\pipe\? what about upper case like \\.\Pipe\ ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also supports like this: \.\pipe\ ...

docker run -it --rm -v \.\pipe\docker_engine:\.\pipe\docker_engine microsoft:windowsservercore:1803 powershell

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the logic here needs to be aligned with logic in the runtime. Here are some references:
https://github.com/moby/moby/blob/master/volume/mounts/windows_parser.go#L44
and
https://github.com/moby/moby/blob/master/libcontainerd/client_local_windows.go#L303
Both consider \\.\pipe as the standard named pipe prefix for local pipes on Windows.

@andyzhangx, \.\pipe\... is rejected by Docker:

C:\k>docker run -ti -v \.\pipe\docker_engine:\.\pipe\docker_engine microsoft/windowsservercore:1803
docker: Error response from daemon: invalid volume specification: '\.\pipe\docker_engine:\.\pipe\docker_engine'.

Copy link
Contributor

@PatrickLang PatrickLang Oct 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The underlying CreateFileW() is case insensitive by default, so \\.\pipe\foo == \\.\Pipe\foo
https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilew

If it's constrained in the lower layer (moby / containerd), then the same check should be used here. I think it's ok as-is

@bertinatto
Copy link
Member

I seems like pull-kubernetes-local-e2e-containerized is failing because of #69465 .

@ddebroy
Copy link
Member Author

ddebroy commented Oct 9, 2018

/test pull-kubernetes-local-e2e-containerized

@ddebroy
Copy link
Member Author

ddebroy commented Oct 10, 2018

/retest

@PatrickLang
Copy link
Contributor

I talked to @ddebroy on Slack, and this requires Docker EE-basic 18.03 or later. If you're testing on an Azure VM, you need to be sure to upgrade Docker first. This is tracked at Azure/acs-engine#3852

containerPath := mount.MountPath
if runtime.GOOS == "windows" {
if (strings.HasPrefix(hostPath, "/") || strings.HasPrefix(hostPath, "\\")) && !strings.Contains(hostPath, ":") {
if !volumeutil.IsWindowsNamedPipe(runtime.GOOS, hostPath) && (strings.HasPrefix(hostPath, "/") || strings.HasPrefix(hostPath, "\\")) && !strings.Contains(hostPath, ":") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - can you preserve the parenthesis so that the grouping is still easy to see?

@ddebroy
Copy link
Member Author

ddebroy commented Oct 17, 2018

@Random-Liu @saad-ali PTAL if this looks good to be approved. Not sure if @dchen1107 (who was originally assigned) is online/offline.

Copy link
Member

@saad-ali saad-ali left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of minor comments.

/approve

// IsWindowsUNCPath checks if path is prefixed with \\
// This can be used to skip any processing of paths
// that point to SMB shares, local named pipes and local UNC path
func IsWindowsUNCPath(goos, path string) bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, why is goos a parameter and not generated inside this method?

Copy link
Member Author

@ddebroy ddebroy Oct 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

goos as a parameter allows for an easy way to unit-test the function to make sure in other OS environments, there are no unexpected results.

@@ -218,11 +218,13 @@ func makeMounts(pod *v1.Pod, podDir string, container *v1.Container, hostName, h
// Docker Volume Mounts fail on Windows if it is not of the form C:/
containerPath := mount.MountPath
if runtime.GOOS == "windows" {
if (strings.HasPrefix(hostPath, "/") || strings.HasPrefix(hostPath, "\\")) && !strings.Contains(hostPath, ":") {
// Append C: only if it looks like a local path. Do not process UNC path/SMB shares/named pipes
if (strings.HasPrefix(hostPath, "/") || strings.HasPrefix(hostPath, "\\")) && !strings.Contains(hostPath, ":") && !volumeutil.IsWindowsUNCPath(runtime.GOOS, hostPath) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsWindowsUNCPath is checking for prefix \ e.g. \foo\bar which is different from what strings.HasPrefix(hostPath, "\") is checking for: \ vs \

That is very subtle. Add a comment explaining this, so folks are less likely to "fix" this in the future by mistake. Also is there any unit test that can be added to kubelet_pods_tests.go for this to catch regressions?

@PatrickLang
Copy link
Contributor

For other reviewers - this change allows Windows mounts that are equivalent to /var/run/docker.sock on Linux. The usual caveats around allowing HostPath mounts should apply to this too.

https://kubernetes.io/docs/concepts/policy/pod-security-policy/#volumes-and-file-systems

@PatrickLang
Copy link
Contributor

/lgtm
/approve

@PatrickLang
Copy link
Contributor

/assign @yujuhong
can you approve or assign to Dawn if you can't?

Signed-off-by: Deep Debroy <ddebroy@docker.com>
@k8s-ci-robot k8s-ci-robot removed the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 25, 2018
@yujuhong
Copy link
Contributor

/assign @yujuhong
can you approve or assign to Dawn if you can't?

Reviewed and left comments.

Signed-off-by: Deep Debroy <ddebroy@docker.com>
@k8s-ci-robot k8s-ci-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Oct 26, 2018
@ddebroy
Copy link
Member Author

ddebroy commented Oct 26, 2018

@yujuhong @PatrickLang @saad-ali thanks for reviewing so far. I have addressed the review comments ... PTAL.


// IsWindowsLocalPath checks if path is a local path
// prefixed with "/" or "\" like "/foo/bar" or "\foo\bar"
func IsWindowsLocalPath(goos, path string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should MakeAbsolutePath call this function instead?

Copy link
Member Author

@ddebroy ddebroy Oct 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yujuhong I would prefer to keep MakeAbsolutePath as is for now in the context of this PR. The scope of this PR is to enable named pipe mounting support in Windows and that code path skips MakeAbsolutePath. MakeAbsolutePath is called in a couple of contexts (not involving named pipes) and maybe refactored in a separate PR later?

hostPath = "c:" + hostPath
}
if volumeutil.IsWindowsLocalPath(runtime.GOOS, hostPath) {
hostPath = "c:" + hostPath
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this call MakeAbsolutePath instead?

Copy link
Member Author

@ddebroy ddebroy Oct 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yujuhong yes, done.

Signed-off-by: Deep Debroy <ddebroy@docker.com>
@ddebroy
Copy link
Member Author

ddebroy commented Oct 27, 2018

/retest

@ddebroy
Copy link
Member Author

ddebroy commented Oct 30, 2018

@yujuhong PTAL

@yujuhong
Copy link
Contributor

/lgtm
/approve

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Oct 30, 2018
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: ddebroy, PatrickLang, saad-ali, yujuhong

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. area/kubelet cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/bug Categorizes issue or PR as related to a bug. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/node Categorizes an issue or PR as relevant to SIG Node. sig/storage Categorizes an issue or PR as relevant to SIG Storage. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants