[步骤] KVM 虚拟机模板的创建 (Rocky Linux 8 版)

注意:

在创建 KVM 虚拟机之前要先安装 KVM 并创建 KVM 虚拟网络

软件准备:

在 Rocky Linux 官网上下载安装系统所需要的镜像:

https://rockylinux.org/download

正文:

步骤目录:

步骤一:理解创建 KVM 虚拟机模板的目的

步骤二:为这个虚拟机创建硬盘文件
2.1 创建硬盘文件
2.2 确认硬盘文件已创建

步骤三:使用 KVM 和刚刚创建的硬盘文件新安装一台虚拟机
3.1 启动 KVM 的 virt-manager
3.2 在 virt-manager 上的左上角点击文件之后点击 “新建虚拟机”
3.2.1 选择以本地安装介质的方式安装系统
3.2.2 选择安装系统的系统镜像
3.2.3 设置内存大小和 CPU 核心数
3.2.4 选择用刚刚创建的硬盘文件来安装系统
3.2.5 给虚拟机命名并选择虚拟网络
3.2.6 开始安装系统
3.2.7 选择系统语言
3.2.8 之后进行系统配置界面
3.2.8.1 通过 “INSTALLATION DESTINATION” 对硬盘进行分区
3.2.8.2 取消 “KDUMP”
3.2.8.3 选择最小化安装系统
3.2.8.4 设置 root 密码
3.2.9 之后点击右下角的 “Begin installation”
3.2.10 安装完成后重启
3.2.11 在安装系统的过程中需要注意的内容总结

步骤四:进入新创建虚拟机修改配置
4.1 修改网卡个性化设置
4.1.1 修改网卡配置文件
4.1.2 使修改的网卡配置生效
4.2 禁用 SELinux
4.3 禁用空路由
4.4 添加 Console 配置
4.4.1 修改 grub 内核配置文件
4.4.2 使修改的 grub 内核配置生效
4.5 将系统自动挂载的硬盘从使用 UUID 换成硬件路径
4.5.1 显示根分区的 UUID
4.5.2 在自动挂载文件里将根分区的 UUID 换成硬件路径
4.6 删除不用的程序
4.7 对虚拟系统进行升级
4.8 进行分区扩展
4.8.1 安装分区扩展软件
4.8.2 给开机自启配置文件相应的权限
4.8.3 设置开机自动扩容根目录
4.9 修改虚拟机系统的名称
4.10 启用 serial 服务实现通过 virsh console 命令控制虚拟机
4.11 清除虚拟系统的历史命令
4.12 关闭虚拟机

步骤五:在真机上对虚拟机进行清理优化

步骤六:此时就可以将此虚拟机的硬件文件作为模板进行批量克隆虚拟机了

具体的操作步骤:

步骤一:理解创建 KVM 虚拟机模板的目的

主要用于批量克隆出新的 KVM 机器,节约创建新虚拟机的时间

步骤二:为这个虚拟机创建硬盘文件
2.1 创建硬盘文件

(只在真机上执行以下步骤)

# qemu-img create -f qcow2 /var/lib/libvirt/images/rockylinux8.qcow2 10G

(补充:这里以创建 10G 大小的 rockylinux8.qcow2 硬盘文件为例)

2.2 确认硬盘文件已创建

(只在真机上执行以下步骤)

# ls /var/lib/libvirt/images/ | grep rockylinux8.qcow2

(补充:这里以显示 rockylinux8.qcow2 硬盘文件为例)

步骤三:使用 KVM 和刚刚创建的硬盘文件新安装一台虚拟机
3.1 启动 KVM 的 virt-manager

(只在真机上执行以下步骤)

# virt-manager

3.2 在 virt-manager 上的左上角点击文件之后点击 “新建虚拟机”

(只在真机上执行以下步骤)

(步骤略)

3.2.1 选择以本地安装介质的方式安装系统

(只在真机上执行以下步骤)

(图:1)

