Chuyển tới nội dung chính

Configure the OpenStack Provider

I. Initial setup & service authentication

terraform {
required_version = ">= 0.14.0"
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = "~> 1.53.0"
}
}
}

provider "openstack" {
user_name = "usera"
tenant_name = "project_name"
password = "pwd"
auth_url = <fptcloud identity endpoint>
region = "RegionOne"
}

# Create infratructures
resource "openstack_compute_instance_v2" "test-server" {
# ...
}
ParametersDescriptionEnvironment Variable
auth_urlURL of Identity ServiceOS_AUTH_URL
regionRegion of FPT cloudOS_REGION_NAME
user_nameUsername provided by FPT CloudOS_USERNAME
user_idOS_USER_ID
user_domain_nameOS_USER_DOMAIN_NAME
user_domain_idOS_USER_DOMAIN_ID
tenant_idOS_PROJECT_ID
tenant_nameVPC name provided by FPTCloudOS_PROJECT_NAME
project_domain_nameOS_PROJECT_DOMAIN_NAME
project_domain_idOS_PROJECT_DOMAIN_ID
domain_nameOS_DOMAIN_NAME
domain_idOS_DOMAIN_ID
insecureOS_INSECURE
interfaceOS_INTERFACE
...

II. Core components

A. Networking

1. Router

Copy   resource "openstack_networking_router_v2" "router_1" {
name = "my_router"
admin_state_up = true
external_network_id = "f67f0d72-0ddf-11e4-9d95-e1f29f417e2f"
}
ParametersDescriptionRequired
regionRegion of vRouter
nameName of vRouter
external_network_idID of external gateway, a router with an external gateway is required if any compute instances or load balancers will be using floating IPs.
...

2. Network

Copy    resource "openstack_networking_network_v2" "network_1" {
name = "network_1"
admin_state_up = "true"
}

resource "openstack_networking_subnet_v2" "subnet_1" {
name = "subnet_1"
network_id = openstack_networking_network_v2.network_1.id
cidr = "192.168.199.0/24"
ip_version = 4
}

resource "openstack_compute_secgroup_v2" "secgroup_1" {
name = "secgroup_1"
description = "a security group"

rule {
from_port = 22
to_port = 22
ip_protocol = "tcp"
cidr = "0.0.0.0/0"
}
}

resource "openstack_networking_port_v2" "port_1" {
name = "port_1"
network_id = openstack_networking_network_v2.network_1.id
admin_state_up = "true"
security_group_ids = [openstack_compute_secgroup_v2.secgroup_1.id]

fixed_ip {
subnet_id = openstack_networking_subnet_v2.subnet_1.id
ip_address = "192.168.199.10"
}
}

resource "openstack_compute_instance_v2" "instance_1" {
name = "instance_1"
security_groups = [openstack_compute_secgroup_v2.secgroup_1.name]

network {
port = openstack_networking_port_v2.port_1.id
}
}
ParametersDescriptionTypeDefaultRequired
nameName of network.stringYes
sharedSpecifies whether the network resource can be accessed by any tenant or not.boolfalseNo
...

3. Subnet

Copy   resource "openstack_networking_network_v2" "network_1" {
name = "tf_test_network"
admin_state_up = "true"
}

resource "openstack_networking_subnet_v2" "subnet_1" {
network_id = openstack_networking_network_v2.network_1.id
cidr = "192.168.199.0/24"
}
ParametersDescriptionTypeDefaultRequired
network_idID of network from previous step.stringYes
cidrCIDR representing IP range for this subnet, based on IP version.stringYes
ip_versionIP version of subnet.int4No
enable_dhcpEnable DHCP for subnet.booltrueNo
allocation_poolsIP pools of DHCP .listNo
gateway_ipDefault IP Gateway.stringNo
host_routesList of default static host routes.listNo
dns_nameserversList of DNS server of subnet.listNo
prefixlenPrefix length of subnet.intNo
...

4. Port

Copy    resource "openstack_networking_network_v2" "network_1" {
name = "network_1"
admin_state_up = "true"
}

resource "openstack_networking_port_v2" "port_1" {
name = "port_1"
network_id = openstack_networking_network_v2.network_1.id
admin_state_up = "true"
}
ParametersDescriptionTypeDefaultRequired
network_idID of network from previous step.stringYes
mac_addressFix MAC address for port.stringNo
namePort name.stringNo
fixed_ipsFixed IP for port.listNo
allowed_address_pairsAn IP/MAC Address pair of additional IP addresses that can be active on this port.listNo
security_group_idsA list of security group IDs to apply to the port.listNo
...

