Chapter 4 存储管理

4.1 存储设备

硬盘设备命名:

  • 物理硬盘: /dev/sd[a-z] /dev/nvme[0,1..]

  • KVM虚拟化:

    半虚拟化驱动:/dev/vd[a-z],可以热添加(online)

    全虚拟化驱动:/dev/sd[a-z],(offline)


按工作原理分类:

  • 机械硬盘 HDD 价格低,寿命长,容量大
  • 固态硬盘 SSD 速度快,防震抗摔(相对),低噪音,低功耗,体积小

机械硬盘的尺寸:

3.5 2.5 1.8 (英寸),常见的是3.5和2.5


插拔方式:

  • 热插拔

  • 非热插拔


硬盘接口:

  • IDE –> SATA 高容量,家用居多

  • SCSI –> SAS 高转速,服务器用居多

PCIE , FC (Fibre Channel)光纤通道


连接方式:

  • 本地存储 计算机的本地磁盘

  • 外部存储 scsi线 sata线 sas线 FC线

  • 网络存储 以太网络(iscsi, glusterFS, ceph) FC网络

4.2 基本分区

ls -l /dev/[vs]d* 查看硬盘

lsblk 列出块设备

fdisk -l /dev/sda 查看硬盘信息,sectors - 扇区


  • MBR 支持最大卷为2 TB, 每个磁盘最多有4个主分区(或3个主分区,1个扩展分区和无限制的逻辑驱动器)
  • GPT 支持最大为128个分区,一个分区最大18 EB

4.2.0.1 MBR

  • fdisk d delete a partition l list known partition types m print this menu n add a new partition p print the partition table q quit without saving changes w write table to disk and exit

  • 创建分区

[root@Cent-KVM ~]# fdisk /dev/vdb

Building a new DOS disklabel with disk identifier 0xef1c2b78.
# -- 自动创建了MBR分区表

# -- 目前还没有分区,按 n 创建
Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p):

# -- +100M ,创建一个100M主分区
Last sector, +sectors or +size{K,M,G} (2048-10485759, default 10485759): +100M

# -- 创建扩展分区
Command (m for help): n
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p): e
Using default value

# -- 在扩展分区上创建逻辑分区
Command (m for help): n
Partition type:
   p   primary (1 primary, 1 extended, 2 free)
   l   logical (numbered from 5)
Select (default p): l
Last sector, +sectors or +size{K,M,G} (208896-10485759, default 10485759): +2G

# -- 查看
Command (m for help): p

   Device Boot      Start         End      Blocks   Id  System
/dev/vdb1            2048      206847      102400   83  Linux
/dev/vdb2          206848    10485759     5139456    5  Extended
/dev/vdb5          208896     4403199     2097152   83  Linux

# -- 一定要输入 w 将改动写入磁盘
Command (m for help): w
The partition table has been altered!

4.2.0.2 GPT

yum -y install gdisk

[root@Cent-KVM ~]# gdisk /dev/sda 

Partition table scan:
Creating new GPT entries.
# -- 自动创建了GPT分区表
Command (? for help): n
Last sector (2048-10485726, default = 10485726) or {+-}size{KMGTP}: +100M

Command (? for help): n
Last sector (206848-10485726, default = 10485726) or {+-}size{KMGTP}: +2G

Command (? for help): p

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048          206847   100.0 MiB   8300  Linux filesystem
   2          206848         4401151   2.0 GiB     8300  Linux filesystem

# -- 写入
Command (? for help): w

Do you want to proceed? (Y/N): Y
The operation has completed successfully.
[root@Cent-KVM ~]# partprobe /dev/sda
[root@Cent-KVM ~]# lsblk
NAME                      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                         8:0    0    5G  0 disk 
├─sda1                      8:1    0  100M  0 part 
└─sda2                      8:2    0    2G  0 part 
vdb                       252:16   0    5G  0 disk 
├─vdb1                    252:17   0  100M  0 part 
├─vdb2                    252:18   0    1K  0 part 
└─vdb5                    252:21   0    2G  0 part 

