Provisioning Instance OpenStack with Public Access Using Terraform
You should see related content below to comply with some requirements before executing terraform,
Provisioning Basic Instance with Terraform
Requirements:
- Endpoint keystone overcloud
- Access user to OpenStack environment
- Terraform project
- OpenStack user role as admin
- Terraform CLI (1.2.0+) installed
- OpenStack Client installed
- OpenStack image
Provide Requirements on the OpenStack side:
Create RC file if needed to verify OpenStack resource from CLI
cat <<EOF> /home/stack/terraform-rc
for key in $( set | awk '{FS="="} /^OS_/ {print $1}' ); do unset $key ; done
export NOVA_VERSION=1.1
export COMPUTE_API_VERSION=1.1
export OS_USERNAME=XXXXX
export OS_PROJECT_NAME=XXXXXX
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_DOMAIN_NAME=Default
export OS_NO_CACHE=True
export OS_CLOUDNAME=terraform
export no_proxy=,10.1.1.100,192.168.240.50
export PYTHONWARNINGS='ignore:Certificate has no, ignore:A true SSLContext object is not available'
export OS_AUTH_TYPE=password
export OS_PASSWORD='XXXXXXXX'
export OS_AUTH_URL=http://192.168.240.50:5000
export OS_IDENTITY_API_VERSION=3
export OS_COMPUTE_API_VERSION=2.latest
export OS_IMAGE_API_VERSION=2
export OS_VOLUME_API_VERSION=3
export OS_REGION_NAME=regionOne# Add OS_CLOUDNAME to PS1
if [ -z "${CLOUDPROMPT_ENABLED:-}" ]; then
export PS1=${PS1:-""}
export PS1=\${OS_CLOUDNAME:+"(\$OS_CLOUDNAME)"}\ $PS1
export CLOUDPROMPT_ENABLED=1
fi
Create a project, user and assign role as admin. This will use by Terraform to create resources.
source ~/terraform-rc
openstack project create --description 'terraform project' terraform
openstack user create --project terraform --password PASSWORD terra
openstack role add --project terraform --user terra admin
Create OpenStack Provider
The OpenStack provider is used to interact with the many resources supported by OpenStack. The provider needs to be configured with the proper credentials before it can be used. Let’s follow this example:
Create a new directory and go into it
mkdir terraform
cd terraform
Create OpenStack provider configuration
#Create provider.tf
cat <<EOF> /home/stack/terraform/provider.tf
terraform {
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = "1.47.0"
}
}
}
# Configure the OpenStack Provider credensial
provider "openstack" {
user_name = "terra"
tenant_name = "terraform"
password = "PASSWORD"
auth_url = "http://192.168.240.50:5000"
region = "regionOne"
}
EOF
When you create a new configuration or check out an existing configuration from version control you need to initialize the directory with terraform init
.
Initializing a configuration directory downloads and installs the providers defined in the configuration, which in this case is the OpenStack provider.
terraform init
Write Configuration
The set of files used to describe infrastructure in Terraform is known as a Terraform configuration. You will write your first configuration to define a single OpenStack instance without public access.
Create main.tf
file, then write configuration to create flavor, volume, keypair and security group.
resource "openstack_compute_flavor_v2" "tf_flavor1" {
name = "tf-flavor"
ram = "512"
vcpus = "1"
disk = "0"
is_public = true
}resource "openstack_blockstorage_volume_v2" "tf-vol1" {
name = "myvol"
size = 5
}resource "openstack_compute_keypair_v2" "tf-keypair" {
name = "terra-keypair"
}resource "openstack_compute_secgroup_v2" "tf-secgroup1" {
name = "tf-secgroup"
description = "a security group by terraform"rule {
from_port = 22
to_port = 22
ip_protocol = "tcp"
cidr = "0.0.0.0/0"
}
}
Stay insidemain.tf
continues to create resources that relate public-net, public-subnet, private-net, private-subnet, router and attach the interface of both networks to the router.
###....Still in main.tf
resource "openstack_networking_network_v2" "tf-publicnet" {
name = "public"
segments {
network_type = "flat"
physical_network = "datacentre"
}
shared = "true"
admin_state_up = "true"
external = "true"
}resource "openstack_networking_subnet_v2" "tf-publicsubnet" {
name = "public-sub"
network_id = "${openstack_networking_network_v2.tf-publicnet.id}"
cidr = "192.168.240.0/24"
ip_version = 4
enable_dhcp = "true"
gateway_ip = "192.168.240.250"
allocation_pool {
end = "192.168.240.100"
start = "192.168.240.60"
}
dns_nameservers = ["192.168.240.250","8.8.8.8"]
}resource "openstack_networking_network_v2" "tf-network1" {
name = "tf-net"
admin_state_up = "true"
}resource "openstack_networking_subnet_v2" "tf-subnet1" {
name = "tf-subnet"
network_id = "${openstack_networking_network_v2.tf-network1.id}"
cidr = "10.20.20.0/24"
ip_version = 4
}resource "openstack_networking_router_v2" "tf-router" {
name = "terra-router"
admin_state_up = true
external_network_id = "${openstack_networking_network_v2.tf-publicnet.id}"
}resource "openstack_networking_router_interface_v2" "tf-router_interface" {
router_id = "${openstack_networking_router_v2.tf-router.id}"
subnet_id = "${openstack_networking_subnet_v2.tf-subnet1.id}"
}
Keep insidemain.tf
next create resources that relate floating ip, launch an instance, attach volume and floating ip to the instance. Save the configuration in one file main.tf
###....Still in main.tf
resource "openstack_networking_floatingip_v2" "tf-fip1" {
pool = "${openstack_networking_network_v2.tf-publicnet.name}"
depends_on = [openstack_networking_subnet_v2.tf-subnet1]
}resource "openstack_compute_instance_v2" "tf-vm1" {
name = "tf-vm"
image_name = "ubuntu20"
flavor_id = "${openstack_compute_flavor_v2.tf_flavor1.id}"
key_pair = "${openstack_compute_keypair_v2.tf-keypair.name}"
security_groups = ["${openstack_compute_secgroup_v2.tf-secgroup1.name}"]
network {
name = "${openstack_networking_network_v2.tf-network1.name}"
}
user_data = file("user_data.yaml")
}resource "openstack_compute_volume_attach_v2" "attached" {
instance_id = "${openstack_compute_instance_v2.tf-vm1.id}"
volume_id = "${openstack_blockstorage_volume_v2.tf-vol1.id}"
}resource "openstack_compute_floatingip_associate_v2" "tf-fip1" {
floating_ip = "${openstack_networking_floatingip_v2.tf-fip1.address}"
instance_id = "${openstack_compute_instance_v2.tf-vm1.id}"
}
Create user_data.yaml
file to inject password via cloud-init.
cat <<EOF> /home/stack/terraform/user_data.yaml
#cloud-config
ssh_pwauth: True
chpasswd:
list: |
root:root
ubuntu:ubuntu
expire: False
EOF
Create Infrastructure
Apply the configuration now with the terraform apply
command. Terraform will print output similar to what is shown below. We have truncated some of the output to save space.
Before it applies any changes, Terraform prints out the execution plan which describes the actions Terraform will take in order to change your infrastructure to match the configuration. In this case, the plan is acceptable so type yes
at the confirmation prompt to proceed. Executing the plan will take a few minutes since Terraform waits for the OpenStack instance to become available.
You have now created infrastructure using Terraform!!!
Inspect the current state using terraform show
.
terraform show
Verify Resources
Verify resources on OpenStack that have already been created with Terraform
terraform output#Notice floating ip
ssh ubuntu@<FLOATING_IP>
Now, check resources via Horizon Dashboard.
1. Instance
2. Volume
3. Network Topology
4. Router
5. Network
6. Floating IP
7. Security Group
8. Key pair
References :
- https://github.com/terraform-provider-openstack/terraform-provider-openstack
- https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs
#RHEL #Terraform #OpenStack #IaC #Hashicorp