A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://developer.hashicorp.com/terraform/tutorials/configuration-language/count below:

Manage similar resources with count | Terraform

The count argument replicates the given resource or module a specific number of times with an incrementing counter. It works best when resources will be identical, or nearly so.

In this tutorial, you will use Terraform to provision a VPC, load balancer, and EC2 instances on AWS. Then you will use the count argument to provision multiple EC2 instances per private subnet with a single resource block.

You can complete this tutorial using the same workflow with either Terraform Community Edition or HCP Terraform. HCP Terraform is a platform that you can use to manage and execute your Terraform projects. It includes features like remote state and execution, structured plan output, workspace resource summaries, and more.

Select the Terraform Community Edition tab to complete this tutorial using Terraform Community Edition.

Clone the example GitHub repository.

$ git clone https://github.com/hashicorp-education/learn-terraform-count

Change into the new directory.

$ cd learn-terraform-count

The configuration in main.tf will provision a new VPC with public and private subnets, a load balancer, and two EC2 instances, one in each private subnet. The variables located in variables.tf allow you to configure the VPC. For instance, the private_subnets_per_vpc variable controls the number of private subnets the configuration will create.

Set the TF_CLOUD_ORGANIZATION environment variable to your HCP Terraform organization name. This will configure your HCP Terraform integration.

$ export TF_CLOUD_ORGANIZATION=

Initialize your configuration. Terraform will automatically create the learn-terraform-count workspace in your HCP Terraform organization.

$ terraform init
Initializing modules...
Downloading registry.terraform.io/terraform-aws-modules/security-group/aws 4.9.0 for app_security_group...
- app_security_group in .terraform/modules/app_security_group/modules/web
- app_security_group.sg in .terraform/modules/app_security_group
Downloading registry.terraform.io/terraform-aws-modules/elb/aws 3.0.1 for elb_http...
- elb_http in .terraform/modules/elb_http
- elb_http.elb in .terraform/modules/elb_http/modules/elb
- elb_http.elb_attachment in .terraform/modules/elb_http/modules/elb_attachment
Downloading registry.terraform.io/terraform-aws-modules/security-group/aws 4.9.0 for lb_security_group...
- lb_security_group in .terraform/modules/lb_security_group/modules/web
- lb_security_group.sg in .terraform/modules/lb_security_group
Downloading registry.terraform.io/terraform-aws-modules/vpc/aws 3.14.2 for vpc...
- vpc in .terraform/modules/vpc

Initializing HCP Terraform...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Reusing previous version of hashicorp/random from the dependency lock file
- Installing hashicorp/random v3.3.2...
- Installed hashicorp/random v3.3.2 (signed by HashiCorp)
- Installing hashicorp/aws v4.22.0...
- Installed hashicorp/aws v4.22.0 (signed by HashiCorp)

HCP Terraform has been successfully initialized!

You may now begin working with HCP Terraform. Try running "terraform plan" to
see any changes that are required for your infrastructure.

If you ever set or change modules or Terraform Settings, run "terraform init"
again to reinitialize your working directory.

Open your terraform.tf file and comment out the cloud block that configures the HCP Terraform integration.

terraform.tf

terraform {
  /*
  cloud {
    workspaces {
      name = "learn-terraform-count"
    }
  }
  */

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.22.0"
    }
  }
  required_version = ">= 1.2"
}

Initialize this configuration.

$ terraform init
Initializing modules...
Downloading registry.terraform.io/terraform-aws-modules/security-group/aws 4.9.0 for app_security_group...
- app_security_group in .terraform/modules/app_security_group/modules/web
- app_security_group.sg in .terraform/modules/app_security_group
Downloading registry.terraform.io/terraform-aws-modules/elb/aws 3.0.1 for elb_http...
- elb_http in .terraform/modules/elb_http
- elb_http.elb in .terraform/modules/elb_http/modules/elb
- elb_http.elb_attachment in .terraform/modules/elb_http/modules/elb_attachment
Downloading registry.terraform.io/terraform-aws-modules/security-group/aws 4.9.0 for lb_security_group...
- lb_security_group in .terraform/modules/lb_security_group/modules/web
- lb_security_group.sg in .terraform/modules/lb_security_group
Downloading registry.terraform.io/terraform-aws-modules/vpc/aws 3.14.2 for vpc...
- vpc in .terraform/modules/vpc

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Reusing previous version of hashicorp/random from the dependency lock file
- Installing hashicorp/aws v4.22.0...
- Installed hashicorp/aws v4.22.0 (signed by HashiCorp)
- Installing hashicorp/random v3.3.2...
- Installed hashicorp/random v3.3.2 (signed by HashiCorp)

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

Once your directory has been initialized, apply the configuration, and remember to confirm with a yes.

$ terraform apply
Running apply in HCP Terraform. Output will stream here. Pressing Ctrl-C
will cancel the remote apply if it's still pending. If the apply started it
will stop streaming the logs, but will not stop the apply running remotely.

Preparing the remote apply...

To view this run in a browser, visit:
https://app.terraform.io/app/hashicorp-learn/learn-terraform-count/runs/run-aGgAn9P3wK4bAGn6

Waiting for the plan to start...

