查看原文
其他

文末送书啦!| Device Mapper,那些你不知道的Docker核心技术

王洪鹏 CSDN云计算 2019-07-14

戳蓝字“CSDN云计算”关注我们哦!


接触Docker 比较早的同学应该知道,Docker 在最开始只能在Ubuntu和Debian等少数的Linux 发行版上运行,并且在这些发行版上默认使用的存储驱动为AUFS。由于Linux 并未将AUFS的支持纳入自己的内核主线(据说是因为AUFS的代码写的太烂了,进入内核的事情一直被linus拒绝),因此一段时间后随着Docker 越发的流行,对于非Ubuntu系列的发行版,比如CentOS,就不能直接使用AUFS 作为Docker 的存储驱动了。在这种情况下,Device Mapper就被作为一种重要的Docker存储驱动被提了出来。


Device Mapper 概述

 

Device Mapper 作为linux 中非常重要的一项技术其实早在linux 2.6 这个内核版本的时候就已经被引入到linux之中。简单说来Device Mapper就是一个基于linux内核的框架,是linux内核用来将块设备映射到虚拟设备的一种框架,Device Mapper对linux 上的高级卷管理技术做了进一步的增强,支持许多的高级卷管理技术。Docker 的devicemapper 存储驱动程序就是基于DeviceMapper 这种框架的自动精简配置(Thin Provisioning)和精简配置快照(Thin Provisioning Snapshot)这两个功能来对Docker 的镜像和容器进行管理的。

 


Device Mapper 存储驱动将我们的每一个Docker 容器镜像都存放在它自身的虚拟设备之上,这些虚拟设备具备自动精简配置、写时拷贝和快照等功能。由于Device Mapper 技术工作在块层面而非文件系统层面,因此Docker 引擎的devicemapper 存储驱动使用块设备来进行数据的存储(包括元数据),而非使用文件系统。

 

不同于AUFS、ext2、ext3、ext4、XFS、NFS等常见的文件系统,Device Mapper 其实并不是一个文件系统。借助Device Mapper 我们可以很方便的根据自己的实际需要制定实现存储资源的管理策略。当前linux 中常见的逻辑卷管理技术有多种,并非只有Device Mapper,其他常用的比如EVMS(enterprise volume management system)、LVM2(linux volume manager 2 version)以及dmraid(device mapper reid tools)等,和Device Mapper 一样这几个工具也是基于逻辑设备映射到物理设备这样一种机制来实现的。

     

需要注意的是Device Mapper 工作的级别为块(block)级别,而不是文件级别,这一点是和文件系统的一个很大的不同点。Device Mapper 从linux 2.6.9这个内核版本开始后就被编译进了linux 的内核之中,因此所有新于linux 2.6.9这个内核的发行版中都会内置Device Mapper 这个存储驱动。虽然从linux2.6.9开始Device Mapper已经被内置到了linux的内核之中,但默认情况下是不能在linux上进行直接的使用的(比如CentOS 发行版的linux中默认使用的存储驱动是overlay),一般需要进行一些配置之后才能在Docker之中进行使用。 

 

Device Mapper 为实现存储资源管理的块设备驱动专门设计开发了一个定制的内核架构,该内核架构采用高度模块化的设计模式。Device Mapper 包含三个主要的概念,这三个概念对应三个名词,分别是:Mapped Device(也称映射设备)、Mapping Table(也称映射表)以及Target Device(也称目标设备)。映射设备就是我们上文中已经提过的对外提供的逻辑设备,映射设备在向下寻找时必须找到支撑的目标设备;映射表用于存储映射设备和目标设备的映射关系;目标设备比较灵活,可以是物理设备也可以是映射设备。其中映射表在内核空间中创建后再传递到内核空间。

 

简单说来Mapped Device 可以理解为linux的内核对外提供的一种逻辑设备,是一种逻辑上的抽象。Mapped Device 借助Mapping Table 的映射关系和Target Device 建立映射。其中,Mapped Device 对应的逻辑设备都会对应一个物理设备,Target Device 所表示的是Mapped Device 所映射的物理空间段。

 


