云原生运维笔记:硬核拆解OpenStack计算与存储——从主机聚合到Cinder挂载全流程

云原生运维笔记:硬核拆解OpenStack计算与存储------从主机聚合到Cinder挂载全流程

前面的时间里,我们把Keystone的认证逻辑、Glance的镜像管理,以及那个神秘的"29步创建虚拟机"的黑盒流程里里外外扒了个遍,算是把OpenStack的"地基"和"仓库"给摸透了。但如果光有镜像和一套认证体系,我们连个毛线都跑不起来。今天算是正式进入了实战的深水区------OpenStack计算管理(Nova)与存储管理(Cinder)。

说实话,这两块的复杂度比前面高了一个量级。计算管理涉及到物理资源的划分、调度算法、实例规格的限制,以及虚拟机极其丰富的生命周期状态流转(暂停、挂起、搁置,傻傻分不清楚对吧?)。而存储管理更是重量级,Cinder的架构、后端LVM的对接、卷的挂载卸载、快照与扩容,每一个概念如果不搞清楚,后面搞生产环境绝对是一踩一个不吱声。

这篇博客当作我今天的实验复盘。我会严格按照实验手册以及补充的管理资料,把Dashboard上的图形化操作,和背后对应的CLI命令完整梳理一遍,并且把今天踩过的坑(比如主机聚合的AZ冲突、规格为什么变不成Public、卷处于in-use状态删不掉)统统记录在案。内容很长,但全都是实打实的干货,建议连同代码块一起直接复制进Typora当字典查。


一、 OpenStack计算管理(Nova)实操复盘

计算管理就是管"算力"。在Nova的世界里,我们要搞清楚谁在提供算力(Hypervisor)、算力怎么分组(主机聚合/可用域)、算力的套餐(实例类型/Flavor),以及虚拟机实例的完整生命周期。

1.1 Hypervisor 与 主机聚合(Host Aggregates)

首先得了解底层的物理资源。登录Dashboard后,进入管理员 -> 计算 -> 虚拟机管理器 。这里能直观看到我们实验环境里的两个计算节点:controller 和 compute。它们的状态都是"激活/启动",后面跟着它们所剩的VCPU和内存。

接下来是重头戏:主机聚合(Host Aggregate)。这个概念在考试和面试里经常和**可用域(Availability Zone, AZ)**放在一起问。简单来说,主机聚合是底层物理机的一个逻辑分组,而AZ是暴露给最终用户的逻辑概念。一个主机聚合通常会对应一个AZ,但一个主机可以加入多个主机聚合。

在界面上创建主机聚合:

  1. 进入 管理员 -> 计算 -> 主机聚合,点击"创建主机聚合"。
  2. 名称填入 HostAggr_web,可用域填入 nova。
  3. 在"管理聚合内的主机"页签,把 controller 移入选中的主机,点击"创建"。

踩坑记录:一个主机能不能加入不同的AZ?

手册里有个验证环节,我照着做了一下。我尝试再创建一个名为 HostAggr_web_test 的聚合,可用域设置为 AZ_web,然后把 controller 加进去。结果直接弹窗报错:"错误:向聚合中添加主机时出错"。这说明同一个物理主机在同一个时间点,只能属于一个AZ 。但是,如果你把 HostAggr_web_test 的AZ改回 nova(和第一个聚合一样),再添加 controller,是可以成功的。也就是说,同一个主机可以加入多个主机聚合,但这些聚合的AZ必须相同。

用命令行验证一下:

bash 复制代码
[root@controller ~]# source keystonerc_admin
[root@controller ~(keystone_admin)]# openstack hypervisor list --long
# 这里会列出 controller 和 compute 的详细资源情况

# 创建主机聚合
[root@controller ~(keystone_admin)]# openstack aggregate create --zone nova HostAggr_cli
+-------------------+---------------------------+
| Field             | Value                     |
+-------------------+---------------------------+
| availability_zone | nova                      |
| created_at        | 2024-08-13T06:30:24.269570|
| id                | 4                         |
| name              | HostAggr_cli              |
| hosts             | None                      |
+-------------------+---------------------------+

# 验证AZ冲突
[root@controller ~(keystone_admin)]# openstack aggregate create --zone AZ_cli HostAggr_cli_test
[root@controller ~(keystone_admin)]# openstack aggregate add host HostAggr_cli_test controller
# 报错:Cannot add host to aggregate 5. Reason: One or more hosts already in availability zone(s) ['nova', 'nova']. (HTTP 409)

