Volume Refactoring for plugin support#13025
Volume Refactoring for plugin support#13025crosbymichael wants to merge 1 commit intomoby:masterfrom
Conversation
|
So with this, there can be only 1 active volume driver? Is there a plan to extend this once we actually have more than 1? |
|
@cpuguy83 Yeah, we think about hook up driver right before |
daemon/daemon.go
Outdated
There was a problem hiding this comment.
Little inconsistence, this variable called as volumeDriver(without s) everywhere else
|
I'm obviously +1 for design, as the behavior changes come with a huge simplicity and readability boost. |
|
feel free to code review and i'll make changes based on feedback in a batch. |
daemon/create.go
Outdated
There was a problem hiding this comment.
Maybe it should be "Driver" instead of "Plugin"?
There was a problem hiding this comment.
How do you all want to call this internally?
There was a problem hiding this comment.
Should be specific to the thing itself. It being an external plugin is abstracted away. It could be a local driver or a remote driver. It would use the same interface. So it would probably be named after how the interface is named. In this case, Driver.
There was a problem hiding this comment.
I think plugin is okay. Because it is actually a plugin :)
There was a problem hiding this comment.
Well do we want to change the interface name and all references to Plugin now?
There was a problem hiding this comment.
But it might not be a plugin, right? If the value is local then it's the local driver...
There was a problem hiding this comment.
"local plugin"?
There was a problem hiding this comment.
It's the name of an object that implements the Driver interface, so whether it is the local driver or a driver from a plugin, it's the name of a the driver ... so Driver makes sense to me. Plugin doesn't just because ... it could be the local driver, right?
There was a problem hiding this comment.
I don't understand. I would rather not have two concepts, is it a Driver or a Plugin?? Lets just pick one term and use it everywhere. I don't think we need two separate terms to describe the same logic that these entities provide.
There was a problem hiding this comment.
Here's the thing. A plugin provides extensions of various types. It can provide a volume driver, a network driver, but maybe non-drivers, like maybe an event listener. These types are based on the interfaces they implement. A plugin is not just a driver or listener, it could be any. So the concept of plugin is just a thing that provides extensions in the form of implemented interfaces.
In this case, you're not even talking about a plugin, you're just talking about a driver. "What driver does this volume use?" Therefore, we call it Driver.
Imagine if there weren't plugins and just native Go pluggable things. What would you call it? Depends on the interface. Driver, Provider, etc
8fb1234 to
c557882
Compare
daemon/create.go
Outdated
There was a problem hiding this comment.
What best way to get this value? We need to do this on each daemon.volumeDriver operation. Seems like it requires at least Volume and Container. So should it be like GetVolumeDriver(container, volume)?
Maybe makes sense to embed it to Volume interface?
There was a problem hiding this comment.
Both places work fine. What do you think is better? A method on Volume that returns the DriverName() ?
There was a problem hiding this comment.
Now I think that Volumes runtime entity anyway and we can return volume.Driver directly for Volume to not seek it every time. Is it mad enough?
There was a problem hiding this comment.
Nice, I wanted to do this, but didn't want to fragment container.Volumes and container.VolumesRW.
This is much better.
|
Overall this design LGTM, some questions on implementation. |
|
@cpuguy83 we have to do some migration to get the existing volumes out of vfs and the repository info into the new container field. Maybe we could work together on that? |
If I understand correctly, this; Will no longer work? That sounds like a BIG change. I know many people are using bind-mounted volumes to either use pre-existing data, or to have control over the data, independent of the container lifecycle. Personally, we use a number of utility images/containers that attach to running containers using |
|
Actually yeah, I agree with that. |
|
Sorry, some additional thoughts on this after some sleep: Bind mounts are really really bad. They should not be 1st class citizens and their own separate thing. Allowing users to specify host paths to volume drivers also seems really really bad and only serves to promote the concept of binds... I can't think of a particularly good use case for it. Originally was ok with names on volumes (b/c it's implemented as either having a user specified name or an ID), however I think names are also something that are likely to only be used by a subset of volume drivers... and even then those cases probably don't actually need it. The reason for having volume configs on disk is primarily due to dangling volumes. |
+1. Wrt my earlier comment; if some (type of) volumes should be shared via
Are there still plans to have volumes as first-class citizens? I.e., being able to create/define a volume before it's being consumed by a container? Then I'd use the same approach as containers; create a volume and generate an ID. Optionally allow a name to be set for easier identification (otherwise a random name) (Wondering if "labels" (metadata) are considered for volumes, but not sure if that's something to discuss in this stage) |
|
@thaJeztah that is why bind mounts are not volumes. And volumes-from for bind mounts should have never worked before. If you already know the bind mount source just use that instead of trying an implicit volumes-from. |
|
@crosbymichael the thing is from a user perspective they are still volumes, ie. just a place to put data. |
|
they used to be different flags then they were merged but they are very different and it's not going to work with new plugins and such. |
Signed-off-by: Michael Crosby <[email protected]> Volumes refactoring continued Signed-off-by: Arnaud Porterie <[email protected]>
|
@crosbymichael first pass at a migration is here: crosbymichael#36 |
There was a problem hiding this comment.
all the logic to handle bind mounts should be wrapper into a big if hostConfig.Binds() > 0, from 1241 to 1272. Otherwise, volumes mounted with volumesFrom and volume can be overridden with an empty array when there are no bind mounts.
|
@crosbymichael why was this closed? is it continued in #13161? |
|
For reference, this PR has been replaced by #13161 |
There were a few undefined behavior changes made in this PR to make things work better and not be as crazy. The order of precedence for how volumes are applied to a container are as follows.
Another behavior change is that bind mounts cannot be inherited from
volumes-from. I doubt this was ever expected and should have never worked.The main areas of change are that there is not central volumes repository. The container's hold volume ID/Names of volumes that they consume along with how and where those volumes are mounted(dest,RO-RW). All other state regarding volumes is stored in the volume specific implementation.
For the default implementation we changed it to not require any on disk metadata about what containers are consuming a volume. When the daemon boots the container's are populated with the volume objects that they use and each volume is reference counted. Everything is done in memory and at runtime so we don't need a bunch of json files for this volume implementation.
Another design change is that bind mounts are not volumes. There were too many bool values on the volume struct to determine if it was a bind mounts or something else. We took the approach that a bind mount is the result of how a volume is consumed, therefore, we can treat the two completely separate.
What is missing
I still have to work on the migration code from the old volume format. This will be a little tricky but I should have a commit adding this soon.