Source Openrc / Login #
# CD into "stack" home directory
cd ~/devstack
# Verify the openrc file
ls *openrc*
# Loads the environment variables set in openrc into current shell: Admin user & project
source openrc admin admin
SSH Key #
I’m using the following SSH key for all the Heat manifest examples in this blog post.
Create SSH Key #
# Create SSH key
openstack keypair create key_vm-1> id_rsa_vm-1
# Change permissions
chmod 600 id_rsa_vm-1
Verify the SSH Key #
# Verify the key
openstack keypair list
# Shell output:
+----------+-------------------------------------------------+------+
| Name | Fingerprint | Type |
+----------+-------------------------------------------------+------+
| key_vm-1 | 20:f3:61:fb:9e:b9:e8:85:93:4f:e2:8f:46:4f:b5:57 | ssh |
+----------+-------------------------------------------------+------+
Network #
I’m using the following network for all the Heat manifest examples in this blog post.
Create Network & Subnet: CLI Version #
# Create a new network "jkw_net-01"
openstack network create jkw_net-01
# Create a new subnet for the network "jkw_net-01"
openstack subnet create --network jkw_net-01 --subnet-range 10.8.5.0/24 \
--allocation-pool start=10.8.5.11,end=10.8.5.254 --dns-nameserver 1.1.1.1 \
--gateway 10.8.5.1 jkw_subnet-01
Create Network & Subnet: Heat Version #
# Create Heat manifest configuration
vi network_setup.yaml
heat_template_version: 2016-10-14
description: Create network & subnet
resources:
jkw_net_01:
type: OS::Neutron::Net
properties:
name: jkw_net-01
jkw_subnet_01:
type: OS::Neutron::Subnet
properties:
name: jkw_subnet-01
network_id: { get_resource: jkw_net_01 }
cidr: 10.8.5.0/24
gateway_ip: 10.8.5.1
dns_nameservers:
- 1.1.1.1
- 8.8.8.8
allocation_pools:
- start: 10.8.5.200
end: 10.8.5.254
# Deploy the networking resources
openstack stack create -t network_setup.yaml centos-network
Find External Network #
# List networks: Copy public / external networkID
openstack network list --long -c ID -c Name -c "Router Type" -c Subnets -f table
# Shell output:
+--------------------------------------+----------+----------------------------------------------------------------------------+-------------+
| ID | Name | Subnets | Router Type |
+--------------------------------------+----------+----------------------------------------------------------------------------+-------------+
| 2055b2ed-3f65-4174-b208-45bcf55cdafc | private | 300c9671-793f-4f8c-9ff5-bc27e43f64ee, 68c5d11c-27ef-4076-ae2c-9f875e67232e | Internal |
| 26911f76-db56-4aee-91a8-a17fb38204de | shared | ef937ded-002a-41c4-b65f-dce94ed24a6b | Internal |
| 5e12176f-a048-460f-83cf-d2b9cd395b10 | jkw_net | 54e303b7-f665-4b24-92b1-4d306676e3b9 | Internal |
| b7c160e7-f189-4a8d-998b-860ea5e47a64 | heat-net | 6be302d4-6c25-470a-a86f-bc84973891ba | Internal |
| c68d5a39-e0bb-426d-8442-ffc60c1d2623 | public | 6e8dfa7e-e901-43b3-8ab9-f8b8090e1715, e9108251-e10e-444f-90af-92edd4559181 | External |
+--------------------------------------+----------+----------------------------------------------------------------------------+-------------+
Create Network Router #
This step is neccessary to add a floating IP the to network port.
# Create a router
openstack router create jkw_router-01
# Set the router gateway to the external network: Define external network ID
openstack router set jkw_router-01 --external-gateway c68d5a39-e0bb-426d-8442-ffc60c1d2623
# Add the internal network subnet to the router
openstack router add subnet jkw_router-01 jkw_subnet-01
Delete Network Resources #
Delete the router:
# Remove the Gateway from the Router
openstack router unset --external-gateway jkw_router-01
# Remove the Subnet Interface from the Router
openstack router remove subnet jkw_router-01 jkw_subnet-01
# Delete the Router
openstack router delete jkw_router-01
Delete the network: Heat version
# Delete the networking resources
openstack stack delete --yes centos-network
Delete the network: Manual version
# Delete the Subnet
openstack subnet delete jkw_subnet-01
# Delete the Network
openstack network delete jkw_net-01
CentOS Cloud Image #
I’m using the following Image for all the Heat manifest examples in this blog post.
Download Cloud Image #
# Download the CentOS Stream cloud image
curl -O https://cloud.centos.org/centos/9-stream/x86_64/images/CentOS-Stream-GenericCloud-x86_64-9-latest.x86_64.qcow2
Upload Image to OpenStack #
# Upload the ISO file to OpenStack
openstack image create \
--container-format bare \
--disk-format qcow2 \
--property hw_disk_bus=scsi \
--property hw_scsi_model=virtio-scsi \
--property os_type=linux \
--property os_distro=rhel \
--property os_admin_user=root \
--public \
--file CentOS-Stream-GenericCloud-x86_64-9-latest.x86_64.qcow2 \
CentOS-Cloud
Heat Manifest Examples #
Create Heat Manifest #
Single VM CentOS Stack
# Create manifest configuration
vi centos-stack.yaml
heat_template_version: 2013-05-23
description: CentOS VM Deployment
resources:
vm_instance-1:
type: OS::Nova::Server
properties:
name: "centos-vm1"
image: "CentOS-Cloud"
flavor: m1.small
key_name: "key_vm-1"
networks:
- network: "jkw_net-01"
security_groups:
- { get_resource: vm_security-group }
user_data_format: RAW
user_data:
get_resource: server_init
tags: ["centos-stack"]
vm_security-group:
type: OS::Neutron::SecurityGroup
properties:
name: "centos-security-group"
description: "Allow SSH and Ping"
rules:
- protocol: tcp
port_range_min: 22
port_range_max: 22
remote_ip_prefix: 0.0.0.0/0
- protocol: icmp
remote_ip_prefix: 0.0.0.0/0
server_init:
type: OS::Heat::MultipartMime
properties:
parts:
- config: {get_resource: one_init}
one_init:
type: OS::Heat::CloudConfig
properties:
cloud_config:
package_update: true
package_upgrade: true
packages:
- httpd
Multi VM RedHat Stack: Define Each VM
# Create manifest configuration
vi centos-stack.yaml
heat_template_version: 2013-05-23
description: CentOS VM Deployment
resources:
vm_instance-1:
type: OS::Nova::Server
properties:
name: "centos-vm1"
image: "CentOS-Cloud"
flavor: m1.small
key_name: "key_vm-1"
networks:
- network: "jkw_net-01"
security_groups:
- { get_resource: vm_security-group }
user_data_format: RAW
user_data:
get_resource: server_init
tags: ["centos-stack"]
vm_instance-2:
type: OS::Nova::Server
properties:
name: "centos-vm2"
image: "CentOS-Cloud"
flavor: m1.small
key_name: "key_vm-1"
networks:
- network: "jkw_net-01"
security_groups:
- { get_resource: vm_security-group }
user_data_format: RAW
user_data:
get_resource: server_init
tags: ["centos-stack"]
vm_instance-3:
type: OS::Nova::Server
properties:
name: "centos-vm3"
image: "CentOS-Cloud"
flavor: m1.small
key_name: "key_vm-1"
networks:
- network: "jkw_net-01"
security_groups:
- { get_resource: vm_security-group }
user_data_format: RAW
user_data:
get_resource: server_init
tags: ["centos-stack"]
vm_security-group:
type: OS::Neutron::SecurityGroup
properties:
name: "centos-security-group"
description: "Allow SSH and Ping"
rules:
- protocol: tcp
port_range_min: 22
port_range_max: 22
remote_ip_prefix: 0.0.0.0/0
- protocol: icmp
remote_ip_prefix: 0.0.0.0/0
server_init:
type: OS::Heat::MultipartMime
properties:
parts:
- config: {get_resource: one_init}
one_init:
type: OS::Heat::CloudConfig
properties:
cloud_config:
package_update: true
package_upgrade: true
packages:
- httpd
Multi VM RedHat Stack: Define VMs Via Resource Group
# Create manifest configuration
vi centos-stack.yaml
heat_template_version: 2013-05-23
description: CentOS VM Deployment
resources:
vm_instance_group:
type: OS::Heat::ResourceGroup
properties:
count: 3 # Number of instances
resource_def:
type: OS::Nova::Server
properties:
name: "%index%-centos-vm"
image: "CentOS-Cloud"
flavor: "m1.small"
key_name: "key_vm-1"
networks:
- network: "jkw_net-01"
security_groups:
- { get_resource: vm_security-group }
user_data_format: RAW
user_data:
get_resource: server_init
tags: ["centos-stack"]
vm_security-group:
type: OS::Neutron::SecurityGroup
properties:
name: "centos-security-group"
description: "Allow SSH and Ping"
rules:
- protocol: tcp
port_range_min: 22
port_range_max: 22
remote_ip_prefix: 0.0.0.0/0
- protocol: icmp
remote_ip_prefix: 0.0.0.0/0
server_init:
type: OS::Heat::MultipartMime
properties:
parts:
- config: {get_resource: one_init}
one_init:
type: OS::Heat::CloudConfig
properties:
cloud_config:
package_update: true
package_upgrade: true
packages:
- httpd
-
"%index%-rhel-vm"
The Heat variable auto-increments for each instance name:0-rhel-vm
,1-rhel-vm
, … -
count
Define the number of VMs
Deploy the Heat Manifest #
# Deploy the manifest: Stack name "centos-stack"
openstack stack create -t centos-stack.yaml centos-stack
Verify the VM Deployment #
# List the VMs via it's tags
openstack server list --tags centos-stack
Single VM CentOS Stack
# Shell output:
+--------------------------------------+------------+--------+-----------------------+--------------+----------+
| ID | Name | Status | Networks | Image | Flavor |
+--------------------------------------+------------+--------+-----------------------+--------------+----------+
| a45e70b2-c368-45c7-a6c0-3c3a53e7d2a3 | centos-vm1 | ACTIVE | jkw_net-01=10.8.5.240 | CentOS-Cloud | m1.small |
+--------------------------------------+------------+--------+-----------------------+--------------+----------+
Multi VM CentOS Stack: Define Each VM
# Shell output:
+--------------------------------------+------------+--------+-----------------------+--------------+----------+
| ID | Name | Status | Networks | Image | Flavor |
+--------------------------------------+------------+--------+-----------------------+--------------+----------+
| 12505464-134c-4fa6-bc95-e161f181b487 | centos-vm1 | ACTIVE | jkw_net-01=10.8.5.231 | CentOS-Cloud | m1.small |
| 43294664-9fe3-4c82-81e7-17e3349610b0 | centos-vm3 | ACTIVE | jkw_net-01=10.8.5.239 | CentOS-Cloud | m1.small |
| a95f8b92-24f4-4ebc-8eae-beae9a99441f | centos-vm2 | ACTIVE | jkw_net-01=10.8.5.234 | CentOS-Cloud | m1.small |
+--------------------------------------+------------+--------+-----------------------+--------------+----------+
Multi VM CentOS Stack: Define VM Via Resource Group
# Shell output:
+--------------------------------------+-------------+--------+-----------------------+--------------+----------+
| ID | Name | Status | Networks | Image | Flavor |
+--------------------------------------+-------------+--------+-----------------------+--------------+----------+
| 6610fddb-5a02-457f-9e07-82d87b3a58d8 | 2-centos-vm | ACTIVE | jkw_net-01=10.8.5.248 | CentOS-Cloud | m1.small |
| 3287c0ad-213d-469c-acc9-f73a0c9ffd0a | 0-centos-vm | ACTIVE | jkw_net-01=10.8.5.239 | CentOS-Cloud | m1.small |
| 3fb622f9-636b-4152-b323-a3eec53f211b | 1-centos-vm | ACTIVE | jkw_net-01=10.8.5.242 | CentOS-Cloud | m1.small |
+--------------------------------------+-------------+--------+-----------------------+--------------+----------+
Assign Floating IP with Script #
Use the following script to assign a floating IP to the vm rhel-vm1
:
# Create a file for the script
vi floating-ip.sh
# Change permission
chmod +x floating-ip.sh
#!/bin/bash
# Set VM name
VM_NAME="centos-vm1"
# Set network name
NETWORK_NAME="public"
# Get VM ID
VM_ID=$(openstack server list --name $VM_NAME -f value -c ID)
# Get port ID
PORT_ID=$(openstack port list --device-id $VM_ID -f value -c ID)
# Create floating IP and assign it to the VM
FLOATING_IP=$(openstack floating ip create $NETWORK_NAME -f value -c floating_ip_address --port $PORT_ID)
echo "Floating IP $FLOATING_IP has been assigned to VM $VM_NAME"
# Assign floating IP
./floating-ip.sh
# Shell output:
Floating IP 192.168.30.247 has been assigned to VM centos-vm1
Access the VM #
# SSH into VM
ssh -i id_rsa_vm-1 cloud-user@192.168.30.247
Verify the cloud-init script has run:
# Switch to root user
sudo su
# Check cloud-init logs: grep for httpd
grep -C 1 "httpd" /var/log/cloud-init.log
# Remove the host key if necessary (useful in playground scenarios)
ssh-keygen -f "/opt/stack/.ssh/known_hosts" -R "192.168.30.246"
Delete the Stack #
# Delete the Deployment
openstack stack delete --yes centos-stack
Cloud Image Examples #
CirrOS #
CirrOS is a minimal Linux distribution that is included by default with DevStack. It’s great for testing and debugging.
Heat Manifest #
CirrOS Deployment: Default Security Group
# Create manifest configuration
vi heat-cirros-vm.yaml
heat_template_version: 2013-05-23
description: CirrOS VM Deployment
resources:
vm_instance-1:
type: OS::Nova::Server
properties:
name: "cirros-vm1"
image: "cirros-0.6.2-x86_64-disk"
flavor: m1.tiny
key_name: "key_vm-1"
networks:
- network: "jkw_net-01"
security_groups:
- default
tags: ["cirros-stack"]
CirrOS Deployment: Dedicated Security Group
# Create manifest configuration
vi heat-cirros-vm.yaml
heat_template_version: 2013-05-23
description: CirrOS VM Deployment
resources:
vm_security-group-1:
type: OS::Neutron::SecurityGroup
properties:
name: "vm-security-group"
description: "Allow SSH and Ping"
rules:
- protocol: tcp
port_range_min: 22
port_range_max: 22
remote_ip_prefix: 0.0.0.0/0
- protocol: icmp
remote_ip_prefix: 0.0.0.0/0
vm_instance-1:
type: OS::Nova::Server
properties:
name: "cirros-vm1"
image: "cirros-0.6.2-x86_64-disk"
flavor: m1.tiny
key_name: "key_vm-1"
networks:
- network: "jkw_net-01"
security_groups:
- { get_resource: vm_security-group-1 }
tags: ["cirros-stack"]
Deploy, Update the Stack #
# Deploy the manifest: Stack name "cirros-stack"
openstack stack create -t heat-cirros-vm.yaml cirros-stack
# Update the sack
openstack stack update -t heat-cirros-vm.yaml cirros-stack
Verify the VM Deployment #
# List VM details
openstack server list --name cirros-vm1
# Shell output:
+--------------------------------------+------------+--------+-----------------------+--------------------------+---------+
| ID | Name | Status | Networks | Image | Flavor |
+--------------------------------------+------------+--------+-----------------------+--------------------------+---------+
| 169b3f85-9f2e-4a8e-9bfe-b9edd8c0d297 | cirros-vm1 | ACTIVE | jkw_net-01=10.8.5.230 | cirros-0.6.2-x86_64-disk | m1.tiny |
+--------------------------------------+------------+--------+-----------------------+--------------------------+---------+
Delete the Stack #
# Delete the deployment / stack
openstack stack delete --yes cirros-stack
Ubuntu Cloud Image #
Download Image #
# Download Ubuntu 22 cloud image
curl -O https://cloud-images.ubuntu.com/releases/jammy/release/ubuntu-22.04-server-cloudimg-amd64.img
Upload Image to OpenStack #
# Upload the ISO file to OpenStack
openstack image create \
--container-format bare \
--disk-format qcow2 \
--property hw_disk_bus=scsi \
--property hw_scsi_model=virtio-scsi \
--property os_type=linux \
--property os_distro=ubuntu \
--property os_admin_user=ubuntu \
--public \
--file ubuntu-22.04-server-cloudimg-amd64.img \
ubuntu-22-cloud
Heat Manifest #
# Create manifest configuration
vi heat-ubuntu-vm.yaml
heat_template_version: 2013-05-23
description: Ubuntu VM Deployment
resources:
vm_security-group-1:
type: OS::Neutron::SecurityGroup
properties:
name: "vm-security-group"
description: "Allow SSH and Ping"
rules:
- protocol: tcp
port_range_min: 22
port_range_max: 22
remote_ip_prefix: 0.0.0.0/0
- protocol: icmp
remote_ip_prefix: 0.0.0.0/0
vm_instance-1:
type: OS::Nova::Server
properties:
name: "ubuntu-vm1"
image: "ubuntu-22-cloud"
flavor: m1.small
key_name: "key_vm-1"
networks:
- network: "jkw_net-01"
security_groups:
- { get_resource: vm_security-group-1 }
user_data_format: RAW
user_data:
get_resource: server_init
Deploy Stack #
# Deploy the manifest: Stack name "ubuntu-stack"
openstack stack create -t heat-ubuntu-vm.yaml ubuntu-stack
Verify the VM Deployment #
# List VM details: Wait till Status jumps to "ACTIVE"
openstack server list --name ubuntu-vm1
Delete the Stack #
# Delete the Deployment
openstack stack delete --yes ubuntu-stack
RedHat Cloud image #
Download Image #
Download the Image from the RedHat website:
https://access.redhat.com/downloads/content/rhel
Upload Image to OpenStack #
# Upload the ISO file to OpenStack
openstack image create \
--container-format bare \
--disk-format qcow2 \
--property hw_disk_bus=scsi \
--property hw_scsi_model=virtio-scsi \
--property os_type=linux \
--property os_distro=rhel \
--property os_admin_user=root \
--public \
--file rhel-9.4-x86_64-kvm.qcow2 \
rhel-9.4-cloud
Heat Manifest #
# Create manifest configuration
vi heat-redhat-stack.yaml
heat_template_version: 2013-05-23
description: RHEL VM Deployment
resources:
vm_instance-1:
type: OS::Nova::Server
properties:
name: "rhel-vm1"
image: "rhel-9.4-cloud"
flavor: m1.small
key_name: "key_vm-1"
networks:
- network: "jkw_net-01"
security_groups:
- { get_resource: vm_security-group }
user_data_format: RAW
user_data:
get_resource: server_init
tags: ["rhel-stack"]
vm_security-group:
type: OS::Neutron::SecurityGroup
properties:
name: "rhel-security-group"
description: "Allow SSH and Ping"
rules:
- protocol: tcp
port_range_min: 22
port_range_max: 22
remote_ip_prefix: 0.0.0.0/0
- protocol: icmp
remote_ip_prefix: 0.0.0.0/0
Deploy Stack #
# Deploy the manifest: Stack name "redhat-stack"
openstack stack create -t heat-redhat-stack.yaml redhat-stack
Verify the VM Deployment #
# List the VMs via it's tags
openstack server list --tags rhel-stack
Delete the Stack #
# Delete the Deployment
openstack stack delete --yes redhat-stack