OpenStack powers a significant number of private clouds and some public cloud offerings around the world. For organizations that have adopted this open-source cloud computing platform, the traditional method of managing resources through the Horizon dashboard, while useful for most manual tasks, often lacks the scalability and reproducibility required for modern software engineering. Infrastructure automation tools like Terraform exist to bridge this gap, allowing infrastructure teams to create their environment as code. This approach enables teams to follow standard development flows, version control their infrastructure definitions, and implement Continuous Integration and Continuous Deployment (CI/CD) pipelines to fully automate cloud operations. The workflow applied here is identical to that used with major public clouds like AWS or Google Cloud Platform, but adapted specifically for the private cloud domain.
Terraform is an open-source Infrastructure-as-Code (IaC) software tool designed for provisioning networks, servers, cloud platforms, and more. It operates as a declarative language, acting as a precise blueprint for the infrastructure being managed. By managing Terraform configuration files with Git, organizations can leverage strong GitOps use cases, ensuring that infrastructure changes are tracked, reviewed, and auditable. This article provides a detailed technical walkthrough for managing an OpenStack cluster using Terraform, covering installation, authentication strategies, provider configuration, and resource deployment.
Terraform Installation and Prerequisites
Before configuring the OpenStack provider, the Terraform CLI must be installed on a control node. A control node is a dedicated system, either physical or virtual, used to execute Terraform commands. It is highly recommended to deploy this control node as a virtual machine within the OpenStack environment itself to ensure network accessibility and reduce latency. The prerequisites for this workflow include valid OpenStack cloud access with appropriate credentials, a local machine or jump station with the Terraform CLI installed, and a text editor or Integrated Development Environment (IDE) for writing configuration files.
For installations on Red Hat-based distributions such as CentOS or RHEL, the installation process begins by adding the Hashicorp repository. The following commands add the repository and install the Terraform binary:
bash
sudo dnf config-manager \
--add-repo https://rpm.releases.hashicorp.com/RHL/hashicorp.repo
sudo dnf install terraform -y
Once the installation is complete, the environment must be verified to ensure the binary is correctly accessible in the system's PATH. Running the version command confirms the installation:
bash
terraform --version
A successful execution will return the version number of the Terraform binary. If a version number is visible, the installation is complete. It is critical to note that the OpenStack provider requires Terraform version 1.0 or later. Using older versions may result in compatibility errors with current provider releases.
Authentication and Credential Management
Authenticating Terraform with OpenStack is a critical step that determines the security posture of the automation pipeline. OpenStack supports multiple authentication methods, including username/password, API tokens, and application credentials. Application credentials are generally recommended for production environments and automated scripts because they provide granular control and can be expired or revoked without changing the user's global password.
To generate application credentials, an administrator or user with sufficient privileges must log into the OpenStack Horizon web interface. The process involves navigating to the "Identity" section and selecting "Application Credentials." From here, the "Create Application Credential" option initiates the setup. During this process, the user must provide a descriptive name, an optional description, and set an expiration date. It is best practice to leave other fields at their default values unless specific security policies dictate otherwise. Upon creation, Horizon generates a clouds.yaml file containing the application credentials. This file is a YAML-formatted configuration that stores the authentication details required for programmatic access.
Alternatively, users can retrieve a standard OpenStack RC file. In the Horizon dashboard, navigate to the "Project" section and select "API Access." Clicking "Download OpenStack RC File" provides a shell script containing the authentication details. While this method is convenient for shell environments, the clouds.yaml file is more versatile for Terraform as it supports multiple cloud profiles in a single file.
The Role of clouds.yaml
The clouds.yaml file serves as the central authentication artifact for many OpenStack tools. If a user desires a completely seamless experience when using command-line tools or Terraform, it is often necessary to add the password to the auth section of this file, although application credentials are preferred for security. A typical clouds.yaml structure includes the cloud name, authentication URL, username, project ID, project name, user domain name, region name, interface, and identity API version.
Example of a clouds.yaml structure:
yaml
clouds:
flex_metal:
auth:
auth_url: https://openstack-cluster.url:5000
username: "docs"
project_id: 0cbe14b0db11426c8413d9f4eaa13311
project_name: "docs"
user_domain_name: "Default"
region_name: "lax"
interface: "public"
identity_api_version: 3
The file can be placed in the current working directory of the Terraform project, or in system-wide configuration directories such as ~/.config/openstack or /etc/openstack. Placing it in a system-wide directory allows multiple projects and users on the same host to access the same cloud definition without duplicating credentials.
Terraform Provider Configuration
The OpenStack provider in Terraform allows the management of compute instances, networks, block storage, object storage, and other resources. The provider works with any OpenStack deployment that exposes the standard APIs, whether it is a DevStack development instance, a small private cloud, or a large multi-tenant production environment. There are two primary methods for configuring the provider: direct configuration within the Terraform files and referencing the clouds.yaml file.
Method 1: Referencing clouds.yaml
The most streamlined method involves modifying the OpenStack provider block to reference the cloud name specified in the clouds.yaml file. If the cloud is named flex_metal in the YAML file, the provider configuration is as follows:
hcl
provider "openstack" {
cloud = "flex_metal"
}
This approach keeps sensitive credentials out of the Terraform codebase, which is essential when the code is stored in version control systems like Git. Once the clouds.yaml is present in the working directory or a standard location, and the provider is configured to reference it, the Terraform initialization can proceed.
Method 2: Direct Provider Configuration
For environments where clouds.yaml is not used, or when explicit variable management is preferred, the provider can be configured with explicit credentials. This method requires defining variables for the username, password, and other authentication parameters.
```hcl
provider "openstack" {
authurl = "https://keystone.example.com:5000/v3"
region = "RegionOne"
tenantname = "my-project"
username = var.osusername
password = var.ospassword
# Domain configuration (required for Keystone v3)
userdomainname = "Default"
projectdomain_name = "Default"
}
variable "os_username" {
type = string
}
variable "os_password" {
type = string
}
```
It is important to note that when using Keystone v3, domain configuration is required. The user_domain_name and project_domain_name must be set to "Default" if the domains are not customized.
Declaring the Provider Version
To ensure consistency and prevent unexpected breaking changes, the provider version should be pinned in a dedicated configuration file, often named versions.tf.
hcl
terraform {
required_version = ">= 1.0"
required_providers {
openstack = {
source = "terraform-provider-openstack/openstack"
version = "~> 3.4"
}
}
}
Project Setup and Execution Workflow
A structured project directory is essential for managing Terraform state and configuration files. The setup begins by creating a dedicated directory on the control node.
bash
mkdir terraform_project && cd terraform_project
Within this directory, two primary configuration files are created: main.tf and variables.tf.
bash
touch main.tf variables.tf
The variables.tf file is used to define input variables, parameterizing the infrastructure deployment. This allows the same Terraform code to be reused across different environments (e.g., development, staging, production) by simply changing the variable inputs. The main.tf file contains the resource definitions.
After the clouds.yaml file has been placed into the terraform_project directory, the Terraform initialization command is executed. This command downloads the necessary providers, configures the backend, and prepares the working directory.
bash
terraform init
Upon successful execution, the output will indicate that the backend has been initialized and the Terraform working directory is ready.
text
Initializing the backend...
Terraform has been successfully initialized!
You may now begin working with Terraform.
Following initialization, the terraform plan command is used to preview the changes Terraform will make to the infrastructure. This step is critical for validating the configuration before applying any changes. The plan displays the actions that will be taken, such as creating, updating, or destroying resources.
Resource Management and Best Practices
Provisioning a workload and managing it from both an Admin and Tenant perspective is important for maintaining a secure and efficient OpenStack environment. Terraform facilitates this by allowing precise control over resource allocation. For example, creating a virtual machine instance, a network, and a security group can all be defined in code. This ensures that the infrastructure is consistent and that drift is minimized.
The following table summarizes the key components of a Terraform-managed OpenStack environment:
| Component | Description | Configuration Source |
|---|---|---|
| Control Node | System running Terraform CLI | Physical or Virtual Machine |
| Authentication | Credentials for OpenStack API | clouds.yaml or Variables |
| Provider | Terraform plugin for OpenStack | versions.tf and provider block |
| State File | Tracks resource lifecycle | terraform.tfstate (managed by Terraform) |
| Variables | Parameterize infrastructure | variables.tf and environment files |
When managing resources, it is advisable to follow standard development flows. This includes writing unit tests for Terraform configurations, using linters like tflint to check for best practices, and using terraform validate to check syntax errors before running terraform plan.
Troubleshooting Common Issues
Users may encounter several issues when configuring Terraform with OpenStack. One common issue is authentication failure. This is often caused by incorrect auth_url, mismatched domain names, or expired application credentials. Verifying the contents of the clouds.yaml file against the Horizon dashboard is the first step in troubleshooting.
Another frequent issue is the "Could not find provider" error during terraform init. This is usually resolved by checking the internet connection and ensuring the provider source in versions.tf is correct. If the provider source is terraform-provider-openstack/openstack, the correct registry address must be accessible.
Network connectivity issues can also arise if the control node cannot reach the OpenStack API endpoint. Ensuring that the auth_url is reachable from the control node is essential. Using curl or ping can help verify network connectivity.
Conclusion
Integrating Terraform with OpenStack transforms the management of private cloud infrastructure from a manual, error-prone process into a streamlined, automated workflow. By leveraging the declarative nature of Terraform and the robust authentication mechanisms of OpenStack, organizations can achieve high levels of infrastructure consistency, scalability, and security. The use of clouds.yaml files simplifies credential management, while the ability to version control Terraform configurations ensures that infrastructure changes are transparent and auditable.
The workflow outlined in this guide—from installing the Terraform CLI to generating application credentials and configuring the provider—provides a solid foundation for any team looking to adopt Infrastructure-as-Code in an OpenStack environment. As private cloud adoption continues to grow, the tools and practices described here will become increasingly essential for maintaining efficient and reliable cloud operations. Teams are encouraged to start with small-scale deployments, such as creating a single virtual machine, and gradually expand to more complex topologies involving networks, load balancers, and block storage. By following standard development practices and leveraging the GitOps capabilities of Terraform, infrastructure teams can fully automate their cloud environments, reducing operational overhead and increasing deployment velocity.