4.2.1 partprobe

  • Inform the operating system about partition table changes

有时修改了分区表之后,系统不能及时更新硬件信息,比如gdisk的警告:

Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot.

没必要重启,只需执行partprobe命令,系统就会更新分区信息

[root@Cent-KVM ~]# partprobe /dev/vdb
[root@Cent-KVM ~]# lsblk

4.2.2 建立文件系统

  • 创建文件系统(格式化) mkfs

    mkfs.ext4 /dev/sda1
    mkfs -t ext4 /dev/sda2
    mkfs -t xfs /dev/vdb1
    mkfs.xfs /dev/vdb5

  • 手动挂载 mount

    mkdir /data{1..4}
    mount /dev/sda1 /data1
    mount UUID="xxxx" /data2
    mount -t xfs -o ro /dev/vdb1 /data3  # 只读
    mount /dev/vdb5 /data4
    
    umount /data1

    df -h 可以看到空间信息和挂载点

    df -Th可以看到已挂载分区的文件系统类型

    blkid可查看UUID

    注意卸载是umount不是unmount

  • 自动挂载fstab

    vim /etc/fstab

    分别是设备(建议用UUID)(file system)、挂载点(dir)、文件系统(可以auto)(type)、挂载选项(options)、备份(dump)、检测(pass)

    blkid /dev/vdb5 |awk '{print $2}' >> /etc/fstab UUID写入fstab

    修改完之后mount -a或重启(其实开机后就是自动执行的mount -a)即可生效

    mount命令可以看到挂载选项(rw,ro…)等

挂载选项 含义
async/sync I/O异步,I/O同步
auto/noauto 使用mount -a后是否挂载
ro/rw 只读/读写
exec/noexec 是否能执行其中的文件
user/users/nouser/owner 允许任意用户/users组中用户/仅root/所有者挂载,指定为user时默认启用noexec, nosuid, nodev
dev/nodev 是否解析文件系统上的块设备
suid/nosuid 是否允许 suid 操作和设定 sgid 位,这一参数通常用于一些特殊任务,使一般用户运行程序时临时提升权限
noatime/nodiratime/relatime atime更新策略
defaults 使用文件系统默认的挂载参数,例如ext4为rw, suid, dev, exec, auto, nouser, async

备份(dump)

0 – 不备份,一般用户不会用到dump,选0即可

1 – 备份

检查(pass)

fsck读取pass值决定检查顺序

0 – 不检查

1 – 根目录应当设为1,有最高优先权

2 – 其他要检查的设备


4.2.3 实例