5. FloatingIP

Copy    resource "openstack_networking_floatingip_v2" "floatip_1" {
pool = "provider-net4"
}
ParametersDescriptionTypeDefaultRequired
poolThe name of the pool from which to obtain the floating IP. Changing this creates a new floating IP. E.g. provider-net4stringYes
port_idID of an existing port with at least one IP address to associate with this floating IP.stringNo
fixed_ipFixed IP of the port to associate with this floating IP.stringNo
descriptionHuman-readable description for the floating IP.stringNo
...

6. Security Group

Copy    resource "openstack_networking_secgroup_v2" "secgroup_1" {
name = "secgroup_1"
description = "My neutron security group"
}
ParametersDescriptionTypeDefaultRequired
nameA unique name for the security group.stringYes
descriptionHuman-readable description for the security group.stringNo
tenant_idThe owner of the security group. Required if admin wants to create a port for another tenant.stringNo
...

7. Security Group Rule

Copy    resource "openstack_networking_secgroup_v2" "secgroup_1" {
name = "secgroup_1"
description = "My neutron security group"
}

resource "openstack_networking_secgroup_rule_v2" "secgroup_rule_1" {
direction = "ingress"
ethertype = "IPv4"
protocol = "tcp"
port_range_min = 22
port_range_max = 22
remote_ip_prefix = "0.0.0.0/0"
security_group_id = openstack_networking_secgroup_v2.secgroup_1.id
}
ParametersDescriptionTypeDefaultRequired
security_group_idThe security group id the rule should belong to, the value needs to be an Openstack ID of a security group in the same tenant.stringYes
directioningress or egress.stringYes
ethertypeLayer 3 protocol type (IPv4 , IPv6).stringYes
protocolLayer 4 protocol type (tcp, udp, icmp, ...).stringYes
remote_ip_prefixremote CIDRstringNo
remote_group_idThe remote group id, the value needs to be an Openstack ID of a security group in the same tenant.stringNo
port_range_minintNo
port_range_maxintNo
descriptionA description of the rule.stringNo
...

B. Storage

1. Volume

Copy    resource "openstack_blockstorage_volume_v3" "volume_1" {
region = "RegionOne"
name = "volume_1"
description = "first test volume"
volume_type = "PremiumSSD-2000_floor5"
availability_zone = "floor5"
size = 40
}
ParametersDescriptionTypeDefaultRequired
sizeThe size of the volume to create (in gigabytes).intYes
nameA unique name for the volume.stringNo
descriptionA description of the volume.stringNo
availability_zoneThe availability zone for the volume.stringNo
image_idThe image ID from which to create the volume.stringNo
volume_typeThe type of volume to create.stringNo
...

C. Compute

1. Instance

Copyresource "openstack_blockstorage_volume_v3" "myvol" {
name = "myvol"
size = 40
volume_type = "PremiumSSD-2000_floor5"
availability_zone = "floor5"
}

resource "openstack_compute_instance_v2" "myinstance" {
name = "myinstance"
image_name = "UBUNTU-20.04-10072023"
flavor_name = "Small.2"
key_pair = "my_key_pair_name"
security_groups = ["default"]
availability_zone = "floor5"

network {
name = "my_network"
}
}

resource "openstack_compute_volume_attach_v2" "attached" {
instance_id = openstack_compute_instance_v2.myinstance.id
volume_id = openstack_blockstorage_volume_v3.myvol.id
}
ParametersDescriptionTypeDefaultRequired
nameA unique name for the resource.stringYes
flavor_nameThe name of the desired flavor for the server.stringYes
image_nameThe name of the desired image for the server.stringYes
key_pairThe name of a key pair to put on the server.stringNo
user_datacloud-init script, the user data to provide when launching the instance.stringNo
metadatamapNo
security_groupsAn array of one or more security group names to associate with the server.listNo
networkAn array of one or more networks to attach to the instance.stringNo
block_deviceConfiguration of block devices.listNo
availability_zoneThe availability zone in which to create the server.stringNo
...

III. Example

This section focus on show up the actual use case of FPT Cloud Iac by using terraform to deploy new Web Application on FPT Cloud, the step described as the following:

  • Setting up terraform
  • Create new project directory include main.tf file with the following content:
Copyterraform {
required_version = ">= 0.14.0"
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = "~> 1.53.0"
}
}
}

