07.OpenStack编排管理
OpenStack 编排管理
文章目录
- OpenStack 编排管理
- 一、OpenStack 编排— 核心服务 Heat
- 为什么一定要用 Heat?
- 二、Heat 的核心:模板(Template)怎么写?
- 1. 模板的 4 个核心部分
- 2. 实战示例:创建 1 台基础虚拟机的模板
- 示例模板:`create_vm.yaml`
- 关键语法解释(新手必看)
- 三、模板使用—Heat 命令行实战
- 前提:准备工作
- 步骤 1:检查模板语法是否正确
- 步骤 2:创建 “栈”(Stack)——Heat 的资源集合
- 命令解释:
- 步骤 3:查看栈的状态和输出结果
- 步骤 4:删除栈(资源清理)
- 四、进阶:让编排更灵活
- 1. 资源依赖:控制资源创建顺序
- 示例:手动指定依赖关系
- 2. 循环创建:批量生成资源
- 示例:批量创建 3 台应用服务器
- 五、常见问题和避坑指南
- 1. 模板语法错误:缩进不对
- 2. 资源不存在:镜像 / 网络 / 规格写错
- 3. 权限不足:创建资源被拒绝
- 六、总结:编排管理的核心价值
在 OpenStack 的日常使用中,你是否遇到过这样的场景:每次部署应用都要重复创建虚拟机、配置网络、挂载存储、安装软件,步骤繁琐又容易出错?这时候, 编排管理就成了提高效率的关键。今天我们就从实际操作角度,把 OpenStack 编排管理讲透,全程结合示例,保证新手也能看懂。
一、OpenStack 编排— 核心服务 Heat
提到 OpenStack 编排,就绕不开Heat—— 它是 OpenStack 官方的编排服务,相当于一个 “自动化管家”。你只需要提前写好一份 “任务清单”(也就是 Heat 模板),Heat 就能按照清单自动完成资源的创建、配置和关联,比如一次性搞定 10 台虚拟机 + 2 个网络 + 1 块共享存储,甚至还能设置 “如果虚拟机宕机就自动重启” 这样的规则。
为什么一定要用 Heat?
假设你要部署一套 Web 服务,需要以下资源:
-
2 台应用服务器(虚拟机,规格 2C4G)
-
1 台数据库服务器(虚拟机,规格 4C8G,需要挂载 100G 云硬盘)
-
1 个私有网络(192.168.1.0/24),并关联公网
-
安全组规则:允许 80(HTTP)、443(HTTPS)、22(SSH)端口访问
如果手动操作,至少需要 15 + 步骤,而且每次扩容或重建都要重复一遍。但用 Heat 的话,只需写一次模板,后续执行一条命令就能自动完成所有操作,出错率还能降到几乎为零。
二、Heat 的核心:模板(Template)怎么写?
Heat 模板是编排的 “灵魂”,它用 YAML 格式编写,本质是 “告诉 Heat 要创建哪些资源、资源之间是什么关系、怎么配置”。我们先从最基础的模板结构讲起,再结合实例一步步拆解。
1. 模板的 4 个核心部分
任何一个 Heat 模板,都离不开以下 4 个部分(可以理解为写作文的 “标题、开头、正文、结尾”):
| 部分 | 作用 | 通俗理解 |
|---|---|---|
heat_template_version | 声明模板版本(必须写在最前面) | 告诉 Heat “用哪个版本的规则解读” |
description | 描述模板的用途(可选,但建议写) | 给模板写个 “备注”,方便自己看 |
parameters | 定义可动态传入的参数(可选) | 比如虚拟机名称、密码,支持 “每次用模板时改值” |
resources | 定义要创建的 OpenStack 资源(核心!) | 比如虚拟机、网络、安全组,是模板的 “主体” |
outputs | 定义模板执行完成后要输出的信息(可选) | 比如创建好的虚拟机 IP,方便后续使用 |
2. 实战示例:创建 1 台基础虚拟机的模板
光说理论太抽象,我们直接写一个 “创建 1 台虚拟机” 的模板,结合代码逐行解释。
示例模板:create_vm.yaml
\# 1. 声明模板版本(这里用最新的rocky版本,不同OpenStack版本对应的值不同,查文档即可)heat\_template\_version: 2018-08-31\# 2. 描述模板用途description: "创建1台基础虚拟机,包含安全组(允许SSH和HTTP访问)"\# 3. 定义可动态传入的参数(比如虚拟机名称、密码,每次执行时可以改)parameters:  \# 参数1:虚拟机名称  vm\_name:  type: string # 参数类型:字符串  label: "虚拟机名称" # 参数的“显示名称”  default: "my-first-vm" # 默认值,如果不传入就用这个  description: "要创建的虚拟机名称" # 参数描述  \# 参数2:虚拟机密码(注意:生产环境建议用密钥,这里为了简单用密码)  vm\_password:  type: string  label: "虚拟机密码"  hidden: true # 隐藏输入(输入时不显示明文)  description: "虚拟机的root用户密码"  \# 参数3:虚拟机规格(比如2C4G,对应OpenStack中的flavor)  vm\_flavor:  type: string  label: "虚拟机规格"  default: "m2.medium" # 假设OpenStack中存在这个规格  constraints: # 限制参数值,只能选指定的几个  \- allowed\_values:  \- "m2.small" # 1C2G  \- "m2.medium" # 2C4G  \- "m2.large" # 4C8G\# 4. 定义要创建的资源(核心部分,这里创建3个资源:安全组、虚拟机)resources:  \# 资源1:安全组(允许SSH和HTTP访问)  my\_security\_group:  type: OS::Neutron::SecurityGroup # 资源类型:Neutron安全组  properties: # 资源的配置属性  name: "allow-ssh-http" # 安全组名称  description: "允许SSH(22端口)和HTTP(80端口)访问"  rules: # 安全组规则  \# 规则1:允许SSH(22端口)从任意IP访问  \- protocol: tcp  port\_range\_min: 22  port\_range\_max: 22  remote\_ip\_prefix: 0.0.0.0/0  \# 规则2:允许HTTP(80端口)从任意IP访问  \- protocol: tcp  port\_range\_min: 80  port\_range\_max: 80  remote\_ip\_prefix: 0.0.0.0/0  \# 资源2:虚拟机(依赖上面创建的安全组)  my\_vm:  type: OS::Nova::Server # 资源类型:Nova虚拟机  depends\_on: my\_security\_group # 依赖关系:先创建安全组,再创建虚拟机  properties:  name: {get\_param: vm\_name} # 引用上面定义的“vm\_name”参数  flavor: {get\_param: vm\_flavor} # 引用“vm\_flavor”参数  image: "CentOS-7-x86\_64" # 镜像名称(必须是OpenStack中已存在的)  networks: # 关联的网络(这里用“demo-net”,需提前创建)  \- network: "demo-net"  security\_groups: # 关联上面创建的安全组  \- {get\_resource: my\_security\_group}  user\_data: | # 虚拟机启动后执行的脚本(比如设置root密码)  \#!/bin/bash  echo "root:{get\_param: vm\_password}" | chpasswd # 设置root密码  systemctl start httpd # 启动Apache服务(假设镜像有httpd)  systemctl enable httpd # 设置开机自启\# 5. 定义输出信息(模板执行完后,输出虚拟机的IP和名称)outputs:  vm\_ip:  description: "虚拟机的私有IP地址"  value: {get\_attr: \[my\_vm, first\_address]} # 获取“my\_vm”资源的“first\_address”属性(即IP)  vm\_name:  description: "虚拟机名称"  value: {get\_param: vm\_name} # 直接输出“vm\_name”参数的值
关键语法解释(新手必看)
上面的模板中,有几个反复出现的语法,比如{get_param: ...}、{get_resource: ...},这些是 Heat 的 “内置函数”,用来引用参数或资源,记住这 3 个最常用的就行:
-
{get_param: 参数名}:引用parameters部分定义的参数(比如vm_name) -
{get_resource: 资源名}:引用resources部分定义的资源(比如my_security_group) -
{get_attr: [资源名, 属性名]}:获取某个资源的属性(比如虚拟机的 IP 是my_vm的first_address属性)
三、模板使用—Heat 命令行实战
写好模板后,接下来就是用 Heat 命令行工具执行模板,完成资源创建。我们分 3 步走:检查模板、创建栈、查看结果。
前提:准备工作
-
已安装 OpenStack 客户端(
openstack-cli),并配置好环境变量(比如OS_AUTH_URL、OS_USERNAME等,通常通过source ``openrc.sh加载)。 -
确保模板中引用的资源存在(比如镜像
CentOS-7-x86_64、网络demo-net),如果不存在,需要提前创建。
步骤 1:检查模板语法是否正确
在执行模板前,先检查语法是否有错误,避免白跑一趟:
openstack orchestration template validate -f yaml -t create\_vm.yaml
如果输出Valid template,说明语法没问题;如果报错,根据提示修改(比如缩进错误、资源类型写错)。
步骤 2:创建 “栈”(Stack)——Heat 的资源集合
在 Heat 中,“栈”(Stack)是资源的集合,比如上面的模板创建了 “安全组 + 虚拟机”,这两个资源会被打包成一个栈。创建栈的命令如下:
openstack orchestration stack create \\  \--template create\_vm.yaml \ # 指定模板文件  \--parameter "vm\_name=web-server-01" \ # 传入参数(覆盖默认值)  \--parameter "vm\_password=MyPass123!" \ # 传入密码参数  \--parameter "vm\_flavor=m2.large" \ # 传入规格参数(4C8G)  my-first-stack # 栈的名称(自己取,方便后续管理)
命令解释:
-
--template:指定要使用的模板文件(create_vm.yaml) -
--parameter:传入参数,格式是 “参数名 = 值”,可以多次使用(这里我们修改了虚拟机名称、密码和规格) -
最后一个参数
my-first-stack是栈的名称,后续管理(比如删除栈)都要用这个名称
步骤 3:查看栈的状态和输出结果
- 查看栈的状态:创建栈需要一点时间(比如 1-2 分钟),可以用以下命令查看进度:
openstack orchestration stack show my-first-stack -f yaml
关键看stack_status字段:
-
CREATE_IN_PROGRESS:正在创建 -
CREATE_COMPLETE:创建成功(没问题了) -
CREATE_FAILED:创建失败(需要看stack_status_reason字段找原因,比如镜像不存在、网络错误)
- 查看输出信息:栈创建成功后,查看我们在
outputs部分定义的虚拟机 IP 和名称:
openstack orchestration stack output show my-first-stack vm\_ip -f valueopenstack orchestration stack output show my-first-stack vm\_name -f value
执行后会输出类似这样的结果:
192.168.1.101 # 虚拟机IPweb-server-01 # 虚拟机名称
- 验证结果:用 SSH 连接虚拟机,测试是否能登录,以及 HTTP 服务是否正常:
\# 用输出的IP登录虚拟机ssh root@192.168.1.101\# 输入密码(MyPass123!),如果能登录,说明没问题\# 测试HTTP服务:在本地浏览器访问虚拟机IP,能看到Apache默认页面就对了
步骤 4:删除栈(资源清理)
如果不需要这些资源了,删除栈会自动删除栈中的所有资源(包括虚拟机、安全组),避免浪费:
openstack orchestration stack delete my-first-stack
删除后,用openstack orchestration stack list确认栈已不存在。
四、进阶:让编排更灵活
上面的示例是基础操作,实际使用中,我们还需要更灵活的编排能力,比如 “资源依赖”“条件判断”“循环创建”,这里介绍 2 个最常用的进阶功能。
1. 资源依赖:控制资源创建顺序
在复杂场景中,资源之间会有明确的依赖关系,比如 “先创建网络,再创建子网,最后创建虚拟机”。Heat 默认会自动分析依赖,但如果需要手动指定,可以用depends_on字段(前面的示例中已经用过)。
示例:手动指定依赖关系
resources:  # 1. 先创建网络  my\_network:  type: OS::Neutron::Net  properties:  name: "my-net"  # 2. 再创建子网(依赖网络)  my\_subnet:  type: OS::Neutron::Subnet  depends\_on: my\_network # 明确依赖“my\_network”,必须先创建网络  properties:  network: {get\_resource: my\_network}  cidr: "192.168.2.0/24"  gateway\_ip: "192.168.2.1"  # 3. 最后创建虚拟机(依赖子网)  my\_vm:  type: OS::Nova::Server  depends\_on: my\_subnet # 依赖子网,必须先创建子网  properties:  # ... 其他配置 ...  networks:  - subnet: {get\_resource: my\_subnet} # 关联子网
2. 循环创建:批量生成资源
如果需要创建多台相同配置的虚拟机(比如 10 台应用服务器),不需要写 10 遍OS::Nova::Server,用OS::Heat::ResourceGroup就能实现循环创建。
示例:批量创建 3 台应用服务器
resources:  # 用ResourceGroup循环创建3台虚拟机  app\_servers:  type: OS::Heat::ResourceGroup  properties:  count: 3 # 循环次数:创建3台  resource\_def: # 每台虚拟机的配置(和之前的OS::Nova::Server一样)  type: OS::Nova::Server  properties:  name: "app-server-%index%" # %index%会自动替换为0、1、2(3台分别是app-server-0、1、2)  flavor: "m2.medium"  image: "CentOS-7-x86\_64"  networks:  - network: "demo-net"  security\_groups:  - {get\_resource: my\_security\_group}
执行模板后,会自动创建 3 台虚拟机,名称分别是app-server-0、app-server-1、app-server-2,配置完全相同,极大减少重复代码。
五、常见问题和避坑指南
新手用 Heat 时,很容易遇到各种问题,这里总结 3 个最常见的坑,帮你少走弯路:
1. 模板语法错误:缩进不对
YAML 格式对缩进非常敏感,比如parameters下面的参数,必须比parameters多 2 个空格(或 1 个 Tab),如果缩进错了,模板会验证失败。
解决方法:用 VS Code、PyCharm 等编辑器,开启 “显示空格” 功能,确保缩进一致(建议用 2 个空格)。
2. 资源不存在:镜像 / 网络 / 规格写错
模板中引用的镜像(比如CentOS-7-x86_64)、网络(demo-net)、规格(m2.medium),必须是 OpenStack 中已存在的,否则会报 “Resource not found” 错误。
解决方法:先用命令确认资源是否存在:
\# 查看所有镜像openstack image list\# 查看所有网络openstack network list\# 查看所有规格openstack flavor list
3. 权限不足:创建资源被拒绝
如果执行命令时报 “Permission denied”,通常是当前用户没有创建资源的权限(比如没有创建安全组的权限)。
解决方法:联系 OpenStack 管理员,给用户添加对应的角色(比如member或admin角色)。
六、总结:编排管理的核心价值
看到这里,你应该明白 OpenStack 编排管理的核心了:用模板定义资源,用 Heat 自动执行,实现 “一次编写,多次复用”。它的价值主要体现在 3 个方面:
-
提高效率:把重复操作自动化,避免手动点击或敲命令。
-
减少错误:模板是 “标准化” 的,避免人为操作失误(比如漏开安全组端口)。
-
便于维护:资源打包成栈,删除栈时能一键清理所有资源,避免残留。
如果你是 OpenStack 的日常使用者,建议从简单的模板开始(比如创建 1 台虚拟机、1 个网络),熟悉后再尝试复杂场景(比如部署 Web + 数据库 + 负载均衡
