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
Родитель d6e01e3337 e47112d3e8
Коммит 661d75f398
4 изменённых файлов: 110 добавлений и 13 удалений

Просмотреть файл

@ -35,7 +35,7 @@ import (
var (
defaultDataLoopbackSize int64 = 100 * 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
defaultUdevSyncOverride = false
maxDeviceID = 0xffffff // 24 bit, pool limit
@ -47,6 +47,7 @@ var (
driverDeferredRemovalSupport = false
enableDeferredRemoval = false
enableDeferredDeletion = false
userBaseSize = false
)
const deviceSetMetaFile string = "deviceset-metadata"
@ -1056,6 +1057,80 @@ func (devices *DeviceSet) setupVerifyBaseImageUUIDFS(baseInfo *devInfo) error {
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 {
oldInfo, _ := devices.lookupDeviceWithLock("")
@ -1069,9 +1144,8 @@ func (devices *DeviceSet) setupBaseImage() error {
return err
}
if devices.baseFsSize != defaultBaseFsSize && devices.baseFsSize != devices.getBaseDeviceSize() {
logrus.Warnf("devmapper: Base device is already initialized to size %s, new value of base device size %s will not take effect",
units.HumanSize(float64(devices.getBaseDeviceSize())), units.HumanSize(float64(devices.baseFsSize)))
if err := devices.checkGrowBaseDeviceFS(oldInfo); err != nil {
return err
}
return nil
@ -2378,6 +2452,7 @@ func NewDeviceSet(root string, doInit bool, options []string, uidMaps, gidMaps [
if err != nil {
return nil, err
}
userBaseSize = true
devices.baseFsSize = uint64(size)
case "dm.loopdatasize":
size, err := units.RAMInBytes(val)

Просмотреть файл

@ -213,11 +213,23 @@ options for `zfs` start with `zfs`.
* `dm.basesize`
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
are inherently "sparse", so a 100G device which is mostly empty doesn't use
100 GB of space on the pool. However, the filesystem will use more space for
size of images and containers. The default value is 10G. Note, thin devices
are inherently "sparse", so a 10G device which is mostly empty doesn't use
10 GB of space on the pool. However, the filesystem will use more space for
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
that may already be initialized and inherited by pulled images. Typically,
a change to this value requires additional steps to take effect:

Просмотреть файл

@ -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
xvda 202:0 0 8G 0 disk
└─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
│ └─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
└─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.

Просмотреть файл

@ -271,12 +271,22 @@ Example use: `docker daemon --storage-opt dm.thinpooldev=/dev/mapper/thin-pool`
#### dm.basesize
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 are inherently "sparse", so a 100G device which is mostly
empty doesn't use 100 GB of space on the pool. However, the filesystem
the size of images and containers. The default value is 10G. Note,
thin devices are inherently "sparse", so a 10G device which is mostly
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
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
be initialized and inherited by pulled images. Typically, a change to this
value requires additional steps to take effect: