-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Add the ability to automount images as volumes via play #22410
Add the ability to automount images as volumes via play #22410
Conversation
Just compile tested right now, will get real tests done after lunch. |
Ephemeral COPR build failed. @containers/packit-build please check. |
pkg/domain/infra/abi/play.go
Outdated
} | ||
|
||
volumes := inspect.Config.Volumes | ||
if len(volumes) != 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The data volume container images can have a single VOLUME directive as a list of volumes. For example,
VOLUME ["/path1/to/vol1", "/path1/to/vol2", "/path2/to/vol3" ]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, do you want to mount the image to every path given as a VOLUME?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, all the defined volumes to the respective path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, just to be clear it’s not the entire image that we want to mount. Just the specific volume paths in the image.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, to be clear, if the volume is /path/to/vol1
, you want to mount /path/to/vol1
in the image to /path/to/vol1
in the container?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright. Based on this, new requirements are:
- The image must already exist in storage.
- The image must have at least 1 Volume directive.
- The volume path in the image will be mounted to the same path in the container; IE, if the image specifies a volume at
/my/volume/a
, the content in the image at/my/volume/a
will be made available in the container at/my/volume/a
- More than one image can be specified, but the paths they mount to (the Volume directives) must be different for all volumes in all images mounted into a single container.
- The images are always mounted read-only.
- Images to mount are defined in the annotation "io.podman.annotations.kube.image.automount/$ctrname" as a semicolon-separated list. They are mounted into a single container in the pod, not the whole pod.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the requirement "but the paths they mount to (the Volume directives) must be different for all volumes in all images mounted into a single container", I was thinking that instead of aborting the operation can we just keep overriding the mount point with the next one in the order in case of conflict? Podman can log a warning message though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should be workable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Matt.
pkg/domain/infra/abi/play.go
Outdated
} | ||
|
||
volumes := inspect.Config.Volumes | ||
if len(volumes) != 1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to limit this to single volume?
@mheon , |
pkg/domain/infra/abi/play.go
Outdated
} | ||
|
||
imgVol := new(specgen.ImageVolume) | ||
imgVol.Source = fullName |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the Source would be something like fullName + volPath
libpod/define/annotations.go
Outdated
@@ -160,6 +160,9 @@ const ( | |||
// the k8s behavior of waiting for the intialDelaySeconds to be over before updating the status | |||
KubeHealthCheckAnnotation = "io.podman.annotations.kube.health.check" | |||
|
|||
// KubeImageAutomountAnnotation | |||
KubeImageAutomountAnnotation = "io.podman.annotations.kube.image.automount" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be named io.podman.annotations.image-volumes.mount
?
bc75132
to
fecebdd
Compare
Repushed. Still need manpages and a test for the |
@Luap99 I think this one is ready for initial review now. |
1b84967
to
08ce620
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
overall looks good, using SubPath for this is a elegant solution
volumes := inspect.Config.Volumes | ||
|
||
for path, _ := range volumes { | ||
if oldPath, ok := volMap[path]; ok && oldPath != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oldPath != nil check seems a bit pointless given we already now we have a map entry by checking ok
pkg/domain/infra/abi/play.go
Outdated
|
||
for path := range volumes { | ||
if oldPath, ok := volMap[path]; ok && oldPath != nil { | ||
logrus.Warnf("Multiple volume mounts to %s requested, overriding image %s with image %s", path, oldPath.Source, fullName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you sue %q
for the paths, given this comes from unknown images we may face weird input such as empty string which would be hard to catch otherwise.
9feb50d
to
739e87f
Compare
This should be ready for final review. |
@@ -981,3 +981,45 @@ _EOF | |||
run_podman pod rm -t 0 -f test_pod | |||
run_podman rmi -f userimage:latest $from_image | |||
} | |||
|
|||
@test "podman play with automount volume" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@edsantiago PTAL if you get a chance, this test works but it can probably be improved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few nits and suggestions
test/system/700-play.bats
Outdated
RUN sh -c 'mkdir /test1 /test2' | ||
RUN sh -c 'touch /test1/a /test1/b /test1/c' | ||
RUN sh -c 'touch /test2/asdf /test2/ejgre /test2/lteghe' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the sh -c
? All of those commands should work just fine with RUN. (Update: they do)
test/system/700-play.bats
Outdated
spec: | ||
restartPolicy: Never | ||
containers: | ||
- name: test1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ARGH. As a bear of very little brain, I found it impossible to figure out "is this test1 the volume or test1 the container?" Could you please rename this to testctr
(or whatever), and similarly update lines 1014, 1018, 1023?
test/system/700-play.bats
Outdated
run_podman run --rm automount_test ls /test1 | ||
run_out_test1="$output" | ||
run_podman exec test_pod-test1 ls /test1 | ||
assert "$output" = "$run_out_test1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a fourth arg here, something like "exec ls /test1"...
test/system/700-play.bats
Outdated
run_podman run --rm automount_test ls /test2 | ||
run_out_test2="$output" | ||
run_podman exec test_pod-test1 ls /test2 | ||
assert "$output" = "$run_out_test2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...and likewise here, "exec ls /test2".
That makes it possible for a human viewing test results to understand what happened without having to scroll up, look at line numbers, scroll back down, etc
run_out_test2="$output" | ||
run_podman exec test_pod-test1 ls /test2 | ||
assert "$output" = "$run_out_test2" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add cleanup to avoid nasty red clutter in test logs:
run_podman rm -f -t0 -a
run_podman rmi automount_test
739e87f
to
687165c
Compare
Final comments addressed, CI should go green, @containers/podman-maintainers PTAL |
LGTM! |
toReturn := make([]*specgen.ImageVolume, 0, len(volMap)) | ||
for _, vol := range volMap { | ||
toReturn = append(toReturn, vol) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the ordering matter? I just noticed that we turn it from something order to a map back then back to a array, the map looping is not deterministic. As such we open the door for undeterministic flakes here if the order veer matters somewhere. I cannot think of any example where this might be a issue but I like to point it out regardless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to hope that crun/runc are capable of sorting mounts so they happen in the correct order (e.g. /etc before /etc/mydir if both are volumes) otherwise we'd have a lot more issues than just this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am pretty sure the runtimes don't do that, they mount in the order they got AFAIK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. Maybe we do a sort before we pass them over in Libpod, during final spec generation? I'll do a bit of poking, but I'm pretty confident ordering is a solved problem - just a question of where.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah yeah sortMounts(g.Mounts())
in the spec generation, so this is good then
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: Luap99, mheon 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 |
687165c
to
0010185
Compare
Bud errors are happening on multiple PRs, something is up with CI |
Image volumes (the `--mount type=image,...` kind, not the `podman volume create --driver image ...` kind - it's strange that we have two) are needed for our automount scheme, but the request is that we mount only specific subpaths from the image into the container. To do that, we need image volume subpath support. Not that difficult code-wise, mostly just plumbing. Also, add support to the CLI; not strictly necessary, but it doesn't hurt anything and will make testing easier. Signed-off-by: Matt Heon <[email protected]>
Effectively, this is an ability to take an image already pulled to the system, and automatically mount it into one or more containers defined in Kubernetes YAML accepted by `podman play`. Requirements: - The image must already exist in storage. - The image must have at least 1 volume directive. - The path given by the volume directive will be mounted from the image into the container. For example, an image with a volume at `/test/test_dir` will have `/test/test_dir` in the image mounted to `/test/test_dir` in the container. - Multiple images can be specified. If multiple images have a volume at a specific path, the last image specified trumps. - The images are always mounted read-only. - Images to mount are defined in the annotation "io.podman.annotations.kube.image.automount/$ctrname" as a semicolon-separated list. They are mounted into a single container in the pod, not the whole pod. As we're using a nonstandard annotation, this is Podman only, any Kubernetes install will just ignore this. Underneath, this compiles down to an image volume (`podman run --mount type=image,...`) with subpaths to specify what bits we want to mount into the container. Signed-off-by: Matt Heon <[email protected]>
0010185
to
30e2c92
Compare
/lgtm |
15cc886
into
containers:main
Effectively, this is an ability to take an image already pulled to the system, and automatically mount it into one or more containers defined in Kubernetes YAML accepted by
podman play
.Requirements:
As we're using a nonstandard annotation, this is Podman only, any Kubernetes install will just ignore this.
Underneath, this compiles down to an image volume
(
podman run --mount type=image,...
).Does this PR introduce a user-facing change?