OpenStack编排服务
Heat(编排服务)简介
Heat是一个使用声明性模板格式,通过OpenStack 原生 REST API 编排复合云应用程序的服务。
Heat模板指定了资源之间的关系(例如,某个卷连接到某个实例)。这样,Heat 就可以调用 OpenStack API,以正确的顺序创建所有基础设施,从而完全启动应用程序。开发人员能够在程序中使用模板以实现资源的自动化部署。
Heat特点
标准化和可重复性:使用 Heat 可以将基础设施和应用程序的配置标准化为模板,在不同环境中重复使用,确保配置的一致性和可重复性。
简化复杂性:定义资源之间的依赖关系和配置规则,简化复杂的资源编排过程,减少手动操作和错误。
弹性和可伸缩性:通过定义资源组和循环实现资源的弹性扩展和收缩,根据需求自动调整资源。
可视化和审计:提供堆栈拓扑图的可视化功能,记录堆栈的操作和资源状态变化,用于跟踪和审计。
Heat基本概念
堆栈(stack):管理资源的集合,单个模板中定义的实例化资源的集合,是 Heat 管理应用程序的逻辑单元,往往对应一个应用程序。
模板(template):描述了所有组件资源以及组件资源之间的关系,是 Heat 的核心。
资源(resource):将在编排期间创建或修改的对象,可以是网络、路由器、子网、实例、卷、浮动IP、安全组等。
Heat架构
heat command-line client:CLI 通过与 heat-api 通信,来调用 API 实现相关功能。
heat-api:实现 OpenStack 原生支持的 REST API,通过把 API 请求经由 AMQP 传送给 Heat engine 来处理 API 请求。
heat-engine:执行模板内容,完成应用系统的创建和部署,并把执行结果返回给 API 调用者。
Heat命令
Heat编排实验
作业与实验环境
超星网址
使用虚拟机openstack-allinone,账户root,密码000000
VmWare 网络设置
在编辑->虚拟网络编辑器中将 Vmnet1 网卡的子网由原来的
192.168.10.0改为192.168.100.0:
上传镜像
Horizon 登录地址
192.168.100.10/dashboard,使用域xiandian、用户名admin、密码000000登录,上传本地的 cirros 镜像到 OpenStack 平台:
执行身份认证
# 加载管理员认证环境变量,后续 openstack/heat 命令会自动使用 [root@controller ~]# source /etc/keystone/admin-openrc.sh
通过模板启动一个堆栈
创建模板文件
新建模板文件
demo.yaml并将以下内容保存:heat_template_version: 2015-04-30 description: Heat 编排示例 resources: # 创建私有网络 my_network: type: OS::Neutron::Net properties: name: private-iso-net # 创建私有子网 my_subnet: type: OS::Neutron::Subnet properties: name: private-iso-net-subnet network_id: { get_resource: my_network } # 子网网段(CIDR 格式) cidr: 192.168.200.0/24 # 网关 IP 地址 gateway_ip: 192.168.200.1 # DNS 服务器地址 dns_nameservers: ["114.114.114.114", "8.8.8.8"] ip_version: 4 # 启用 DHCP,自动分配 IP enable_dhcp: true创建堆栈
根据模板文件创建堆栈:
# 创建堆栈(-t 指定模板文件,test_net 为堆栈名) # 堆栈会按模板顺序创建私有网络与子网 [root@controller ~]# openstack stack create -t demo.yaml test_net +---------------------+-----------------------------------------------------------------+ | Field | Value | +---------------------+-----------------------------------------------------------------+ | id | be89980b-a28e-4110-97d4-1b7a0284b045 | | stack_name | test_net | | description | Create an isolated private network and subnet without a router. | | creation_time | 2025-12-03T19:04:48 | | updated_time | None | | stack_status | CREATE_IN_PROGRESS | | stack_status_reason | | +---------------------+-----------------------------------------------------------------+ # 查看堆栈资源,确认各资源状态(查看名称、ID、类型、状态) [root@controller ~]# openstack stack resource list test_net +---------------+--------------------------------------+---------------------+-----------------+---------------------+ | resource_name | physical_resource_id | resource_type | resource_status | updated_time | +---------------+--------------------------------------+---------------------+-----------------+---------------------+ | my_subnet | a93cdcce-ba23-4743-bb95-dcf15ca18897 | OS::Neutron::Subnet | CREATE_COMPLETE | 2025-12-03T20:09:57 | | my_network | 35f5a966-3f0e-496c-94cb-36e9ac600755 | OS::Neutron::Net | CREATE_COMPLETE | 2025-12-03T20:09:57 | +---------------+--------------------------------------+---------------------+-----------------+---------------------+ # 查看网络列表 [root@controller ~]# openstack network list +--------------------------------------+-----------------+--------------------------------------+ | ID | Name | Subnets | +--------------------------------------+-----------------+--------------------------------------+ | c4c7e383-ade0-4d50-bf55-1b56dcf45fa7 | private-iso-net | 1bb613ed-8062-4e40-9614-4d90892fbfbc | +--------------------------------------+-----------------+--------------------------------------+ # 查看子网列表 [root@controller ~]# openstack subnet list +--------------------------------------+------------------------+--------------------------------------+------------------+ | ID | Name | Network | Subnet | +--------------------------------------+------------------------+--------------------------------------+------------------+ | 1bb613ed-8062-4e40-9614-4d90892fbfbc | private-iso-net-subnet | c4c7e383-ade0-4d50-bf55-1b56dcf45fa7 | 192.168.200.0/24 | +--------------------------------------+------------------------+--------------------------------------+------------------+作业1:执行
openstack stack resource list test_net查看堆栈资源列表后截图。删除堆栈
删除堆栈后,相应的资源会被自动删除:
# 删除堆栈(y 确认后会级联删除模板创建的资源) [root@controller ~]# openstack stack delete test_net Are you sure you want to delete this stack(s) [y/N]? y [root@controller ~]# # 验证子网已删除 [root@controller ~]# openstack subnet list # 验证网络已删除 [root@controller ~]# openstack network list [root@controller ~]#添加云主机资源
编写以下模板内容保存到
demo.yaml文件中resources下,和my_network以及my_subnet平级:# 创建云主机实例 my_instance: type: OS::Nova::Server properties: name: my-test-instance # 指定镜像和规格 image: cirros flavor: m1.small # 指定网络 networks: - network: { get_resource: my_network }重新创建堆栈
重新创建堆栈,包含网络、子网和云主机:
# 创建堆栈,包含网络、子网和云主机资源 [root@controller ~]# openstack stack create -t demo.yaml test +---------------------+--------------------------------------+ | Field | Value | +---------------------+--------------------------------------+ | id | f24806af-af0b-4bd4-a756-1f6eb032f086 | | stack_name | test | | description | No description | | creation_time | 2025-12-03T20:12:57 | | updated_time | None | | stack_status | CREATE_IN_PROGRESS | | stack_status_reason | | +---------------------+--------------------------------------+ # 查看资源列表,确认实例、网络、子网均创建完成 [root@controller ~]# openstack stack resource list test +---------------+--------------------------------------+---------------------+-----------------+---------------------+ | resource_name | physical_resource_id | resource_type | resource_status | updated_time | +---------------+--------------------------------------+---------------------+-----------------+---------------------+ | my_instance | 08379aaa-e2f9-4b03-82e7-44c486b8f26b | OS::Nova::Server | CREATE_COMPLETE | 2025-12-03T20:12:57 | | my_subnet | 4fcba899-bb37-48ad-b7a4-39764701060b | OS::Neutron::Subnet | CREATE_COMPLETE | 2025-12-03T20:12:57 | | my_network | 644c93f6-c62a-4393-ad5e-b1f085c51ab0 | OS::Neutron::Net | CREATE_COMPLETE | 2025-12-03T20:12:57 | +---------------+--------------------------------------+---------------------+-----------------+---------------------+查看实例运行状态
在 Horizon 上查看实例运行状态:
或者通过 OpenStack 命令查看实例列表:
# 列出当前项目中的云主机 [root@controller ~]# openstack server list +--------------------------------------+--------------------------------------+--------+---------------------+ | ID | Name | Status | Networks | +--------------------------------------+--------------------------------------+--------+---------------------+ | 2324c631-cf3e-49eb-a8e2-be384341e4ac | demo-struct-my_instance-clk6vt6fuwe4 | ACTIVE | | +--------------------------------------+--------------------------------------+--------+---------------------+作业2:在原有模板内添加实例资源后创建堆栈,使用
openstack stack resource list test查看堆栈资源列表后截图。删除堆栈
# 删除包含实例的堆栈 [root@controller ~]# openstack stack delete test Are you sure you want to delete this stack(s) [y/N]? y
模板文件基本构成
一个典型的 Heat 模板包含以下部分:
heat_template_version: 2015-04-30 description: Simple template to deploy a single compute instance resources: my_instance: type: OS::Nova::Server properties: image: cirros flavor: m1.small
heat_template_version:每个模板文件必须要包含的键,值是具体的版本号(如
2013-05-23),参考 Heat template version list 获取版本号。description:可选的键,用来描述模板所执行操作,支持多行文本。
resources:必须要包含的键,至少需要定义一个 resource,例子中定义了一个实例资源并包含了若干个属性。
模板文件的输入参数
模板文件中的 parameters 段允许用户在构建的过程中自定义模板。比如用户可以提供 镜像ID 和 实例类型 来构建堆栈,通过输入参数可以使得模板更容易重用。
引入数据参数
以下是一个引入数据参数的模板示例,参考修改上文的
demo.yaml文件:heat_template_version: 2015-04-30 description: Simple template to deploy a single compute instance parameters: # 定义镜像参数 image_id: type: string label: Image ID description: Image to be used for compute instance # 定义实例类型参数 flavor: type: string label: Instance Type description: Type of instance (flavor) to be used resources: my_instance: type: OS::Nova::Server properties: # 使用 get_param 获取用户提供的镜像参数 image: { get_param: image_id } # 使用 get_param 获取用户提供的规格参数 flavor: { get_param: flavor }模板中的参数必须在构建堆栈的过程中提供,
get_param内建函数检索用户所提供的值并用于相关属性。通过传递参数创建堆栈
# 传参创建堆栈(--parameter 注入镜像与规格参数) [root@controller ~]# openstack stack create -t demo.yaml demo-struct --parameter image_id=cirros --parameter flavor=m1.small +---------------------+-----------------------------------------------------+ | Field | Value | +---------------------+-----------------------------------------------------+ | id | f3ab8bbe-f769-495f-88db-46a6a373aa22 | | stack_name | demo-struct | | description | Simple template to deploy a single compute instance | | creation_time | 2023-12-04T09:24:14 | | updated_time | None | | stack_status | CREATE_IN_PROGRESS | | stack_status_reason | | +---------------------+-----------------------------------------------------+设置默认参数
给模板设置默认参数,默认参数可以当用户没有提供参数时用来构建堆栈。参考代码片段修改
demo.yaml文件:parameters: flavor: type: string label: Instance Type description: Flavor to be used # 设置默认值 default: m1.small当模板中没有设置默认参数时,用户必须提供所有参数,否则堆栈就会创建失败。
使用默认参数创建堆栈
修改完以上片段后只提供 image 参数来启动一个堆栈:
# 仅提供镜像参数(--parameter 注入参数) # flavor 使用模板中的默认值 m1.small [root@controller ~]# openstack stack create -t demo.yaml demo-struct --parameter image_id=cirros +---------------------+-----------------------------------------------------+ | Field | Value | +---------------------+-----------------------------------------------------+ | id | 1765bf8d-f792-4ac7-b842-664773fa79c1 | | stack_name | demo-struct | | description | Simple template to deploy a single compute instance | | creation_time | 2023-12-04T09:38:36 | | updated_time | None | | stack_status | CREATE_IN_PROGRESS | | stack_status_reason | Stack CREATE started | +---------------------+-----------------------------------------------------+作业3:使用默认参数的方式启动堆栈后上传截图。
限制参数值
对于用户输入的参数可以进行限制。通过在
parameters段中添加constraints属性并定义一个列表来限制用户输入的参数,参考以下片段修改demo.yaml:parameters: flavor: type: string label: Instance Type description: Type of instance (flavor) to be used # 限制参数的允许值 constraints: - allowed_values: [ m1.medium, m1.large, m1.xlarge ] description: Value must be one of m1.medium, m1.large or m1.xlarge.除了直接对参数的值做限制以外还可以使用多个条件进行限制,以下是一个限制指定创建数据库密码的参数的示例:
parameters: database_password: type: string label: Database Password description: Password to be used for database # 隐藏密码输入 hidden: true # 设置多个约束条件 constraints: # 限制密码长度(6-8 位) - length: { min: 6, max: 8 } description: Password length must be between 6 and 8 characters. # 限制密码只能包含字母和数字 - allowed_pattern: "[a-zA-Z0-9]+" description: Password must consist of characters and numbers only. # 限制密码必须以大写字母开头 - allowed_pattern: "[A-Z]+[a-zA-Z0-9]*" description: Password must start with an uppercase character.
编写一个模板文件
参考以下代码编写一个模板文件,实现从卷启动实例:
resources: # 创建可启动的卷(包含操作系统) bootable_volume: type: OS::Cinder::Volume properties: size: 10 image: ubuntu-trusty-x86_64 # 从卷启动实例 instance: type: OS::Nova::Server properties: flavor: m1.small networks: - network: private # 配置块设备映射,从卷启动 block_device_mapping: - device_name: vda # 指定启动卷 volume_id: { get_resource: bootable_volume } # 实例删除时不删除卷 delete_on_termination: false
作业4:进入实例的控制台后截图上传。