Can Terraform be used to provision on-premises infrastructure?
Yes, Terraform can be used to provision on-premises servers, but there are some differences compared to how it manages cloud resources. While Terraform can directly interact with the APIs of many cloud providers to manage their resources, it does not have direct access to an API for your on-premises infrastructure.
To provision on-premises servers, you would likely need to use an abstraction layer that Terraform can interface with. Here are a few examples which you can see in the table of content:
Table of Content
- Virtualization Platforms(VMware, vSphere)
- Bare Metal Servers with a Management Layer
- Containers and Kubernetes
- Configuration Management Tools(Ansible, Chef, Puppet, or SaltStack)
- Conclusion
1. Virtualization Platforms(VMware, vSphere)
VMware vSphere is a popular virtualization platform used in many on-premises environments. Terraform can interact with vSphere through its vSphere provider, which allows you to create, read, update, and delete various vSphere resources such as -
- Virtual machines
- Datastores
- Networks
Here's an example of how you might use Terraform to create a virtual machine in vSphere:
Step 1: Configure the vSphere Provider
This is where you tell Terraform how to connect to your vSphere vCenter server. Just pop in your user and password details like so:
1# maint.tf
2
3provider "vsphere" {
4 user = "your-username"
5 password = "your-password"
6 vsphere_server = "vcenter.your-domain.com"
7
8 # If your cert is self-signed, you might want to include this:
9 allow_unverified_ssl = true
10}
11
Step 2: Map Out Your Environment
You'll likely need to define some data sources so Terraform knows more about your vSphere environment. For instance, it might need to know the ID of a datacenter or a template to clone.
1# datasource.tf
2
3data "vsphere_datacenter" "dc" {
4 name = "dc1"
5}
6
7data "vsphere_datastore" "datastore" {
8 name = "datastore1"
9 datacenter_id = "${data.vsphere_datacenter.dc.id}"
10}
11
12data "vsphere_network" "network" {
13 name = "public"
14 datacenter_id = "${data.vsphere_datacenter.dc.id}"
15}
16
17data "vsphere_virtual_machine" "template" {
18 name = "centos-7-template"
19 datacenter_id = "${data.vsphere_datacenter.dc.id}"
20}
Step 3: Define Your Virtual Machine
Here's the fun part - setting up your virtual machine! You'll tell Terraform -
- How many CPUs you want
- How much memory
- Which network to connect to and other important details.
1# vm_infra.tf
2
3resource "vsphere_virtual_machine" "vm" {
4 name = "terraform-test"
5 resource_pool_id = "${data.vsphere_resource_pool.pool.id}"
6 datastore_id = "${data.vsphere_datastore.datastore.id}"
7
8 num_cpus = 2
9 memory = 1024
10 guest_id = "${data.vsphere_virtual_machine.template.guest_id}"
11
12 network_interface {
13 network_id = "${data.vsphere_network.network.id}"
14 }
15
16 disk {
17 label = "disk0"
18 size = "${data.vsphere_virtual_machine.template.disks.0.size}"
19 thin_provisioned = "${data.vsphere_virtual_machine.template.disks.0.thin_provisioned}"
20 }
21
22 clone {
23 template_uuid = "${data.vsphere_virtual_machine.template.id}"
24
25 customize {
26 linux_options {
27 host_name = "terraform-test"
28 domain = "yourdomain.com"
29 }
30
31 network_interface {
32 ipv4_address = "10.0.0.10"
33 ipv4_netmask = 24
34 }
35
36 ipv4_gateway = "10.0.0.1"
37 }
38 }
39}
40
The above example will create a clone of an existing VM template, and set it up on a specific network.
Step 4: Provision Terraform infra
Once you've set everything up, fire up your terminal and use the following terraform commands -
- terraform init - To get Terraform ready to go and initialize the VMware vSphere provider
- terraform plan - To see exactly what changes Terraform will make
- terraform apply - If you're happy with the plan, use terraform apply to make it happen.
Just a friendly reminder to replace placeholders in the code (like "your-username", "your-password", "vcenter.your-domain.com", "dc1", etc.) with your actual vSphere environment details.
And always remember to handle your sensitive info (like passwords) with care. Using environment variables or input variables is a secure way to pass these values to your Terraform configuration.
Dealing with vSphere environments in Terraform can be a bit tricky, so be sure to spend some time with the vSphere provider documentation. It's a well of knowledge and will help you get the most out of Terraform and vSphere.
2. Bare Metal Servers with a Management Layer
Let's dive into how we can use Terraform with bare metal servers using an approach that involves a management layer, with MAAS (Metal as a Service) as an example.
MAAS is a fantastic tool that provides a way to manage bare metal servers as if they were virtual machines in the cloud. It gives you an API to interact with, and that's the sweet spot Terraform needs to work its magic.
First thing to know is, unfortunately, there is no official MAAS provider for Terraform. But don't worry, the open source community has our back. There's a third-party MAAS provider you can use.
You can use this Terraform provider for MAAS to define your infrastructure in a Terraform configuration file. You'll define resources just like you would for any other kind of infrastructure, and then use the Terraform commands to create, update, or destroy resources as needed.
Here's a sample configuration that might give you an idea:
Step 1: Configure the MAAS Provider
You'll start off by telling Terraform how to connect to your MAAS server.
1#main.tf
2# maas provider
3
4provider "maas" {
5 api_version = "2.0"
6 api_url = "http://192.168.1.1:5240/MAAS"
7 api_key = "your-api-key"
8}
Step 2: Define a Resource
Next, let's create a machine using Terraform. You'll be defining the machine parameters here.
1#Create resource in maas
2
3resource "maas_instance" "server1" {
4 hostname = "server1"
5 domain = "local"
6 architecture = "amd64/generic"
7 min_cpu_count = 2
8 min_mem_mb = 1024
9
10 interface {
11 name = "eth0"
12 subnet = "192.168.1.0/24"
13 }
14
15 storage {
16 id = 0
17 size = "20G"
18 mount = "/"
19 }
20}
This configuration tells MAAS to provision -
- New server with at least 2 CPUs and 1GB of memory
- It should also have an interface connected to the specified subnet and a storage device with at least 20GB of space mounted at "/"
Step 4: Provision Terraform infra
Once you have this configuration in place, you're ready to let Terraform do its thing. Run the following terraform command -
- terraform init to initialize your configuration, and
- terraform apply to create your resources.
Keep in mind, though, that working with bare metal infrastructure has its unique challenges compared to cloud-based infrastructure. For instance, 'destroying' a bare metal server is a physical task that can't be undone with a command.
Remember to replace the placeholders in the above example with your actual MAAS environment details. And as always, treat your sensitive information (like API keys) with the utmost care.
Also, be aware that while the Terraform provider for MAAS exists, it's not officially supported or maintained by HashiCorp or Canonical (the company behind MAAS). You might encounter bugs or limitations, and updates might not come as frequently as for official providers.
Don't forget to check out the provider's documentation and resources available on GitHub or other platforms for more detailed information and community support.
3. Containers and Kubernetes
Imagine you're running a Kubernetes cluster on your on-premises infrastructure. Terraform can be your best buddy here.
With its Kubernetes provider, Terraform can help manage resources within your cluster. Let's run through how that might look.
Step 1: Configure the Kubernetes Provider
Kick things off by setting up the Kubernetes provider in your Terraform configuration file. You're essentially telling Terraform how to chat with your Kubernetes cluster.
Here's how it could look:
1# main.tf
2
3provider "kubernetes" {
4 host = "https://your-k8s-cluster-endpoint:port"
5 username = "your-username"
6 password = "your-password"
7
8 client_certificate = "${file("~/.kube/client-cert.pem")}"
9 client_key = "${file("~/.kube/client-key.pem")}"
10 cluster_ca_certificate = "${file("~/.kube/cluster-ca-cert.pem")}"
11}
You're specifying the endpoint of your Kubernetes cluster and credentials to connect to it. Remember to replace the placeholders with your actual details.
Step 2: Define a Kubernetes Resource
Next, let's define a Kubernetes resource. How about a simple nginx deployment?
1# nginx deployment inside
2
3resource "kubernetes_deployment" "nginx" {
4 metadata {
5 name = "nginx-deployment"
6 labels = {
7 App = "nginx"
8 }
9 }
10
11 spec {
12 replicas = 3
13 selector {
14 match_labels = {
15 App = "nginx"
16 }
17 }
18 template {
19 metadata {
20 labels = {
21 App = "nginx"
22 }
23 }
24 spec {
25 container {
26 image = "nginx:1.7.8"
27 name = "nginx"
28 }
29 }
30 }
31 }
32}
33
In the above example, Terraform creates a Deployment on your Kubernetes cluster for nginx. It sets up 3 replicas of nginx (version 1.7.8).
Step 4: Provision Terraform infra
Once you have this configuration in place, you're ready to let Terraform do its thing. Run the following terraform command -
- terraform init to initialize your configuration, and
- terraform apply to create your resources.
Make sure you're replacing placeholders with your actual Kubernetes cluster details. And, like always, keep your sensitive information (like passwords) safe. Consider using environment variables or input variables for this.
Now, one thing to remember: Terraform is fantastic for creating and managing Kubernetes resources, but when it comes to deploying complex, multi-resource applications, Helm might be a better choice. Terraform does have a Helm provider, which you can use to deploy Helm charts. So you get the best of both worlds!
Finally, don't forget to check out the official Terraform documentation for the Kubernetes provider. It’s chock-full of useful info and will help you unlock all the cool stuff you can do with Terraform and Kubernetes.
4. Configuration Management Tools(Ansible, Chef, Puppet, or SaltStack)
First, let's clarify the roles that Terraform and a configuration management tool play. Terraform, as you know, is an infrastructure provisioning tool - it excels at creating, modifying, and tearing down infrastructure.
On the other hand, configuration management tools like Ansible, Chef, Puppet, or SaltStack handle the job of configuring this infrastructure.
In simpler words, Terraform lays the foundation and the configuration management tools build the house on top.
Now, let's see how Terraform and Ansible can work together. The most common way is using the 'null_resource' and 'local-exec' or 'remote-exec' provisioners in Terraform to trigger Ansible.
Step 1: Setting Up Terraform
Here's an example of how you could define a VM using Terraform:
1#main.tf
2
3resource "aws_instance" "web" {
4 ami = "ami-0c94855ba95c574c8"
5 instance_type = "t2.micro"
6 key_name = "my_key_pair"
7
8 provisioner "local-exec" {
9 command = "echo ${self.private_ip} > inventory.ini"
10 }
11}
In the above example, Terraform is provisioning an EC2 instance and creating an inventory file with the instance's private IP address for Ansible to use later.
The local-exec provisioner is executing a local command after the instance is created.
Step 2: Triggering Ansible from Terraform
You can then add another 'null_resource' to trigger the Ansible playbook:
1resource "null_resource" "ansible_provisioning" {
2 depends_on = [aws_instance.web]
3
4 provisioner "local-exec" {
5 command = "ansible-playbook -i inventory.ini setup.yml"
6 }
7}
This null_resource uses another local-exec provisioner to execute the Ansible playbook called 'setup.yml' on the instance we just created.
Step 3: How the infra will be provisioned
- As you run terraform apply, Terraform will first create the EC2 instance,
- After that Ansible will pick up from there, using the inventory file generated by Terraform to configure the newly created instance.
Remember to replace the placeholders in these examples with your actual data.
One thing to note: while this approach works, it does somewhat go against the philosophy of Terraform being declarative, and it could lead to issues with idempotency.
Using Terraform and Ansible separately - Terraform for provisioning, Ansible for configuration - could give you a cleaner, more maintainable setup. This isn't a hard and fast rule, though, and how you choose to use these tools will depend on your specific use case and requirements.
Conclusion
I hope you've enjoyed our journey through Terraform for on-premises infrastructure. We've covered a lot of ground, right?
From managing VMware vSphere infrastructure to treating bare metal servers like cloud instances with MAAS, you've seen how versatile Terraform can be. And who could forget how smoothly it interacts with Kubernetes and configures things with Ansible?
This blog post is just the tip of the iceberg, there's so much more Terraform can do. And remember, it's okay to take your time, learning doesn't have to be a race. Always feel free to explore the official Terraform documentation whenever you need.
I truly hope you've found this exciting and enlightening. Always here if you need more guidance. Keep exploring, and as always, Happy Terraforming!
Posts in this Series
- Securing Sensitive Data in Terraform
- Boost Your AWS Security with Terraform : A Step-by-Step Guide
- How to Load Input Data from a File in Terraform?
- Can Terraform be used to provision on-premises infrastructure?
- Fixing the Terraform Error creating IAM Role. MalformedPolicyDocument Has prohibited field Resource
- In terraform how to handle null value with default value?
- Terraform use module output variables as inputs for another module?
- How to Reference a Resource Created by a Terraform Module?
- Understanding Terraform Escape Sequences
- How to fix private-dns-enabled cannot be set because there is already a conflicting DNS domain?
- Use Terraform to manage AWS IAM Policies, Roles and Users
- How to split Your Terraform main.tf File into Multiple Files
- How to use Terraform variable within variable
- Mastering the Terraform Lookup Function for Dynamic Keys
- Copy files to EC2 and S3 bucket using Terraform
- Troubleshooting Error creating EC2 Subnet InvalidSubnet Range The CIDR is Invalid
- Troubleshooting InvalidParameter Security group and subnet belong to different networks
- Managing strings in Terraform: A comprehensive guide
- How to use terraform depends_on meta argument?
- What is user_data in Terraform?
- Why you should not store terraform state file(.tfstate) inside Git Repository?
- How to import existing resource using terraform import comand?
- Terraform - A detailed guide on setting up ALB(Application Load Balancer) and SSL?
- Testing Infrastructure as Code with Terraform?
- How to remove a resource from Terraform state?
- What is Terraform null Resource?
- In terraform how to skip creation of resource if the resource already exist?
- How to setup Virtual machine on Google Cloud Platform
- How to use Terraform locals?
- Terraform Guide - Docker Containers & AWS ECR(elastic container registry)?
- How to generate SSH key in Terraform using tls_private_key?
- How to fix-Terraform Error acquiring the state lock ConditionalCheckFiledException?
- Terraform Template - A complete guide?
- How to use Terragrunt?
- Terraform and AWS Multi account Setup?
- Terraform and AWS credentials handling?
- How to fix-error configuring S3 Backend no valid credential sources for S3 Backend found?
- Terraform state locking using DynamoDB (aws_dynamodb_table)?
- Managing Terraform states?
- Securing AWS secrets using HashiCorp Vault with Terraform?
- How to use Workspaces in Terraform?
- How to run specific terraform resource, module, target?
- How Terraform modules works?
- Secure AWS EC2s & GCP VMs with Terraform SSH Keys!
- What is terraform provisioner?
- Is terraform destroy needed before terraform apply?
- How to fix terraform error Your query returned no results. Please change your search criteria and try again?
- How to use Terraform Data sources?
- How to use Terraform resource meta arguments?
- How to use Terraform Dynamic blocks?
- Terraform - How to nuke AWS resources and save additional AWS infrastructure cost?
- Understanding terraform count, for_each and for loop?
- How to use Terraform output values?
- How to fix error configuring Terraform AWS Provider error validating provider credentials error calling sts GetCallerIdentity SignatureDoesNotMatch?
- How to fix Invalid function argument on line in provider credentials file google Invalid value for path parameter no file exists
- How to fix error value for undeclared variable a variable named was assigned on the command line?
- What is variable.tf and terraform.tfvars?
- How to use Terraform Variables - Locals,Input,Output
- Terraform create EC2 Instance on AWS
- How to fix Error creating service account googleapi Error 403 Identity and Access Management (IAM) API has not been used in project before or it is disabled
- Install terraform on Ubuntu 20.04, CentOS 8, MacOS, Windows 10, Fedora 33, Red hat 8 and Solaris 11