3.2.2 选择安装系统的系统镜像

(只在真机上执行以下步骤)

(图:2)

(补充:这里以使用 Rocky-8.5-x86_6-dvd1.iso 系统镜像为例)

3.2.3 设置内存大小和 CPU 核心数

(只在真机上执行以下步骤)

(图:3)

(补充:这里以设置 2048 MiB 内容和 2 核 CPU 为例)

3.2.4 选择用刚刚创建的硬盘文件来安装系统

(只在真机上执行以下步骤)

(图:4)

(补充:这里以使用 rockylinux8.qcow2 硬盘文件为例)

3.2.5 给虚拟机命名并选择虚拟网络

(只在真机上执行以下步骤)

(注意:虚拟网络必须提前创建好)

(图:5)

(补充:这里以将虚拟机命名为 rockylinux8 并使用 0 网络为例)

3.2.6 开始安装系统

(只在真机上执行以下步骤)

(图:6)

3.2.7 选择系统语言

(只在真机上执行以下步骤)

(图:7)

3.2.8 之后进行系统配置界面

(只在真机上执行以下步骤)

需要手动配置的地方有四个:
1) “INSTALLATION DESTINATION”
2) “KDUMP”
3) “SOFTWARE SELECTION”
4) “Root Password”
分别点击以后就可以配置了

3.2.8.1 通过 “INSTALLATION DESTINATION” 对硬盘进行分区

(只在真机上执行以下步骤)

(补充:完成后点击左上角的 “DONE”)

(注意:只分一个分区,只设置一个挂载点挂载到根,使用标准硬盘类型,硬盘格式设置为 XFS)

(图:8)
(图:9)

3.2.8.2 取消 “KDUMP”

(只在真机上执行以下步骤)

(补充:完成后点击左上角的 “DONE”)

(图:10)

3.2.8.3 选择最小化安装系统

(只在真机上执行以下步骤)

(补充:完成后点击左上角的 “DONE”)

(图:11)

3.2.8.4 设置 root 密码

(只在真机上执行以下步骤)

(图:12)

3.2.9 之后点击右下角的 “Begin installation”

(只在真机上执行以下步骤)

(图:13)

3.2.10 安装完成后重启

(只在真机上执行以下步骤)

(图:14)

3.2.11 在安装系统的过程中需要注意的内容总结

(只在真机上执行以下步骤)

1) 一定要使用刚刚创建的 /var/lib/libvirt/images/rockylinux8.qcow2 作为安装虚拟机的硬件文件
2) 虚拟机网络 “0” 要提前创建好
3) 只分一个分区,只设置一个挂载点挂载到根,使用标准硬盘,硬盘格式是 XFS
4) 取消 “KDUMP”
5) 选择最小化安装系统
6) 设置 root 密码

步骤四:进入新创建虚拟机修改配置
4.1 修改网卡个性化设置
4.1.1 修改网卡配置文件

(只在虚拟机上执行以下步骤)

# vi /etc/sysconfig/network-scripts/ifcfg-enp1s0

将全部内容修改如下:

TYPE=Ethernet
BOOTPROTO=dhcp
NAME=enp1s0
DEVICE=enp1s0
ONBOOT=yes

4.1.2 使修改的网卡配置生效

(只在虚拟机上执行以下步骤)

# reboot

4.2 禁用 SELinux

(只在虚拟机上执行以下步骤)

# vi /etc/selinux/config

将全部内容修改如下:

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

4.3 禁用空路由

(只在虚拟机上执行以下步骤)

# vi /etc/sysconfig/network

将全部内容修改如下:

# Created by anaconda
NOZEROCONF="yes"

4.4 添加 Console 配置
4.4.1 修改 grub 内核配置文件

(只在虚拟机上执行以下步骤)

# vi /etc/default/grub

将全部内容修改如下:

GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL="serial console"
GRUB_SERIAL_COMMAND="serial --unit=1 --speed=115200"
GRUB_CMDLINE_LINUX="biosdevname=0 net.ifnames=0 console=tty0 console=ttyS0,115200n8"
GRUB_DISABLE_LINUX_UUID="true"
GRUB_ENABLE_LINUX_LABEL="true"
GRUB_DISABLE_RECOVERY="true"

4.4.2 使修改的 grub 内核配置生效

(只在虚拟机上执行以下步骤)

# grub2-mkconfig -o grub

4.5 将系统自动挂载的硬盘从使用 UUID 换成硬件路径
4.5.1 显示根分区的 UUID

(只在虚拟机上执行以下步骤)

# blkid
/dev/sda1: UUID="e76ed189-6d0f-49d5-8586-c5aae4bdc9b5" TYPE="xfs" PARTUUID="3d8377ef-01"

(补充:这里的 UUID 是: e76ed189-6d0f-49d5-8586-c5aae4bdc9b5)

4.5.2 在自动挂载文件里将根分区的 UUID 换成硬件路径

(只在虚拟机上执行以下步骤)

# vi /etc/fstab

将以下内容:

......
UUID=e76ed189-6d0f-49d5-8586-c5aae4bdc9b5 /                   xfs     defaults        0 0

(补充:这里的 UUID 是: e76ed189-6d0f-49d5-8586-c5aae4bdc9b5)

修改为:

/dev/sda1 /                   xfs     defaults        0 0

4.6 删除不用的程序

(只在虚拟机上执行以下步骤)

# yum -y remove firewalld-* python-firewall

4.7 对虚拟系统进行升级

(只在虚拟机上执行以下步骤)

# yum -y update

4.8 进行分区扩展
4.8.1 安装分区扩展软件

(只在虚拟机上执行以下步骤)

# yum install -y cloud-utils-growpart

4.8.2 给开机自启配置文件相应的权限

# chmod 755 /etc/rc.local

4.8.3 设置开机自动扩容根目录

(只在虚拟机上执行以下步骤)

# vi /etc/rc.local

添加以下内容:

......
/usr/bin/growpart /dev/sda1
/usr/sbin/xfs_growfs /

4.9 修改虚拟机系统的名称

(只在虚拟机上执行以下步骤)

# vi /etc/hostname

将全部内容修改如下:

rockylinux8

4.10 启用 serial 服务实现通过 virsh console 命令控制虚拟机

(只在虚拟机上执行以下步骤)

# systemctl start serial-getty@ttyS0
# systemctl enable serial-getty@ttyS0

4.11 清除虚拟系统的历史命令

(只在虚拟机上执行以下步骤)

# history -c

4.12 关闭虚拟机

(只在虚拟机上执行以下步骤)

# poweroff

步骤五:在真机上对虚拟机进行清理优化

(只在真机上执行以下步骤)

# sudo virt-sysprep -d rockylinux8

(补充:这里以清理 rockylinux8 虚拟机为例)


注意:如果此命令不存在
1) Rocky Linux 系统的话需要安装 libguestfs-tools
2) openSUSE 系统的话需要安装 guestfs-tools

步骤六:此时就可以将此虚拟机的硬件文件作为模板进行批量克隆虚拟机了

(只在真机上执行以下步骤)

分布式存储算法介绍

章节一:传统的 Hash 存储算法
1.1 传统的 Hash 存储算法简介

  将数据进行切片,对每份切片进行 Hash 取值,并对获取的 Hash 值除以存储节点的数量以取余,余数是多少就将此切片存在第几个 OSD 节点里,主要是 Swift 在使用。

1.2 传统的 Hash 存储算法的缺点

  如果要增加存或减少存储节点,需要对所有已存储数据切片的 Hash 值重新取余,大概 90% 的数据需要重新均衡数据(rebalance)。

章节二:一致性 Hash 算法
2.1 一致性 Hash 算法简介

  1) 给电脑也计算 Hash 值(可以是给电脑名计算 Hash 值,也可以给 IP 地址计算 Hash 值)
  2) 再给数据也计算 Hash 值,将数据存到比它的 Hash 值大,且与它的差值最小的一台电脑上,如果没有 Hash 值比它大的电脑就直接将数据存在 Hash 值最小的电脑上
  3) 整个架构类似一个环

2.2 一致性 Hash 算法的缺点

  1) 电脑太少时切换数据也会有较大的数据量,但是可以多设置几个虚拟节点,给以后新增加的节点使用,虚拟节点里的数据会影射到对应的物理节点里面去
  2) 电脑太少时,两台电脑的 Hash 值比较接近导致,数据分配极度不平均

(注意:在开始创建数据架构时,要评估未来数据的规模,如果最后要添加的电脑数量超过了虚拟节点数量,那么这个架构就不能使用了。此时只能备份数据,然后新建一个架构出来)

章节三:CRUSH
3.1 CRUSH 简介

  CRUSH(Controlled Replication Under Scalable Hashing)算法,在可扩展 Hash 算法下的可控制复制,主要是 Ceph 在使用。

3.2 CRUSH 算法
3.2.1 CRUSH 算法的第一层

  由 Ceph 的 OSD(Object Storage Deivces)组成。

3.2.2 CRUSH 算法的第二层
3.2.3 CRUSH 算法的第二层的组成

  由 Ceph 的 PG(Placement Group)归置组组成。

3.2.4 CRUSH 算法的第二层的由来

  在 OSD 节点上虚拟出多个 PG,每个 PG 默认会被指定对应 3 个 OSD 节点(每个 OSD 节点同时可以属于多个 PG),其中第一个 OSD 节点为主要(primary)的硬盘,其他两 OSD 节点为从(second)硬盘,PG 会对应几个 OSD 节点取决于 Ceph 的存储副本被设置了几份。

3.2.5 CRUSH 算法的第二层的算法

  1) 给每个 OSD 节点设置一个权重值,OSD 节点的容量越大则其权重值越大
  2) 主要(primary)硬盘的 OSD 节点:将 PG 的 ID 值和 OSD 的 ID 值组合在一起并计算 Hash 值,将得到的 Hash 值乘以此 OSD 节点的权重,当最终获得的值最大时,此 PG 就和此 OSD 绑定在一起
  3) 第一个从(second)硬盘的 OSD 节点:将 PG 的 ID 值逐一和 OSD 的 ID 值和一个随机的常数组合在一起并计算 Hash 值(这个值在 Ceph 的代码里被叫做 draw),将得到的 Hash 值乘以此 OSD 节点的权重,当最终获得的值最大时(这个值在 Ceph 的源代码里叫做 straw)则此 PG 就和此 OSD 绑定在一起
  4) 第二个从(second)硬盘的 OSD 节点:将 PG 的 ID 值逐一和 OSD 的 ID 值和上一个随机常数加 1 的和组合在一起并计算 Hash 值(这个值在 Ceph 的代码里被叫做 draw),将得到的 Hash 值乘以此 OSD 节点的权重,当最终获得的值最大时(这个值在 Ceph 的源代码里叫做 straw),则此 PG 就和此 OSD 绑定在一起(如果找到的 OSD 节点和前面的 OSD 节点重复,则将这个随机常数再加 1 并进行重复操作,最终获得和前面不通的 OSD 节点为止)
……

3.3 CRUSH 算法的第三层
3.3.1 CRUSH 算法的第三层的组成

  由池组成。

3.3.2 CRUSH 算法的第三层的由来

  1) 在 PG 上虚拟出多个池,每个池对应多个 PG,数据可以存储到指定的池里
  2) 总硬盘容量有多大,每个池最大可以使用的容量就有多大,但是如果如果一个池使用了一部分容量,其他的池就要少使用一部分容量

3.4 CRUSH 算法的第四层
3.4.1 CRUSH 算法的第四层的组成

  由数据组成。

3.4.2 CRUSH 算法的第四层的算法

  1) 对要放入某个池里的数据进行切片,默认每片 4M
  2) 对每份切片进行 Hash 取值,并对获取的 Hash 值除以这个池里 PG 节点的数量以取余,余数是多少就存在第几个 OSD 节点里

[内容] Ceph 介绍

内容一:Ceph 简介

Ceph 是一种分布式存储架构和技术。此项目是 2004 年由 Sage Weil 在加州大学 Santa Cruz 分校攻读博士期间的创建和研究的课题,并于 2006 年将其开源,同时成立 Inktank 公司专注 Ceph 的研发。2014 年 5 月 Inktank 公司被 Red Hat 收购。

内容二:Ceph 的特点

1) 高性能(硬盘越多性能越高,所有硬盘可以同时读写)
2) 高可用(硬盘越多高可用越高)

内容三:Ceph 使用的方式

1) 自己写程序:通过 C C++ Java Python Ruby PHP 等语言写程序调用 Ceph 底层存储 LIBRADOS,此方法性能最高
2) 自己写脚本:写对象脚本,通过 RGW(RADOSGW)对象存储网关的 Rest API 接口去访问 Ceph 的底层存储 LIBRADOS,此方法性能第二高
3) 挂载块存储:通过 Linux 内核或者 KVM 等虚拟机存储驱动访问 Ceph 的块存储,此方法性能第三高
4) 挂载文件系统:通过 Linux 内核(POSIX 命令)挂载 Ceph 的文件系统存储,此方法性能最弱

内容四:Ceph 的组成

1) OSD(Object Storage Deivces):负责存储、复制、恢复数据等,默认要有 3 台以上才能实现高可用,因为 Ceph 默认有三副本
2) MON(Monitor):负责监控集群状态制作和更新存储地图(map),供客户端从下载,在生产环境里必须要有 3 台以上,且最好是奇数台,因为必须遵循过半原则
3) MDS(Metadata Servers):实现文件系统存储,允许客户端通过 Linux 内核(POSIX 命令)挂载 Ceph 的文件系统存储
4) RGW(RADOSGW):实现对象存储网关,允许客户端通过 RGW(RADOSGW)对象存储网关的 Rest API 接口去访问 Ceph 的底层存储 LIBRADOS
5) 客户端:使用从 MON 下载和更新的存储地图,通过算法,直接从 OSD 访问数据

内容五:Ceph 架构
5.1 Ceph 使用架构
5.1.1 Ceph 的上层

自己写程序、自己写脚本、挂载块存储、挂载文件系统 4 种使用方式。

5.1.2 Ceph 的下层

RADOS,基于对象的存储(比我们平时所说的对象存储更原始,更底层),通过软件实现自我检查、自我备份和自我修复的功能。

5.2 Ceph 组成架构

                                  File

                  Cut1(Objects1) Cut2(Objects2) Cut3(Objects3)......

                              choice Pool

              Pool1                                   Pool2
     PG1                PG2                  PG2               PG3
OSD1 OSD2 OSD3    OSD2 OSD5 OSD3        OSD1 OSD4 OSD3    OSD4 OSD5 OSD3
Disk Disk Disk    Disk Disk Disk        Disk Disk Disk    Disk Disk Disk

内容六:Ceph 的算法:CRUSH
6.1 CRUSH 简介

CRUSH(Controlled Replication Under Scalable Hashing)算法,在可扩展 Hash 算法下的可控制复制

6.2 CRUSH 算法的第一层

由 OSD(Object Storage Deivces)组成。

6.3 CRUSH 算法的第二层
6.3.1 CRUSH 算法的第二层的组成

由 PG(Placement Group)归置组组成。

6.3.2 CRUSH 算法的第二层的由来

在 OSD 节点上虚拟出多个 PG,每个 PG 默认会被指定对应 3 个 OSD 节点(每个 OSD 节点同时可以属于多个 PG),其中第一个 OSD 节点为主要(primary)的硬盘,其他两 OSD 节点为从(second)硬盘,PG 会对应几个 OSD 节点取决于 Ceph 的存储副本被设置了几份。

6.3.3 CRUSH 算法的第二层的算法

1) 给每个 OSD 节点设置一个权重值,OSD 节点的容量越大则其权重值越大
2) 主要(primary)硬盘的 OSD 节点:将 PG 的 ID 值和 OSD 的 ID 值组合在一起并计算 Hash 值,将得到的 Hash 值乘以此 OSD 节点的权重,当最终获得的值最大时,此 PG 就和此 OSD 绑定在一起
3) 第一个从(second)硬盘的 OSD 节点:将 PG 的 ID 值逐一和 OSD 的 ID 值和一个随机的常数组合在一起并计算 Hash 值(这个值在 Ceph 的代码里被叫做 draw),将得到的 Hash 值乘以此 OSD 节点的权重,当最终获得的值最大时(这个值在 Ceph 的源代码里叫做 straw)则此 PG 就和此 OSD 绑定在一起
4) 第二个从(second)硬盘的 OSD 节点:将 PG 的 ID 值逐一和 OSD 的 ID 值和上一个随机常数加 1 的和组合在一起并计算 Hash 值(这个值在 Ceph 的代码里被叫做 draw),将得到的 Hash 值乘以此 OSD 节点的权重,当最终获得的值最大时(这个值在 Ceph 的源代码里叫做 straw),则此 PG 就和此 OSD 绑定在一起(如果找到的 OSD 节点和前面的 OSD 节点重复,则将这个随机常数再加 1 并进行重复操作,最终获得和前面不通的 OSD 节点为止)
5) 第三个从(second)硬盘的 OSD 节点:仿照第二个从(second)硬盘的 OSD 节点方式以此类推

6.4 CRUSH 算法的第三层
6.4.1 CRUSH 算法的第三层的组成

由池组成。

6.4.2 CRUSH 算法的第三层的由来

1) 在 PG 上虚拟出多个池,每个池对应多个 PG,数据可以存储到指定的池里
2) 总硬盘容量有多大,每个池最大可以使用的容量就有多大,但是如果如果一个池使用了一部分容量,其他的池就要少使用一部分容量

6.5 CRUSH 算法的第四层
6.5.1 CRUSH 算法的第四层的组成

由数据组成。

6.5.2 CRUSH 算法的第四层的算法

1) 对要放入某个池里的数据进行切片,默认每片 4M
2) 对每份切片进行 Hash 取值,并对获取的 Hash 值除以这个池里 PG 节点的数量以取余,余数是多少就存在第几个 OSD 节点里

内容七:Ceph 的工作流程

1) 客户端从 MON 上下载最新的存储地图(map)
2) 存储地图(map)把集群里所有 MON、OSD 和 MDS 的信息告诉客户端,但是客户端依然不知道想要找的数据存放在哪
3) 客户端通过 CRUSH 计算出所需要读写的数据存放的 OSD 节点位置
4) 客户端直接在 OSD 节点位置上读写数据
5) 用户只需要把数据数据写入主要 OSD 节点硬盘上,然后 Ceph 自动同步给其他的从 OSD 节点硬盘上

内容八:Ceph 的维护

1) PG 的个数肯定要大于 OSD 节点的数量,在生产的环境中 PG 设计的数量往往会远远大于 OSD 节点的数量,以满足未来可能几年的需求,可能会在 3 个硬盘上添加上百个 PG
2) 当增加存或减少存储节点时,PG 的数量不会发生变化,只有 PG 对应 OSD 节点有变化的数据才会需要重新均衡数据(rebalance)的数据
3) 当增加存或减少 PG 数量时,就需要像传统的 Hash 存储算法那样,对所有已存储数据切片的 Hash 值重新取余,大概 90 % 的数据需要重新均衡数据(rebalance)