Terraform v1.2.0
on linux_amd64
Initializing plugins and modules...
data.aws_ami.amazon_linux: Reading...
data.aws_availability_zones.available: Reading...
data.aws_availability_zones.available: Read complete after 0s [id=us-east-2]
data.aws_ami.amazon_linux: Read complete after 2s [id=ami-07251f912d2a831a3]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.app_a will be created
  + resource "aws_instance" "app_a" {
      + ami                                  = "ami-07251f912d2a831a3"
##...

Plan: 40 to add, 0 to change, 0 to destroy.

Changes to Outputs:
  + instance_ids    = [
      + (known after apply),
      + (known after apply),
    ]
  + public_dns_name = (known after apply)
  + vpc_arn         = (known after apply)

Do you want to perform these actions in workspace "learn-terraform-count"?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

random_string.lb_id: Creating...
random_string.lb_id: Creation complete after 0s [id=X9C5]
module.vpc.aws_vpc.this[0]: Creating...
##...
Apply complete! Resources: 40 added, 0 changed, 0 destroyed.

Outputs:

instance_ids = [
  "i-02a950922e3bc138a",
  "i-0862c3304b43491ea",
]
public_dns_name = "lb-X9C5-client-webapp-dev-96481859.us-east-2.elb.amazonaws.com"
vpc_arn = "arn:aws:ec2:us-east-2:561656980159:vpc/vpc-0f693f9721b61333b"

This configuration has some limitations. Currently, each private subnet only contains one EC2 instance. If you increase the private_subnets_per_vpc variable, Terraform won't automatically add EC2 instances, because the EC2 instance resources are hard coded.

Make this configuration more robust by adding a variable to control the number of EC2 instances in each private subnet with count.

Refactor the EC2 configuration to make it more generic. Remove or comment out the entire block defining the app_b EC2 instance from main.tf.

main.tf

- resource "aws_instance" "app_b" {
-   depends_on = [module.vpc]
-
-   ami           = data.aws_ami.amazon_linux.id
-   instance_type = var.instance_type
-
-   ## ...
-
-   tags = {
-     Terraform   = "true"
-     Project     = var.project_name
-     Environment = var.environment
-   }
- }

Next, rename the resource for the other EC2 instance from app_a to app.

main.tf

- resource "aws_instance" "app_a" {
+ resource "aws_instance" "app" {

Now, add the instances_per_subnet variable to variables.tf to define how many instances each private subnet will have.

variables.tf

variable "instances_per_subnet" {
  description = "Number of EC2 instances in each private subnet"
  type        = number
  default     = 2
}

Next, edit main.tf to use count to provision multiple EC2 instances with the app resource block, based on the value of the new instances_per_subnet variable and the number of private subnets.

main.tf

resource "aws_instance" "app" {
  depends_on = [module.vpc]

  count = var.instances_per_subnet * length(module.vpc.private_subnets)

  ami           = data.aws_ami.amazon_linux.id
  instance_type = var.instance_type

  subnet_id              = module.vpc.private_subnets[count.index % length(module.vpc.private_subnets)]
  vpc_security_group_ids = [module.app_security_group.this_security_group_id]

  ## ...
}

Each instance provisioned by the resource block with count will have a different incrementing value for count.index - starting with zero. This configuration uses count.index and modulo division to assign each instance to a private subnet.

Because the default value of instances_per_subnet is 2, Terraform will provision two EC2 instances per private subnet.

Update the load balancer configuration in the elb_http block to attach the instances to the load balancer.

main.tf

module "elb_http" {
  source  = "terraform-aws-modules/elb/aws"
  version = "3.0.1"

##...

  security_groups = [module.lb_security_group.this_security_group_id]
  subnets         = module.vpc.public_subnets

  number_of_instances = length(aws_instance.app)
  instances           = aws_instance.app.*.id

  listener = [{
    instance_port     = "80"
    instance_protocol = "HTTP"
    lb_port           = "80"
    lb_protocol       = "HTTP"
  }]

##...

The name of resources or modules provisioned with count refers to the entire collection. In this example, aws_instance.app now refers to all of the EC2 instances. You can reference individual items in collections with the same notation as list indexing. For example, aws_instance.app[0] refers to the first instance Terraform provisions.

You can create a list of all of the values of a given attribute for the items in the collection with a star. For instance, aws_instance.app.*.id will be a list of all of the IDs of the instances.

Update outputs.tf to refer to the new aws_instance.app block instead of app_a and app_b.

outputs.tf

output "instance_ids" {
  description = "IDs of EC2 instances"
  value       = aws_instance.app.*.id
}

Apply this configuration now. Be sure to respond to the confirmation prompt with yes.

Terraform will output values for the VPC, load balancer, and instances.

$ terraform apply
## ...

Apply complete! Resources: 8 added, 0 changed, 4 destroyed.

Outputs:

instance_ids = [
  "i-0bc4309c117df766a",
  "i-0aaa6de2b610ae749",
  "i-035ff2723aace0f12",
  "i-02640c564d3f08152",
]
public_dns_name = "lb-yksg-client-webapp-dev-702243816.us-west-2.elb.amazonaws.com"
vpc_arn = "arn:aws:ec2:us-west-2:561656980159:vpc/vpc-0195a5982b1ad302b"

Now you have configured the number EC2 instances per private subnet using the instances_per_subnet variable and count. Terraform configured that many instances per subnet, assigned them to subnets, and attached them to the load balancer.

After verifying that the resources were deployed successfully, run terraform destroy to destroy them. Remember to respond to the confirmation prompt with yes.

If you used HCP Terraform for this tutorial, after destroying your resources, delete the learn-terraform-count workspace from your HCP Terraform organization.

Now that you have used count in your configuration, explore the following resources.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4