本例需要准备两个yaml文件,一个是heat模板,一个是传入的参数,然后执行如下命令创建stack
openstack --debug stack create -t <heat_template_yaml> -e <env_yaml> <stack_name> --wait
Note for arguments:
--debug Show tracebacks on errors.
-t <template>, --template <template>
Path to the template
-e <environment>, --environment <environment>
Path to the environment. Can be specified multiple times
--dry-run Do not actually perform the stack create, but show what would be created
--wait Wait until stack goes to CREATE_COMPLETE or CREATE_FAILED
本文包括4个部分
- 资源准备
- 传入参数的yaml文件
- Heat模板文件
- 创建stack
1.资源准备(此处假设资源已齐全,仅需要记录一些参数)
(1) 镜像
~$ nova image-list | egrep 'ID|CentOS7-TEST'
| ID | Name | Status | Server |
| 5d6e5666-86c5-4eb1-a937-fcbc41172c04 | CentOS7-TEST | ACTIVE | |
~$
(2) flavor
~$ nova flavor-list | egrep 'ID|flavor_8vC16M'
| ID | Name | Memory_MB | Disk | Ephemeral | Swap | VCPUs | RXTX_Factor | Is_Public |
| 8cb21666-44da-4407-ad8f-0fecb93f93ca | TESTflavor_8vC16M | 16384 | 310 | 0 | | 8 | 1.0 | True |
~$
~$ nova flavor-show TESTflavor_8vC16M
+----------------------------+---------------------------------------------------------------+
| Property | Value |
+----------------------------+---------------------------------------------------------------+
| OS-FLV-DISABLED:disabled | False |
| OS-FLV-EXT-DATA:ephemeral | 0 |
| disk | 310 |
| extra_specs | {"hw:cpu_policy": "dedicated", "hw:mem_page_size": "1048576"} |
| id | 8cb21666-44da-4407-ad8f-0fecb93f93ca |
| name | TESTflavor_8vC16M |
| os-flavor-access:is_public | True |
| ram | 16384 |
| rxtx_factor | 1.0 |
| swap | |
| vcpus | 8 |
+----------------------------+---------------------------------------------------------------+
~$
(3) 可用区
~$ openstack availability zone list | egrep 'Zone Name|ZONE'
| Zone Name | Zone Status |
| XX-TEST-ZONE | available |
~$
(4) 安全组
~$ openstack security group list | egrep 'ID|default'
| ID | Name | Description | Project |
| 0546b666-9dce-40aa-94b9-0470bcc35e4f | default | Default security group | 7849b4a666694e666ac52095f38ed666 |
~$
~$ openstack security group show default
+-------------+----------------------------------------------------------------------------+
| Field | Value |
+-------------+----------------------------------------------------------------------------+
| description | Default security group |
| id | 0546b666-9dce-40aa-94b9-0470bcc35e4f |
| name | default |
| project_id | 7849b4a666694e666ac52095f38ed666 |
| rules | id='3989d666-9a35-42a6-bd99-9e702f7d9032', remote_security_group='default' |
| | id='f08deaaa-5d20-4078-979f-69cd95a26f36', remote_security_group='default' |
+-------------+----------------------------------------------------------------------------+
~$
(5) 网络
===> 查看网络
~$ neutron net-list | egrep 'id|3a190666'
| id | name | subnets |
| 3a190666-bee3-4e5e-b228-1e32a83ab70b | XX_Net | 3a27faaa-823d-454a-ab4c-24f0ce41e2ad 10.166.166.192/27 |
~$
===> 查看子网,记录网关和子网掩码
~$ neutron subnet-show 3a27faaa-823d-454a-ab4c-24f0ce41e2ad
+-------------------+------------------------------------------------------+
| Field | Value |
+-------------------+------------------------------------------------------+
| allocation_pools | {"start": "10.166.166.200", "end": "10.166.166.220"} |
| cidr | 10.166.166.192/27 |
| created_at | 2020-12-03T02:26:33 |
| description | |
| dns_nameservers | |
| enable_dhcp | True |
| gateway_ip | 10.166.166.193 |
| host_routes | |
| id | 3a27faaa-823d-454a-ab4c-24f0ce41e2ad |
| ip_version | 4 |
| ipv6_address_mode | |
| ipv6_ra_mode | |
| name | XXNet_SubNet |
| network_id | 3a190666-bee3-4e5e-b228-1e32a83ab70b |
| subnetpool_id | |
| tenant_id | 7849b4a666694e666ac52095f38ed666 |
| updated_at | 2020-12-03T02:26:33 |
+-------------------+------------------------------------------------------+
~$
===> 创建PORT
确认PORT名和地址未被使用
~$ neutron port-list | grep TEST-ETH0
~$ neutron port-list | grep 10.166.166.212
~$
创建PORT,仅设定PORT名称
neutron port-create [--name NAME] <net_id>
注意:不要加参数[--fixed-ip subnet_id=SUBNET,ip_address=IP_ADDR],之后传入的env会传入地址,否则创建时会有地址冲突 ===> [TEST-STACK]: CREATE_FAILED Resource CREATE failed: IpAddressInUseClient: resources.VM_Port_1_v4: Unable to complete operation for network 3a1904e1-bee3-4e5e-b228-1e32a83ab70b. The IP address 10.166.166.212 is in use.
~$ neutron port-create --name TEST-ETH0 3a190666-bee3-4e5e-b228-1e32a83ab70b
Created a new port:
+-----------------------+---------------------------------------------------------------------------------------+
| Field | Value |
+-----------------------+---------------------------------------------------------------------------------------+
| admin_state_up | True |
| allowed_address_pairs | |
| binding:host_id | |
| binding:profile | {} |
| binding:vif_details | {} |
| binding:vif_type | unbound |
| binding:vnic_type | normal |
| created_at | 2021-07-30T07:31:26 |
| description | |
| device_id | |
| device_owner | |
| extra_dhcp_opts | |
| fixed_ips | {"subnet_id": "3a27faaa-823d-454a-ab4c-24f0ce41e2ad", "ip_address": "10.166.166.209"} |
| id | 612ab666-f843-4343-9b0c-a295ae4bd850 |
| mac_address | fa:16:3e:de:30:24 |
| name | TEST-ETH0 |
| network_id | 3a190666-bee3-4e5e-b228-1e32a83ab70b |
| port_security_enabled | True |
| qos_policy_id | |
| security_groups | 0546b666-9dce-40aa-94b9-0470bcc35e4f |
| status | DOWN |
| tenant_id | 7849b4a666694e666ac52095f38ed666 |
| updated_at | 2021-07-30T07:31:26 |
+-----------------------+---------------------------------------------------------------------------------------+
~$
(6)确认未使用的server,stack名称
~$ openstack server list --all-projects | grep TEST-VM
~$ openstack stack list | grep TEST-STACK
~$
2.传入参数的yaml文件
$ cat IPv4-VM.yaml
parameters:
network_type: IPv4_Only
VM_servername: TEST-VM
VM_instance-name: TEST-VM
root-image-uuid: 5d6e5666-86c5-4eb1-a937-fcbc41172c04
flavor_name: TESTflavor_8vC16M
availability-zone: XX-TEST-ZONE
security-group-uuid: 0546b666-9dce-40aa-94b9-0470bcc35e4f
eth0_ipv4_address: 10.166.166.212
eth0_ipv4_prefix: 27
eth0_ipv4_gateway: 10.166.166.193
eth0_ipv4_network_subnet_uuid: 3a27faaa-823d-454a-ab4c-24f0ce41e2ad
eth0_network_uuid: 3a190666-bee3-4e5e-b228-1e32a83ab70b
eth0_port_name: TEST-ETH0
~$
说明:
参考1(6) VM_instance-name
参考1(1) root-image-uuid
参考1(2) flavor_name
参考1(3) availability-zone
参考1(4) security-group-uuid
参考1(5) eth0_ipv4_address
参考1(5) eth0_ipv4_prefix
参考1(5) eth0_ipv4_gateway
参考1(5) eth0_ipv4_network_subnet_uuid
参考1(5) eth0_network_uuid
参考1(5) eth0_port_name: TEST-ETH0
3. Heat模板文件
~$ cat Heat-Orchestration-Template-example.yaml
heat_template_version: "2016-10-14"
parameters:
network_type:
description: "The network deployment type. Supports IPv4 only, IPv6 only and dual stack."
type: string
VM_servername:
description: "The hostname for TEST VM."
type: string
flavor_name:
description: "The flavor name for TEST VM."
type: string
availability-zone:
description: "The availability zone name for TEST VM in Openstack."
type: string
root-image-uuid:
description: "The image UUID for TEST."
type: string
security-group-uuid:
description: "The security group UUID for TEST VM."
type: string
eth0_ipv4_address:
description: "The eth0 network IPv4 address for TEST VM."
type: string
default: ""
eth0_ipv4_prefix:
description: "The eth0 network IPv4 prefix for TEST VM."
type: string
default: ""
eth0_ipv4_gateway:
description: "The eth0 network IPv4 gateway for TEST VM."
type: string
default: ""
eth0_ipv6_address:
description: "The eth0 network IPv6 address for TEST VM."
type: string
default: ""
eth0_ipv6_prefix:
description: "The eth0 network IPv6 prefix for TEST VM."
type: string
default: ""
eth0_ipv6_gateway:
description: "The eth0 network IPv6 gateway for TEST VM."
type: string
default: ""
eth0_network_uuid:
description: "The eth0 network UUID in Openstack."
type: string
eth0_ipv4_network_subnet_uuid:
description: "The eth0 network IPv4 subnet UUID in Openstack."
type: string
default: ""
eth0_ipv6_network_subnet_u:uid:
description: "The eth0 network IPv6 subnet UUID in Openstack."
type: string
default: ""
eth0_port_name:
description: "The eth0 network port name for TEST VM in Openstack."
type: string
VM_instance-name:
description: "The TEST instance name displayed in Openstack."
type: string
conditions:
ipv4_only:
equals:
- get_param: network_type
- "IPv4_Only"
ipv6_only:
equals:
- get_param: network_type
- "IPv6_Only"
dual_stack:
equals:
- get_param: network_type
- "Dual_Stack"
resources:
VM_Port_v4:
type: OS::Neutron::Port
condition: ipv4_only
properties:
fixed_ips: [{"ip_address": { get_param: eth0_ipv4_address }, "subnet": { get_param: eth0_ipv4_network_subnet_uuid }}]
security_groups: [ get_param: security-group-uuid ]
name: { get_param: eth0_port_name }
network: { get_param: eth0_network_uuid }
VM_Port_v6:
type: OS::Neutron::Port
condition: ipv6_only
properties:
fixed_ips: [{"ip_address": { get_param: eth0_ipv6_address }, "subnet": { get_param: eth0_ipv6_network_subnet_uuid }}]
security_groups: [ get_param: security-group-uuid ]
name: { get_param: eth0_port_name }
network: { get_param: eth0_network_uuid }
VM_Port_dual:
type: OS::Neutron::Port
condition: dual_stack
properties:
fixed_ips: [{"ip_address": { get_param: eth0_ipv4_address }, "subnet": { get_param: eth0_ipv4_network_subnet_uuid }}, {"ip_address": { get_param: eth0_ipv6_address }, "subnet": { get_param: eth0_ipv6_network_subnet_uuid }}]
security_groups: [ get_param: security-group-uuid ]
name: { get_param: eth0_port_name }
network: { get_param: eth0_network_uuid }
VM_net_data:
type: OS::Heat::MultipartMime
properties:
parts:
- config:
str_replace:
params:
_ETH0_IPV4_: { get_param: eth0_ipv4_address }
_ETH0_IPV4_PREFIX_: { get_param: eth0_ipv4_prefix }
_ETH0_IPV4_GATEWAY_: { get_param: eth0_ipv4_gateway }
_ETH0_IPV6_: {get_param: eth0_ipv6_address}
_ETH0_IPV6_PREFIX_: { get_param: eth0_ipv6_prefix }
_ETH0_IPV6_GATEWAY_: { get_param: eth0_ipv6_gateway }
_VM_HOSTNAME_: { get_param: VM_servername }
template: |
#cloud-config
merge_how: 'list(append)+dict(recurse_array,no_replace)+str()'
write_files:
- path: /run/cloud-init/update_network.sh
owner: root:root
permissions: '0700'
content : |
#!/bin/bash
sed -i '/^PasswordAuthentication/ s/no/yes/' /etc/ssh/sshd_config
sed -i '/^PermitRootLogin/ s/no/yes/' /etc/ssh/sshd_config
systemctl restart sshd
sed -i 's/DHCPV6C=yes/DHCPV6C=no/g' /etc/sysconfig/network-scripts/ifcfg-eth0
sed -i 's/dhcp/static/g' /etc/sysconfig/network-scripts/ifcfg-eth0
if [ _ETH0_IPV4_ != "" ];then
echo IPADDR=_ETH0_IPV4_ >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo PREFIX=_ETH0_IPV4_PREFIX_ >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo GATEWAY=_ETH0_IPV4_GATEWAY_ >> /etc/sysconfig/network-scripts/ifcfg-eth0
fi
if [ _ETH0_IPV6_ != "" ];then
echo IPV6INIT=yes >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo IPV6ADDR=_ETH0_IPV6_/_ETH0_IPV6_PREFIX_ >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo IPV6_DEFAULTGW=_ETH0_IPV6_GATEWAY_ >> /etc/sysconfig/network-scripts/ifcfg-eth0
echo IPV6_AUTOCONF=no >> /etc/sysconfig/network-scripts/ifcfg-eth0
fi
systemctl restart network
runcmd:
- /run/cloud-init/update_network.sh
- hostnamectl set-hostname _VM_HOSTNAME_
VM_Server:
type: OS::Nova::Server
properties:
networks:
- port: {if: [ipv4_only, {get_resource: VM_Port_v4}, {if: [ipv6_only, {get_resource: VM_Port_v6}, {if: [dual_stack, {get_resource: VM_Port_dual}, ""]}]}]}
name: { get_param: VM_instance-name }
config_drive: true
flavor: { get_param: flavor_name }
availability_zone: { get_param: availability-zone }
image: { get_param: root-image-uuid }
user_data: { get_resource: VM_net_data }
user_data_format: RAW
说明: 以下为个人理解,具体参考官方文档[2]
line2 parameters部分定义参数,这些参数由"-e"后的文件传入,其中network_type支持IPv4、IPv6和双栈
line62 conditions部分定义条件,network_type等于IPv4_Only(第2部分IPv4-VM.yaml中network_type的值),符合条件ipv4_only
line75 resources部分前三个资源(type: OS::Neutron::Port)中选择满足条件condition: ipv4_only的PORT,即VM_Port_v4
line100 resources部分的资源VM_net_data, line106 params传入参数; line114 template 使用cloud-init初始化VM(参考官方文档[1]),修改ssh配置文件使root可以ssh登录,添加了网卡信息,修改主机名,这样就不用等创建好VM再去console里配置网络
line143 resources部分的资源VM_Server,网络有一个网卡,如果需要多个网卡可以添加多个port字段,同时添加OS::Neutron::Port资源以及传入的参数
4.创建stack
使用dry run测试yaml文件正确配置,返回参数为0
~$ openstack --debug stack create -t Heat-Orchestration-Template-example.yaml -e IPv4-VM.yaml TEST-STACK --dry-run
……
END return value: 0
执行如下命令创建stack,成功创建的话返回参数为0
~$ openstack --debug stack create -t Heat-Orchestration-Template-example.yaml -e IPv4-VM.yaml TEST-STACK --wait
……
+---------------------+--------------------------------------+
| Field | Value |
+---------------------+--------------------------------------+
| id | 7aba7666-e05a-4f6d-a7f1-93935284c212 |
| stack_name | TEST-STACK |
| description | No description |
| creation_time | 2021-07-30T08:30:34Z |
| updated_time | None |
| stack_status | CREATE_COMPLETE |
| stack_status_reason | Stack CREATE completed successfully |
+---------------------+--------------------------------------+
clean_up CreateStack:
END return value: 0
~$
查看新创建的stack
~$ openstack stack show TEST-STACK
+-----------------------+-----------------------------------------------------------------------------------------------------------------------------------+
| Field | Value |
+-----------------------+-----------------------------------------------------------------------------------------------------------------------------------+
| id | 7aba7666-e05a-4f6d-a7f1-93935284c212 |
| stack_name | TEST-STACK |
| description | No description |
| creation_time | 2021-07-30T08:30:34Z |
| updated_time | None |
| stack_status | CREATE_COMPLETE |
| stack_status_reason | Stack CREATE completed successfully |
| parameters | OS::project_id: 7849b4a666694e666ac52095f38ed666 |
| | OS::stack_id: 7aba7666-e05a-4f6d-a7f1-93935284c212 |
| | OS::stack_name: TEST-STACK |
| | VM_instance-name: TEST-VM |
| | VM_servername: TEST-VM |
| | availability-zone: XX-TEST-ZONE |
| | eth0_ipv4_address: 10.166.166.212 |
| | eth0_ipv4_gateway: 10.166.166.193 |
| | eth0_ipv4_network_subnet_uuid: 3a27faaa-823d-454a-ab4c-24f0ce41e2ad |
| | eth0_ipv4_prefix: '27' |
| | eth0_ipv6_address: '' |
| | eth0_ipv6_gateway: '' |
| | eth0_ipv6_network_subnet_u:uid: '' |
| | eth0_ipv6_prefix: '' |
| | eth0_network_uuid: 3a190666-bee3-4e5e-b228-1e32a83ab70b |
| | eth0_port_name: TEST-ETH0 |
| | flavor_name: TESTflavor_8vC16M |
| | network_type: IPv4_Only |
| | root-image-uuid: 5d6e5666-86c5-4eb1-a937-fcbc41172c04 |
| | security-group-uuid: 0546b666-9dce-40aa-94b9-0470bcc35e4f |
| | |
| outputs | [] |
| | |
| links | - href: https://[2120:0:0:bfe::3]:8004/v1/7849b4a666694e666ac52095f38ed666/stacks/TEST-STACK/7aba7666-e05a-4f6d-a7f1-93935284c212 |
| | rel: self |
| | |
| parent | None |
| disable_rollback | True |
| deletion_time | None |
| stack_user_project_id | aaac4c521ec042e88588469126034d2c |
| capabilities | [] |
| notification_topics | [] |
| stack_owner | None |
| timeout_mins | None |
| tags | null |
| | ... |
| | |
+-----------------------+-----------------------------------------------------------------------------------------------------------------------------------+
~$
查看stack中的VM
$ nova list | egrep 'ID|TEST-VM'
| ID | Name | Status | Task State | Power State | Networks |
| dab59666-0762-4a1b-989f-4ddf94239679 | TEST-VM | ACTIVE | - | Running | XX_Net=10.166.166.212
$ nova show TEST-VM
……
$
(END)
官方文档参考:
[1] cloud-init => https://cloudinit.readthedocs.io/en/latest/
[2] openstack => https://docs.openstack.org/heat/latest/template_guide/index.html