原标题:Docker本身的存储空间管理

目标:两台host主机透过一个网络接口共享磁盘设备

(iSCSI)

共享设备的主机和名字

target(/dev/loop8) —> initiator(/dev/sdb) —> initiator_docker(dev/sdb_test)
Target(10.43.100.a)
initiator(10.43.100.b)

注意点:防火墙和selinux,本次关闭了防火墙

target端和inititor端简单介绍

target端即磁盘阵列或其他装有磁盘的主机,server端。

通过iscsitarget工具将磁盘空间映射到网络上,initiator端就可以寻找发现并使用该磁盘。注意,一个target主机上可以映射多个target到网络上,即可以映射多个块设备到网络上。

initiator就是iSCSI传输的客户端,client端。

iSCSI initiator通过IP网络传输SCSI命令。

target端配置

软件安装

[target]# yum install scsi-target-utils

建立大型文件,创建所需要分享的磁盘设备,loop8

[target dev]# dd if=/dev/zero of=floppy.img bs=512 count=1880
1880+0 records in
1880+0 records out
962560 bytes (963 kB) copied, 0.0017846 s, 539 MB/s
[target dev]# losetup /dev/lo
log loop0 loop1 loop2 loop-control
[target dev]# losetup /dev/loop8 floppy.img
[target dev]# ll loop
loop0 loop1 loop2 loop8 loop-control
tgtadm——Linux SCSI Target管理工具
tgtadm是用来监控、修改Linux SCSI target 的工具,包括target设置、卷设置,等。
提供为装有SCSI initiator的其它操作系统提供块级(block-level)的SCSI存储。
Linux iSCSI target,通过网络向装有iSCSI initiator的系统提供存储服务。

查看帮助文档,对命令参数进行一点了解

[target]# tgtadm —help

iSCSI 有一套自己分享 target 设备名的定义:

以iqn为开头,意思是:『iSCSI Qualified Name (iSCSI 合格名称)』。

iqn 后面通常是:iqn.yyyy-mm. :identifier

所以本次取名:iqn.2015-03.com.huawei:designDisk

iqn号是局域网内iSCSI target的唯一标识,用来区分不同的target,所以在一个网络内,iqn号一定不能相同!

设定tgt的配置文件 /etc/tgt/targets.conf

添加下面几行配置代码:

[target]# vi /etc/tgt/targets.conf
backing-store /dev/loop8
initiator-address 10.43.100.a/24
重启服务
[target]# service tgtd restart
[target]# netstat -tlunp | grep tgt
tcp 0 0 0.0.0.0:3260 0.0.0.0:* LISTEN 3896/tgtd
tcp6 0 0 :::3260 :::* LISTEN 3896/tgtd
查看target端的配置信息
[target]# tgt-admin —show
等同于(===)
[target]# tgtadm —lld iscsi —op show —mode target
[target fengshq]# tgt-admin —show
Target 1: iqn.2017-12.com.example:mytest.target1
System information:
Driver: iscsi
State: ready
I_T nexus information:
I_T nexus: 1
Initiator: iqn.opencos.rh:b139ea76ced alias: tfg-33
Connection: 0
IP Address: 10.43.100.b
LUN information:
LUN: 0
Type: controller
SCSI ID: IET 00010000
SCSI SN: beaf10
Size: 0 MB, Block size: 1
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
SWP: No
Thin-provisioning: No
Backing store type: null
Backing store path: None
Backing store flags:
LUN: 1
Type: disk
SCSI ID: IET 00010001
SCSI SN: beaf11
Size: 1 MB, Block size: 512
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
SWP: No
Thin-provisioning: No
Backing store type: rdwr
Backing store path: /dev/loop8
Backing store flags:
Account information:
ACL information:
10.43.100.a/24
initiator端配置
软件安装和服务启动
[initiator]# yum install iscsi-initiator-utils
[initiator]# service iscsi start
查看initiator没有连接target时的磁盘设备
[initiator]#ls /dev/sd*
/dev/sda /dev/sda1 /dev/sda2

搜索targets

通过iscsiadm命令来搜索和登录到iSCSI的target,同时它也可以读取和访问open-iscsi提供的数据库。 存储服务器(target)的ip地址为 10.43.100.b,输入:

[initiator]# iscsiadm -m discovery -t sendtargets -p 10.43.100.b
10.43.100.b:3260,1 iqn.2017-12.com.example:mytest.target1
[initiator]# cd /var/lib/iscsi/send_targets/10.43.100.b,3260/
[initiator 186.100.8.117,3260]#ll
lrwxrwxrwx. 1 root root 80 Dec 25 15:04 iqn.2017-12.com.example:mytest.target1,10.43.100.b,3260,1,default -> /var/lib/iscsi/nodes/iqn.2017-12.com.example:mytest.target1/10.43.100.b,3260,1

表明客户端已经成功发现服务端共享target并连接到本地上来了;

登陆到服务器target上

[initiator]# iscsiadm -m node -T iqn.2017-12.com.example:mytest.target1 -p 10.43.100.b:3260 -l
Logging in to [iface: default, target: iqn.2017-12.com.example:mytest.target1, portal: 10.43.100.b,3260] (multiple)
Login to [iface: default, target: iqn.2017-12.com.example:mytest.target1, portal: 10.43.100.b,3260] successful.
看到successful,证明已经登录成功了!
在target上,再查看target的信息
[target]# Target 1: iqn.2017-2.com.example:mytest.target1
System information:
Driver: iscsi
State: ready
I_T nexus information:
I_T nexus: 1
Initiator: iqn.opencos.rh:b139ea76ced alias: tfg-33
Connection: 0
IP Address: 10.43.100.b
LUN information:
LUN: 0
Type: controller
SCSI ID: IET 00010000
SCSI SN: beaf10
Size: 0 MB, Block size: 1
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
SWP: No
Thin-provisioning: No
Backing store type: null
Backing store path: None
Backing store flags:
LUN: 1
Type: disk
SCSI ID: IET 00010001
SCSI SN: beaf11
Size: 1 MB, Block size: 512
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
SWP: No
Thin-provisioning: No
Backing store type: rdwr
Backing store path: /dev/loop8
Backing store flags:
Account information:
ACL information:
10.43.166.0/24
查看initiator连接上target后的磁盘设备
[initiator]# ls /dev/sd*
/dev/sda /dev/sda1 /dev/sda2 /dev/sdb
可以看到,产生了一个sdb设备,这也就是target上的loop8设备。
在initiator启docker容器,并将sdb与docker容器共享
localfs方式测试
[initiator]# docker run -i -t —rm —privileged -v /dev/sdb:dev/sdb_test centos /bin/bash
创建a.txt,并将其写入共享block
[initiator docker]# echo “hello world” >a.txt
[initiator docker]# dd if=a.txt of=/dev/sdb_test
0+1 records in
0+1 records out
12 bytes (12 B) copied, 6.9711e-05 s, 172 kB/s
验证:查看已修改的共享block
[target]# dd if=/dev/loop8 of=c.txt bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000108951 s, 4.7 MB/s
[target]# cat c.txt
hello world
device方式测试
[initiator]# docker run -i -t —rm —privileged —device /dev/sdb:/dev/sdb centos /bin/bash
创建a.txt,并将其写入共享block
[initiator docker]# echo “hello device mount” >a.txt
[initiator docker]# dd if=a.txt of=/dev/sdb
0+1 records in
0+1 records out
12 bytes (12 B) copied, 6.9711e-05 s, 172 kB/s
验证:查看已修改的共享block
[target]# dd if=/dev/loop8 of=c.txt bs=512 count=1
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.000108951 s, 4.7 MB/s
[target]# cat c.txt
hello device mount
设备是否需要特权级
Localfs需要privileged 权限
如果不加特权级则没有权限访问
[root@tfg-33 common]# docker run —rm -ti -v /dev/sdb:/dev/sdb_test test:1 /bin/sh
sh-4.2# echo “local fs” > /home/1
sh-4.2# dd if=/home/1 of=/dev/sdb_test
dd: failed to open ‘/dev/sdb_test’: Operation not permitted
sh-4.2# ls -al /dev/sdb_test
brw-rw——. 1 root disk 8, 16 Dec 25 07:17 /dev/sdb_test
而添加特权级就有权限访问了
[root@tfg-33 noarch]# docker run —rm —privileged -ti -v /dev/sdb:/dev/sdb_test test:1 /bin/sh
sh-4.2# echo “local fs + privileged” > /home/1
sh-4.2# dd if=/home/1 of=/dev/sdb_test
0+1 records in
0+1 records out
22 bytes (22 B) copied, 9.6358e-05 s, 228 kB/s
sh-4.2#
sh-4.2# ls -al /dev/sdb_test
brw-rw——. 1 root disk 8, 16 Dec 26 10:19 /dev/sdb_test
Device不需要privileged
两者方式都能访问
[root@tfg-33 ~]# docker run —rm -ti —device /dev/sdb:/dev/sdb test:1 /bin/sh
sh-4.2#
sh-4.2# ls -al /dev/sdb
brw-rw——. 1 root disk 8, 16 Dec 26 10:23 /dev/sdb
sh-4.2#
sh-4.2#
sh-4.2# echo “device” > /home/1
sh-4.2# dd if=/home/1 of=/dev/sdb
0+1 records in
0+1 records out
7 bytes (7 B) copied, 9.6972e-05 s, 72.2 kB/s
sh-4.2#
sh-4.2# exit
exit
[root@tfg-33 ~]# docker run —rm -ti —privileged —device /dev/sdb:/dev/sdb test:1 /bin/sh
sh-4.2# ls -al /dev/sdb
brw-rw——. 1 root disk 8, 16 Dec 26 10:25 /dev/sdb
sh-4.2# echo “device + privileged” > /home/1
sh-4.2#
sh-4.2# dd if=/home/1 of=/dev/sdb
0+1 records in
0+1 records out
20 bytes (20 B) copied, 9.2424e-05 s, 216 kB/s

原理说明

默认情况下,Docker的容器是没有特权,例如不能在容器中再启动一个容器。这是因为默认情况下容器不能访问任何其它设备。但通过privileged,容器就拥有了访问其它任何设备的权限。当操作者执行docker run —privileged时,Docker将拥有访问主机所有设备的权限,同时Docker也会在apparmor或者selinux做一些设置,使容器可以访问那些运行在容器外部的设备。

同时可以限制容器只能访问一些指定的设备,下面的命令将允许容器只访问一些特定设备:

docker run —device=/dev/snd:/dev/snd …