需要注意的是Mapping Table 中的地址和offset 以linux磁盘的扇区(512字节)作为基本单位,所以当我们看到128时,实际代表其实是128 * 512字节。Device Mapper 存储驱动中的Mapping Table 里有逻辑的起始地址、地址范围、所在物理设备的地址偏移量以及Target 类型等数据。Mapped Device 支持映射一个或者多个物理设备到Target Device,同时也支持嵌套形式的映射(类似linux文件系统中目录里面还可以再有目录或者文件),比如将一个Device Mapper 映射到其他的Device Mapper,理论上可以无限嵌套下去。

 

Device Mapper 借助linux 内核中众多的模块化的Target 驱动插件对I/O请求进行过滤或者进行重定向。有些同学可能会问为什么要在内核中提供这么多的内核插件,这样设计的依据是什么? 最开始我也有同样的疑惑,后来专门花时间确认了下,最终查到这样的设计其实依据的是linux内核中策略和机制分离的原则。目前已经提供的插件包括镜像、快照、加密、多路径以及软raid等。

 

上文中我们讲过,Device Mapper 其实就是一个框架(区别于常见的文件系统),我们可以根据自己的业务的实际需要在这个框架上添加自己需要的各种各样的策略,这一点上有些类似面向对象中的策略模式。比较知名的插件比如Docker中DeviceMapper 里面最重要的模块--精简配置快照模块(thin provisioning snapshot)。


 

简单说来,Device Mapper 就是对外提供一个虚拟设备供用户进行使用,这块设备可以通过映射表找到相应的地址,这个地址可以指向一个设备,也可指向到一个虚拟设备。


Docker 中默认使用的存储驱动可以借助命令docker info 直接进行查看,以CentOS 发行版为例:

 

[root@localhost ~]# docker info

Containers: 13

 Running: 0

 Paused: 0

 Stopped: 13

Images: 13

Server Version: 1.10.3

Storage Driver: devicemapper

 Pool Name: docker-8:3-404820673-pool

 Pool Blocksize: 65.54 kB

 Base Device Size: 10.74 GB

 Backing Filesystem: xfs

 Data file: /dev/loop0

 Metadata file: /dev/loop1

 Data Space Used: 13.49 GB

 Data Space Total: 107.4 GB

 Data Space Available: 81.52 GB

 Metadata Space Used: 12.5 MB

 Metadata Space Total: 2.147 GB

 Metadata Space Available: 2.135 GB

 Udev Sync Supported: true

 Deferred Removal Enabled: false

 Deferred Deletion Enabled: false

 Deferred Deleted Device Count: 0

 Data loop file: /var/lib/docker/devicemapper/devicemapper/data

 WARNING: Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.

 Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata

 Library Version: 1.02.107-RHEL7 (2016-06-09)

Execution Driver: native-0.2

Logging Driver: journald

Plugins:

 Volume: local

 Network: null host bridge

Kernel Version: 3.10.0-327.36.1.el7.x86_64

Operating System: CentOS Linux 7 (Core)

OSType: linux

Architecture: x86_64

Number of Docker Hooks: 2

CPUs: 4

Total Memory: 1.781 GiB

Name: localhost.localdomain

ID: V7HM:XRBY:P6ZU:SGWK:J52L:VYOY:UK6L:TR45:YJRC:SZBS:DQRF:CFP5

WARNING: bridge-nf-call-iptables is disabled

WARNING: bridge-nf-call-ip6tables is disabled

Registries: docker.io (secure)

[root@localhost ~]#

 

通过上面的命令输出我们可以看出,Docker host 使用的默认存储驱动为devicemapper。另外从结果中Data loop file: /var/lib/docker/devicemapper/devicemapper/data和Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata 这两个文件可以看出Data loop file 和Metadata loop file 是存在的,且这两个文件都是loopback映射的稀疏文件,具体可以判断使用了loop-lvm模式。

 

Device Mapper 核心技术

 

1. 空间划分

 

Device Mapper 的空间主要分为两部分:用户空间、内核空间。

 

(1) 用户空间


在Device Mapper中用户空间这部分主要负责完成的是配置具体的策略和控制逻辑,这样描述可能比较笼统,举个例子,比如我们的逻辑设备需要和哪些物理设备建立映射,以及这种映射的具体建立方式等。


Device Mapper 用户空间和内核空间中包含device mapper 库和工具dmsrtup,会对Device Mapper 中用户空间中的device mapper 设备的创建和删除等操作进行二次封装。

 

(2) 内核空间

 

Device Mapper中内核空间主要做的工作就是提供机制,这些机制的作用就是完成上面说的用户空间策略所需要的一些机制,比如过滤和重定向I/O请求。Device Mapper 内核空间中通过不同的驱动插件来将I/O请求转发到目的设备上面。

 


2. 自动精简配置

 

自动精简配置是隶属于虚拟化中的一种技术,类似公有云中的资源超售,逻辑上可以提供很多的资源,似乎可以无限无限分配资源,但实际上用多少分配多少,目的就是为了提高资源的使用率。结合超售的概念再通过下面的一张图我们就可以清楚Device Mapper 中自动精简配置到底是怎么一回事。

 


3. 精简配置快照


说了那么多,Docker 到底是怎么使用自动精简配置来实现Docker 容器镜像的分层的呢? 答案是Docker 借助了自动精简配置中的快照技术,下面我们会具体看下自动精简配置中是如何实现快照这个功能的。

 

# 新建数据文件demo-data.img,在此直接以dd快速新建一下

[root@localhost ~]# dd if=/dev/zero of=demo-data.img bs=1M count=1 seek=10M

1+0 records in

1+0 records out

1048576 bytes (1.0 MB) copied, 0.00111645 s, 939 MB/s

 

# 新建元数据文件demo-meta.data.img

[root@localhost ~]# dd if=/dev/zero of=demo-meta.data.img bs=1M count=1 seek=1G

1+0 records in

1+0 records out

1048576 bytes (1.0 MB) copied, 0.00169702 s, 618 MB/s

 

创建完成后为两个文件各自创建一个环回设备。

 

# 为demo-data.img 文件新建环回设备

[root@localhost ~]# losetup /dev/loop0 demo-data.img

 

# 为demo-meta.data.img文件新建环回设备

[root@localhost ~]# losetup /dev/loop1 demo-meta.data.img

 

# 查看设备

[root@localhost ~]# losetup -a

/dev/loop0: [2051]:134991410 (/var/lib/docker/devicemapper/devicemapper/data)

/dev/loop1: [2051]:134991411 (/var/lib/docker/devicemapper/devicemapper/metadata)

 

# 新建一个自动精简配置的池,起始sector 0,最小可分配sectro数128

[root@localhost ~]# dmsetup create demo-thin-pool --table "0 20971522 thin-pool /dev/loop1 /dev/loop0 128 65536 1 skip_block_zeroing"

 

# 正常的话可以看到新建的DeviceMapper设备

[root@localhost ~]# ls /dev/mapper/

control  docker-8:3-404820673-pool  demo-thin-pool

 

# 格式化之前需要先新建一个自动精简配置的卷

[root@localhost ~]# dmsetup message /dev/mapper/demo-thin-pool 0 "create_thin 0"

 

注:上面命令引号部分中,create_thin 为关键字,0为我们为这个卷分配额设备id。

 

# 为上面新建的卷创建一个可以挂载的设备

[root@localhost ~]# dmsetup create demo-thin-volume-1 --table "0 2097152 thin /dev/mapper/demo-thin-pool 0"

 

后面需要挂载我们新加的设备,但是在挂载之前我们需要先对新加的设备进行格式化。

 

# 格式化卷,格式化的文件系统在此我们以ext4为例

[root@localhost ~]# mkfs.ext4 /dev/mapper/demo-thin-volume-1

 

格式化完成之后,后面就可以进行挂载操作了。

 

# 新建挂载点目录,在此我们以dm为例

[root@localhost ~]# mkdir /mnt/dm

 

# 将上面我们格式化好的卷挂载到挂载点dm

[root@localhost ~]# mount /dev/mapper/demo-thin-volume-1 /mnt/dm

 

下面我们在我们的device mapper设备中添加一个文件,并写入一些测试的数据。

 

# 新建测试文件

[root@localhost ~]# echo "demo thin-vloume" > /mnt/dm/demo

[root@localhost ~]# cat /mnt/dm/demo

demo thin-vloume

 

新建的DeviceMapper设备挂载完成之后,下面我们开始处理快照的事情。

 

# 向demo-thin-pool 发送创建快照的消息

[root@localhost ~]# dmsetup message /dev/mapper/demo-thin-pool 0 "create_snap 1 0"

 

# 创建设备,名称此处以demosnap为例

[root@localhost ~]# dmsetup create demosnap --table "0 2097152 thin /dev/mapper/demo-thin-pool 1"

 

# 为demosnap 创建挂载点目录

[root@localhost ~]# mkdir /mnt/demosnap

 

# 挂载demosnap 到新建的挂载点目录

[root@localhost ~]# mount /dev/mapper/demosnap /mnt/demosnap

 

# 查看快照里是否有我们前面新建的文件demo

[root@localhost ~]# ls /mnt/demosnap

demo

 

# 查看文件内容是否和之前的一致

[root@localhost ~]# cat /mnt/demosnap/demo

demo thin-vloume


从结果可以看出镜像中可以看到我们前面新建的文件,且我们这里新建的镜像中的文件以及文件中的数据和源数据是一样的,下面我们看下镜像到底有没有分层。要验证这个问题,我们只需要修改下快照的数据,然后看下源数据是否会被同样的修改掉即可。

 

# 修改快照中的文件demo中的数据

[root@localhost ~]# echo "demo thin-volume snap" > /mnt/demosnap/demo

 

# 快照中添加一个新的文件

[root@localhost ~]# echo "demo thin-volume snap2" > /mnt/demosnap/demo2

 

# 查看当前快照数据

[root@localhost ~]# ls /mnt/demosnap/

demo  demo2

 

# 查看/mnt/dm下数据是否发生变化

[root@localhost ~]# ls /mnt/dm/

demo

 

从结果看快照中新增的文件demo2并未出现,我们再看下demo文件的数据是否被修改掉。

 

[root@localhost ~]# cat /mnt/dm/demo

demo thin-vloume


从结果看demo文件中的数据并未因为镜像中的修改而被修改,可见确实是进行了分层。

 

在此我们只建了一个快照,因此镜像的分层现象看着并不是很明显,我们可以再在刚刚新建的镜像上再添加一个镜像,这样就可以比较明确的看到分层镜像了

 

# 创建新镜像demosnap2

[root@localhost ~]# dmsetup message /dev/mapper/demo-thin-pool 0 "create_snap 2 1"

[root@localhost ~]# dmsetup create demosnap2 --table "0 2097152 thin /dev/mapper/demo-thin-pool 2"

 

# 新建新镜像的挂载点目录

[root@localhost ~]# mkdir /mnt/demosnap2

 

# 挂载新镜像到新的挂载点上

[root@localhost ~]# mount /dev/mapper/demosnap2  /mnt/demosnap2

 

# 查看新镜像的数据

[root@localhost ~]# ls /mnt/demosnap2

demo2

 

可以参考上文中对第一个镜像的操作来操作下第二个镜像,看下现象是否是一样。

 

以上就是对DeviceMapper 核心原理的一个解释和基本的操作演示,下文中我们会看下DeviceMapper 在Docker 中具体是如何使用的。


Docker 中的Device Mapper核心技术

 

Docker 中的devicemapper 存储驱动有三个核心概念,分别是:写时复制(copy on write)、自动精简配置(thin provisioning)以及快照(snapshot)。其中自动精简配置和快照技术上文中在讲Device Mapper 核心原理时我们已经说过,这里我们先简单介绍下写时复制技术。

 

1. 写时复制原理

 

写时复制技术是Docker 容器中非常核心的一个功能,Docker 容器运行后,当我们需要去修改一个不在最顶层分支中的文件时,这个时候最顶层的分支需要先将需要修改的文件从其所在的层拷贝到最顶层的分支,然后再对拷贝上上来的文件进行修改,文件修改完成后位于底层分支的文件内容并未发生改变,这种方式就是写时复制技术,也称COW。

 

当我们在最上层的分支中去删除从底层分支拷贝上来的文件时,此时文件文件并没有被实际删除,只是在最顶层的分支中对被删文件进行了重命名和隐藏的操作,因此被执行删除操作的文件实际并没有被删除,只是不可见了。

 

如下图所示,我们看到的文件file1 其实是镜像层中branch0分支中的文件:

 


当我们需要修改文件file1时,Device Mapper 中的写时复制技术会将文件file1直接拷贝到最上层的top branch,然后再进行修改,即我们修改的其实是从底层拷贝的文件:

 


