Heat examples
You will find below different examples to achieve several usecases you've read in the documentation.
List of heat resource types you might find in this page
OS::Nova::ResourceGroup
OS::Nova::ServerGroup
OS::Neutron::SecurityGroup
OS::Neutron::SecurityGroupRule
Example 1 : VMs Affinity - Anti-affinity. 3 VMs physically in different datacenter zones
VMs Affinity - Anti-affinity documentation and manual creation
How to create 3 VMs, each one in a different zone (meaning physically in different datacenter zones)
You need resources of type OS::Heat::ResourceGroup
in combination with OS::Nova::ServerGroup
and define an additional template for the VMs themselves called in this example node.yaml
The example below will create
- a group of server called
group_nodes
with the policy anti-affinity - 3 VMs of type node.yaml in the same group
group_nodes
therefore using the anti-affinity policy
group_nodes
group_nodes:
type: OS::Nova::ServerGroup
properties:
name: {list_join: ['-', [{get_param: "OS::stack_name"}, 'group-nodes']]}
policies: ["anti-affinity"]
nodes:
type: OS::Heat::ResourceGroup
properties:
count: 3
resource_def:
type: node.yaml
properties:
flavorname: a1-ram2-disk20-perf1
image: Debian 11 bullseye
private_network: mynetwork
name: {list_join: ['-', [{get_param: "OS::stack_name"}, 'node', '%index%']]}
servergroup: {get_resource: group_nodes}
key_name: my_keypair
security_groups:
- default
node.yaml
---
heat_template_version: 2018-08-31
parameters:
private_network:
type: string
key_name:
type: string
label: Key Name
description: Name of key-pair to be used for compute instance
default: my_keypair
flavorname:
type: string
default: a1-ram2-disk20-perf1
image:
type: string
default: Debian 11 bullseye
name:
type: string
servergroup:
type: string
security_groups:
type: comma_delimited_list
default: "default"
resources:
port:
type: OS::Neutron::Port
properties:
network: {get_param: private_network}
security_groups: {get_param: security_groups}
instance:
type: OS::Nova::Server
properties:
name: {get_param: name}
flavor: {get_param: flavorname}
image: {get_param: image}
key_name: {get_param: key_name}
networks: [port: {get_resource: port}]
scheduler_hints:
group: {get_param: servergroup}
outputs:
internal_ip:
description: Internal IP of the host
value: {get_attr: [instance, first_address]}
server_id:
description: ID of instance
value: {get_attr: [instance, name]}
Example 2 : Security groups & Remote security groups
In this example :
- allow ping from anywhere (ipv4 and ipv6)
- allow ssh
tcp port 22
from IPs10.8.0.2
and2001:1600:10:100::7a
only - Allow tcp traffic from anywhere except
tcp port 22 ipv4 and ipv6
- Allow VMs using securityGroupRuleA only to SSH VMs using securityGroupRuleB
You need resources of type OS::Neutron::SecurityGroup
and OS::Neutron::SecurityGroupRule
Info
you can't mix IPv4 and IPv6 rules in the same security group Heat resource, you must create 2 different security groups like we did below : bastion_security_group_ipv4
and bastion_security_group_ipv6
Info
There are 2 syntaxes possible, one has been used for IPv4 and the other one for IPv6.
bastion_security_group.yaml
---
heat_template_version: 2015-04-30
resources:
# ---------------------------------- CLASSIC AND PREFIX SECURITY GROUP EXAMPLE -----------------------------
bastion_security_group_ipv4:
type: OS::Neutron::SecurityGroup
properties:
description: Security group for bastion
name: {list_join: ['-', [{get_param: OS::stack_name}, 'bastion-ipv4']]}
rules:
- protocol: "icmp"
direction: "ingress"
remote_ip_prefix: 0.0.0.0/0
- protocol: "tcp"
direction: "ingress"
remote_ip_prefix: 0.0.0.0/0
port_range_min: 1
port_range_max: 21
- protocol: "tcp"
direction: "ingress"
remote_ip_prefix: 10.8.0.0/32
port_range_min: 22
port_range_max: 22
- protocol: "tcp"
direction: "ingress"
remote_ip_prefix: 0.0.0.0/0
port_range_min: 23
port_range_max: 65535
bastion_security_group_ipv6:
type: OS::Neutron::SecurityGroup
properties:
description: Security group for bastion
name: {list_join: ['-', [{get_param: OS::stack_name}, 'bastion-ipv6']]}
rules:
- {"direction": ingress, "ethertype": IPv6, "protocol": icmpv6, "remote_ip_prefix": "::/0"}
- {"direction": ingress, "ethertype": IPv6, "port_range_min": 1, "port_range_max": 21, "protocol": tcp, "remote_ip_prefix": "::/0"}
- {"direction": ingress, "ethertype": IPv6, "port_range_min": 22, "port_range_max": 22, "protocol": tcp, "remote_ip_prefix": "2001:1600:10:100::7a/32"}
- {"direction": ingress, "ethertype": IPv6, "port_range_min": 23, "port_range_max": 65535, "protocol": tcp, "remote_ip_prefix": "::/0"}
# ---------------------------------- REMOTE SECURITY GROUP EXAMPLE ---------------------------------------
securityGroupA:
type: OS::Neutron::SecurityGroup
properties:
description: Security group allowing icmp from anywhere
name: "securityGroupA"
rules:
- {"direction": ingress, "ethertype": IPv4, "protocol": icmp, "remote_ip_prefix": "0.0.0.0/0"}
securityGroupB:
type: OS::Neutron::SecurityGroup
properties:
description: Security group where will be added a rule allowing tcp port 22 from VMs using securityGroupA only (securityGroupRuleB)
name: "securityGroupB"
securityGroupRuleB:
type: OS::Neutron::SecurityGroupRule
depends_on: securityGroupB
properties:
description: Security group allowing tcp port 22 from VMs using securityGroupA only
direction: ingress
ethertype: IPv4
port_range_min: 22
port_range_max: 22
protocol: tcp
remote_group: {get_resource: securityGroupA}
security_group: {get_resource: securityGroupB}
Apply and check rules have been created
openstack stack create -t bastion_security_group.yaml bastion_security_group
$ openstack security group rule list bastion_security_group-bastion-ipv4 --long
+--------------------------------------+-------------+-----------+-------------+------------+-----------+-----------------------+
| ID | IP Protocol | Ethertype | IP Range | Port Range | Direction | Remote Security Group |
+--------------------------------------+-------------+-----------+-------------+------------+-----------+-----------------------+
| 07b4e3ac-cd2e-4ad9-8ae4-633749e56397 | tcp | IPv4 | 0.0.0.0/0 | 23:65535 | ingress | None |
| 8bfdcb54-53d7-47aa-a9ae-e53998465b42 | None | IPv4 | 0.0.0.0/0 | | egress | None |
| 8c88e43d-356b-4ac2-839f-2d1841ee9733 | icmp | IPv4 | 0.0.0.0/0 | | ingress | None |
| ad73629e-9570-4182-aee0-a6e0a49242da | tcp | IPv4 | 0.0.0.0/0 | 1:21 | ingress | None |
| b05e111b-fc58-46ab-b374-ce1f1e81dd38 | tcp | IPv4 | 10.8.0.0/24 | 22:22 | ingress | None |
| c645c0da-f0fd-4aa4-ae5a-857ac51e2232 | None | IPv6 | ::/0 | | egress | None |
+--------------------------------------+-------------+-----------+-------------+------------+-----------+-----------------------+
$ openstack security group rule list bastion_security_group-bastion-ipv6 --long
+--------------------------------------+-------------+-----------+-------------------------+------------+-----------+-----------------------+
| ID | IP Protocol | Ethertype | IP Range | Port Range | Direction | Remote Security Group |
+--------------------------------------+-------------+-----------+-------------------------+------------+-----------+-----------------------+
| 04cdee6f-7469-426d-8df6-98736105a8c0 | tcp | IPv6 | ::/0 | 23:65535 | ingress | None |
| 2ac7f77e-7598-4864-84c3-a51c019ad9de | None | IPv6 | ::/0 | | egress | None |
| 3c00cdb8-8e4b-4184-ac8b-182df7b35c44 | ipv6-icmp | IPv6 | ::/0 | | ingress | None |
| 92255a66-53d4-428f-87ce-61df98580e99 | tcp | IPv6 | ::/0 | 1:21 | ingress | None |
| d5799100-b7e5-442e-a74b-7a72f99b22b4 | tcp | IPv6 | 2001:1600:10:100::7a/32 | 22:22 | ingress | None |
| dddf71fd-d570-451b-b4d7-850de9bc54e2 | None | IPv4 | 0.0.0.0/0 | | egress | None |
+--------------------------------------+-------------+-----------+-------------------------+------------+-----------+-----------------------+
$ openstack security group rule list securityGroupA
+--------------------------------------+-------------+-----------+-----------+------------+-----------------------+
| ID | IP Protocol | Ethertype | IP Range | Port Range | Remote Security Group |
+--------------------------------------+-------------+-----------+-----------+------------+-----------------------+
| 1e79830f-c1ca-4046-b2e3-b300f05ea7af | None | IPv4 | 0.0.0.0/0 | | None |
| d1c400d8-33ae-4d8e-bbcb-3e739e034e14 | icmp | IPv4 | 0.0.0.0/0 | | None |
| e82709ed-2307-4db8-9438-98b629623e0e | None | IPv6 | ::/0 | | None |
+--------------------------------------+-------------+-----------+-----------+------------+-----------------------+
$ openstack security group rule list securityGroupB
+--------------------------------------+-------------+-----------+-----------+------------+--------------------------------------+
| ID | IP Protocol | Ethertype | IP Range | Port Range | Remote Security Group |
+--------------------------------------+-------------+-----------+-----------+------------+--------------------------------------+
| 3981cc09-532b-49de-9c65-40f4107ffb55 | None | IPv6 | ::/0 | | None |
| 9c8f04a8-2779-4cde-9413-b4203c62955c | tcp | IPv4 | 0.0.0.0/0 | 22:22 | 4cfe556b-39d7-4cd5-8d59-42ccd654c6a7 |
| b4782f10-1738-4797-bc89-a3c43c488d2c | None | IPv4 | 0.0.0.0/0 | | None |
+--------------------------------------+-------------+-----------+-----------+------------+--------------------------------------+
To apply these security groups to a server add these lines to your instance resource definition, for example :
security_groups:
- {get_resource: bastion_security_group_ipv4 }
- {get_resource: bastion_security_group_ipv6 }