1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #19123 from shishir-a412ed/rootfs_size_configurable

daemon option (--storage-opt dm.basesize) for increasing the base device size on daemon restart
This commit is contained in:
Sebastiaan van Stijn 2016-01-13 13:22:08 -08:00
commit 661d75f398
4 changed files with 110 additions and 13 deletions

View file

@ -35,7 +35,7 @@ import (
var ( var (
defaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024 defaultDataLoopbackSize int64 = 100 * 1024 * 1024 * 1024
defaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024 defaultMetaDataLoopbackSize int64 = 2 * 1024 * 1024 * 1024
defaultBaseFsSize uint64 = 100 * 1024 * 1024 * 1024 defaultBaseFsSize uint64 = 10 * 1024 * 1024 * 1024
defaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors defaultThinpBlockSize uint32 = 128 // 64K = 128 512b sectors
defaultUdevSyncOverride = false defaultUdevSyncOverride = false
maxDeviceID = 0xffffff // 24 bit, pool limit maxDeviceID = 0xffffff // 24 bit, pool limit
@ -47,6 +47,7 @@ var (
driverDeferredRemovalSupport = false driverDeferredRemovalSupport = false
enableDeferredRemoval = false enableDeferredRemoval = false
enableDeferredDeletion = false enableDeferredDeletion = false
userBaseSize = false
) )
const deviceSetMetaFile string = "deviceset-metadata" const deviceSetMetaFile string = "deviceset-metadata"
@ -1056,6 +1057,80 @@ func (devices *DeviceSet) setupVerifyBaseImageUUIDFS(baseInfo *devInfo) error {
return nil return nil
} }
func (devices *DeviceSet) checkGrowBaseDeviceFS(info *devInfo) error {
if !userBaseSize {
return nil
}
if devices.baseFsSize < devices.getBaseDeviceSize() {
return fmt.Errorf("devmapper: Base device size cannot be smaller than %s", units.HumanSize(float64(devices.getBaseDeviceSize())))
}
if devices.baseFsSize == devices.getBaseDeviceSize() {
return nil
}
info.lock.Lock()
defer info.lock.Unlock()
devices.Lock()
defer devices.Unlock()
info.Size = devices.baseFsSize
if err := devices.saveMetadata(info); err != nil {
// Try to remove unused device
delete(devices.Devices, info.Hash)
return err
}
return devices.growFS(info)
}
func (devices *DeviceSet) growFS(info *devInfo) error {
if err := devices.activateDeviceIfNeeded(info, false); err != nil {
return fmt.Errorf("Error activating devmapper device: %s", err)
}
defer devices.deactivateDevice(info)
fsMountPoint := "/run/docker/mnt"
if _, err := os.Stat(fsMountPoint); os.IsNotExist(err) {
if err := os.MkdirAll(fsMountPoint, 0700); err != nil {
return err
}
defer os.RemoveAll(fsMountPoint)
}
options := ""
if devices.BaseDeviceFilesystem == "xfs" {
// XFS needs nouuid or it can't mount filesystems with the same fs
options = joinMountOptions(options, "nouuid")
}
options = joinMountOptions(options, devices.mountOptions)
if err := mount.Mount(info.DevName(), fsMountPoint, devices.BaseDeviceFilesystem, options); err != nil {
return fmt.Errorf("Error mounting '%s' on '%s': %s", info.DevName(), fsMountPoint, err)
}
defer syscall.Unmount(fsMountPoint, syscall.MNT_DETACH)
switch devices.BaseDeviceFilesystem {
case "ext4":
if out, err := exec.Command("resize2fs", info.DevName()).CombinedOutput(); err != nil {
return fmt.Errorf("Failed to grow rootfs:%v:%s", err, string(out))
}
case "xfs":
if out, err := exec.Command("xfs_growfs", info.DevName()).CombinedOutput(); err != nil {
return fmt.Errorf("Failed to grow rootfs:%v:%s", err, string(out))
}
default:
return fmt.Errorf("Unsupported filesystem type %s", devices.BaseDeviceFilesystem)
}
return nil
}
func (devices *DeviceSet) setupBaseImage() error { func (devices *DeviceSet) setupBaseImage() error {
oldInfo, _ := devices.lookupDeviceWithLock("") oldInfo, _ := devices.lookupDeviceWithLock("")
@ -1069,9 +1144,8 @@ func (devices *DeviceSet) setupBaseImage() error {
return err return err
} }
if devices.baseFsSize != defaultBaseFsSize && devices.baseFsSize != devices.getBaseDeviceSize() { if err := devices.checkGrowBaseDeviceFS(oldInfo); err != nil {
logrus.Warnf("devmapper: Base device is already initialized to size %s, new value of base device size %s will not take effect", return err
units.HumanSize(float64(devices.getBaseDeviceSize())), units.HumanSize(float64(devices.baseFsSize)))
} }
return nil return nil
@ -2378,6 +2452,7 @@ func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps [
if err != nil { if err != nil {
return nil, err return nil, err
} }
userBaseSize = true
devices.baseFsSize = uint64(size) devices.baseFsSize = uint64(size)
case "dm.loopdatasize": case "dm.loopdatasize":
size, err := units.RAMInBytes(val) size, err := units.RAMInBytes(val)

View file

@ -213,11 +213,23 @@ options for `zfs` start with `zfs`.
* `dm.basesize` * `dm.basesize`
Specifies the size to use when creating the base device, which limits the Specifies the size to use when creating the base device, which limits the
size of images and containers. The default value is 100G. Note, thin devices size of images and containers. The default value is 10G. Note, thin devices
are inherently "sparse", so a 100G device which is mostly empty doesn't use are inherently "sparse", so a 10G device which is mostly empty doesn't use
100 GB of space on the pool. However, the filesystem will use more space for 10 GB of space on the pool. However, the filesystem will use more space for
the empty case the larger the device is. the empty case the larger the device is.
The base device size can be increased at daemon restart which will allow
all future images and containers (based on those new images) to be of the
new base device size.
Example use:
$ docker daemon --storage-opt dm.basesize=50G
This will increase the base device size to 50G. The Docker daemon will throw an
error if existing base device size is larger than 50G. A user can use
this option to expand the base device size however shrinking is not permitted.
This value affects the system-wide "base" empty filesystem This value affects the system-wide "base" empty filesystem
that may already be initialized and inherited by pulled images. Typically, that may already be initialized and inherited by pulled images. Typically,
a change to this value requires additional steps to take effect: a change to this value requires additional steps to take effect:

View file

@ -249,11 +249,11 @@ You can use the `lsblk` command to see the device files created above and the `p
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda 202:0 0 8G 0 disk xvda 202:0 0 8G 0 disk
└─xvda1 202:1 0 8G 0 part / └─xvda1 202:1 0 8G 0 part /
xvdf 202:80 0 100G 0 disk xvdf 202:80 0 10G 0 disk
├─vg--docker-data 253:0 0 90G 0 lvm ├─vg--docker-data 253:0 0 90G 0 lvm
│ └─docker-202:1-1032-pool 253:2 0 100G 0 dm │ └─docker-202:1-1032-pool 253:2 0 10G 0 dm
└─vg--docker-metadata 253:1 0 4G 0 lvm └─vg--docker-metadata 253:1 0 4G 0 lvm
└─docker-202:1-1032-pool 253:2 0 100G 0 dm └─docker-202:1-1032-pool 253:2 0 10G 0 dm
The diagram below shows the image from prior examples updated with the detail from the `lsblk` command above. The diagram below shows the image from prior examples updated with the detail from the `lsblk` command above.

View file

@ -271,12 +271,22 @@ Example use: `docker daemon --storage-opt dm.thinpooldev=/dev/mapper/thin-pool`
#### dm.basesize #### dm.basesize
Specifies the size to use when creating the base device, which limits Specifies the size to use when creating the base device, which limits
the size of images and containers. The default value is 100G. Note, the size of images and containers. The default value is 10G. Note,
thin devices are inherently "sparse", so a 100G device which is mostly thin devices are inherently "sparse", so a 10G device which is mostly
empty doesn't use 100 GB of space on the pool. However, the filesystem empty doesn't use 10 GB of space on the pool. However, the filesystem
will use more space for base images the larger the device will use more space for base images the larger the device
is. is.
The base device size can be increased at daemon restart which will allow
all future images and containers (based on those new images) to be of the
new base device size.
Example use: `docker daemon --storage-opt dm.basesize=50G`
This will increase the base device size to 50G. The Docker daemon will throw an
error if existing base device size is larger than 50G. A user can use
this option to expand the base device size however shrinking is not permitted.
This value affects the system-wide "base" empty filesystem that may already This value affects the system-wide "base" empty filesystem that may already
be initialized and inherited by pulled images. Typically, a change to this be initialized and inherited by pulled images. Typically, a change to this
value requires additional steps to take effect: value requires additional steps to take effect: