This article describes the inner-workings of PouchContainer volumes, which are designed to address the data persistence issue of PouchContainer.

A PouchContainer volume is specifically designed for container data persistence. Knowledge of the PouchContainer image mechanism is a premise for understanding how a volume works. PouchContainer implements image layering in the same way as Docker. A container image consists of multiple read-only image layers, and an image layer can be reused by different images, which greatly improves the image distribution efficiency and reduces the container startup time. When a container starts, PouchContainer Daemon (pouchd) adds a read and write layer on top of the startup image to record all subsequent read and write operations of the container. An issue of container data persistence exists. If the container is deleted and then started using the startup image, all previous modifications made to the container are lost, which is fatal for stateful applications, such as databases.

A volume is used to store the data of a container on a host in the form of files or directories, without the intervention of the image mechanism. Stopping or deleting the container does not affect the data of the volume, which ensures data persistence. Volume data can be shared among different containers.

Overall Architecture of a PouchContainer Volume

The following content may involve the volume source coding of PouchContainer.

Currently, a PouchContainer volume consists of the following elements:



VolumeManager: Portal to volume-related operations. Core: A core module of a volume, which includes the service logic of volume operations. Store: Stores volume metadata in a local boltdb file. Driver: Volume driver interface, which abstracts the basic functions of volume-related drivers. Modules: Specific volume drivers, which are local, tmpfs, volume plugin, and Ceph.

VolumeManager is a storage component of PouchContainer (other components are ContainerManager, ImageManager, and NetworkManager) and a portal to all volume operations. Currently, the Create, Remove, List, Get, Attach, and Detach interfaces are available. Core includes the core logic of volume operations. It calls underlying volume drivers for volume-related operations such as Create, Delete, Attach, and Detach, and calls Store for volume metadata management. Store is a dedicated module of volume metadata management for ease of future scaling. Volume status data is also stored by this module. Currently, volume metadata is stored in boltdb, and may be stored in etcd in the future. Driver abstracts the interfaces implemented by a volume driver, including Name, StoreMode, Create, Remove, and Path.

type Driver interface { // Name returns backend driver's name. Name(Context) string // StoreMode defines backend driver's store model. StoreMode(Context) VolumeStoreMode // Create a volume. Create(Context, *types.Volume, *types.Storage) error // Remove a volume. Remove(Context, *types.Volume, *types.Storage) error // Path returns volume's path. Path(Context, *types.Volume) (string, error) }

Volume Types Supported by PouchContainer

Currently, PouchContainer supports three volume types: local, tmpfs, and Ceph, and supports more third-party storage by means of a general storage plugin called volume plugin.

Local Volume

A default volume type of PouchContainer, a local volume is suitable for storing data that requires persistence. The volume lifecycle is independent of the container lifecycle.

When you create a volume without specifying the driver type, the local volume is of the driver type by default. In essence, a local volume is a subdirectory created by pouchd in the /var/lib/pouch/volume directory. Compared with Docker, a local volume of PouchContainer has more practical features, allowing you to:



Specify a directory to mount a volume to be created. Specify the volume size.

You can specify a directory for creating a local volume. This feature is very practical in production. Some applications such as databases require mounting of dedicated block devices to store database data. For example, O&M engineers mount formatted block devices to the /mnt/mysql_data directory. Run the following command to create a volume mounted to the /mnt/mysql_data directory. Then, mount the volume to a directory of a container and start the container.



pouch volume create --driver local --option mount=/mnt/mysql_data --name mysql_data

You can limit the size of a volume. This feature depends on the quota function provided by an underlying file system. Currently, ext4 and xfs underlying file systems are supported. This feature works with specified kernel versions.



pouch volume create --driver local --option size=10G --name test_quota

Tmpfs Volume

The data of a tmpfs volume is only stored in memory (or in swap if memory is insufficient), but is not stored as persistent data in a disk, and the data can be accessed at fast speeds. However, when the container stops, all information in the volume disappears. Therefore, a tmpfs volume is suitable for storing temporary and sensitive data.

By default, a tmpfs volume is stored in the /mnt/tmpfs directory. You can also use -o mount to specify a mount path. Since the content of a tmpfs volume is directly stored in memory, it makes little sense to specify a mount path for the tmpfs volume.



pouch volume create --driver tmpfs --name tmpfs_test

Ceph Volume

A special volume type, a Ceph volume stores data in a Ceph cluster (Ceph rbd storage), which enables volume migration across physical machines.

Currently, Ceph volumes are not available for external use. In the PouchContainer volume architecture, an Alibaba storage controller (an alternative name) lies between the Ceph driver and Driver. It is an internal container storage management platform of Alibaba and interoperates with multiple storage solutions such as Ceph, Pangu, and NAS. PouchContainer interoperates with the container storage management platform to provide volumes directly by using Ceph. The container storage management platform may be available in open source in the future.

Volume Plugin

A volume plugin is a universal volume, or more accurately, a type of extended volume. Currently, Docker manages a range of third-party storage by using plugins. PouchContainer implements a volume plugin mechanism to seamlessly interoperate with the existing volume plugins of Docker.

A volume plugin must implement the volume plugin protocol. In essence, a volume plugin is a web server which provides the following services (all requests are POST requests):

/VolumeDriver.Create // Creates a volume. /VolumeDriver.Remove // Deletes a volume. /VolumeDriver.Mount // Mounts a volume. /VolumeDriver.Path // Specifies a volume mount path. /VolumeDriver.Unmount // Unmounts a volume. /VolumeDriver.Get // Gets a volume. /VolumeDriver.List // Lists volumes. /VolumeDriver.Capabilities // Provides volume driver capabilities.

Bind Mounts and Volumes

Currently, PouchContainer supports two data persistence methods: volumes and bind mounts. Literally, bind mounts means mounting a directory of a host to a container directly.



pouch run -d -t -v /hostpath/data:/containerpath/data:ro ubuntu sh

The preceding command mounts the /hostpath/data directory of a host to the /containerpath/data directory of a container in read-only mode.

Bind mounts depends on the file system directory structure of a host, whereas volumes are managed in a dedicated manner in PouchContainer. Volumes have the following advantages over bind mounts:



Volumes are easier to back up and manage. Volumes are managed by dedicated CLI and APIs in PouchContainer. Volumes can be shared among containers securely. Volumes provide plugins to interoperate with third-party storage with ease.

Future Development of PouchContainer Volumes

Container Storage Interface (CSI) defines storage interfaces between the container scheduling layer and containers. The latest version is v0.2. PouchContainer may add a universal driver type in the future to interoperate with CSI-enabled storage systems.

Conclusion

This document describes the inner-workings of PouchContainer volumes, designed to address the data persistence issue of PouchContainer. Currently, PouchContainer supports the local, tmpfs, and Ceph drivers, and provides volume plugins to interoperate with more third-party storage.