Skip to content

Add overlay2.size daemon storage-opt#32977

Merged
thaJeztah merged 1 commit into
moby:masterfrom
imkin:30491-default-container-size
Jun 28, 2017
Merged

Add overlay2.size daemon storage-opt#32977
thaJeztah merged 1 commit into
moby:masterfrom
imkin:30491-default-container-size

Conversation

@imkin

@imkin imkin commented May 2, 2017

Copy link
Copy Markdown
Contributor

This commit adds the overlay2.size option to the daemon daemon storage opts.

The user can override this option by the "docker run --storage-opts" options.

Signed-off-by: Dhawal Yogesh Bhanushali [email protected]

closes #30491

- What I did

Added the daemon storage opt overlay2.size option

docker daemon --storage-opt overlay2.size=5G

@imkin

imkin commented May 3, 2017

Copy link
Copy Markdown
Contributor Author

@GordonTheTurtle @amir73il any comments?

Comment thread daemon/graphdriver/overlay2/overlay.go Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

extra change

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Made the change.

Comment thread daemon/graphdriver/overlay2/overlay.go Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

please wrap err with a human-friendly text

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Do you suggest to have something like graphdriver.ErrPrjQuotaNotSupported ? or graphdriver.FeatureNotSupported ?

Please suggest a name otherwise. Thanks :-)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Looked at some of the other drivers and made the change. Thanks

Comment thread daemon/graphdriver/overlay2/overlay.go Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One problem with the way this code is structured is that it doesn't allow the user to override the default size with 0 (i.e. no quota for container).

Another problem is that it is just unneeded code duplication.
How about setting
driver.options.quota = d.options.quota
just before d.parseStorageOpt

This will also be generic enough to apply future defaults if Quota struct ever
gets values like soft limit, inode limit etc...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestion. Made the change.

Comment thread daemon/graphdriver/overlay2/overlay.go Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Because the storage option name in create/start command is the same for all graphdrivers that support it (i.e. "size=") I think the option name for dockerd storage option should be equally generic (i.e. "default_size="). This will also make documentation more generic. BTW, how about the documentation?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added the documentation portion.

Made the change to the option being called as overlay2.size instead of overlay2.default_size

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So you removed the "default_" part and not the "overlay2." part. Oh well, I guess there are arguments to justify both alternatives. Either are fine by me.

@imkin
imkin force-pushed the 30491-default-container-size branch from 30754f3 to 2c63e6a Compare May 5, 2017 01:04
Comment thread docs/reference/commandline/dockerd.md Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

overlayfs2 -> overlay2

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ah thanks fixed.

@imkin
imkin force-pushed the 30491-default-container-size branch from 2c63e6a to 2188281 Compare May 5, 2017 02:47

@amir73il amir73il left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@rhvgoyal

rhvgoyal commented May 5, 2017

Copy link
Copy Markdown
Contributor

Does this apply to only containers or to image as well?

Comment thread daemon/graphdriver/overlay2/overlay.go Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we should if we are on xfs and we can enable quota. Otherwise we should fail during Init() time itself if user wants to use a default size but we can't enforce that default size.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

IOW, in Init() this check should be there and driver initialization should fail if quota can't be supported and user asked for it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Right. I missed that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In sync with the other comments have made the change.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@amir73il Q: so the overlay2.size storage opt sets the default for RW layer only or includes the base image(Rootfs)?
Pls clarify.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Only for RW layer.

@amir73il

amir73il commented May 5, 2017

Copy link
Copy Markdown
Contributor

The quota is only applied to container root dir, which is where the overlay upper dir is,
so unlike btrfs and devicemapper drivers, 'size' doesn't limit the size of the image at all,
only the size of the changes that container can make to the image.
However that is the 'size' that will be observed by user running 'df /' command inside container.

Comment thread daemon/graphdriver/overlay2/overlay.go Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Oh, I see, here is the check and error out if quota is not supported. But this will run only if we are running on to of xfs.

How about moving this check out of backingFs == "xfs" if block.

Also error message could probably be more verbose. Say.

If we are not running on xfs, that could be first check and error message could be.

Storage option overlay2.size not supported. Underlying filesystem needs to be xfs

And if we are running on xfs but not supporting quota, we could say.

Storage option overlay2.size not supported. Filesystem is does not support project quota

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That was a race in review :) I did not notice you posted this. Agreed.
Typo "Filesystem is does not ..."

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Made the change as suggested. The messages are little different but mean the same.

Comment thread daemon/graphdriver/overlay2/overlay.go Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As @rhvgoyal noted correctly, this test should move outside the backingFs == "xfs" block
(i.e. if !projectQuotaSupported) and error message should be made more clear to the user, something like the error in Create():
"overlay2.size option is supported only for overlay over xfs with 'pquota' mount option"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added as per @rhvgoyal suggestions.

@rhvgoyal

rhvgoyal commented May 5, 2017

Copy link
Copy Markdown
Contributor

@amir73il We seem to enforce quota restrictions in Create(). And IIUC, that's used both by images as well as container root. So IIUC, this quota will be applied to both images as well as container (after this patch).

Previously, it will not apply to images because option was per container and there was no way to pass this option for images.

Am I missing something?

@rhvgoyal

rhvgoyal commented May 5, 2017

Copy link
Copy Markdown
Contributor

I think applying these limits for images is a good idea though. People have raised concerns about pulling images with sparse files in it. And being able to put a limit on the max size of each layer will help prevent somebody trying to explode 1TB sparse file on disk.

@amir73il

amir73il commented May 5, 2017

Copy link
Copy Markdown
Contributor

I see. confession: I don't know docker that well... I guess applying limits to images make sense. So an image will contain single or multi lower layers, which will all limited cumulatively by the project quota limit?
Specifically, I also don't know what the container '-init' dir is, but it gets assigned a project id as well, so I am guessing it will get a project default quota limit too now.

@rhvgoyal

rhvgoyal commented May 5, 2017

Copy link
Copy Markdown
Contributor

Right. -init is another intermediate layer where docker might want to scribble something and then use it as lower layer for actual container rootfs. So quota will be applied to that too. Though contents written there by docker are very small, so applying quota to -init layer is not a problem.

I think being able to apply it to container rootfs and to image layer are going to be very useful.

@rhvgoyal

rhvgoyal commented May 5, 2017

Copy link
Copy Markdown
Contributor

That's my understanding that every image layer will be limited to project quota specified by overlay2.size. But I also have not spent too much time in looking at overlay2 code. So @imkin might have more definitive answer.

@imkin
imkin force-pushed the 30491-default-container-size branch from 2188281 to e5ec2be Compare May 5, 2017 21:33
@thaJeztah

Copy link
Copy Markdown
Member

/cc @dmcgowan

@imkin

imkin commented May 5, 2017

Copy link
Copy Markdown
Contributor Author

@rhvgoyal I do see that all the layers comply with the "size" parameter.

This, however, is same as what the existing size storage option for the docker run command. So I believe if anything else needs to comply with this "size" param then it should be a holistic issue of the overlayfs2's docker driver here and not in the scope of this PR.

@imkin

imkin commented May 5, 2017

Copy link
Copy Markdown
Contributor Author

The powerpc test failure is a flake. #33041

@imkin

imkin commented May 8, 2017

Copy link
Copy Markdown
Contributor Author

@amir73il Made the suggested changes. Please bless :-)

@rhvgoyal

rhvgoyal commented May 8, 2017

Copy link
Copy Markdown
Contributor

@imkin, I am just trying to understand the behavior better. Previously though it was in create path, there was no way to pass in this during create for images so it did not impact us.

But with your changes, this being a daemon flag, it will apply to both image layer create and container rootfs. And it will impact image pull.

Given your changes impact that behavior I want to understand the impact on images.

So this will pull size restriction on image layer as well, right? Only thing seems to be that size limit will
be per image layer (and not the whole image if image has multiple layers).

@amir73il amir73il left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

code looks fine to me. still need to understand the implication of image pull. and there is a typo in commit message (daemon daemon)

@imkin

imkin commented May 8, 2017

Copy link
Copy Markdown
Contributor Author

@rhvgoyal just now did a docker pull of a image larger than what the overlay2.size parameter allowed.

bash-4.3# docker pull openjdk
Using default tag: latest
latest: Pulling from library/openjdk
cd0a524342ef: Extracting [==================================================>] 52.55 MB/52.55 MB
e39c3ffe4133: Download complete
85334a7c2001: Download complete
b46c5b79125e: Download complete
30d4cb7cc8bc: Download complete
4d273117faaf: Download complete
2b271bed4ca3: Download complete
30e4d8ac7a54: Download complete
45858d68b18d: Download complete
failed to register layer: Error processing tar file(exit status 1): open /usr/share/locale/nb/LC_MESSAGES/tar.mo: disk quota exceeded

So @rhvgoyal @amir73il it docker pull also honors the size parameter. The pull is successful when I increase the value of the "size" param.

@thaJeztah thaJeztah left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

left some questions

Comment thread daemon/graphdriver/overlay2/overlay.go Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So if we don't want Create to be called with quota; perhaps we should add a non-exported create() that's both called by Create() and CreateReadWrite();

func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr error) {
	if opts != nil && len(opts.StorageOpt) != 0 && !projectQuotaSupported {
		return fmt.Errorf("--storage-opt is supported only for overlay over xfs with 'pquota' mount option")
	}

	return d.create(id, parent string, opts)
}

The check in Create() could even be;

if opts != nil && len(opts.StorageOpt) != 0 {
    // error...
}

Given that Create() then won't support any options

Comment thread daemon/graphdriver/overlay2/overlay.go Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks like we now always pass opts, even if no option is set on dockerd or is passed with docker run; should the code here check if either opts.StorageOpt is set or d.options.quota.Size is set, and otherwise just keep opts as nil?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

When we reach CreateReadWrite we have lost the information whether opts.StorageOpt is defined or not. We only have d.options.quota.Size. Unintialized "d.options.quota.Size" is 0. I am not sure if it is semantically right to assume d.options.quota.Size with "0" as "Not-Initialized". The current "size" option for docker run allows you to define this as "0".

@imkin

imkin commented Jun 21, 2017

Copy link
Copy Markdown
Contributor Author

@thaJeztah I could not comment on your second question since it may not be a "git review comment" so paraphrasing you here.

So if we don't want Create to be called with quota; perhaps we should add a non-exported create() that's both called by Create() and CreateReadWrite();

func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr error) {
	if opts != nil && len(opts.StorageOpt) != 0 && !projectQuotaSupported {
		return fmt.Errorf("--storage-opt is supported only for overlay over xfs with 'pquota' mount option")
	}

	return d.create(id, parent string, opts)
}
The check in Create() could even be;

if opts != nil && len(opts.StorageOpt) != 0 {
    // error...
}
Given that Create() then won't support any options

The check of "projectquotasupport" is not a concern of "Create()" but of CreateReadWrite() since only quota should only be set in the ReadWrite layer. Hence the check is moved to CreateReadWrite.

@thaJeztah

Copy link
Copy Markdown
Member

The check of "projectquotasupport" is not a concern of "Create()" but of CreateReadWrite() since only quota should only be set in the ReadWrite layer. Hence the check is moved to CreateReadWrite.

The point is that Create() is an exported function, and, while true that it's currently not called with a quota; being an exported function means it can be called in a different code path.

By splitting the Exported Create(), that situation would be covered

@bklau

bklau commented Jun 21, 2017

Copy link
Copy Markdown

thaJeztah : Q: How is the default for container storage size set for other drivers like dm , btrfs and zfs? Is this just a one-off for Overlay2 driver only??

@imkin

imkin commented Jun 21, 2017

Copy link
Copy Markdown
Contributor Author

@thaJeztah quota support does not make sense for read layers because they are anyways "readonly". Calling Create directly for setting quota may never be the right way. I could have a private create function that does what Create is doing today. As per your suggestion both Create and CreateReadWrite could call it. However the check in Create could be to completely disallow setting quota directly.

@bklau

bklau commented Jun 22, 2017

Copy link
Copy Markdown

@imkin @rhvgoyal Earlier goyal did a test that shows that the size parameter also affects the "base image". On the client side, i thought that it just impacted the CoW RW layers.
Isn't this behaviour a discrepancy between what is set on by docker run --storage-opt size=xxx and dockerd --storage-opt overlay2.size=xxx ?? Pls clarify. I refer to below chat:

"@rhvgoyal just now did a docker pull of a image larger than what the overlay2.size parameter allowed.

bash-4.3# docker pull openjdk
Using default tag: latest
latest: Pulling from library/openjdk
cd0a524342ef: Extracting [==================================================>] 52.55 MB/52.55 MB
e39c3ffe4133: Download complete
85334a7c2001: Download complete
b46c5b79125e: Download complete
30d4cb7cc8bc: Download complete
4d273117faaf: Download complete
2b271bed4ca3: Download complete
30e4d8ac7a54: Download complete
45858d68b18d: Download complete
failed to register layer: Error processing tar file(exit status 1): open /usr/share/locale/nb/LC_MESSAGES/tar.mo: disk quota exceeded

So @rhvgoyal @amir73il it docker pull also honors the size parameter. The pull is successful when I increase the value of the "size" param."

@imkin

imkin commented Jun 22, 2017

Copy link
Copy Markdown
Contributor Author

@bklau Initially the idea was to impact all layers. Then based on comments from @dmcgowan and @cpuguy83 we reduced the impact to be on ReadWrite Layer.(rootfs)

This commit adds the overlay2.size option to the daemon daemon
storage opts.

The user can override this option by the "docker run --storage-opt"
options.

Signed-off-by: Dhawal Yogesh Bhanushali <[email protected]>
@imkin
imkin force-pushed the 30491-default-container-size branch from 9a48175 to a63d5bc Compare June 27, 2017 08:20
@imkin

imkin commented Jun 27, 2017

Copy link
Copy Markdown
Contributor Author

@thaJeztah made the changes as per the discussion. Can you check if it satisfies your comments?

@thaJeztah thaJeztah left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM thanks!

@stevvooe

Copy link
Copy Markdown
Contributor

@thaJeztah Wish we had taken the feedback in #32977 (comment) before merging this. The parameter overlay2.size is extremely unclear that it is a quota. What if soft and hard quotas are added? What if a different quota system is used to enforce that quota?

@cpuguy83

Copy link
Copy Markdown
Member

@stevvooe This is not a new option, only able to specified at the daemon level in addition to per-container.

But sorry, your suggestion definitely got lost in the sea of comments. Review->RequestChanges may help here in the future.
Please open an issue if you think this should still be changed.

@stevvooe

Copy link
Copy Markdown
Contributor

overlay2.quota.size seems correct.

@imkin

imkin commented Jun 30, 2017

Copy link
Copy Markdown
Contributor Author

@stevvooe I did respond to you but did not hear back from you.

I am not sure why "quota" should be mentioned. Thats an implementation detail right?

@stevvooe

Copy link
Copy Markdown
Contributor

I am not sure why "quota" should be mentioned. Thats an implementation detail right?

"Project Quota" is an implementation detail, yes, but the semantic meaning of size is that this is enforcing a quota. The fact that it is a quota is not an implementation detail.

The conversation is happening in #33903.

albers added a commit to albers/docker-cli that referenced this pull request Jul 3, 2017
This adds bash completion for
- docker#215
- moby/moby#32977

Signed-off-by: Harald Albers <[email protected]>
andrewhsu pushed a commit to docker-archive/docker-ce that referenced this pull request Jul 14, 2017
This adds bash completion for
- docker/cli#215
- moby/moby#32977

Signed-off-by: Harald Albers <[email protected]>
Upstream-commit: a4b1769bb600edf9c7542247fccc3e7dae074da0
Component: cli
@amir73il amir73il mentioned this pull request Jul 21, 2017
alshabib pushed a commit to alshabib/cli that referenced this pull request Aug 1, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docker daemon should support support default option for --storage-opts "size" parameter for supported drivers.