当我们需要删除文件file1时,由于文件file1是镜像层的文件,此时会在容器最上层中创建一个.wh开头的隐藏文件,从而将文件file1隐藏掉,所以文件file1并未被删除掉,这样也就保证了镜像层数据的完整性和复用性。

 

有些同学可能会问,每次修改底层的文件时都需要先从底层将文件复制上来,是否会影响容器的性能?答案是会影响,所以一般建议对于容器中需要经常修改的文件不要放到底层的镜像层中,可以在容器运行起来后再将需要频繁修改的文件添加到容器中。

 

2. Docker DeviceMapper 实践

 

devicemapper 是红帽系列linux发行版上的默认存储驱动,它有两种配置模式:loop-lvm以及direct-lvm。

 

我们知道使用Device Mapper 作为Docker 的存储驱动时,默认情况下使用的配置模式一般是loop-lvm,loop-lvm 使用操作系统层面离散的文件来构建精简池。Loop-lvm 模式会借助服务器中空闲的文件来构建存储池,这些存储池主要提供给Docker 容器镜像和Docker 容器快照进行使用。Loop-lvm 在使用上非常简单,无需额外的配置,开箱即可使用,不过一般不太建议在生产环境中使用lvm模式,Docker 官方明文说明不推荐使用该模式:

 

WARNING: Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.

 

direct-lvm 是Docker 官方推荐的生产环境中可以使用的模式,该模式使用块设备来构建精简池来存放镜像和Docker容器的数据。

 

早期使用direct-lvm 模式时一般需要技术人员自己手动配置lvm,所有的配置项都需要自己逐个手动的添加,整个过程相对比较繁琐,好在从Docker 17.06开始Docker 已经支持了自动化配置direct-lvm(需要注意单个块设备的限制)。

 

(1) direct-lvm 模式自动配置


需要注意的是direct-lvm目前还只能支持1个块设备,如果需要使用多个块设备,这个时候direct-lvm 自动配置就不适合了,需要进行手动配置。


direct-lvm 模式自动配置的示例配置文件位置为:/usr/lib/docker-storage-setup/docker-storage-setup,可以在此查看一些常见配置的详细说明,另外也可通过docker storage setup 的linux man 手册来查看具体的使用文档和配置项说明,在此笔者整理了一下几个常用的关键选项:

 

参数名称

参数说明

是否必填

默认值

参数示例值

directlvm_device

将要配置的direct-lvm的块设备的路径

yes


directlvm_device=“/dev/your-device”

directlvm_device_force

指定需要创建的data thin pool 的大小

no

95

thinp_percent=95

thinp_autoextend_percen

指定需要创建的metadata thin pool的大小

no

1

thinp_metapercent=1

thinp_autoextend_threshold

指定自动扩容的百分比,其中100代表disable,百分比最小为50

no

80

thinp_autoextend_threshold=80

t thinp_metapercent

指定每次扩容的大小,即实际值,上面的为百分比。需要注意的是也是100代表disable

no

20

thinp_autoextend_percent=20

thinp_percent

当需要使用的块设备中已经有文件系统时,是否需要对该 设备执行格式化

no

false

directlvm_device_force=true

 

参数的具体配置路径为:/etc/docker/daemon.json,上面表格中参数对应的示例配置如下:

 

[root@localhost ~]# cat /etc/docker/daemon.json

{

  "storage-driver": "devicemapper",

  "storage-opts": [

    "dm.directlvm_device=/dev/xdf",

    "dm.thinp_percent=95",

    "dm.thinp_metapercent=1",

    "dm.thinp_autoextend_threshold=80",

    "dm.thinp_autoextend_percent=20",

    "dm.directlvm_device_force=false"

  ]

}

 

以上便是对Docker device mapper 中direct-lvm 模式自动配置的一个简单的描述,下面我们一起看下direct-lvm 模式的手动配置。

 

(2) direct-lvm 手动配置

 

a. 停止Docker daemon

 

    进行手动配置前我们需要确保服务器上的Docker Daemon 是停止的。

 

    # 停止Docker 的守护进程

[root@localhost ~]# systemctl stop docker

 

# 查看Docker 守护进程状态