移动家目录到新分区

  • 新分区创建好文件系统并临时挂载

  • 复制文件到新设备

    cp -a /home/* 临时挂载点 (注意*不会匹配隐藏文件)

  • 新分区写入fstab,挂载点设置为/home

  • /home目录改名做备份

  • 卸载临时挂载的分区,然后mount -a

4.3 逻辑分区

4.3.1 逻辑分区的创建

逻辑分区的优势:可在线扩容,在线迁移

几个名词:

PV  Physical Volume
LV  Logical Volume
VG  Volume Group
PE  Physical Extent,有 4M(default) 8M 16M 32M 64M等 可在创建VG时指定
LE  Logical Extent

  • pvcreate /dev/vdb

    pv可以使用整个磁盘,也可以使用分区,在fdiskgdisk中使用t命令将分区转换为Linux LVM

  • vgcreate datavg /dev/vdb

    创建卷组

  • lvcreate -L 40M -n lv1 datavg

    lvcreate -l 100%FREE -n lv2 datavg

    创建逻辑卷

  • mkfs.ext4 /dev/datavg/lv1

    mkfs.xfs /dev/datavg/lv2

    创建文件系统

查看状态:

pvs, pvscan, pvdispaly (pv换成vg , lv 都可以)


4.3.2 逻辑分区的大小调整

开始时给/home/data都分了80G,一些大文件都放到了/data分区,后来发现/data分区已经快满了,而/home分区用了1G不到,打算重新调整一下两个分区的容量。

4.3.2.1 分区缩减

  • umount /home

    先卸载分区,ext4不能在线缩减

  • e2fsck -f /dev/vg1/home

    强制文件系统检查( resize2fs 执行的前提)

  • resize2fs /dev/vg1/home 60G

    重设文件系统的大小为60G

  • lvreduce -L 60G /dev/vg1/home

    缩减逻辑卷

然后即可挂载使用

4.3.2.2 分区扩容

  • lvextend -l +100%free /dev/vg1/data

    扩容逻辑卷

  • e2fsck -f /dev/vg1/data

    文件系统检查

  • resize2fs /dev/vg1/data -p

    扩展文件系统到物理边界

注:xfs文件系统不能缩减,可使用xfs_growfs扩容

4.3.2.3 pv移除

/home/data的大小调整在前两步已经完成了,这里另外介绍在不影响数据的情况下,移除pv来缩小卷组的一种方法

  • pvmove /dev/vdb

    数据迁移

  • vgreduce datavg /dev/vdb

4.3.3 snapshot

作用:实现copy-on-write,保证数据一致性

[root@Cent-KVM ~]# vgextend datavg /dev/vdd
[root@Cent-KVM ~]# lvcreate -l 50%FREE -s -n lv1-snap /dev/datavg/lv1
[root@Cent-KVM ~]# lvs    
[root@Cent-KVM mnt]# mkdir /mnt/lv1-snap
# 对于xfs文件系统,挂载时要加 nouuid 否则挂载不上
[root@Cent-KVM mnt]# mount -o ro,nouuid /dev/datavg/lv1-snap /mnt/lv1-snap
  • 加全局锁,禁止写操作
  • lvm snapshot 拍摄快照
  • 释放锁
  • mount -o snapshot
  • 从snapshot卷中复制数据
  • 卸载snapshot
  • lvremove -f snapshot

4.4 swap

作用:防止OOM (Out Of Memory)(内核在内存不足时主动杀死一些进程)

查看:free -hswapon -s

关闭一个交换分区swapoff /dev/vdd1

Swap可以是基本分区、LVM或文件

分区:

  • 新建分区,可以使用t命令转换类型为

  • 创建文件系统

    mkswap /dev/vdd1

  • 写入fstab

    UUID=xxxx swap swap defaults 0 0

  • swapon -a 激活fstab里的所有交换分区

LVM:

  • 创建一个逻辑分区lvcreate -L 200M -n lv-swap datavg

  • mkswap /dev/datavg/lv-swap 创建文件系统

  • 写入fstab,逻辑卷没必要使用UUID

    /dev/datavg/lv-swap swap swap defaults 0 0

  • swapon -a

FILE:

  • dd if=/dev/zero of=/swapfile bs=1M count=512 创建文件

  • mkswap /swapfile

  • 写入fstab

    /swapfile swap swap defaults 0 0

  • chmod 0600 /swapfile 修改权限

  • swapon -a


swapon -s查看交换分区信息,最后一列数字是优先级

优先级可以在fstab的挂载选项设定,例如defaults,pri=-2,不同swap优先级可相同

4.5 parted

parted有两种模式:交互模式和非交互模式

parted /dev/设备名 进入交互模式

非交互模式无非就是parted /dev/设备名后直接跟命令,适合在脚本中使用

命令:

  • print

    列出分区表信息

  • mklable label_type

    创建分区表,可以是msdos, gpt等

  • mkpart part-type [fs-type] start end

    part_type可以是primary, extended, 还有logical

    fs_type可以是btrfs, ext2, ext3, ext4, fat32, linux-swap, ntfs, xfs等

4.6 磁盘阵列 RAID

4.6.1 RAID级别

(下面假设用的都是相同型号的磁盘)

  • RAID 0

    数据等量切割,并行地写入n个磁盘,读写速度是单个磁盘的n倍。任何一块磁盘损坏,则数据丢失。

  • RAID 1

    磁盘互为镜像,存储相同的内容。只要一块可用,数据就不会丢失。

  • RAID 10

    即RAID 1+0,磁盘两两镜像,然后组RAID 0提升速度。

  • RAID 5

    数据分散地写入n-1块磁盘中,还有一块存奇偶校验数据。当一块磁盘损坏时,可以凭借其他n-1块计算出其上的数据

  • RAID 6

    RAID 6有两个独立的奇偶校验系统,最多允许两块磁盘损坏

RAID 0 RAID 1 RAID 10 RAID 5 RAID 6
最大容错磁盘数 0 n-1 1~n/2 1 2
理论写入速度 n 1 n/2 <n-1 <n-2
理论读取速度 n n n n-1 n-2
可用容量 n 1 n/2 n-1 n-2

由此可见,数据安全与容量和写入性能不可兼得,服务器、云系统常用的是RAID 10

4.6.2 软件磁盘阵列

我们可以用软件模拟磁盘阵列卡(硬件磁盘阵列)的功能,只是这种方法比较消耗CPU和I/O资源,在生产环境下并不适用

首先创建一些分区,分区类型可以设置为Linux raid (fd00)

yum -y install mdadm


mdadm –create

-C /dev/md[0,1..]   --create,要创建的设备
-c (size)           --chunk,数据块大小,默认516K
-a [yes|no]         --auto,自动创建设备文件
-l [0|1|4|5|6|10]   --level,RAID级别
-n number           --raid-devices,设备数
-x number           --spare-devices,热备磁盘数,有设备故障时,可自动替补上去
-D /dev/md?         --detail,查看RAID设备的详情

举例:

  • mdadm -C /dev/md0 -a yes -l 5 -n 4 -x 1 /dev/vdb{1..5}

    使用4块磁盘创建RAID 5,另有一块热备盘

  • mdadm -D /dev/md0

    查看这个RAID设备的详情


mdadm 管理模式

有 –add 添加,–remove 移除,–fail 设置为出错 等命令

举例:

  • mdadm /dev/md0 -f /dev/vdb2

    认为该设备出错,将自动在热备盘重建其上的数据

  • mdadm /dev/md0 -r /dev/vdb2

    将这块磁盘移除

  • mdadm /dev/md0 -a /dev/vdb2

    添加一块磁盘,将自动成为热备盘

4.6.3 开机自动挂载

  • 创建配置文件

mdadm --detail /dev/md0 | grep -i uuid >> /etc/mdadm.conf

然后去修改/etc/mdadm.conf,改成如下形式:

ARRAY /dev/md0 UUID=xxxxxx

  • 修改fstab

blkid /dev/md0 >> /etc/fstab

然后去fstab里面添加必要的信息

  • 测试

mount -a

df -Th

这时能看到挂载成功就可以了

4.6.4 关闭软件RAID

  • 卸载并注释掉fstab以及删除/etc/mdadm.conf里的相关配置

  • 关闭RAID

    mdadm -S /dev/md0

  • 清理磁盘超级块信息

    mdadm --misc --zero-superblock /dev/vdb{1..5}

    --misc可不写

有时候,我们不正确地删除了软RAID。后来建立分区时,发现无法建立文件系统,用cat /proc/mdstat一看,之前的软RAID又出现了。这应当是超级块信息未清理所致,应当重新执行上述命令。

[root@localhost ~]# cat /proc/mdstat 
Personalities : 
md0 : inactive vdb3[6](S)
      3142656 blocks super 1.2
       
unused devices: <none>
[root@localhost ~]# mdadm -S /dev/md0 
mdadm: stopped /dev/md0
[root@localhost ~]# mdadm --zero-superblock /dev/vdb3

4.7 练习:安装 Arch Linux

虚拟机上利用LVM安装 Arch Linux

首先下载iso镜像,开机

网络应该会自动配置,ping一下baidu,通

  • [零] 验证引导模式

    ls /sys/firmware/efi/efivars,我这里没有该目录

    因为这次使用的虚拟机是以BIOS模式引导的

  • [一] 磁盘分区

    • lsblk

    • fdisk /dev/sda

      首先按g生成GPT分区表(fdisk也是支持gpt的)

      创建1M的BIOS boot分区安装grub

      依次输入n, +1M, t, 4

      剩下的创建LVM分区,n, t, 30

      记得保存 w

    • 创建逻辑卷

      pvcreate /dev/sda2
      vgcreate vg1 /dev/sda2
      
      lvcreate -L 2G -n swap vg1
      lvcreate -l 50%free -n root vg1
      lvcreate -l 100%free -n home vg1
    • 创建文件系统

      mkfs.ext4 /dev/vg1/root
      mkfs.ext4 /dev/vg1/home
      mkswap /dev/vg1/swap
    • 挂载

      swapon /dev/vg1/swap
      mount /dev/vg1/root /mnt
      mkdir /mnt/home
      mount /dev/vg1/home !$
  • [二] 安装系统

    • pacstrap /mnt base linux linux-firmware vim

    • 生成fstab

      genfstab -U /mnt >> /mnt/etc/fstab
      cat !$
  • [三] chroot进行配置

    • arch-chroot /mnt

    • 设置时区

      ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
      hwclock --systohc
      date

      此时应该会显示当地时间

    • 网络 (dhcp)

      pacman -S dhcpcd

    • Initramfs

      pacman -S lvm2

      编辑/etc/mkinitcpio.conf

      找到HOOKS,在block后面加上lvm2

      mkinitcpio -P生成支持LVM的initramfs

    • 微码更新

      如果有 Intel 或 AMD 的 CPU,在安装引导程序之前可以先启用微码更新

      amd处理器安装 amd-ucode

      intel处理器安装 intel-ucode

    • grub

      pacman -S os-prober grub

      os-prober用于探测其他系统,只有一个系统也可不装

      grub-install --target=i386-pc /dev/sda
      grub-mkconfig -o /boot/grub/grub.cfg

      grub.cfg的启动项(menuentry)里面应当有arch

    • 记得设置root密码

      passwd

    • exit退出并reboot重启

  • [四] 开始使用新系统

    • 连接网络

      systemctl start dhcpcd
      systemctl enable dhcpcd

      ping一下baidu,通

    • 静态ip

      做远程服务器的话,最好使用静态ip,dhcpcd也有静态ip功能

      vim /etc/dhcpcd.conf

      添加如下配置:

      # 网卡名称, 可以使用ip addr查看
      interface enp1s0
      static ip_address=192.168.0.65/24
      static routers=192.168.0.1
      static domain_name_servers=114.114.114.114

      systemctl restart dhcpcd

    • hostname

      echo arch > /etc/hostname

    • hosts

      cat >> /etc/hosts <<-@@
      > 127.0.0.1    localhost
      > ::1          localhost
      > 127.0.1.1    arch.localdomain  arch
      > @@
    • ssh

      pacman -S openssh

      编辑/etc/ssh/sshd_config 设置PermitRootLogin yes

      systemctl restart sshd
      systemctl enable sshd
    • 本地化

      编辑 /etc/locale.gen,然后去掉 en_US/zh_CN/zh_TW/zh_HK.UTF-8 UTF-8这四项的注释

      接着执行locale-gen

      echo LANG=en_US.UTF-8 > /etc/locale.conf 创建locale.conf

  • [完成]

    arch