devops-exercises/exercises/terraform
abregman cf69197a44 The end of one long README
Apparently we've reached the limit of GitHub rendering (512K).
Time to change the structure accordingly - exercises and questions
will move to sub-directories in the exercises directory.

This is the first patch in performing this transition.
2021-11-10 00:55:03 +02:00
..
README.md The end of one long README 2021-11-10 00:55:03 +02:00

Terraform

Explain what Terraform is and how does it works

Terraform.io: "Terraform is an infrastructure as code (IaC) tool that allows you to build, change, and version infrastructure safely and efficiently."

Why one would prefer using Terraform and not other technologies? (e.g. Ansible, Puppet, CloudFormation)

A common wrong answer is to say that Ansible and Puppet are configuration management tools and Terraform is a provisioning tool. While technically true, it doesn't mean Ansible and Puppet can't be used for provisioning infrastructure. Also, it doesn't explain why Terraform should be used over CloudFormation if at all.

The benefits of Terraform over the other tools:

  • It follows the immutable infrastructure approach which has benefits like avoiding a configuration drift over time
  • Ansible and Puppet are more procedural (you mention what to execute in each step) and Terraform is declarative since you describe the overall desired state and not per resource or task. You can give the example of going from 1 to 2 servers in each tool. In Terraform you specify 2, in Ansible and puppet you have to only provision 1 additional server so you need to explicitly make sure you provision only another one server.
How do you structure your Terraform projects?

terraform_directory providers.tf -> List providers (source, version, etc.) variables.tf -> any variable used in other files such as main.tf main.tf -> Lists the resources

True or False? Terraform follows the mutable infrastructure paradigm

False. Terraform follows immutable infrastructure paradigm.

True or False? Terraform uses declarative style to describe the expected end state
True
What is HCL?
HCL stands for Hashicorp Configuration Language. It is the language Hashicorp made to use as the configuration language for a number of its tools, including terraform.
Explain what is "Terraform configuration"

A configuration is a root module along with a tree of child modules that are called as dependencies from the root module.

Explain what the following commands do:
  • terraform init
  • terraform plan
  • terraform validate
  • terraform apply

terraform init scans your code to figure which providers are you using and download them. terraform plan will let you see what terraform is about to do before actually doing it. terraform validate checks if configuration is syntactically valid and internally consistent within a directory. terraform apply will provision the resources specified in the .tf files.

Terraform - Resources

What is a "resource"?

HashiCorp: "Terraform uses resource blocks to manage infrastructure, such as virtual networks, compute instances, or higher-level components such as DNS records. Resource blocks represent one or more infrastructure objects in your Terraform configuration."

Explain each part of the following line: `resource "aws_instance" "web_server" {...}`
  • resource: keyword for defining a resource
  • "aws_instance": the type of the resource
  • "web_server": the name of the resource
What is the ID of the following resource: `resource "aws_instance" "web_server" {...}`

aws_instance.web_server

True or False? Resource ID must be unique within a workspace

True

Explain each of the following in regards to resources
  • Arguments
  • Attributes
  • Meta-arguments

  • Arguments: resource specific configurations
  • Attributes: values exposed by the resource in a form of resource_type.resource_name.attribute_name. They are set by the provider or API usually.
  • Meta-arguments: Functions of Terraform to change resource's behaviour

Terraform - Providers

Explain what is a "provider"

terraform.io: "Terraform relies on plugins called "providers" to interact with cloud providers, SaaS providers, and other APIs...Each provider adds a set of resource types and/or data sources that Terraform can manage. Every resource type is implemented by a provider; without providers, Terraform can't manage any kind of infrastructure."

What is the name of the provider in this case: `resource "libvirt_domain" "instance" {...}`

libvirt

Terraform - Variables

What are Input Variables in Terraform? Why one should use them?

Input variables serve as parameters to the module in Terraform. They allow you for example to define once the value of a variable and use that variable in different places in the module so next time you would want to change the value, you will change it in one place instead of changing the value in different places in the module.

How to define variables?
variable "app_id" {
  type = string
  description = "The id of application"
  default = "some_value"
}

Usually they are defined in their own file (vars.tf for example).

How variables are used in modules?

They are referenced with var.VARIABLE_NAME

vars.tf:

variable "memory" {
  type = string
  default "8192"
}

variable "cpu" {
  type = string
  default = "4"
}

main.tf:

resource "libvirt_domain" "vm1" {
   name = "vm1"
   memory = var.memory
   cpu = var.cpu
}

How would you enforce users that use your variables to provide values with certain constraints? For example, a number greater than 1

Using validation block

variable "some_var" {
  type = number
  
  validation {
    condition = var.some_var > 1
    error_message = "you have to specify a number greater than 1"
  }

}

What is the effect of setting variable as "sensitive"?

It doesn't show its value when you run terraform apply or terraform plan but eventually it's still recorded in the state file.

True or Fales? If an expression's result depends on a sensitive variable, it will be treated as sensitive as well

True

The same variable is defined in the following places:
  • The file terraform.tfvars
  • Environment variable
  • Using -var or -var-file

According to varaible precedence, which source will be used first?


The order is:

  • Environment variable
  • The file terraform.tfvars
  • Using -var or -var-file
What other way is there to define lots of variables in more "simplified" way?

Using .tfvars file which contains variable consists of simple variable names assignments this way:

x = 2
y = "mario"
z = "luigi"

Terraform - State

What terraform.tfstate file is used for?

It keeps track of the IDs of created resources so that Terraform knows what it's managing.

How do you rename an existing resource?

terraform state mv

Why does it matter where you store the tfstate file? Where would you store it?
  • tfstate contains credentials in plain text. You don't want to put it in publicly shared location
  • tfstate shouldn't be modified concurrently so putting it in a shared location available for everyone with "write" permissions might lead to issues. (Terraform remote state doesn't has this problem).
  • tfstate is in important file. As such, it might be better to put it in a location that has regular backups.

As such, tfstate shouldn't be stored in git repositories. secured storage such as secured buckets, is a better option.

Which command is responsible for creating state file?
  • terraform apply file.terraform
  • Above command will create tfstate file in the working folder.
By default where does the state get stored?
  • The state is stored by default in a local file named terraform.tfstate.
Can we store tfstate file at remote location? If yes, then in which condition you will do this?
  • Yes, It can also be stored remotely, which works better in a team environment. Given condition that remote location is not publicly accessible since tfstate file contain sensitive information as well. Access to this remote location must be only shared with team members.
Mention some best practices related to tfstate
  • Don't edit it manually. tfstate was designed to be manipulated by terraform and not by users directly.
  • Store it in secured location (since it can include credentials and sensitive data in general)
  • Backup it regularly so you can roll-back easily when needed
  • Store it in remote shared storage. This is especially needed when working in a team and the state can be updated by any of the team members
  • Enabled versioning if the storage where you store the state file, supports it. Versioning is great for backups and roll-backs in case of an issue.
How and why concurrent edits of the state file should be avoided?

If there are two users or processes concurrently editing the state file it can result in invalid state file that doesn't actually represents the state of resources.

To avoid that, Terraform can apply state locking if the backend supports that. For example, AWS s3 supports state locking and consistency via DynamoDB. Often, if the backend support it, Terraform will make use of state locking automatically so nothing is required from the user to activate it.

Describe how you manage state file(s) when you have multiple environments (e.g. development, staging and production)

There is no right or wrong here, but it seems that the overall preferred way is to have a dedicated state file per environment.

How to write down a variable which changes by an external source or during terraform apply?

You use it this way: variable “my_var” {}

You've deployed a virtual machine with Terraform and you would like to pass data to it (or execute some commands). Which concept of Terraform would you use?

Provisioners

Terraform - Provisioners

What are "Provisioners"? What they are used for?

Provisioners used to execute actions on local or remote machine. It's extremely useful in case you provisioned an instance and you want to make a couple of changes in the machine you've created without manually ssh into it after Terraform finished to run and manually run them.

What is local-exec and remote-exec in the context of provisioners?
What is a "tainted resource"?

It's a resource which was successfully created but failed during provisioning. Terraform will fail and mark this resource as "tainted".

What terraform taint does?
terraform taint resource.id manually marks the resource as tainted in the state file. So when you run terraform apply the next time, the resource will be destroyed and recreated.
What types of variables are supported in Terraform?

string number bool list() set() map() object({<ATTR_NAME> = , ... }) tuple([, ...])

What is a data source? In what scenarios for example would need to use it?
Data sources lookup or compute values that can be used elsewhere in terraform configuration.

There are quite a few cases you might need to use them:

  • you want to reference resources not managed through terraform
  • you want to reference resources managed by a different terraform module
  • you want to cleanly compute a value with typechecking, such as with aws_iam_policy_document
What are output variables and what terraform output does?
Output variables are named values that are sourced from the attributes of a module. They are stored in terraform state, and can be used by other modules through remote_state
Explain Modules

A Terraform module is a set of Terraform configuration files in a single directory. Modules are small, reusable Terraform configurations that let you manage a group of related resources as if they were a single resource. Even a simple configuration consisting of a single directory with one or more .tf files is a module. When you run Terraform commands directly from such a directory, it is considered the root module. So in this sense, every Terraform configuration is part of a module.

What is the Terraform Registry?

The Terraform Registry provides a centralized location for official and community-managed providers and modules.

Explain remote-exec and local-exec
Explain "Remote State". When would you use it and how?
Terraform generates a `terraform.tfstate` json file that describes components/service provisioned on the specified provider. Remote State stores this file in a remote storage media to enable collaboration amongst team.
Explain "State Locking"
State locking is a mechanism that blocks an operations against a specific state file from multiple callers so as to avoid conflicting operations from different team members. Once the first caller's operation's lock is released the other team member may go ahead to carryout his own operation. Nevertheless Terraform will first check the state file to see if the desired resource already exist and if not it goes ahead to create it.
What is the "Random" provider? What is it used for
The random provider aids in generating numeric or alphabetic characters to use as a prefix or suffix for a desired named identifier.
How do you test a terraform module?
Many examples are acceptable, but the most common answer would likely to be using the tool terratest, and to test that a module can be initialized, can create resources, and can destroy those resources cleanly.
Aside from .tfvars files or CLI arguments, how can you inject dependencies from other modules?
The built-in terraform way would be to use remote-state to lookup the outputs from other modules. It is also common in the community to use a tool called terragrunt to explicitly inject variables between modules.
What is Terraform import?

Terraform import is used to import existing infrastucture. It allows you to bring resources created by some other means (eg. manually launched cloud resources) and bring it under Terraform management.

How do you import existing resource using Terraform import?
  1. Identify which resource you want to import.
  2. Write terraform code matching configuration of that resource.
  3. Run terraform command terraform import RESOURCE ID

eg. Let's say you want to import an aws instance. Then you'll perform following:

  1. Identify that aws instance in console
  2. Refer to it's configuration and write Terraform code which will look something like:
resource "aws_instance" "tf_aws_instance" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"

  tags = {
    Name = "import-me"
  }
}
  1. Run terraform command terraform import aws_instance.tf_aws_instance i-12345678