mirror of https://github.com/docker/docs.git
devmapper: Add --storage-opt options for basic devicemapper settings
This allows setting these settings to be passed: dm.basesize dm.loopdatasize dm.loopmetadatasize Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl@redhat.com> (github: alexlarsson)
This commit is contained in:
parent
822ea97ffc
commit
7f5ba068f4
|
@ -0,0 +1,73 @@
|
||||||
|
## devicemapper - a storage backend based on Device Mapper
|
||||||
|
|
||||||
|
### Theory of operation
|
||||||
|
|
||||||
|
The device mapper graphdriver uses the device mapper thin provisioning
|
||||||
|
module (dm-thinp) to implement CoW snapshots. For each devicemapper
|
||||||
|
graph locaion (typically `/var/lib/docker/devicemapper`, $graph below)
|
||||||
|
a thin pool is created based on two block devices, one for data and
|
||||||
|
one for metadata. By default these block devices are created
|
||||||
|
automatically by using loopback mounts of automatically creates sparse
|
||||||
|
files.
|
||||||
|
|
||||||
|
The default loopback files used are `$graph/devicemapper/data` and
|
||||||
|
`$graph/devicemapper/metadata`. Additional metadata required to map
|
||||||
|
from docker entities to the corresponding devicemapper volumes is
|
||||||
|
stored in the `$graph/devicemapper/json` file (encoded as Json).
|
||||||
|
|
||||||
|
In order to support multiple devicemapper graphs on a system the thin
|
||||||
|
pool will be named something like: `docker-0:33-19478248-pool`, where
|
||||||
|
the `0:30` part is the minor/major device nr and `19478248` is the
|
||||||
|
inode number of the $graph directory.
|
||||||
|
|
||||||
|
On the thin pool docker automatically creates a base thin device,
|
||||||
|
called something like `docker-0:33-19478248-base` of a fixed
|
||||||
|
size. This is automatically formated on creation and contains just an
|
||||||
|
empty filesystem. This device is the base of all docker images and
|
||||||
|
containers. All base images are snapshots of this device and those
|
||||||
|
images are then in turn used as snapshots for other images and
|
||||||
|
eventually containers.
|
||||||
|
|
||||||
|
### options
|
||||||
|
|
||||||
|
The devicemapper backend supports some options that you can specify
|
||||||
|
when starting the docker daemon using the --storage-opt flags.
|
||||||
|
This uses the `dm` prefix and would be used somthing like `docker -d --storage-opt dm.foo=bar`.
|
||||||
|
|
||||||
|
Here is the list of supported options:
|
||||||
|
|
||||||
|
* `dm.basesize`
|
||||||
|
|
||||||
|
Specifies the size to use when creating the base device, which
|
||||||
|
limits 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 the empty
|
||||||
|
case the larger the device is.
|
||||||
|
|
||||||
|
Example use:
|
||||||
|
|
||||||
|
``docker -d --storage-opt dm.basesize=20G``
|
||||||
|
|
||||||
|
* `dm.loopdatasize`
|
||||||
|
|
||||||
|
Specifies the size to use when creating the loopback file for the
|
||||||
|
"data" device which is used for the thin pool. The default size is
|
||||||
|
100G. Note that the file is sparse, so it will not initially take
|
||||||
|
up this much space.
|
||||||
|
|
||||||
|
Example use:
|
||||||
|
|
||||||
|
``docker -d --storage-opt dm.loopdatasize=200G``
|
||||||
|
|
||||||
|
* `dm.loopmetadatasize`
|
||||||
|
|
||||||
|
Specifies the size to use when creating the loopback file for the
|
||||||
|
"metadadata" device which is used for the thin pool. The default size is
|
||||||
|
2G. Note that the file is sparse, so it will not initially take
|
||||||
|
up this much space.
|
||||||
|
|
||||||
|
Example use:
|
||||||
|
|
||||||
|
``docker -d --storage-opt dm.loopmetadatasize=4G``
|
||||||
|
|
|
@ -13,12 +13,14 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/dotcloud/docker/daemon/graphdriver"
|
"github.com/dotcloud/docker/daemon/graphdriver"
|
||||||
"github.com/dotcloud/docker/pkg/label"
|
"github.com/dotcloud/docker/pkg/label"
|
||||||
|
"github.com/dotcloud/docker/pkg/units"
|
||||||
"github.com/dotcloud/docker/utils"
|
"github.com/dotcloud/docker/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -65,6 +67,11 @@ type DeviceSet struct {
|
||||||
TransactionId uint64
|
TransactionId uint64
|
||||||
NewTransactionId uint64
|
NewTransactionId uint64
|
||||||
nextDeviceId int
|
nextDeviceId int
|
||||||
|
|
||||||
|
// Options
|
||||||
|
dataLoopbackSize int64
|
||||||
|
metaDataLoopbackSize int64
|
||||||
|
baseFsSize uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type DiskUsage struct {
|
type DiskUsage struct {
|
||||||
|
@ -378,8 +385,8 @@ func (devices *DeviceSet) setupBaseImage() error {
|
||||||
// Ids are 24bit, so wrap around
|
// Ids are 24bit, so wrap around
|
||||||
devices.nextDeviceId = (id + 1) & 0xffffff
|
devices.nextDeviceId = (id + 1) & 0xffffff
|
||||||
|
|
||||||
utils.Debugf("Registering base device (id %v) with FS size %v", id, DefaultBaseFsSize)
|
utils.Debugf("Registering base device (id %v) with FS size %v", id, devices.baseFsSize)
|
||||||
info, err := devices.registerDevice(id, "", DefaultBaseFsSize)
|
info, err := devices.registerDevice(id, "", devices.baseFsSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = deleteDevice(devices.getPoolDevName(), id)
|
_ = deleteDevice(devices.getPoolDevName(), id)
|
||||||
utils.Debugf("\n--->Err: %s\n", err)
|
utils.Debugf("\n--->Err: %s\n", err)
|
||||||
|
@ -567,12 +574,12 @@ func (devices *DeviceSet) initDevmapper(doInit bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
createdLoopback = !hasData || !hasMetadata
|
createdLoopback = !hasData || !hasMetadata
|
||||||
data, err := devices.ensureImage("data", DefaultDataLoopbackSize)
|
data, err := devices.ensureImage("data", devices.dataLoopbackSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Debugf("Error device ensureImage (data): %s\n", err)
|
utils.Debugf("Error device ensureImage (data): %s\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
metadata, err := devices.ensureImage("metadata", DefaultMetaDataLoopbackSize)
|
metadata, err := devices.ensureImage("metadata", devices.metaDataLoopbackSize)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Debugf("Error device ensureImage (metadata): %s\n", err)
|
utils.Debugf("Error device ensureImage (metadata): %s\n", err)
|
||||||
return err
|
return err
|
||||||
|
@ -1091,12 +1098,45 @@ func (devices *DeviceSet) Status() *Status {
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeviceSet(root string, doInit bool) (*DeviceSet, error) {
|
func NewDeviceSet(root string, doInit bool, options []string) (*DeviceSet, error) {
|
||||||
SetDevDir("/dev")
|
SetDevDir("/dev")
|
||||||
|
|
||||||
devices := &DeviceSet{
|
devices := &DeviceSet{
|
||||||
root: root,
|
root: root,
|
||||||
MetaData: MetaData{Devices: make(map[string]*DevInfo)},
|
MetaData: MetaData{Devices: make(map[string]*DevInfo)},
|
||||||
|
dataLoopbackSize: DefaultDataLoopbackSize,
|
||||||
|
metaDataLoopbackSize: DefaultMetaDataLoopbackSize,
|
||||||
|
baseFsSize: DefaultBaseFsSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, option := range options {
|
||||||
|
key, val, err := utils.ParseKeyValueOpt(option)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key = strings.ToLower(key)
|
||||||
|
switch key {
|
||||||
|
case "dm.basesize":
|
||||||
|
size, err := units.FromHumanSize(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
devices.baseFsSize = uint64(size)
|
||||||
|
case "dm.loopdatasize":
|
||||||
|
size, err := units.FromHumanSize(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
devices.dataLoopbackSize = size
|
||||||
|
case "dm.loopmetadatasize":
|
||||||
|
size, err := units.FromHumanSize(val)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
devices.metaDataLoopbackSize = size
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Unknown option %s\n", key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := devices.initDevmapper(doInit); err != nil {
|
if err := devices.initDevmapper(doInit); err != nil {
|
||||||
|
|
|
@ -27,7 +27,7 @@ type Driver struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Init(home string, options []string) (graphdriver.Driver, error) {
|
func Init(home string, options []string) (graphdriver.Driver, error) {
|
||||||
deviceSet, err := NewDeviceSet(home, true)
|
deviceSet, err := NewDeviceSet(home, true, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue