You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

269 lines
20 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 05 | 云硬盘云上IO到底给不给力
你好,我是何恺铎。
通过前几讲的学习,我想你对云虚拟机应该有了不少的了解,也对如何根据实际情况来选择和运用虚拟机,有了一定的认识。在前面的学习过程中,我也留下了许多伏笔。其中之一,就是云虚拟机的重要组件:**云硬盘**。
那么今天这一讲,我们就来深入讨论一下这个话题,来帮助你了解不同云硬盘的差别,以及如何在实际场景中挑选最合适你的硬盘型号。
## 云硬盘是什么?
云硬盘,又叫做“云盘”或者“云磁盘”,就是云虚拟机上可以挂载和使用的硬盘。这里,它既包含了用于承载操作系统的系统盘,也包括了承载数据的数据盘。
在云计算的领域有时我们还会把云端磁盘服务叫做块存储Block Storage因为它们与Linux操作系统中的块设备相对应是云上提供的“裸盘”可以格式化并且施加文件系统。
既然是硬盘,那么它就与我们通常的认知相一致,当然是带有数据持久化功能的。这在专业上被称为“**非易失性存储**”Non-ephemeral Storage也就是说**写入的数据不会丢失**。即便所在虚拟机重启、关机甚至下线删除,这块云硬盘只要还存在,其中的数据也并不会被擦除。
事实上,云厂商对于云盘,不仅仅会保障数据的顺利写入,一般还会帮你在存储端同步和保留至少三份副本的数据。所以说,云硬盘的冗余度和可用性是非常之高的,一般极少发生云硬盘数据丢失的情况,你大可放心地使用。
重要提示尽管云硬盘有良好的存储冗余但你不能仅仅依赖它的可靠性。从数据的层面来看你必须进行额外的备份。2018年7月曾有创业公司因为云厂商故障丢失了在云硬盘上的所有重要数据一时成为业界的热点新闻这个教训是非常深刻的。所以你应当通过定期为云磁盘创建快照、异地备份数据文件等方式来保护你的关键数据。
云硬盘与传统磁盘的真正差异在于,绝大多数的云硬盘都是**远程**的。我们都知道在经典计算机的体系结构中硬盘是通过本地机器内部主板的高速总线与CPU、内存等部件相连接而在云端你的硬盘则很可能并不在宿主机上而是在专用的磁盘服务器阵列中**两者是通过数据中心内部的特有IO线路进行连接**。没错,这也正是**计算存储分离架构**的一种体现。
理解了这样的一个结构你就能明白有些云上的“IO优化实例”AWS上称为EBS-Optimized是指什么了。它就是指云虚拟机与云硬盘之间的网络传输进行了软硬件层面的优化这样可以充分地发挥所挂载磁盘的性能。现在较新型号、较强性能的云虚拟机一般都自动启用了这个优化。
## 云硬盘的性能等级
你可能听说过一些,网上对于云硬盘性能方面的质疑。这在云计算发展的早期尤其多见,甚至成为了很多人反对上云的主要原因之一。
不错,云硬盘的确有多副本写入的开销,同时也比较依赖于远程传输。所以,早期云硬盘的确存在一些性能上的短板。不过,那都是老黄历了。
当下的云硬盘经过了多次的软硬件迭代尤其是SSD的迅速发展吞吐量和随机读写能力等各项性能指标都已经不再是问题了。在现代云计算中已经发展出了基于不同存储介质的、丰富的性能等级选择你已经能够找到单盘IOPS在数十万量级甚至达到百万的云硬盘产品了。
所以,现在的云硬盘,性能上已经非常“给力”了。**你更多的是要考虑如何根据应用场景,选择合适介质的硬盘等级,同时权衡好相应的成本。**
那么下面,我们就分别来看一看主流云硬盘的不同性能等级,以及它们对应的磁盘类型和存储介质。
**第一个等级的云硬盘是基于传统HDD硬盘构建而成的**。这类云盘的性能一般最高IOPS大概在**数百**左右。在很多的云上,已经不把它作为推荐的选择了。但它并非一无是处,**成本低**就是它的最大优势,在不注重性能的测试环境,或者是个人自用的服务器,它就是一个很好的选择。
**第二个等级往往是基于混合硬盘也就是结合HDD和SSD硬盘构建的云硬盘**。它会综合发挥SSD的性能优势和HDD的容量优势。比如它可以用SSD部分来承载热点区域数据或是作为缓存来提高响应性能。在这个等级下典型的IOPS为**数千**左右,是很多云上创建硬盘的**默认选项**,比较适合像是操作系统启动盘这样的常规负载。
**第三个等级的云硬盘它的存储介质就是纯SSD硬盘了**。虽然贵一些但一分价钱一分货这个等级下的云硬盘能够提供非常稳定的IO能力IOPS通常能够**上万**也有相当不俗的吞吐量和较低的访问延时。你可以用它来承载生产环境中重要的关键业务应用或是各类数据库等IO密集型应用。
**第四个等级也是当下业界的最高等级就是进一步优化增强的最新SSD云盘**。它一般会采用更新一代的企业级闪存硬件配合自研或改进后的底层传输协议和虚拟化技术栈的优化来提供服务。因此它能够达到惊人的性能水平满足我们最为苛刻的性能场景需求比如承载SAP HANASAP的高性能计算平台、高并发OLTP数据库等等。这类SSD云盘的IOPS通常能够**突破十万以上**。
各个云对于不同等级云硬盘的命名方法各有不同,我把相应的产品类型和名称整理成了一个表格,方便你去了解和查询:
![](https://static001.geekbang.org/resource/image/97/13/97150c100ba7b7d25dd5750e1c01ad13.jpg)
当然这个表格只是一个大致的划分仅供你作为参考。在具体的情况中云和云必然存在一些差异也会有一些各自的产品特点建议你在使用时针对性地确认。比如说AWS的gp2通用型SSD类型它具有比较宽广的性能指标范围还具备I/O积分和性能突增机制与性能突增VM实例的CPU类似可以提供比较高的峰值性能应用场景是相当广泛的。
除了云盘性能等级之外,**还有一个影响云盘性能的重要因素,就是这块云硬盘的容量**。不论是哪种磁盘类型,它的容量大小几乎都与性能正向相关。同等的性能等级下,云硬盘的容量越大,一般来说它的性能就越高,直到达到这个等级的上限。这是由云上磁盘能力共享的底层设计所决定的。
**所以在某些时候,你可能需要刻意地增大所申请的云硬盘的容量,以获取更高的性能,即便这些额外的空间不一定能被用上。**
好了,对于云盘性能的讨论就先到这里。在上面的性能讨论当中,我们主要通过**IOPS**来进行衡量。事实上衡量IO性能还有吞吐量、访问延时等其他的重要指标。这些指标同样会由磁盘的类型和大小所决定你可以查询云厂商文档来确认。这里限于篇幅我就不详细展开了。
## 云硬盘实战
接下来,让我们进入实战环节,一起学习一下云硬盘的使用。在这个过程中,你也能真实地感受一下不同性能等级的区别。
这里,可以继续沿用我们在[第2讲](https://time.geekbang.org/column/article/206296)中创建的阿里云虚拟机,目前它是默认挂载了一个**40G的高效云盘**作为系统盘。
**我们可以先用lsblk和df命令查看一下磁盘的情况**
```
[root@my-ecs-vm1 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 40G 0 disk
└─vda1 253:1 0 40G 0 part /
[root@my-ecs-vm1 ~]# df -hT -x tmpfs -x devtmpfs
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda1 ext4 40G 1.6G 36G 5% /
```
通过命令的输出可以清晰地看到这台机器有一块40G的系统盘挂载在根目录下。
**然后我们可以使用fio工具来测试一下这块系统盘的性能表现。**我们通过fio在系统盘上创建一个1GB的文件接着进行4K大小的随机读取实验。
```
[root@my-ecs-vm1 ~]# fio --name=mytest1 --filename=~/testfile1 --rw=randread --refill_buffers --bs=4k --size=1G -runtime=10 -direct=1 -iodepth=128 -ioengine=libaio
mytest1: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=l
ibaio, iodepth=128
fio-3.7
Starting 1 process
mytest1: Laying out IO file (1 file / 1024MiB)
Jobs: 1 (f=1): [r(1)][100.0%][r=8560KiB/s,w=0KiB/s][r=2140,w=0 IOPS][eta 00m:00s]
mytest1: (groupid=0, jobs=1): err= 0: pid=1324: Sat Jan 25 17:03:53 2020
read: IOPS=2154, BW=8619KiB/s (8826kB/s)(84.9MiB/10090msec)
slat (nsec): min=2529, max=38138, avg=3080.22, stdev=575.39
clat (usec): min=444, max=102701, avg=59394.84, stdev=46276.36
lat (usec): min=448, max=102705, avg=59398.39, stdev=46276.34
clat percentiles (msec):
| 1.00th=[ 3], 5.00th=[ 3], 10.00th=[ 4], 20.00th=[ 4],
| 30.00th=[ 4], 40.00th=[ 5], 50.00th=[ 96], 60.00th=[ 97],
| 70.00th=[ 99], 80.00th=[ 99], 90.00th=[ 100], 95.00th=[ 100],
| 99.00th=[ 101], 99.50th=[ 102], 99.90th=[ 102], 99.95th=[ 102],
| 99.99th=[ 103]
bw ( KiB/s): min= 8552, max=10280, per=100.00%, avg=8645.20, stdev=384.80, samples=20
iops : min= 2138, max= 2570, avg=2161.30, stdev=96.20, samples=20
lat (usec) : 500=0.01%, 1000=0.03%
lat (msec) : 2=0.50%, 4=36.26%, 10=3.74%, 100=57.13%, 250=2.34%
cpu : usr=0.50%, sys=1.19%, ctx=20986, majf=0, minf=161
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.7%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1%
issued rwts: total=21741,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=128
Run status group 0 (all jobs):
READ: bw=8619KiB/s (8826kB/s), 8619KiB/s-8619KiB/s (8826kB/s-8826kB/s), io=84.9MiB (89.1MB
), run=10090-10090msec
Disk stats (read/write):
vda: ios=21399/2, merge=0/1, ticks=1266052/242, in_queue=1039418, util=81.1
```
实际命令输出的结果比较长这里我们主要关注下IOPS的部分。你可以看到平均IOPS的数值都在2100左右这个跑分的成绩和我们当初建立这块高效云盘时提示的性能目标值“2120”相当一致。
![](https://static001.geekbang.org/resource/image/83/ec/8396f50d9acd70d7e4186dbeee124fec.jpg)
如果高效云盘还不够满足你的业务要求,你可以随时为机器添加更高规格的硬盘,这也是云硬盘的灵活性所在。
**接下来,我们就来试一下动态挂载新硬盘的过程。**
首先来到这个虚拟机的“本实例磁盘”管理界面选择“创建云盘”这里我们选择一块300G的SSD云盘按照提示这样我们就能够拥有1万的IOPS。
![](https://static001.geekbang.org/resource/image/3f/6c/3fb419666c386c7582b17821bd3efc6c.jpg)
之后按照提示确认创建即可。OK阿里云很快地为我们创建好了磁盘但此时这块SSD磁盘的状态为“未挂载”我们可以通过界面操作把它挂载到正在运行中的目标虚拟机里。
挂载完成后磁盘的状态开始变为“使用中”说明磁盘已经“上线”。这时我们再在Linux操作系统中用lsblk命令查看
```
[root@my-ecs-vm1 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
vda 253:0 0 40G 0 disk
└─vda1 253:1 0 40G 0 part /
vdb 253:16 0 300G 0 disk
```
你可以看到磁盘中已经出现了一个新的块设备vdb。
这时我们需要将这块磁盘进行格式化并创建ext4文件系统
```
[root@my-ecs-vm1 ~]# mkfs.ext4 /dev/vdb
mke2fs 1.42.9 (28-Dec-2013)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
19660800 inodes, 78643200 blocks
3932160 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=2227175424
2400 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done
```
好,还差最后一步,我们要在/mnt下创建一个data目录并将这个新的块设备挂载到该目录。
```
[root@my-ecs-vm1 ~]# mkdir /mnt/data
[root@my-ecs-vm1 ~]# mount /dev/vdb /mnt/data/
```
终于大功告成。我们再次使用fio工具来测试下这块SSD盘4K随机读方面的能力。**和前面不同的是**,这回我们要把测试文件路径定位到“/mnt/data”目录因为这个目录指向的是刚刚创建的新硬盘
```
[root@my-ecs-vm1 ~]# fio --name=mytest2 --filename=/mnt/data/testfile2 --rw=randread --refill_buffers --bs=4k --size=1G -runtime=10 -direct=1 -iodepth=128 -ioengine=libaio
mytest2: (g=0): rw=randread, bs=(R) 4096B-4096B, (W) 4096B-4096B, (T) 4096B-4096B, ioengine=l
ibaio, iodepth=128
fio-3.7
Starting 1 process
Jobs: 1 (f=1): [r(1)][100.0%][r=41.1MiB/s,w=0KiB/s][r=10.5k,w=0 IOPS][eta 00m:00s]
mytest2: (groupid=0, jobs=1): err= 0: pid=1302: Sat Jan 25 16:59:30 2020
read: IOPS=10.6k, BW=41.2MiB/s (43.2MB/s)(415MiB/10067msec)
slat (usec): min=2, max=445, avg= 3.10, stdev= 1.49
clat (usec): min=828, max=77219, avg=12115.14, stdev=20941.23
lat (usec): min=841, max=77222, avg=12118.74, stdev=20941.22
clat percentiles (usec):
| 1.00th=[ 2737], 5.00th=[ 3326], 10.00th=[ 3523], 20.00th=[ 3687],
| 30.00th=[ 3785], 40.00th=[ 3884], 50.00th=[ 3949], 60.00th=[ 4047],
| 70.00th=[ 4146], 80.00th=[ 4359], 90.00th=[56361], 95.00th=[71828],
| 99.00th=[73925], 99.50th=[73925], 99.90th=[74974], 99.95th=[76022],
| 99.99th=[76022]
bw ( KiB/s): min=41916, max=43600, per=100.00%, avg=42464.60, stdev=724.17, samples=20
iops : min=10479, max=10900, avg=10616.15, stdev=181.04, samples=20
lat (usec) : 1000=0.02%
lat (msec) : 2=0.17%, 4=55.50%, 10=29.30%, 20=0.83%, 50=3.47%
lat (msec) : 100=10.71%
cpu : usr=3.24%, sys=5.58%, ctx=96090, majf=0, minf=163
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.9%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1%
issued rwts: total=106300,0,0,0 short=0,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=128
Run status group 0 (all jobs):
READ: bw=41.2MiB/s (43.2MB/s), 41.2MiB/s-41.2MiB/s (43.2MB/s-43.2MB/s), io=415MiB (435MB),
run=10067-10067msec
Disk stats (read/write):
vdb: ios=105123/3, merge=0/1, ticks=1265938/41, in_queue=1266532, util
```
上面的测试结果表明这块SSD盘对/mnt/data目录中文件的4K随机读成功地达到了1万IOPS的标称水准。也就是说新创建的SSD磁盘性能还是相当给力的。
在实际的使用场景中你就可以把一些读写较为密集的负载比如数据库的数据目录配置到这个SSD盘对应的目录下。
好了,通过上面的实验,相信你对云盘的挂载和使用有了比较直观的认识。**云盘的热挂载特性让它使用起来特别灵活方便,而且大小性能任你调度。挂载后的云硬盘真正使用起来,和你熟悉的硬盘操作也并没有什么两样。**
## 认识和使用本地磁盘
前面我们对于云虚拟机的硬盘作了许多讨论,都是围绕着“远程硬盘”这个产品形态来展开的。的确,远程云硬盘的好处很多,是计算存储分离架构的体现,也是云虚拟机硬盘的主流方式。
不过,有时我们还是会有点怀念“本地磁盘”,也就是直接位于宿主机上的硬盘。因为看似传统的本地硬盘,与远程硬盘相比起来,还是会有它自己的优点。毕竟它和计算单元离得近,而且没有三副本的负担,所以往往性能不俗,价格又相对便宜。
**那么,云上能否使用本地磁盘呢?**
**答案是肯定的。**而且本地磁盘一般不需要自行创建,只要你选择了带有本地磁盘的机型,启动后,该型号对应大小和规格的本地磁盘就会自动被挂载。
你应该还记得,我在介绍虚拟机型号的[第3讲](https://time.geekbang.org/column/article/208288)中提到了“本地存储”系列的虚拟机吧那些正是自带有大容量、高性能本地磁盘的虚拟机型号。它们或是配备了高性能的本地NVMe SSD磁盘或是装备有高吞吐的先进HDD数量可能还不止一块。妥善使用这些本地磁盘在合适的场景下能够帮你发挥很大的作用。
比如你要在云上用虚拟机自己搭建一个经典的Hadoop集群要用虚拟机的磁盘组合成HDFSHadoop的分布式文件系统并希望使用MapReduce或Spark等支持数据本地性Data Locality的计算框架。这时你就应该考虑使用带有本地磁盘的机型了。
所以,当一些应用软件系统本身考虑到了硬件的不可靠性,设计了上层的存储冗余机制时,你就可以考虑采用本地磁盘。因为这种情况下,本地磁盘的可靠性缺陷得到了弥补,**它的相对高性能和低成本就成为了优势**。这时如果选用三副本的远程云硬盘,反倒显得有些笨重了。
还有一类,对数据丢失不敏感的**临时性存储**的场景也是本地磁盘可以发挥的舞台。这些场景包括操作系统的pagefile或swap分区以及数据库的硬盘缓存区如SQL Server的Buffer Pool Extension等等。
不过我还是要提醒你本地磁盘的缺点它在本质上还是易失性Ephemeral的存储**当机器关机或删除,以及出现硬件故障时,本地磁盘上的数据就可能损坏或丢失。**这一点我们必须牢记,不适用的场合必须使用更可靠的远程云硬盘。
## 课堂总结与思考
今天我们围绕云硬盘,进行了一系列的讲解,可以简单总结如下:
* 云硬盘是云虚拟机的主要持久化存储,与宿主机往往是分离的;
* 云硬盘支持动态添加和删除,使用起来灵活方便;
* 云硬盘一般提供多种性能等级,最终性能会受存储介质和容量大小的共同影响;
* 部分虚拟机型号会自带高性能的本地磁盘,在可以容忍数据丢失风险时,是你值得考虑的一个选择。
最后,我还想补充一点,**云硬盘的付费模式,同样有按量付费和包年包月之分。**在很多的云上,你能够为一块云盘启用包年,长期租用的确定性也能够给你带来折扣,这和虚拟机资源的包年包月是一样的。
**今天,我想和你讨论的问题如下:**
* 我们说云硬盘可以动态地挂载和卸载,使用起来十分方便。那么更进一步的问题是,已经挂载的云硬盘能够支持在线扩容吗?
* 还有一种云端常见的存储类产品如阿里云的文件存储NAS、AWS的EFS等也可以挂载到云虚拟机。那么你知道这种产品形态和云硬盘有什么区别主要用于什么场景吗
你可以在留言区和我互动。如果觉得有收获,也欢迎你把这篇文章分享给你的朋友。感谢阅读,我们下期再见。