[root@localhost ~]# systemctl status docker

● docker.service - Docker Application Container Engine

   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)

   Active: inactive (dead) since Thu 2019-06-27 20:11:59 PDT; 6s ago

     Docs: http://docs.docker.com

  Process: 1505 ExecStart=/usr/bin/docker-current daemon --exec-opt native.cgroupdriver=systemd $OPTIONS $DOCKER_STORAGE_OPTIONS $DOCKER_NETWORK_OPTIONS $ADD_REGISTRY $BLOCK_REGISTRY $INSECURE_REGISTRY (code=exited, status=0/SUCCESS)

 Main PID: 1505 (code=exited, status=0/SUCCESS)

 

Jun 25 18:38:24 localhost.localdomain docker-current[1505]: .............time="2019-06-25T18:38:24.934695010-07:00" level=error m...nted"

Jun 25 18:38:24 localhost.localdomain docker-current[1505]: time="2019-06-25T18:38:24.936034267-07:00" level=error msg="Error unm...nted"

Jun 25 18:38:25 localhost.localdomain docker-current[1505]: time="2019-06-25T18:38:25.003155308-07:00" level=info msg="Loading co...one."

Jun 25 18:38:25 localhost.localdomain docker-current[1505]: time="2019-06-25T18:38:25.003207642-07:00" level=info msg="Daemon has...tion"

Jun 25 18:38:25 localhost.localdomain docker-current[1505]: time="2019-06-25T18:38:25.003244444-07:00" level=info msg="Docker dae....10.3

Jun 25 18:38:25 localhost.localdomain systemd[1]: Started Docker Application Container Engine.

Jun 25 18:38:25 localhost.localdomain docker-current[1505]: time="2019-06-25T18:38:25.009717428-07:00" level=info msg="API listen...sock"

Jun 27 20:11:59 localhost.localdomain systemd[1]: Stopping Docker Application Container Engine...

Jun 27 20:11:59 localhost.localdomain docker-current[1505]: time="2019-06-27T20:11:59.755131077-07:00" level=info msg="Processing...ted'"

Jun 27 20:11:59 localhost.localdomain systemd[1]: Stopped Docker Application Container Engine.

Hint: Some lines were ellipsized, use -l to show in full.

 

b. 部署lVM2

 

       LVM2 不是单个软件,是一个包含管理linux上逻辑卷的用户空间工具集。

 

       # 安装device mapper persistent data

       [root@localhost ~]# yum install -y device-mapper-persistent-data

 

       # 安装lvm2

       [root@localhost ~]# yum install -y lvm2

 

c. 管理

 

上面的工具集安装完成后接下来就是对卷的管理操作,过程和我们日常使用lvm基本一致。

 

# 新建物理卷

[root@localhost ~]# pvcreate /dev/sdb

  Physical volume "/dev/sdb" successfully created.

 

# 新建一个名为docker 卷组

[root@localhost ~]# vgcreate docker /dev/sdb

  Volume group "docker" successfully created

 

# 新建存储池,此处存储池名称以thinpool 为例

[root@localhost ~]#  lvcreate --wipesignatures y -n thinpool docker -l 95%VG

  Logical volume "thinpool" created.


参数95%代表设置存储池的大小为卷组的尺寸的90%,的10%的空间可以用于后续的数据的自动扩展和元数据的存储。

 

# 新建元数据存储池,在此我们只分配1%的空间

[root@localhost ~]# lvcreate --wipesignatures y -n thinpoolmeta docker -l 1%VG

  Logical volume "thinpoolmeta" created.

 

以上我们就准备好了存储池和元数据的存储池,接下来我们将存储池转换为thinpool格式。

 

# 存储池格式转换为thinpool 格式

[root@localhost ~]# lvconvert -y --zero n -c 512K --thinpool docker/thinpool --poolmetadata docker/thinpoolmeta

  Thin pool volume with chunk size 512.00 KiB can address at most 126.50 TiB of data.

  WARNING: Converting docker/thinpool and docker/thinpoolmeta to thin pool's data and metadata volumes with metadata wiping.

  THIS WILL DESTROY CONTENT OF LOGICAL VOLUME (filesystem etc.)

  Converted docker/thinpool and docker/thinpoolmeta to thin pool.

 

