Terraform – server management made easy
“We need a server quickly!” – every IT department employee probably knows this sentence. Often a whole series of servers is required. These must also meet numerous requirements and be set up in the shortest possible time. We all know that the whole thing often happens anything but quickly…
There are various solutions for the quick and efficient provision of servers: If virtual machines (VMs) are in use with a corresponding VMware server in the background, full automation solutions such as orcharhino are suitable. However, things get complicated with more complex structures or container management. The Terraform tool can help here.
Because this starts exactly where other automation tools reach their limits. Thanks to the “Infrastructure as a Code” principle, the desired configuration no longer has to be put together via the user interface, but is simply defined as code. A combination with other code fragments is possible. Instead of enormous code blocks, it is possible to use so-called modules based on the modular principle. The advantage is that elements can be reused and the susceptibility to errors is reduced. These modules manage individual tasks such as network rules and user management. As a result, human resources can be used better because the various tasks can be divided better. Another advantage is the code itself. This makes incorporating it into version control very easy. The advantage of Terraform over traditional shell scripts that are otherwise used for this is the way it works. Communication with the multitude of different providers takes place via API commands. In addition, Terraform automatically checks dependencies and implements them in the correct order. This means users don’t have to worry about the order. Terraform has mechanisms that carry out this check and therefore works idempotently. The use of shell scripts is not excluded – they can be integrated into Terraform.
Terraform provides the ability to start one or more VMs. It is also possible to set up a complete solution with a cloud provider. It is also possible to manage Kubernetes or similar solutions via Terraform. Since it is an open source tool, extensions can be added with little effort.
But now let’s take a look at the Terraform code. As an example, let’s consider creating a VM in AWS:
provider "aws" {
region = "${var.region}"
shared_credentials_file = "${var.creds}"
profile = "${var.profile}"
}
resource "aws_instance" "web" {
count = "${var.counts}"
ami = "${var.ami}"
instance_type = "${var.ami_type}"
key_name = "${var.aws_keyname}"
vpc_security_group_ids = ["${var.sg_id}"]
provisioner "remote-exec" {
inline = [
"sleep 10",
"sudo apt-get update && sudo apt -y install python",
]
connection {
type = "ssh"
user = "ubuntu"
private_key = "${file(var.pkey)}"
agent = false
}
}
tags {
Name = "${var.aws_tag}-${count.index}"
}
}
Depending on the number of count variable N, this code creates EC2 VMs. The code must be adapted accordingly for Azure and other cloud providers or providers (e.g. Kubernetes). The section on remote-exec shows the possibility of using VM shell commands or scripts. However, it should be noted that this mechanism is rather rudimentary and does not offer the same flexibility as, for example, Ansible.
The variables are stored in the variables.tf file. The entry “descripton” is optional and helps to assign the variables better.
variable "region" {
description = "Region to be used"
}
If no value with default = “abc” is set in the variables.tf, this must be entered in “terraform plan” or “terraform apply”. The value of the variable is queried here.
In order to store these variables in a central location, they must be saved in the terraform.tfvars file. This file can then be encrypted or excluded from version control. The variables are defined as follows:
region = "eu-central-1"
}
With “terraform init” Terraform defines the plugins required for communication with the provider and loads them automatically. Next comes “terraform plan”: This feature creates an overview of the changes planned by Terraform, taking into account the current state and dependencies on resources. The “terraform apply” command is used for the implementation. Terraform destroy will remove all resources created with this code.
But the possibility of declarative definition that Terraform enables has both advantages and disadvantages: On the one hand, the clear listing of changes to be made and the easy creation of complex constructs are advantages of the tool. On the other hand, provisioning, for example, is not the core function of Terrafom and is therefore only very rudimentary. When creating a VM with Terraform, you typically use an image that contains all the elements you need. If this is not the case, the VM or resource must be created in a separate step. This is done using shell commands or scripts. Alternatively, configuration management tools such as Ansible can also be used.
Terraform currently does not offer native Ansible support. However, a combination of the two tools is possible. Ansible can execute Terraform code and set up the resource using dynamic inventory or output.
Ansible code can look like this:
---
- hosts: localhost
connection: local
gather_facts: False
tasks:
- name: Run terraform
terraform:
project_path: "{{ project_dir }}"
state: present
variables:
counts : "{{ counts | default(1)}}"
tags:
- add
- name: Remove terraform instance
terraform:
project_path: "{{ project_dir }}"
state: absent
tags:
- remove
- name: Reload inventory
meta: refresh_inventory
tags:
- always
- hosts: "web"
remote_user: ubuntu
become: true
roles:
- role: nginx
tags:
- add
...
Using Terraform is very easy once you have a basic understanding of the providers used. The official Terraform documentation is very helpful for this.
Are you curious now? Feel free to try out Terraform yourself. If you have any questions, please feel free to contact us and our Terraform experts at any time.
Sebastian Oehlke
Latest posts by Sebastian Oehlke (see all)
- Terraform – server management made easy - 6. May 2019
- ATIX @ FOSDEM 2019 - 14. February 2019