Linux——卷
介绍
最近做的项目,涉及到对系统的一些维护,有些盘没有使用,需要创建逻辑盘并挂载到指定目录下。有些软件需要依赖空的逻辑盘(LVM)。
先简单介绍一下卷的一些概念,有分区、物理存储介质、物理卷、卷组、逻辑卷。下面介绍一下概念:
概念介绍参考文章:
- 分区(Partition) :是在物理存储介质上(磁盘)上划分出来的独立存储区域,每个分区可以视为一个独立的磁盘,格式化后可挂载到文件系统目录下使用。
- 物理存储介质(The physical media) :这里指系统的存储设备:硬盘,如:/dev/hda、/dev/sda等等,是存储系统最低层的存储单元。
- 物理卷(physical volume,PV) :物理卷就是指硬盘分区或从逻辑上与磁盘分区具有同样功能的设备(如RAID),是LVM的基本存储逻辑块,但和基本的物理存储介质(如分区、磁盘等)比较,却包含有与LVM相关的管理参数。是用来构建卷组的基本单元,通常不会被直接挂载,而是通过组合成卷组,然后从卷组中创建逻辑卷。
- 卷组(Volume Group,VG) :LVM卷组类似于非LVM系统中的物理硬盘,其由物理卷组成。可以在卷组上创建一个或多个“LVM分区”(逻辑卷),LVM卷组由一个或多个物理卷组成。是逻辑卷的基础。
- 逻辑卷(Logical Volume, LV) :LVM的逻辑卷类似于非LVM系统中的硬盘分区,在逻辑卷之上可以建立文件系统(比如/home或者/usr等)。逻辑卷是卷组中的可分配存储空间,它类似于传统的磁盘分区,提供了更多的灵活性,可以在无需重新分区的情况下,动态调整大小。
- 设备:无论是物理卷还是逻辑卷,都是
/dev
下的块设备,可以通过块设备管理工具来对其直接操作,比如:k8s上的符合OCI标准的块设备Storage Class、PV、PVC
分盘
记录一下分盘实战操作。
第一个场景:VG中分配剩余的磁盘空间创建LVM
场景描述
- OS:ubuntu24.04
- 系统磁盘有500GB,系统默认只给根分区分配了100GB,剩余400GB未分配LVM
- 存在VG:
/dev/mapper/ubuntu--vg
- 存在LVM:
/dev/mapper/ubuntu--vg-ubuntu--lv
,挂载到根分区 - 任务:需要将VG中剩余的空间分配给系统目录使用
操作步骤
查看卷组信息:
vgdisplay
分出可用空间
如果卷组有可用的未分配空间,可以创建新的 LVM 逻辑卷:
sudo lvcreate -L <size>G -n new_lv_name ubuntu--vg
这里
<size>
是要分配的大小(如10
),new_lv_name
是新逻辑卷名字,比如data1
。格式化新的逻辑卷:
sudo mkfs.ext4 /dev/ubuntu--vg/new_lv_name
挂载新逻辑卷到文件系统:
sudo mkdir /mnt/new_lv_name sudo mount /dev/ubuntu--vg/new_lv_name /mnt/new_lv_name
更新
/etc/fstab
如果想要系统启动时自动挂载,请编辑
/etc/fstab
echo '/dev/ubuntu--vg/new_lv_name /mnt/new_lv_name ext4 defaults 0 2' | sudo tee -a /etc/fstab
<文件系统> <挂载点> <类型> <选项> <转储> <检查>
经过上面步骤的操作,顺利的将剩余磁盘分配出来,创建了新的LVM并挂载到文件系统使用,同时支持开机自动挂载。
可以使用如下命令查看相关信息:
LVM信息:
lvdisplay
卷的信息:
lsblk
第二个场景:从已存在的LVM中分配出空间,分配给新的LVM
场景描述
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 50G 0 loop
sda 8:0 0 447.1G 0 disk
sda1 8:1 0 1G 0 part /boot/efi
sda2 8:2 0 2G 0 part /boot
sda3 8:3 0 444.1G 0 part
ubuntu--vg-ubuntu--lv 252:0 0 100G 0 lvm /
ubuntu--vg-new--lv 252:1 0 344G 0 lvm /data
项目需要安装阿里巴巴开源的软件open-local,它需要一块空的逻辑卷,也就是空闲块设备,可以作为存储底座
并且对设备的类型有要求,逻辑卷具有更多的功能
不同类型 PV 所支持的存储能力也不同。
类型 动态分配 PV扩容 PV快照 原生块设备 IO限流 临时卷 监控数据 LVM(共享盘类型) 支持 支持 支持 支持 支持 支持 支持 Device(独占盘类型) 支持 不支持 不支持 支持 不支持 不支持 支持 同时,机器的VG中没有空闲的空间了,只能从现有的LVM中分离出部分空间
同时,保证现有的LVM空间中的数据不丢失
操作步骤
建议提前备份数据,再尝试以下操作
查看当前系统卷信息
lsblk
umount当前LVM
umount /data
杀死占用mount目录的进程
sudo lsof +D /data kill -9 xxx
对文件系统检查
sudo e2fsck -f /dev/ubuntu-vg/new-lv
如果有提示被占用,建议重启操作系统,注意把
/etc/fstab
中开机自动挂载的配置注释掉缩小文件系统,确保缩小后的空间还能容纳之前的数据
此操作将文件系统调整为 144GB(344GB - 200GB),确保在缩小逻辑卷时不会丢失数据。现在就有200GB的可用空间。
sudo resize2fs /dev/ubuntu-vg/new-lv 144G
缩小逻辑卷
这将把逻辑卷的大小调整为 144GB,释放出 200GB 的空间
sudo lvreduce -L 144G /dev/ubuntu-vg/new-lv
创建新的逻辑卷
sudo lvcreate -L 200G -n open-local-lv ubuntu-vg
格式化新的逻辑卷
sudo mkfs.ext4 /dev/ubuntu-vg/open-local-lv
恢复旧逻辑卷挂载点
mount /dev/ubuntu-vg/new-lv /data lsblk lvdisplay
注:记得把
/etc/fstab
文件中的注释去掉
这样就完成了需求,分离出了200GB的LVM供open-local
使用,且恢复了原来的文件系统和文件。
第三个场景:使用本地持久卷作为k8s集群的块存储
https://kubernetes.io/blog/2019/01/15/container-storage-interface-ga/
场景描述
为k8s集群创建本地的块存储设备
操作步骤
创建虚拟磁盘文件,将其绑定到循环设备(循环设备不建议在生产环境中使用,这里只是本地测试使用)
$ loop_file="/tmp/test-image-storage.img" $ sudo dd if=/dev/zero of=$loop_file bs=1M count=2500 $ sudo losetup /dev/loop0 $loop_file
创建存储类
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer
创建持久卷
apiVersion: v1 kind: PersistentVolume metadata: name: test-block-pv spec: capacity: storage: 10Gi volumeMode: Block accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: local-storage local: path: /dev/loop0 nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - NODE_NAME
创建持久卷claim
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: test-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi volumeMode: Block storageClassName: local-storage
测试pod示例
apiVersion: v1 kind: Pod metadata: name: large-image-pod spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - NODE_NAME volumes: - name: test-image-storage persistentVolumeClaim: claimName: test-pvc containers: - name: app-container image: xxx command: ["/bin/sh", "-c"] args: - sleep 6000 volumeDevices: - devicePath: /dev/xxx name: test-image-storage