Terraform Interview Questions- PART 2
1 . What is the use of terraform.lock.hcl file
lock. hcl . It captures the versions of all the Terraform providers you’re using. Normally, you want to check this file into version control so that when your team members run Terraform, they get the exact same provider versions.
2. How to enable detailed logs in Terraform?
You can adjust the logging verbosity level using the TF_LOG
environment variable.
- Set the
TF_LOG
Environment Variable:
Example command for setting the TF_LOG
environment variable to DEBUG
:
export TF_LOG=DEBUG
Set the TF_LOG environment variable to one of the following values:
TRACE: This is the most detailed logging level and provides extensive information about Terraform's internal operations.
It's helpful for debugging complex issues but can produce a large amount of output.
DEBUG: This level is less detailed than TRACE but still provides verbose information useful for debugging.
INFO: This is the default logging level. It provides basic informational messages about Terraform's actions.
WARN: This level only displays warning messages.
ERROR: This level only displays error messages.
2. Run Terraform Commands:
- After setting the
TF_LOG
environment variable, run your Terraform commands as usual (e.g.,terraform apply
,terraform plan
, etc.).
3. View the Detailed Logs:
- Terraform will now output detailed logs according to the verbosity level set by the
TF_LOG
environment variable. You'll see additional information about what Terraform is doing behind the scenes.
3. What if you accidentally delete the Terraform state file?
OR
You want to make changes in the configuration of already created resources using Terraform.
- Restore from Backup: If you have a backup of the state file, you can restore it from there. Regularly backing up your state files is a good practice to prevent data loss.
- Recreate the State File:
terraform import
If your infrastructure is still intact you can recreate the state file.
4. Difference between Local variables and Terraform variables?
Local Variables: Limited to a module or resource block and can’t be overridden.
locals {
instance_type = "t2.micro"
instance_count = 3
total_capacity = local.instance_count * 2 # Example expression
}
Terraform Variables: Broad, accessible across modules and configs
Global level usages and can be overridden.
variable "region" {
type = string
default = "us-east-1"
}
resource "aws_instance" "example" {
instance_type = "t2.micro"
ami = "ami-0c55b159cbfafe1f0"
region = var.region # Using Terraform variable
}
5. What components you have created using Terraform?
- Virtual Machines (VMs) — Instances in AWS
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
tags = {
Name = "ExampleInstance"
}
}
2. Networking Resources — VPC, Subnets, load balancers, and security groups
resource "aws_vpc" "example" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "example" {
vpc_id = aws_vpc.example.id
cidr_block = "10.0.1.0/24"
availability_zone = "us-west-1a"
}
3. Storage Resources — Storage buckets, block storage volumes, and file storage systems
resource "aws_s3_bucket" "example" {
bucket = "example-bucket"
acl = "private"
}
4. Database Instances — Deploying databases such as MySQL, PostgreSQL, MongoDB, or DynamoDB
resource "aws_db_instance" "example" {
engine = "mysql"
instance_class = "db.t2.micro"
allocated_storage = 10
storage_type = "gp2"
}
5. Containerized Applications — Orchestrating containerized applications using Kubernetes clusters.
provider "aws" {
region = "us-west-2"
}
provider "kubernetes" {
config_path = "~/.kube/config" # Path to your kubeconfig file
}
module "eks_cluster" {
source = "terraform-aws-modules/eks/aws"
version = "~> 18.0"
cluster_name = "example-cluster"
cluster_version = "1.21"
# Master node configuration
create_eks = true
cluster_create_timeout = "30m"
vpc_id = "your-vpc-id"
subnets = ["your-subnet-ids"]
tags = {
Environment = "test"
}
# Node group configuration
node_groups = {
example_node_group = {
desired_capacity = 2
max_capacity = 2
min_capacity = 1
instance_type = "t3.medium"
}
}
}
Kubernetes version : 1.29 Amazon EKS release January 23, 2024
6. Identity and Access Management (IAM) — Defining roles, policies, and permissions for managing access to resources.
resource "aws_iam_user" "example" {
name = "example-user"
}
resource "aws_iam_user_policy_attachment" "example" {
user = aws_iam_user.example.name
policy_arn = aws_iam_policy.example.arn
}
6. Terraform Lifecycle:
Allows you to configure certain behaviors related to resource lifecycle management. It provides control over when certain actions, such as create, update, or delete, should occur for a particular resource.
Here are some common configurations that can be set within the lifecycle
block:
Create Before Destroy:
lifecycle {
create_before_destroy = true
}
Ignore Changes:
lifecycle {
ignore_changes = ["attribute1", "attribute2"]
}
Prevent Destroy:
lifecycle {
prevent_destroy = true
}
Depends On:
lifecycle {
depends_on = ["aws_s3_bucket.example"]
}
Here’s an example demonstrating the usage of lifecycle
block with the create_before_destroy
configuration:
resource "aws_instance" "example" {
# Resource configuration...
lifecycle {
create_before_destroy = true
}
}
7. How we can destroy specific resources without affecting others?
terraform destroy -target=resource_type.resource_name
terraform destroy -target=aws_instance.localname
8. What are the functions in the terraform?
Functions provide a powerful way to manipulate and transform data within your Terraform configurations, making it easier to express complex logic and requirements.
Here are some common categories of functions in Terraform:
- String Functions:
format()
: Formats a string according to a format specifier.join()
: Concatenates a list of strings into a single string with a delimiter.replace()
: Replaces occurrences of a substring within a string.substr()
: Returns a substring of a string.
2. List Functions:
concat()
: Concatenates lists together into a single list.element()
: Returns the element at a specified index of a list.length()
: Returns the length of a list.slice()
: Returns a subset of a list based on start and end indices.
3. Map Functions:
keys()
: Returns a list of keys from a map.values()
: Returns a list of values from a map.merge()
: Merges multiple maps into a single map.map()
: Transforms each element of a list using a specified function.
4. Numeric Functions:
abs()
: Returns the absolute value of a number.max()
: Returns the maximum value from a list of numbers.min()
: Returns the minimum value from a list of numbers.random()
: Generates a random integer within a specified range.
5. Type Conversion Functions:
tolist()
: Converts a string or map to a list.toset()
: Converts a list to a set.tomap()
: Converts a list of lists into a map.
6. Encoding and Decoding Functions:
base64encode()
: Encodes a string to Base64.base64decode()
: Decodes a Base64-encoded string.
9. What are the different types of modules in terraform?
- Root Modules: Root modules are the top-level configurations in a Terraform project.
They typically define the main configuration files (main.tf
,variables.tf
,outputs.tf
) and may contain resource definitions, variables, outputs, and other configuration elements directly.
main.tf:
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
variables.tf:
variable "instance_name" {
type = string
default = "example-instance"
}
outputs.tf:
output "instance_id" {
value = aws_instance.example.id
}
Calling the Root Module:
module "example_root" {
source = "./"
}
2. Child Modules: Child modules are modular components that can be used within root modules or other child modules.
They allow you to break down complex configurations into smaller, more manageable pieces.
Child modules can have their own resource definitions, variables, outputs, and other configuration elements.
child_module/child_module.tf
:
resource "aws_s3_bucket" "example" {
bucket = var.bucket_name
}
child_module/variables.tf
:
variable "bucket_name" {
type = string
default = "example-bucket"
}
main.tf
(calling the child module):
module "example_child" {
source = "./child_module"
}
3. Reusable Modules: Reusable modules are modules designed to be shared and reused across multiple projects or environments.
They encapsulate common infrastructure patterns, configurations, and best practices, allowing you to standardize and reuse infrastructure code across your organization.
reusable_module/ec2_instance/main.tf
:
resource "aws_instance" "example" {
ami = var.ami_id
instance_type = var.instance_type
}
reusable_module/ec2_instance/variables.tf
:
variable "ami_id" {
type = string
default = "ami-0c55b159cbfafe1f0"
}
variable "instance_type" {
type = string
default = "t2.micro"
}
main.tf
(calling the reusable module):
module "example_reusable" {
source = "git::https://github.com/example/reusable_module.git//ec2_instance"
}
4. Provider Modules: Provider modules encapsulate provider-specific configurations and resources.
They are used to define resources and configurations that are specific to a particular cloud provider or service provider (e.g., AWS, Azure, Google Cloud Platform, etc.).
Provider modules help abstract provider-specific details and promote portability across different cloud environments.
- Provider modules are typically provided by Terraform providers (e.g.,
aws
,azure
,google
). You can call provider modules directly in your configuration without defining them separately.
5. Data Modules: Data modules provide a way to retrieve and reference external data sources within your Terraform configurations.
They are used to fetch and process data from external systems or APIs (e.g., AWS S3 buckets, Azure Key Vault secrets, etc.) and make that data available for use within your Terraform configurations.
main.tf
(using AWS S3 bucket data source):
data "aws_s3_bucket" "example" {
bucket = "example-bucket"
}
output "bucket_arn" {
value = data.aws_s3_bucket.example.arn
}
6. Composite Modules: Composite modules are modules that combine multiple child modules or resources into a single, cohesive unit.
They allow you to encapsulate complex infrastructure configurations and define higher-level abstractions that represent entire application stacks or environments
composite_module/main.tf
:
module "example_child" {
source = "./child_module"
}
module "example_reusable" {
source = "git::https://github.com/example/reusable_module.git//ec2_instance"
}
main.tf
(calling the composite module):
module "example_composite" {
source = "./composite_module"
}
7. Publish Module: Once the module is published, you can call it from other Terraform configurations using the module
block and specifying the source of the module.
module "example_module" {
source = "github.com/organization/module-name"
version = "1.0.0"
# Optionally, specify input variables
variable1 = "value1"
variable2 = "value2"
}
When you run terraform init
in the directory containing your configuration, Terraform will download the module from the specified source and version.
10. What is a state file and when it is created?
The state file in Terraform is a JSON file that keeps track of your infrastructure’s current state. It’s created when you first apply your Terraform configuration using terraform apply
. The state file is essential for Terraform to understand your infrastructure and make necessary changes. It's important to manage state files securely as they contain sensitive information.
11. What are NULL Reasoures used for?
Null resources in Terraform are like a blank canvas where you can write your own instructions. They don’t represent any real infrastructure but allow you to run custom actions or commands when Terraform runs.
resource "null_resource" "example" {
provisioner "local-exec" {
command = "echo 'Hello, Terraform!'"
}
}
12. What are Date sources block in Terraform and how do you use them?
Data sources in Terraform allow you to use the information defined outside of Terraform, defined by another separate Terraform configuration or modified by functions
data "aws_ami" "example" {
most_recent = true
owners = ["self"]
tags = {
Name = "app-server"
Tested = "true"
}
}
13. What is a Dynamic block?
The dynamic
block in Terraform allows you to generate multiple nested blocks dynamically based on a list or map variable.
The syntax for the dynamic
block is as follows:
dynamic "block_type" {
for_each = var.collection
content {
# Block content
}
}
Here’s a simple example of how you might use the dynamic
block to create multiple AWS EC2 instances based on a list of instance types:
resource "aws_instance" "example" {
dynamic "instance" {
for_each = var.instance_types
content {
ami = "ami-12345678"
instance_type = instance.value
}
}
}
variable "instance_types" {
type = list(string)
default = ["t2.micro", "t2.small", "t2.medium"]
}
14. What are service endpoint and private endpoint?
Service endpoints in AWS provide private connectivity between your VPC and AWS services like S3 or DynamoDB.
While private endpoints (powered by AWS PrivateLink) offer private access to services like EC2 or RDS within your VPC.
Both ensure secure communication without exposure to the public internet.
- Service Endpoint:
- A service endpoint is an interface provided by AWS that allows you to privately connect your VPC to supported AWS services.
- When you create a service endpoint, AWS allocates a private IP address from your VPC’s CIDR block for the service.
- Traffic to the service endpoint stays within the AWS network and doesn’t traverse the internet.
- Service endpoints are used for AWS services like Amazon S3, DynamoDB, and others.
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.example.id
service_name = "com.amazonaws.region.s3"
route_table_ids = [aws_route_table.private.id]
}
2. Private Endpoint:
- A private endpoint, also known as an interface endpoint, allows you to connect to AWS services using a private IP address in your VPC.
- Private endpoints are used for services that are powered by AWS PrivateLink, which enables private connectivity between VPCs and AWS services.
- They provide a more granular control over access to the service and can be placed in specific subnets within your VPC.
- Private endpoints are used for services like Amazon EC2, Amazon RDS, and others.
resource "aws_vpc_endpoint_service" "example" {
service_name = "com.amazonaws.region.ec2"
}
resource "aws_vpc_endpoint" "example" {
vpc_id = aws_vpc.example.id
service_name = aws_vpc_endpoint_service.example.service_name
subnet_ids = [aws_subnet.private.id]
}
15. How can we rename a resource in Terraform without deleting it?
terraform state mv <resource_type>.<current_name> <resource_type>.<new_name>
terraform state mv aws_instance.example_instance aws_instance.new_instance
16. What is a Terraform workspace?
Let’s assume you have a simple Terraform configuration for provisioning an AWS EC2 instance:
# main.tf
provider "aws" {
region = "us-west-2"
}
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
}
Now, let's create two separate workspaces for the development and production environments:
# Create a new workspace for development
terraform workspace new development
# Switch to the development workspace
terraform workspace select development
In the development workspace, you might want to override certain configuration values, such as the instance type:
# Override instance type for development environment
variable "instance_type" {
default = "t2.small"
}
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = var.instance_type
}
Similarly, for the production workspace:
# Create a new workspace for production
terraform workspace new production
# Switch to the production workspace
terraform workspace select production
# Override instance type for production environment
variable "instance_type" {
default = "t2.large"
}
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = var.instance_type
}
Here’s an example of how you can use Terraform workspaces to manage multiple environments:
# Set the workspace based on the value of an environment variable
terraform {
backend "local" {
workspace_dir = "${path.root}/workspaces/${var.environment}"
}
}
variable "environment" {x
default = "development"
}
# Use the workspace name to create environment-specific resources
resource "aws_instance" "my_instance" {
ami = data.aws_ami.ubuntu.id
instance_type = "t2.micro"
tags = {
Name = "my-instance-${terraform.workspace}"
}
}
We’re using a local backend and setting the workspace_dir
based on the value of an environment variable called environment
. This allows us to switch between different workspaces by setting the environment
variable to the desired value.
If you found this guide helpful then do click on 👏 the button.
Follow for more Learning like this 😊
If there’s a specific topic you’re curious about, feel free to drop a personal note or comment. I’m here to help you explore whatever interests you!