Docker和Kubernetes中使用Ceph RBD卷的原理分析
在Docker
或者Kubernetes
中使用Ceph RBD
塊裝置,相比於在宿主機中,是否會對效能造成額外損失?帶著這些疑問對相關技術進行原理分析。
Linux中的Mount繫結傳播
參考文件:
- Shared Subtrees;
- Mount namespaces and shared subtrees;
- Mount namespaces, mount propagation, and unbindable mounts。
Linux的Mount繫結關係
Linux
Mount
名稱空間通過隔離檔案系統掛載點對隔離檔案系統提供支援,它是歷史上第一個 Linux
Namespace
,所以它的標識位比較特殊,就是 CLONE_NEWNS
Mount
Namespace
中的檔案結構發生變化也互不影響。你可以通過 /proc/[pid]/mounts
檢視到所有掛載在當前 Namespace 中的檔案系統,還可以通過 /proc/[pid]/mountstats
看到 Mount
Namespace
中檔案裝置的統計資訊,包括掛載檔案的名字、檔案系統型別、掛載位置等等。
程序在建立 Mount
Namespace
時,會把當前的檔案結構複製給新的 Namespace
。新 Namespace
中的所有 Mount 操作都隻影響自身的檔案系統,而對外界不會產生任何影響。這樣做非常嚴格地實現了隔離,但是某些情況可能並不適用。比如父節點 Namespace
CD-ROM
,這時子節點 Namespace
拷貝的目錄結構就無法自動掛載上這張 CD-ROM
,因為這種操作會影響到父節點的檔案系統。
2006 年引入的掛載傳播(Mount
Propagation
)解決了這個問題,掛載傳播定義了掛載物件(Mount
Object
)之間的關係,系統用這些關係決定任何掛載物件中的掛載事件如何傳播到其他掛載物件(參考自:http://www.ibm.com/developerworks/library/l-mount-namespaces/)。所謂傳播事件,是指由一個掛載物件的狀態變化導致的其它掛載物件的掛載與解除掛載動作的事件。
- 共享關係(
Share
Relationship
- 從屬關係(
Slave
Relationship
)。如果兩個掛載物件形成從屬關係,那麼一個掛載物件中的掛載事件會傳播到另一個掛載物件,但是反過來不行;在這種關係中,從屬物件是事件的接收者。
一個掛載狀態可能為如下的其中一種:
- 共享掛載(
Shared
) - 從屬掛載(
Slave
) - 共享
/
從屬掛載(Shared
And
Slave
) - 私有掛載(
Private
) - 不可繫結掛載(
Unbindable
)
傳播事件的掛載物件稱為共享掛載(Shared
Mount
);接收傳播事件的掛載物件稱為從屬掛載(Slave
Mount
)。既不傳播也不接收傳播事件的掛載物件稱為私有掛載(Private
Mount
)。另一種特殊的掛載物件稱為不可繫結的掛載(Unbindable
Mount
),它們與私有掛載相似,但是不允許執行繫結掛載,即建立 Mount
Namespace
時這塊檔案物件不可被複制。
共享掛載的應用場景非常明顯,就是為了檔案資料的共享所必須存在的一種掛載方式;從屬掛載更大的意義在於某些“只讀”場景;私有掛載其實就是純粹的隔離,作為一個獨立的個體而存在;不可繫結掛載則有助於防止沒有必要的檔案拷貝,如某個使用者資料目錄,當根目錄被遞迴式的複製時,使用者目錄無論從隱私還是實際用途考慮都需要有一個不可被複制的選項。
- 預設情況下,所有掛載都是私有的。設定為共享掛載的命令如下:
$ mount --make-shared <mount-object>
從共享掛載克隆的掛載物件也是共享的掛載;它們相互傳播掛載事件。
- 設定為從屬掛載的命令如下:
$ mount --make-slave <shared-mount-object>
從從屬掛載克隆的掛載物件也是從屬的掛載,它也從屬於原來的從屬掛載的主掛載物件。
- 將一個從屬掛載物件設定為共享 / 從屬掛載,可以執行如下命令或者將其移動到一個共享掛載物件下:
$ mount --make-shared <slave-mount-object>
- 如果你想把修改過的掛載物件重新標記為私有的,可以執行如下命令:
$ mount --make-private <mount-object>
- 通過執行以下命令,可以將掛載物件標記為不可繫結的:
$ mount --make-unbindable <mount-object>
Linux的Mount繫結測試
- 檢視本機塊裝置:
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 222.6G 0 disk
├─sda1 8:1 0 200M 0 part /boot
└─sda2 8:2 0 222.4G 0 part
├─centos-root 253:0 0 122.4G 0 lvm /
└─centos-home 253:1 0 100G 0 lvm /home
- 建立和繫結目錄:
$ mkdir /opt/tmp /mnt/tmp /mnt/tmp1 /mnt/tmp2
$ mount --bind /opt/tmp /mnt/tmp
$ mount --bind /mnt/tmp1 /mnt/tmp2
- 檢視繫結目錄的詳細資訊:
$ cat /proc/self/mountinfo | grep /mnt/tmp
549 40 253:0 /opt/tmp /mnt/tmp rw,relatime shared:1 - xfs /dev/mapper/centos-root rw,seclabel,attr2,inode64,noquota
583 40 253:0 /mnt/tmp1 /mnt/tmp2 rw,relatime shared:1 - xfs /dev/mapper/centos-root rw,seclabel,attr2,inode64,noquota
可以看到兩個繫結目錄都是共享的,且共享ID
為1
,父目錄在253:0
裝置上。
在Docker中使用資料卷的主要方式
參考文件:
Docker
支援的掛載模式:
- 建立一個數據卷(卷掛載):
$ docker run --rm -it -v /data1 centos:7 bash
# Or
$ docker run --rm -it -v data1:/data1 centos:7 bash
# Or
$ docker run --rm -it --mount target=/data1 centos:7 bash
# Or
$ docker run --rm -it --mount type=volume,target=/data1 centos:7 bash
# Or
$ docker run --rm -it --mount type=volume,source=data1,target=/data1 centos:7 bash
$ docker ps | awk 'NR==2 {print $1}' | xargs -i docker inspect -f '{{.State.Pid}}' {} | xargs -i cat /proc/{}/mountinfo | grep data
1029 1011 253:0 /var/lib/docker/volumes/239be79a64f7fa6ec815b1d9f2a7773a678ee5c8c1150f03ca81b0d5177b36a0/_data /data1 rw,relatime master:1 - xfs /dev/mapper/centos-root rw,seclabel,attr2,inode64,noquota
- 對映一個外部卷(繫結掛載):
$ docker run --rm -it -v /opt:/data2 centos:7 bash
# Or
$ docker run --rm -it --mount type=bind,source=/opt,target=/data2 centos:7 bash
$ docker ps | awk 'NR==2 {print $1}' | xargs -i docker inspect -f '{{.State.Pid}}' {} | xargs -i cat /proc/{}/mountinfo | grep data
1029 1011 253:0 /opt /data2 rw,relatime - xfs /dev/mapper/centos-root rw,seclabel,attr2,inode64,noquota
- 使用資料型容器(卷掛載):
$ docker create --name vc -v /data1 centos:7
$ docker run --rm -it --volumes-from vc centos:7 bash
$ docker ps | awk 'NR==2 {print $1}' | xargs -i docker inspect -f '{{.State.Pid}}' {} | xargs -i cat /proc/{}/mountinfo | grep data
1029 1011 253:0 /var/lib/docker/volumes/fe71f2d0ef18beb92cab7b99afcc5f501e47ed18224463e8c1aa1e8733003803/_data /data1 rw,relatime master:1 - xfs /dev/mapper/centos-root rw,seclabel,attr2,inode64,noquota
- 帶打包資料的容器(卷掛載):
編輯Dockerfile
FROM busybox:latest
ADD htdocs /usr/local/apache2/htdocs
VOLUME /usr/local/apache2/htdocs
建立容器
$ mkdir htdocs
$ echo `date` > htdocs/test.txt
$ docker build -t volume-test .
$ docker create --name vc2 -v /data1 volume-test
$ docker run --rm -it --volumes-from vc2 volume-test sh
/ # cat /proc/self/mountinfo | grep htdocs
1034 1011 253:0 /var/lib/docker/volumes/54f47af60b8fb25602f022dcd8ad5b3e1a93a2d20c1045184a70391d9bed69b6/_data /usr/local/apache2/htdocs rw,relatime master:1 - xfs /dev/mapper/centos-root rw,seclabel,attr2,inode64,noquota
$ docker ps | awk 'NR==2 {print $1}' | xargs -i docker inspect -f '{{.State.Pid}}' {} | xargs -i cat /proc/{}/mountinfo | grep htdocs
1034 1011 253:0 /var/lib/docker/volumes/54f47af60b8fb25602f022dcd8ad5b3e1a93a2d20c1045184a70391d9bed69b6/_data /usr/local/apache2/htdocs rw,relatime master:1 - xfs /dev/mapper/centos-root rw,seclabel,attr2,inode64,noquota
- 使用臨時外部卷(臨時掛載):
$ docker run --rm -it --mount type=tmpfs,target=/data1 centos:7 bash
$ docker ps | awk 'NR==2 {print $1}' | xargs -i docker inspect -f '{{.State.Pid}}' {} | xargs -i cat /proc/{}/mountinfo | grep data
1029 1011 0:160 / /data1 rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw,seclabel
在Docker中使用塊裝置的相關測試
- 在容器內通過繫結掛載使用宿主機的塊裝置,只能使用已經在宿主機格式化和掛載好的目錄:
$ docker run --rm -it -v /data1 -v /opt:/data2 centos:7 bash
[root@4282b3df2417 /]# mount | grep data
/dev/sdb1 on /data2 type xfs (rw,relatime,attr2,inode64,noquota)
/dev/sda1 on /data1 type xfs (rw,relatime,attr2,inode64,noquota)
$ docker inspect 4282b3df2417 | grep -i pid
"Pid": 12797,
"PidMode": "",
"PidsLimit": 0,
$ cat /proc/12797/mounts | grep data
/dev/sdb1 /data2 xfs rw,relatime,attr2,inode64,noquota 0 0
/dev/sda1 /data1 xfs rw,relatime,attr2,inode64,noquota 0 0
- 在容器內通過共享裝置使用塊裝置,可以讀寫,但是不能掛載:
$ docker run --rm -it --device /dev/sdc:/dev/sdc centos:7 bash
[root@55423f5eaeea /]# mkfs -t minix /dev/sdc
21856 inodes
65535 blocks
Firstdatazone=696 (696)
Zonesize=1024
Maxsize=268966912
[root@55423f5eaeea /]# mknod /dev/sdd b 8 48
[root@55423f5eaeea /]# mkfs -t minix /dev/sdd
mkfs.minix: cannot open /dev/sdd: Operation not permitted
[root@55423f5eaeea /]# rm /dev/sdc
rm: remove block special file '/dev/sdc'? y
[root@55423f5eaeea /]# mknod /dev/sdc b 8 32
[root@55423f5eaeea /]# mkfs -t minix /dev/sdc
21856 inodes
65535 blocks
Firstdatazone=696 (696)
Zonesize=1024
Maxsize=268966912
[root@55423f5eaeea /]# mount /dev/sdc mnt/
[root@55423f5eaeea /]# mount: permission denied
[root@55423f5eaeea /]# dd if=/dev/sdc of=/dev/null bs=512 count=10
10+0 records in
10+0 records out
5120 bytes (5.1 kB) copied, 0.000664491 s, 7.7 MB/s
[root@55423f5eaeea /]# dd if=/dev/zero of=/dev/sdc bs=512 count=10
10+0 records in
10+0 records out
5120 bytes (5.1 kB) copied, 0.00124138 s, 4.1 MB/s
- 在容器內通過特權模式使用塊裝置,可以讀寫和掛載:
$ docker run --rm -it --privileged=true centos:7 bash
[root@b5c40e199476 /]# mount /dev/sdc mnt
[root@b5c40e199476 /]# mkfs -t minix /dev/sdc
mount: unknown filesystem type 'minix'
[root@b5c40e199476 /]# yum install -y xfsprogs
[root@b5c40e199476 /]# mkfs.xfs /dev/sdc -f
meta-data=/dev/sdc isize=512 agcount=4, agsize=6553600 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0, sparse=0
data = bsize=4096 blocks=26214400, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal log bsize=4096 blocks=12800, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
[root@b5c40e199476 /]# mount /dev/sdc mnt
[root@b5c40e199476 /]# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 30G 19G 12G 62% /
tmpfs 910M 0 910M 0% /dev
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/sda1 30G 19G 12G 62% /etc/hosts
shm 64M 0 64M 0% /dev/shm
/dev/sdc 100G 33M 100G 1% /mnt
[root@b5c40e199476 /]# echo `date` > /mnt/time.txt
[root@b5c40e199476 /]# cat /mnt/time.txt
Wed Mar 6 12:23:05 UTC 2019
Kubernetes中的塊裝置使用和實現
- 檢視
kublet
初始化根目錄/var/lib/kubelet
時的原始碼,可以看到kubelet
使用syscall.MS_SHARED|syscall.MS_REC
標誌,該目錄下下所有的Mount
都預設共享(相當於執行mount --make-rshared /var/lib/kubelet
):
// pkg/kubelet/kubelet.go
// setupDataDirs creates:
// 1. the root directory
// 2. the pods directory
// 3. the plugins directory
// 4. the pod-resources directory
func (kl *Kubelet) setupDataDirs() error {
...
if err := kl.mounter.MakeRShared(kl.getRootDir()); err != nil {
return fmt.Errorf("error configuring root directory: %v", err)
}
...
}
// pkg/util/mount/nsenter_mount.go
func (n *NsenterMounter) MakeRShared(path string) error {
return doMakeRShared(path, hostProcMountinfoPath)
}
// pkg/util/mount/mount_linux.go
// doMakeRShared is common implementation of MakeRShared on Linux. It checks if
// path is shared and bind-mounts it as rshared if needed. mountCmd and
// mountArgs are expected to contain mount-like command, doMakeRShared will add
// '--bind <path> <path>' and '--make-rshared <path>' to mountArgs.
func doMakeRShared(path string, mountInfoFilename string) error {
shared, err := isShared(path, mountInfoFilename)
if err != nil {
return err
}
if shared {
klog.V(4).Infof("Directory %s is already on a shared mount", path)
return nil
}
klog.V(2).Infof("Bind-mounting %q with shared mount propagation", path)
// mount --bind /var/lib/kubelet /var/lib/kubelet
if err := syscall.Mount(path, path, "" /*fstype*/, syscall.MS_BIND, "" /*data*/); err != nil {
return fmt.Errorf("failed to bind-mount %s: %v", path, err)
}
// mount --make-rshared /var/lib/kubelet
if err := syscall.Mount(path, path, "" /*fstype*/, syscall.MS_SHARED|syscall.MS_REC, "" /*data*/); err != nil {
return fmt.Errorf("failed to make %s rshared: %v", path, err)
}
return nil
}
- 建立一個使用
PVC
建立RBD
的Pod
:
$ echo 'apiVersion: v1
kind: Pod
metadata:
name: nginx-test
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: nginx-test-vol1
mountPath: /data/
readOnly: false
volumes:
- name: nginx-test-vol1
persistentVolumeClaim:
claimName: nginx-test-vol1-claim' | kubectl create -f -
pod/nginx-test created
- 檢視
PVC
的狀態:
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nginx-test-vol1-claim Bound pvc-d6f6b6f8-446c-11e9-bbd8-6c92bf74be54 10Gi RWO ceph-rbd 114s
$ kubectl describe pvc nginx-test-vol1-claim
Name: nginx-test-vol1-claim
Namespace: default
StorageClass: ceph-rbd
Status: Bound
Volume: pvc-d6f6b6f8-446c-11e9-bbd8-6c92bf74be54
Labels: <none>
Annotations: pv.kubernetes.io/bind-completed: yes
pv.kubernetes.io/bound-by-controller: yes
volume.beta.kubernetes.io/storage-provisioner: kubernetes.io/rbd
Finalizers: [kubernetes.io/pvc-protection]
Capacity: 10Gi
Access Modes: RWO
VolumeMode: Filesystem
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ProvisioningSucceeded 6m36s persistentvolume-controller Successfully provisioned volume pvc-d6f6b6f8-446c-11e9-bbd8-6c92bf74be54 using kubernetes.io/rbd
Mounted By: nginx-test
- 檢視
PV
的狀態:
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-d6f6b6f8-446c-11e9-bbd8-6c92bf74be54 10Gi RWO Delete Bound default/nginx-test-vol1-claim ceph-rbd 105s
$ kubectl describe pv pvc-d6f6b6f8-446c-11e9-bbd8-6c92bf74be54
Name: pvc-d6f6b6f8-446c-11e9-bbd8-6c92bf74be54
Labels: <none>
Annotations: kubernetes.io/createdby: rbd-dynamic-provisioner
pv.kubernetes.io/bound-by-controller: yes
pv.kubernetes.io/provisioned-by: kubernetes.io/rbd
Finalizers: [kubernetes.io/pv-protection]
StorageClass: ceph-rbd
Status: Bound
Claim: default/nginx-test-vol1-claim
Reclaim Policy: Delete
Access Modes: RWO
VolumeMode: Filesystem
Capacity: 10Gi
Node Affinity: <none>
Message:
Source:
Type: RBD (a Rados Block Device mount on the host that shares a pod's lifetime)
CephMonitors: [172.29.201.125:6789 172.29.201.126:6789 172.29.201.201:6789]
RBDImage: kubernetes-dynamic-pvc-db7fcd29-446c-11e9-af81-6c92bf74be54
FSType:
RBDPool: k8s
RadosUser: k8s
Keyring: /etc/ceph/keyring
SecretRef: &SecretReference{Name:ceph-k8s-secret,Namespace:,}
ReadOnly: false
Events: <none>
- 檢視建立和對映的
RBD
:
$ rbd ls -p k8s
kubernetes-dynamic-pvc-db7fcd29-446c-11e9-af81-6c92bf74be54
$ lsblk | grep rbd0
rbd0 252:0 0 10G 0 disk /var/lib/kubelet/pods/18a8fb7b-446d-11e9-bbd8-6c92bf74be54/volumes/kubernetes.io~rbd/pvc-d6f6b6f8-446c-11e9-bbd8-6c92bf74be54
- 檢視
RBD
的掛載資訊:
$ cat /proc/self/mountinfo | grep rbd0
313 40 252:0 / /var/lib/kubelet/plugins/kubernetes.io/rbd/mounts/k8s-image-kubernetes-dynamic-pvc-db7fcd29-446c-11e9-af81-6c92bf74be54 rw,relatime shared:262 - ext4 /dev/rbd0 rw,seclabel,stripe=1024,data=ordered
318 40 252:0 / /var/lib/kubelet/pods/18a8fb7b-446d-11e9-bbd8-6c92bf74be54/volumes/kubernetes.io~rbd/pvc-d6f6b6f8-446c-11e9-bbd8-6c92bf74be54 rw,relatime shared:262 - ext4 /dev/rbd0 rw,seclabel,stripe=1024,data=ordered
可以看到RBD
被掛載在兩個位置,一個是Pod
的Volume
目錄,還有一個是RBD
外掛目錄,而且這兩個目錄都是shared:262
,說明這兩個目錄是被繫結的。
- 檢視
RBD
掛載目錄的位置:
$ cat /proc/self/mountinfo | grep "^40 "
40 0 253:0 / / rw,relatime shared:1 - xfs /dev/mapper/centos-root rw,seclabel,attr2,inode64,noquota
可以看到RBD
掛載在253:0
裝置上,這是宿主機的根目錄所掛載的位置。
- 檢視
Pod
掛載的卷目錄:
$ cat /proc/self/mountinfo | grep 18a8fb7b-446d-11e9-bbd8-6c92bf74be54
303 40 0:56 / /var/lib/kubelet/pods/18a8fb7b-446d-11e9-bbd8-6c92bf74be54/volumes/kubernetes.io~secret/default-token-zn95h rw,relatime shared:233 - tmpfs tmpfs rw,seclabel
318 40 252:0 / /var/lib/kubelet/pods/18a8fb7b-446d-11e9-bbd8-6c92bf74be54/volumes/kubernetes.io~rbd/pvc-d6f6b6f8-446c-11e9-bbd8-6c92bf74be54 rw,relatime shared:262 - ext4 /dev/rbd0 rw,seclabel,stripe=1024,data=ordered
$ cat /proc/self/mountinfo | grep shared:233
303 40 0:56 / /var/lib/kubelet/pods/18a8fb7b-446d-11e9-bbd8-6c92bf74be54/volumes/kubernetes.io~secret/default-token-zn95h rw,relatime shared:233 - tmpfs tmpfs rw,seclabel
可以看到Pod
掛載了兩個卷,除了之前的RBD
,還有就是一個存放Secret
的卷。
- 檢視
Pod
的Docker
容器中掛載目錄:
$ docker inspect $(docker ps | grep nginx_nginx-test | awk '{print $1}') | grep Mounts -A33
"Mounts": [
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/18a8fb7b-446d-11e9-bbd8-6c92bf74be54/volumes/kubernetes.io~rbd/pvc-d6f6b6f8-446c-11e9-bbd8-6c92bf74be54",
"Destination": "/data",
"Mode": "Z",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/18a8fb7b-446d-11e9-bbd8-6c92bf74be54/volumes/kubernetes.io~secret/default-token-zn95h",
"Destination": "/var/run/secrets/kubernetes.io/serviceaccount",
"Mode": "ro,Z",
"RW": false,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/18a8fb7b-446d-11e9-bbd8-6c92bf74be54/etc-hosts",
"Destination": "/etc/hosts",
"Mode": "Z",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/var/lib/kubelet/pods/18a8fb7b-446d-11e9-bbd8-6c92bf74be54/containers/nginx/190cc168",
"Destination": "/dev/termination-log",
"Mode": "Z",
"RW": true,
"Propagation": "rprivate"
}
],
可以看到Docker
的這些卷最後都是通過Bind
掛載的,而且Mount
廣播使用的是rprivate
屬性。
- 看看
Pod
的容器內Mount
情況:
$ docker exec -it $(docker ps | grep nginx_nginx-test | awk '{print $1}') df -h
Filesystem Size Used Avail Use% Mounted on
overlay 123G 4.7G 118G 4% /
tmpfs 64M 0 64M 0% /dev
tmpfs 189G 0 189G 0% /sys/fs/cgroup
/dev/rbd0 9.8G 37M 9.7G 1% /data
/dev/mapper/centos-root 123G 4.7G 118G 4% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 189G 12K 189G 1% /run/secrets/kubernetes.io/serviceaccount
tmpfs 189G 0 189G 0% /proc/acpi
tmpfs 189G 0 189G 0% /proc/scsi
tmpfs 189G 0 189G 0% /sys/firmware
$ docker exec -it $(docker ps | grep nginx_nginx-test | awk '{print $1}') cat /proc/self/mountinfo | grep -e rbd -e serviceaccount
617 599 252:0 / /data rw,relatime - ext4 /dev/rbd0 rw,seclabel,stripe=1024,data=ordered
623 599 0:56 / /run/secrets/kubernetes.io/serviceaccount ro,relatime - tmpfs tmpfs rw,seclabel
可以看到Pod
的容器內的確主要掛載了RBD
和Secret
兩個目錄。
分析總結
- 在
Docker
中,無論使用哪種方式使用資料卷,實際上都是利用的Linux
的的mount --bind
繫結掛載功能實現。 - 在
Kubernetes
中使用RBD
卷時,首先通過rbd map
到宿主機並進行格式化,然後mount
到宿主機目錄,最後把這個宿主機目錄mount --bind
到容器的指定目錄中使用。
根據原理分析可以初步推斷:在宿主機中測試RBD
讀寫效能和在Docker
和Kubernetes
中分別測試的效能沒有本質區別,Docker
和Kubernetes
本身不會對RBD
效能造成影響(之後我又使用Fio對其進行完整的效能測試,和這個結論也是一