这背后的逻辑其实很好理解,AZ往往对应着机架或者数据中心,防止单点故障。如果一台机器同时属于两个不同的AZ,那高可用调度的时候就彻底乱套了。

1.2 实例类型(Flavor)管理与公有/私有之惑

规格(Flavor)就是虚拟机的硬件套餐。创建虚拟机时,你只能选规格,不能自己随便填CPU和内存。

界面操作: 进入 管理员 -> 计算 -> 实例类型 ,点击"创建实例类型"。填入名称 Flavor_web,VCPU给1,RAM给128MB,根磁盘给1GB。在"实例类型使用权"页签,只勾选 Project_web,点击创建。这说明这个规格是私有的,只有Project_web能用。

踩坑记录:移除所有项目,规格会变成公有(Public)吗?

手册里特别提了一个验证题。如果我把刚才选中的 Project_web 移除,是不是等于所有项目都能用了?

答案是否定的。移除所有项目后,该规格不仅不是Public,反而变成了"谁都不能用(不可见)"。如果你想要一个Public的规格,在命令行创建时,直接不指定任何项目就行了。

bash 复制代码
# 创建指定项目可见的规格
[root@controller ~(keystone_admin)]# openstack flavor create --vcpus 1 --ram 128 --disk 1 --private --project Project_cli Flavor_cli
+----------------------------+--------------------------------------+
| Field                      | Value                                |
+----------------------------+--------------------------------------+
| OS-FLV-DISABLED:disabled   | False                                |
| name                       | Flavor_cli                           |
| os-flavor-access:is_public | False                                |
| ram                        | 128                                  |
| vcpus                      | 1                                    |
+----------------------------+--------------------------------------+

# 移除项目的可见性,它依然不是 Public
[root@controller ~(keystone_admin)]# openstack flavor unset --project Project_cli Flavor_cli
[root@controller ~(keystone_admin)]# openstack flavor show Flavor_cli | grep is_public
| os-flavor-access:is_public | False |

# 如何创建 Public 的规格?直接建,不加 --private
[root@controller ~(keystone_admin)]# openstack flavor create --vcpus 1 --ram 128 --disk 1 Flavor_cli_public

总结:规格一旦创建,就无法动态修改其属性(比如从Private变Public)。想改?只能删了重建,这是Nova的一个硬性规定。

1.3 密钥对与虚拟机组(Server Group)

密钥对(Key Pair)大家都很熟悉了,就是SSH登录凭证。在 项目 -> 计算 -> 密钥对 中,点击"创建密钥对",生成 KeyPair_web 并自动下载 .pem 文件。

虚拟机组(Server Group)是控制虚拟机调度的一种策略。我们在创建时,有几种策略可选:

  • 关联(Affinity):组内的虚拟机必须挤在同一台物理机上。适合需要极低延迟通信的集群(比如HPC)。
  • 不关联(Anti-Affinity):组内的虚拟机绝对不能在同一台物理机上。适合高可用场景,防止物理机宕机导致全军覆没。
  • 软关联 / 软不关联:柔性策略,资源充足时遵守,不充足时妥协。

我们在界面创建一个名为 ServerGroup_web 的组,策略选择"关联"。

1.4 虚拟机实例的"一生":发放与状态流转

在界面 项目 -> 计算 -> 实例 中点击"创建实例",一路Next。选源(Img_web)、选规格(Flavor_web_test)、选网络(shared)、选密钥对,最后在服务器组里选中刚才创建的那个亲和性组,点击创建。