# Configure the OpenStack Provider
provider "openstack" {
user_name = <user-name>
tenant_id = <project-uuid>
user_domain_name = <domain-name>
password = <password>
auth_url = <fptcloud identity endpoint>
region = "RegionOne"
}

# Network
data "openstack_networking_network_v2" "provider_net" {
name = "provider-net5"
}

resource "openstack_networking_router_v2" "webapp_router" {
name = "webapp_router"
admin_state_up = true
external_network_id = data.openstack_networking_network_v2.provider_net.id
}

resource "openstack_networking_network_v2" "webapp_network" {
name = "webapp_network"
admin_state_up = true
}

resource "openstack_networking_subnet_v2" "webapp_subnet" {
name = "webapp_subnet"
network_id = openstack_networking_network_v2.webapp_network.id
cidr = "10.0.0.0/24"
ip_version = 4
dns_nameservers = ["1.1.1.1"]
}

resource "openstack_networking_router_interface_v2" "webapp_router_interface" {
router_id = openstack_networking_router_v2.webapp_router.id
subnet_id = openstack_networking_subnet_v2.webapp_subnet.id
}

resource "openstack_compute_secgroup_v2" "webapp_secgroup" {
name = "webapp_secgroup"
description = "Allow web traffic"
rule {
from_port = 80
to_port = 80
ip_protocol = "tcp"
cidr = "0.0.0.0/0"
}
rule {
from_port = 22
to_port = 22
ip_protocol = "tcp"
cidr = "0.0.0.0/0"
}
}

resource "openstack_compute_floatingip_v2" "webapp_floatingip" {
pool = "provider-net5"
}

# Volume
data "openstack_images_image_v2" "ubuntu_image" {
name = "UBUNTU-22.04-10072023"
}

resource "openstack_blockstorage_volume_v3" "webapp_volume" {
name = "webapp_volume"
description = "Volume for webapp"
size = 40
volume_type = "Premium-SSD_floor5"
image_id = data.openstack_images_image_v2.ubuntu_image.id
}

# Instance
data "openstack_compute_keypair_v2" "webapp_key" {
name = "webapp_key"
}

data "openstack_compute_flavor_v2" "s2_medium_1" {
name = "2C2G"
}

/* Userdata
#cloud-config
package_update: true
chpasswd:
list: | root:<password-vm>
packages:
- nginx - gitruncmd:
- systemctl enable nginx
- systemctl start nginx
- git clone https://github.com/cloudacademy/static-website-example.git
- cp -r ./static-website-example/* /var/www/html/
- rm -r ./static-website-example*/

resource "openstack_compute_instance_v2" "webapp_instance" {
name = "webapp_instance"
image_id = data.openstack_images_image_v2.ubuntu_image.id
flavor_id = data.openstack_compute_flavor_v2.s2_medium_1.id
key_pair = data.openstack_compute_keypair_v2.webapp_key.name
security_groups = [openstack_compute_secgroup_v2.webapp_secgroup.name]
availability_zone = "floor5"

user_data = "#cloud-config\npackage_update: true\nchpasswd:\n list: |\n root:Welcome***123\npackages:\n - nginx\n - git\nruncmd:\n - systemctl enable nginx\n - systemctl start nginx\n - git clone https://github.com/cloudacademy/static-website-example.git\n - cp -r ./static-website-example/* /var/www/html/\n - rm -r ./static-website-example"
network {
name = openstack_networking_network_v2.webapp_network.name
}
block_device {
uuid = openstack_blockstorage_volume_v3.webapp_volume.id
source_type = "volume"
destination_type = "volume"
boot_index = 0
delete_on_termination = true
}
}

resource "openstack_compute_floatingip_associate_v2" "webapp_floatingip_associate" {
floating_ip = openstack_compute_floatingip_v2.webapp_floatingip.address
instance_id = openstack_compute_instance_v2.webapp_instance.id
}

output "webapp_public_ip" {
value = openstack_compute_floatingip_v2.webapp_floatingip.address
description = "Web Application URL"
}

output "webapp_private_ip" {
value = openstack_compute_instance_v2.webapp_instance.access_ip_v4
description = "Web Application Private IP"
}
  • Deploying application
Copyterraform init
terraform apply --auto-approve
  • The result of terraform CLI: file
  • Acces the floating IP and enjoy the result of webapp file
  • Cleaning-up the whole resources created by IaC stack:
Copyterraform destroy --auto-approve

References