OpenStack private networks enable instances to be reached safely without being exposed to the public internet. Private networks are vital for internal services, database layers, or application layers.
In this post, we’re going to automate private networks and subnets creation using a Terraform module stored in a github repository.
Prerequisites
- Terraform installed
- OpenStack credentials and network access
- OpenStack provider properly configured
Step 1: Install Terraform
If you don’t have terraform installed, run one of the following commands that match your working environment:
# Ubuntu/Debian
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
# CentOS/RHEL
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install terraform
# Fedora
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager addrepo --from-repofile=https://rpm.releases.hashicorp.com/fedora/hashicorp.repo
sudo dnf -y install terraform
# Amazon Linux
sudo yum install -y yum-utils shadow-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
sudo yum -y install terraform
# macOS Homebrew
brew tap hashicorp/tap
brew install hashicorp/tap/terraform
Step 2: Configure Terraform Provider
To authenticate Terraform with OpenStack, define the provider as follows in your main.tf
file:
# Define required providers
terraform {
required_version = ">= 0.14.0"
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = "~> 2.1.0"
}
}
}
# Configure the OpenStack Provider
provider "openstack" {
user_name = "admin"
tenant_name = "admin"
password = "pwd"
auth_url = "http://myauthurl:5000/v3"
region = "RegionOne"
}
For a local statefile, you can configure it as follows:
terraform {
backend "local" {
path = "${path.module}/terraform.tfstate"
}
}
Step 3: The Network Module Overview
The netowork module uses resources such as the openstack_networking_network_v2
to create private networks and subnets. This module creates a private network, a private subnet, a router, and attaches the subnet to the private network.
It utilizes four main configuration files to achieve this:
data.tf
: Defines data sourcesmain.tf
: Contains resource definitionsoutputs.tf
: Declares input variablesvariables.tf
: Defines module outputs
The files are configured as follows:
data.tf
This file defines data sources to retrieve existing OpenStack resources, such as the external network:
# Data source to get the external network ID
data "openstack_networking_network_v2" "external_network" {
name = var.external_network_name
}
main.tf
This file contains the primary resource definitions for creating the network and subnet:
# Create a private network
resource "openstack_networking_network_v2" "private_network" {
name = var.network_name
admin_state_up = true
}
# Create a private subnet
resource "openstack_networking_subnet_v2" "private_subnet" {
name = var.subnet_name
network_id = openstack_networking_network_v2.private_network.id
cidr = var.subnet_cidr
ip_version = 4
dns_nameservers = var.dns_nameservers
}
# Create a router
resource "openstack_networking_router_v2" "router" {
name = "${var.network_name}-router"
admin_state_up = true
external_network_id = data.openstack_networking_network_v2.external_network.id
}
# Attach the private subnet to the router
resource "openstack_networking_router_interface_v2" "router_interface" {
router_id = openstack_networking_router_v2.router.id
subnet_id = openstack_networking_subnet_v2.private_subnet.id
}
variables.tf
This file declares the input variables required by the module:
variable "network_name" {
description = "The name of the private network"
type = string
}
variable "subnet_name" {
description = "The name of the private subnet"
type = string
}
variable "subnet_cidr" {
description = "The CIDR block of the private subnet"
type = string
}
variable "external_network_name" {
description = "The name of the external network"
type = string
}
variable "region" {
description = "The region in which to create the network resources"
type = string
default = "RegionOne"
}
variable "dns_nameservers" {
description = "List of DNS nameservers for the subnet"
type = list(string)
default = ["8.8.8.8", "8.8.4.4"]
}
outputs.tf
This file defines the outputs of the module, which can be used by other modules or resources:
variable "network_name" {
description = "The name of the private network"
type = string
}
variable "subnet_name" {
description = "The name of the private subnet"
type = string
}
variable "subnet_cidr" {
description = "The CIDR block of the private subnet"
type = string
}
variable "external_network_name" {
description = "The name of the external network"
type = string
}
variable "region" {
description = "The region in which to create the network resources"
type = string
default = "RegionOne"
}
variable "dns_nameservers" {
description = "List of DNS nameservers for the subnet"
type = list(string)
default = ["8.8.8.8", "8.8.4.4"]
}
Step 4: Using the Module
Configure your main.tf
file as follows:
module "network" {
source = "git::https://github.com/cloudspinx/terraform-openstack.git//modules/network?ref=main"
network_name = privatenet
subnet_name = privatenet_subnet
subnet_cidr = 172.34.50.0/24
external_network_name = public
region = RegionOne
dns_nameservers = ["8.8.8.8", "8.8.4.4"]
}
Run the following terraform commands to deploy the resources:
terraform init
terraform apply
The private network and subnet should be created on your OpenStack cloud.
Optional: Run the module locally
If you want to customize the module to match your needs, it’s best to clone the repo and run the module locally on your working environment:
git clone https://github.com/cloudspinx/terraform-openstack.git
Create a main.tf
file in the root folder for module usage configs.
terraform-openstack/
├── main.tf # Provider and module usage configs
├── modules # Modules, including kepair
│ ├── network/ # The module you're using
│ │ ├── data.tf
│ │ ├── main.tf # Define resouces
│ │ ├── variables.tf # Define any variables
│ │ ├── outputs.tf # Optional outputs
│ └── other_modules/
Be sure to reference the module path in your source. See below:
module "network" {
source = "./modules/network"
network_name = privatenet
subnet_name = privatenet_subnet
subnet_cidr = 172.34.50.0/24
external_network_name = public
region = RegionOne
dns_nameservers = ["8.8.8.8", "8.8.4.4"]
}
Run the following commands in your OpenStack environment to verify the resource creation:
openstack network list
openstack subnet list