但这只是开始,真正的重头戏是虚拟机的生命周期管理。今天的实验里,我几乎把所有的状态都点了一遍:

  1. 关机 / 开机 :常规操作,Status 变为 关机。
  2. 软重启 / 硬重启 :软重启只是重启OS(相当于Linux里的 reboot),硬重启是直接拔电源再开机。界面上执行软重启后,任务状态会显示"软重启中"。
  3. 锁定 / 解锁 :为了防止手滑误删实例,admin用户可以将实例"锁定"。踩坑点 :默认情况下,普通用户(非admin)是可以对admin锁定的实例进行"解锁"并删除的!这非常不安全。后来我跟着资料把 /etc/openstack-dashboard/nova_policy.json 里面的 unlock 权限改为了 rule:admin_api,普通用户就彻底懵了,完全动不了锁定的实例。
  4. 暂停(Pause)与 挂起(Suspend) :
    • 暂停 :把虚拟机的状态直接保存在宿主机的内存里,电源状态变为"已暂停"。恢复(Unpause)极快。
    • 挂起 :把状态保存到宿主机的磁盘上,电源状态变为"关闭"。恢复(Resume)需要从磁盘读回内存,相对较慢。
  5. 废弃(Shelve):这个最狠。它会把虚拟机变成Glance里的一个镜像,然后在宿主机上把它彻底删掉,释放所有资源。需要的时候(UnShelve)再重新创建出来。适合长期不用的僵尸机。
  6. 快照与重建:给运行中的机器打快照(本质上是变成一张新镜像),如果虚拟机系统崩了,可以选择"重建实例",选择刚才的快照,相当于一键还原。

用CLI看下实例列表和发放过程:

bash 复制代码
[root@controller ~(keystone_admin)]# openstack server create --availability-zone nova --image Img_cli --flavor Flavor_cli --network shared --key-name KeyPair_cli Instance_cli_01
# 命令回显中会显示 OS-EXT-STS:task_state 为 scheduling,然后 building,最后 active

# 查看实例列表
[root@controller ~(keystone_admin)]# openstack server list
+--------------------------------------+----------------+--------+-----------------------+
| ID                                   | Name           | Status | Networks              |
+--------------------------------------+----------------+--------+-----------------------+
| 0f0b35d5-4c7d-42dd-8edf-9655748a5013 | Instance_cli_01| ACTIVE | shared=192.168.233.186|
+--------------------------------------+----------------+--------+-----------------------+

1.5 调整实例大小(Resize)的坑

在实例的操作列表里,有个"调整实例大小"。我们试着把原本 128MB 内存的规格调整为 156MB 的 Flavor_web_new。

界面点击调整后,状态会变成 确认或放弃调整大小/迁移。你必须再点一次"确认调整大小/迁移",才算真正完成。

踩坑点:手册里提到,如果把内存调到"64MB"(比当前还小),或者环境里没有共享存储(NFS/Ceph)且是多节点环境,调整大小会失败。因为调整大小本质上是一个带迁移的动作,底层存储如果不在共享目录里,数据根本拉不过去。这为后面搞Cinder NFS存储埋下了伏笔。


二、 深入OpenStack存储管理(Cinder)

计算折腾完,终于来到了存储。按照资料里说的,OpenStack的持久化存储有三大类:块存储(Cinder)、对象存储(Swift)和文件系统存储(Manila)。今天重点折腾的是块存储Cinder。

2.1 Cinder 架构与核心概念

不要把Cinder当成一个真实的物理硬盘,它其实是一个抽象的中间层 。

架构上,cinder-api 负责收请求,cinder-scheduler 负责选后端节点,cinder-volume 负责真正干活,底层对接的可能是LVM、SAN、Ceph等。

默认的实验环境里,Cinder对接的后端就是LVM。具体来说,它是把Linux的物理卷(PV)做成卷组(VG),然后从中切出逻辑卷(LV)给虚拟机用。我们可以在控制节点执行 vgdisplay cinder-volumes 看到,系统切了 20GB 的空间作为存储池。

在创建卷之前,得先搞定**卷类型(Volume Type)**和 QoS(服务质量)。

  • 界面操作:管理员 -> 卷 -> 卷类型 ,创建 VolumeType_web,勾选"公有"。
  • 接着创建 QoS 规格 QoS_web,消费者选"后端"。
  • 然后回到卷类型列表,把 QoS 关联到 VolumeType_web 上。

用CLI走一遍:

bash 复制代码
# 创建卷类型
[root@controller ~(keystone_admin)]# openstack volume type create --public VolumeType_cli

# 创建QoS
[root@controller ~(keystone_admin)]# openstack volume qos create --consume back-end QoS_cli

# 将QoS关联到卷类型
[root@controller ~(keystone_admin)]# openstack volume qos associate QoS_cli VolumeType_cli

2.2 卷的创建、挂载与卸载

这是最核心的日常操作。我们在 项目 -> 卷 -> 卷 里创建一个基于镜像的卷。

  • 卷名称:Volume_web_01
  • 卷来源:镜像
  • 使用镜像:Img_web
  • 类型:VolumeType_web
  • 大小:1GB