# 配置存储池的自动扩展

[root@localhost ~]# vim /etc/lvm/profile/docker-thinpool.profile

 

设置参数thin_pool_autoextend_threshold、thin_pool_autoextend_percent,这两个参数的含义在direct-lvm 模式自动配置中已经描述过,在此我们不再赘述。

 

示例配置:

 

[root@localhost ~]# cat /etc/lvm/profile/docker-thinpool.profile

activation{

  thin_pool_autoextend_threshold = 80

  thin_pool_autoextend_percent = 20

}

 

# 新lvm 配置生效

[root@localhost ~]# lvchange --metadataprofile docker-thinpool docker/thinpool

  Logical volume docker/thinpool changed.

 

# 通过卷信息查看逻辑卷是否受监控

[root@localhost ~]# lvs -o+seg_monitor

  LV       VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert Monitor  

  thinpool docker twi-a-t--- <19.00g             0.00   0.03                             monitored

 

# 备份Docker 的数据

[root@localhost ~]# mkdir /var/lib/docker.bk

[root@localhost ~]# mv /var/lib/docker/* /var/lib/docker.bk

 

修改配置文件/etc/docker/daemon.json,打开参数dm.use_deferred_removal、dm.use_deferred_deletion,防止意外产生的挂载点泄露问题。

[root@localhost ~]# cat /etc/docker/daemon.json

{

    "storage-driver": "devicemapper",

    "storage-opts": [

    "dm.thinpooldev=/dev/mapper/docker-thinpool",

    "dm.use_deferred_removal=true",

    "dm.use_deferred_deletion=true"

    ]

}

 

# 查看服务器上的devicemapper 结构,查看上面创建的设备文件和存储池是否就绪

[root@localhost ~]# lsblk

NAME                    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT

sda                       8:0    0  100G  0 disk

├─sda1                    8:1    0  300M  0 part /boot

├─sda2                    8:2    0    2G  0 part [SWAP]

└─sda3                    8:3    0 97.7G  0 part /

sdb                       8:16   0   20G  0 disk

├─docker-thinpool_tmeta 253:1    0  204M  0 lvm  

│ └─docker-thinpool     253:3    0   19G  0 lvm  

└─docker-thinpool_tdata 253:2    0   19G  0 lvm  

  └─docker-thinpool     253:3    0   19G  0 lvm  

sr0                      11:0    1 1024M  0 rom  

 

从查询结果可以看出docker-thinpool 存储池在data 和 metadata两个设备之上。一般建议的存储池的命名规则为:Docker-主设备号:二级设备号-inode号-pool。

 

需要注意的是,生产环境中一般不建议过于依赖lvm的自动扩展,虽然大部分情况下卷组可以自动进行扩展,但是有时候卷组可能会被塞满。所以在生产环境中需要根据自己的实际需要降低对自动扩展的依赖,同时建议添加对卷空间使用量的监控。

 




福利来了!!!


评论区留下你对容器的理解与看法,

我们将抽取点赞数最高的三位读者,

送出以下精美图书一份

活动时间截止7月11日18:00



内容简介:本书将以企业落地实践为切入点,分享作为终端用户的企业在关键业务环境中落地使用 Docker 及 Kubernetes 技术的经验和心得。内容既有扎实的技术实现方法,又有各行业容器技术企业级落地实践的深度解读。


内容简介: 本书给开发者、架构师、运维工程师提供了富有实践价值的技术资料。阅读本书,将学习到如何使用以容器为中心的方法,帮助团队交付高质量软件,而这都是基于红帽的云化PaaS 平台OpenShift 来自动服务的。本书详细介绍了如何配置容器应用、如何使用OpenShift的开发运维工具管理Kubernetes 集群。



内容简介: 本书提供几十个基于场景的演示,介绍使用OpenDaylight可以解决的基础案例,包括讨论虚拟用户边缘、动态互连、网络虚拟化、虚拟核心和聚合、意图和策略联网、自定义OpenDaylight容器、认证和授权。经典场景的介绍,能帮助读者快速学习和掌握OpenDaylight相关知识。


福利

扫描添加小编微信,备注“姓名+公司职位”,加入【云计算学习交流群】,和志同道合的朋友们共同打卡学习!



推荐阅读:


真香,朕在看了!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存