创建完成后,状态从"创建中"变为"可用"。接着,我们要把它挂载到刚才发放的虚拟机 Instance_web_01 上。

点击"管理连接",选择实例,点击"连接卷"。此时,卷的状态变为"正在使用",在实例内部,你会多出一块 /dev/vdb 的裸盘。

如果不需要了,点击"管理连接",点击"分离卷",状态重新回到"可用"。

CLI 操作流:

bash 复制代码
# 创建卷
[root@controller ~(keystone_admin)]# openstack volume create --image Img_cli --type VolumeType_cli --size 1 Volume_cli_01

# 挂载给实例
[root@controller ~(keystone_admin)]# openstack server add volume Instance_cli_01 Volume_cli_01
# 查看卷挂载状态
[root@controller ~(keystone_admin)]# openstack volume list
| aa0caa97-3369-4310-b159-e5ade3eea939 | Volume_cli_01 | in-use | 1 | Attached to Instance_cli_01 on /dev/vdb |

# 卸载
[root@controller ~(keystone_admin)]# openstack server remove volume Instance_cli_01 Volume_cli_01

2.3 高级操作:上传、快照、扩容与基于快照建卷

Cinder的强大之处在于它的快照和克隆能力。

上传卷到镜像:如果我们把系统盘装好了环境,可以直接把这个卷打包成Glance镜像。在界面上点击卷的"上传镜像",填入名称,格式选QCOW2。在CLI下就是:

bash 复制代码
[root@controller ~(keystone_admin)]# openstack image create --volume Volume_cli_01 --disk-format qcow2 Volume_Img_cli

创建卷快照 :点击卷的"创建快照",起名 Volume_Snap_web。注意,快照依赖原卷,如果原卷不删,快照就占着坑。

卷扩容:点击"扩展卷",把大小从1GB改成2GB。

bash 复制代码
[root@controller ~(keystone_admin)]# openstack volume set --size 2 Volume_cli_01

注意:扩容后,只是Cinder层面的容量变大了,如果里面已经跑着文件系统,还需要在虚拟机内部执行 resize2fs 或 xfs_growfs 才能真正用上新增的空间。

基于卷快照创建卷 :在快照列表里,点击"创建卷",相当于恢复数据。

基于卷发放虚拟机实例:如果卷里已经有完整的OS,可以直接用这个卷当启动盘发虚拟机。

bash 复制代码
# 使用已有卷创建实例
[root@controller ~(keystone_admin)]# openstack server create --volume Volume_cli_02 --flavor Flavor_cli Instance_cli_03

踩坑点 :如果这个卷被标记为"非启动卷"(--non-bootable),用它是建不了虚拟机的,直接报错 Block Device ... is not bootable。

2.4 删不掉!卷的删除依赖链

实验到最后,我想把创建的东西清理一下。结果发现卷删不掉。

系统报错:Invalid volume: Volume status must be available or error... and must not be migrating, attached, belong to a group, have snapshots...

这个报错信息其实极其精准:

  1. 卷现在是 in-use,必须先卸载(如果卸载报错说它是系统盘,那你只能先删虚拟机)。
  2. 卷还有快照,必须先删快照。
  3. 如果状态是 error,反而可以直接删。

删卷的顺序必须是:卸载卷 -> 删快照 -> 删卷。

bash 复制代码
# 尝试直接删卷(失败)
[root@controller ~(keystone_admin)]# openstack volume delete Volume_cli_01
# 报错,因为有快照

# 删除快照
[root@controller ~(keystone_admin)]# openstack volume snapshot delete Volume_Snap_cli

# 再次删除卷(成功)
[root@controller ~(keystone_admin)]# openstack volume delete Volume_cli_01

2.5 扩展实战:配置 NFS 共享存储后端

手册最后提到了一个非常关键的配置项:配置NFS共享存储。因为我们在虚拟机调整大小(Resize)的时候,如果是多节点且没有共享存储,就一定会失败。为了彻底解决这个问题,我们需要把Cinder的后端从纯本地LVM改为对接NFS。

操作步骤:

  1. 准备一台NFS服务器(或者用模板克隆一台IP为 192.168.108.12 的节点)。
  2. 在NFS节点上安装服务并配置共享目录:
bash 复制代码
mkdir /nfs_share
chmod -R 777 /nfs_share
yum -y install nfs-utils
echo "/nfs_share *(rw,sync,no_root_squash)" > /etc/exports
systemctl stop firewalld.service
systemctl restart nfs-server
systemctl enable nfs-server
  1. 在控制节点 上,修改 /etc/cinder/cinder.conf:
ini 复制代码
# 开启多后端支持
enabled_backends = lvm,nfs

[lvm]
volume_backend_name = lvm
volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver
target_ip_address = 192.168.108.10
target_helper = lioadm
volume_group = cinder-volumes

[nfs]
nfs_mount_point_base = /mnt/nfs_share
nfs_shares_config = /etc/cinder/nfs_shares
volume_driver = cinder.volume.drivers.nfs.NfsDriver
volume_backend_name = nfs
  1. 创建共享配置文件:
bash 复制代码
echo "192.168.108.12:/nfs_share" > /etc/cinder/nfs_shares
mkdir -p /mnt/nfs_share
chown -R cinder:cinder /mnt/nfs_share
systemctl restart openstack-cinder-volume
  1. 关键一步:创建对应的卷类型 。在界面上创建一个名为 nfs 的卷类型,并在"扩展规格"里配置键值对:键填 volume_backend_name,值填 nfs。这样用户在创建卷时,选择 nfs 类型,Cinder就会把数据写进NFS共享目录里了。

当有了这个共享存储后,多节点间的虚拟机调整大小和迁移就完全不在话下了。


三、 踩坑总结与心得感悟

今天这一大波计算和存储的实操,信息量确实有点大。挑几个印象最深的说:

  1. 主机聚合(Host Aggregate)的坑:同一台物理机不能跨AZ加入多个聚合,Nova死板是为了保护高可用机制。
  2. Flavor的Public到底怎么来:移除所有项目可访问权,并不会让它变成所有人可见的Public,而是变成了"隐形人"。要Public,建的时候别指定项目。
  3. 虚拟机生命周期里的细节:暂停(Pause)是把内存存在宿主机,挂起(Suspend)是存在磁盘。废弃(Shelve)是直接删机器存镜像。这几个动作如果不亲手点一遍,光看书真的很容易混。
  4. 安全组的解锁策略 :默认配置下普通用户居然能解开管理员上的锁,这是一个很危险的设计,必须改 nova_policy.json 才能达到真正的"防误删"目的。
  5. Cinder的删除链 :删卷之前必须断挂载、删快照、删备份。哪个环节卡住都会报 Invalid volume,学会看报错原因,按顺序清资源才是王道。
  6. Cinder背后有LVM和NFS:Cinder本身不存数据,它是在指挥后端存储。本地的LVM只能单机玩,要搞热迁移和调整大小,还得是共享的NFS或者Ceph。

从图形界面的直觉操作,到CLI命令行的底表操作,再到配置文件里的深水区(比如Cinder的 cinder.conf 和后端对接),这不仅是把知识点过了一遍,更是对"云"这个东西从抽象走向了具体的认知。

云原生这条路确实很长,光是一个Nova的计算调度(Filter和Weight的计算)就足够写几篇论文了,更别提还有对象存储Swift和网络Neutron还没正式开搞。但今天这一套组合拳打下来,我已经能脑补出:当你在Dashboard上轻轻点一下"创建实例"时,底下的物理资源是如何被Flavor限制、被Scheduler调度、被Cinder挂盘、最后被Hypervisor拉起来的全貌了。

相关推荐
CodeGL2 小时前
一文了解:K8s
云原生·容器·kubernetes
开开心心就好2 小时前
电脑语音实时转文字工具,会议记录很省事
运维·服务器·前端·c#·ocr·perl·1024程序员节
坤坤子吖2 小时前
Linux网络编程基础:从 MAC 到 IP,理解网络数据是怎么传输的
linux·网络·笔记·学习
霅昪忞昉2 小时前
DSP_28002x的SPI代码注释_文3
笔记·dsp开发
磁场转动100万匹2 小时前
Doris 学习(二):底层架构与三种数据模型深入解析
学习·架构
海绵宝宝转agent2 小时前
Leetcode100+面经
java·笔记·学习·算法·leetcode·深度优先
前进的李工2 小时前
Agent 学习笔记 01:从工具调用到 ReAct 循环
笔记·学习·llm·agent·react·工具调用
海绵宝宝转agent2 小时前
LeetCode100个人题解+java面经总结
java·开发语言·笔记·学习·算法
一只鹿鹿鹿2 小时前
医院绩效管理体系方案
大数据·运维·安全·web安全·制造