A RetroSearch Logo

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

Search Query:

Showing content from https://developer.hashicorp.com/terraform/tutorials/state/resource-lifecycle below:

Manage resource lifecycle | Terraform

Lifecycle arguments help control the flow of your Terraform operations by creating custom rules for resource creation and destruction. Instead of Terraform managing operations in the built-in dependency graph, lifecycle arguments help minimize potential downtime based on your resource needs as well as protect specific resources from changing or impacting infrastructure.

This tutorial assumes you are familiar with the standard Terraform workflow. If you are unfamiliar with Terraform, complete the Get Started tutorials first.

For this tutorial, you will need:

Start by cloning the example repository. This configuration builds an EC2 instance and a security group rule to allow port 8080 access to the instance.

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

Change into the repository directory.

$ cd learn-terraform-lifecycle-management

Confirm your AWS CLI region.

$ aws configure get region
us-east-2

Open the terraform.tfvars file and edit the region to match your AWS CLI configuration.

Open the main.tf file and review your configuration. Your two main resources are an EC2 instance and a security group that allows TCP access on port 8080.

##...

resource "aws_instance" "example" {
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.sg_web.id]
  user_data              = <<-EOF
              #!/bin/bash
              apt-get update
              apt-get install -y apache2
              sed -i -e 's/80/8080/' /etc/apache2/ports.conf
              echo "Hello World" > /var/www/html/index.html
              systemctl restart apache2
              EOF
  tags = {
    Name          = "terraform-learn-state-ec2"
    drift_example = "v1"
  }
}

resource "aws_security_group" "sg_web" {
  name = "sg_web"
  ingress {
    from_port   = "8080"
    to_port     = "8080"
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  // connectivity to ubuntu mirrors is required to run `apt-get update` and `apt-get install apache2`
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Initialize your configuration.

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Installing hashicorp/aws v3.26.0...
- Installed hashicorp/aws v3.26.0 (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.

Apply your configuration. Enter yes when prompted to accept your changes.

$ terraform apply


## …

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Outputs:

instance_id = "i-099bb19ca402a6761"
public_ip = "3.138.139.170"

When your apply operation completes, run terraform state list to review the resources managed by Terraform in your state file.

$ terraform state list
data.aws_ami.ubuntu
aws_instance.example
aws_security_group.sg_web

To prevent destroy operations for specific resources, you can add the prevent_destroy attribute to your resource definition. This lifecycle option prevents Terraform from accidentally removing critical resources.

Add prevent_destroy to your EC2 instance.

resource "aws_instance" "example" {
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.sg_web.id]
  user_data              = <<-EOF
              #!/bin/bash
              apt-get update
              apt-get install -y apache2
              sed -i -e 's/80/8080/' /etc/apache2/ports.conf
              echo "Hello World" > /var/www/html/index.html
              systemctl restart apache2
              EOF
  tags = {
    Name          = "terraform-learn-state-ec2"
    drift_example = "v1"
  }

+ lifecycle {
+   prevent_destroy = true
+ }
}

Run terraform destroy to observe the behavior.

$ terraform destroy
aws_security_group.sg_web: Refreshing state... [id=sg-0c9b526ba6f89d910]
aws_instance.example: Refreshing state... [id=i-099bb19ca402a6761]

│ Error: Instance cannot be destroyed

│   on main.tf line 31:
│   31: resource "aws_instance" "example" {

│ Resource aws_instance.example has lifecycle.prevent_destroy set, but the
│ plan calls for this resource to be destroyed. To avoid this error and
│ continue with the plan, either disable lifecycle.prevent_destroy or reduce
│ the scope of the plan using the -target flag.

The prevent_destroy attribute is useful in situations where a change to an attribute would force a replacement and create downtime.

For changes that may cause downtime but must happen, use the create_before_destroy attribute to create your new resource before destroying the old resource.

Update your security group rule to allow port 80 access instead of 8080.

resource "aws_security_group" "sg_web" {
  name = "sg_web"
  ingress {
-  from_port   = "8080"
+  from_port   = "80"
-  to_port   = "8080"
+  to_port   = "80"
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ## ...
}

Update your EC2 instance to reflect this change by adding the create_before_destroy attribute and updating the VM so it runs on port 80.

resource "aws_instance" "example" {
  ami                    = data.aws_ami.ubuntu.id
  instance_type          = "t2.micro"
  vpc_security_group_ids = [aws_security_group.sg_web.id]
  user_data              = <<-EOF
              #!/bin/bash
              apt-get update
              apt-get install -y apache2
-             sed -i -e 's/80/8080/' /etc/apache2/ports.conf
              echo "Hello World" > /var/www/html/index.html
              systemctl restart apache2
              EOF
  tags = {
    Name          = "terraform-learn-state-ec2"
    Drift_example = "v1"
  }

  lifecycle {
-   prevent_destroy = true
+   create_before_destroy = true
  }
}

Run terraform apply and observe the changes that force a replacement. Without the create_before_destroy tag, Terraform would destroy the instance before recreating it, which may lead to downtime. Enter yes when prompted to accept your changes.

$ terraform apply
aws_security_group.sg_web: Refreshing state... [id=sg-0c9b526ba6f89d910]
aws_instance.example: Refreshing state... [id=i-099bb19ca402a6761]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  ~ update in-place
+/- create replacement and then destroy

Terraform will perform the following actions:

  # aws_instance.example must be replaced
+/- resource "aws_instance" "example" {
##...

  # aws_security_group.sg_web will be updated in-place
  ~ resource "aws_security_group" "sg_web" {
        id                     = "sg-0c9b526ba6f89d910"
   ##...

Plan: 1 to add, 1 to change, 1 to destroy.

Changes to Outputs:
  ~ instance_id = "i-099bb19ca402a6761" -> (known after apply)
  ~ public_ip   = "3.138.139.170" -> (known after apply)

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
aws_security_group.sg_web: Modifying... [id=sg-0c9b526ba6f89d910]
aws_security_group.sg_web: Still modifying... [id=sg-0c9b526ba6f89d910, 10s elapsed]
aws_security_group.sg_web: Still modifying... [id=sg-0c9b526ba6f89d910, 20s elapsed]
aws_security_group.sg_web: Modifications complete after 22s [id=sg-0c9b526ba6f89d910]
aws_instance.example: Creating…
aws_instance.example: Creation complete after 1m14s [id=i-0b2fd8a0df19c215d]
aws_instance.example (940b3833): Destroying... [id=i-099bb19ca402a6761]
aws_instance.example: Destruction complete after 41s

Apply complete! Resources: 1 added, 1 changed, 1 destroyed.

Outputs:

instance_id = "i-0b2fd8a0df19c215d"
public_ip = "18.116.49.153"

For changes outside the Terraform workflow that should not impact Terraform operations, use the ignore_changes argument.

Update the drift_example tag in the AWS CLI.

$ aws ec2 create-tags --resources $(terraform output -raw instance_id) --tags Key=drift_example,Value=v2

Add the ignore_changes attribute to your lifecycle block in the EC2 instance.

resource "aws_instance" "example" {
##...
  lifecycle {
    create_before_destroy = true
+   ignore_changes        = [tags]
  }
}

Run terraform apply. This apply will refresh your state file with v2 instead of overwriting your tag with v1 as written in your configuration.

$ terraform apply
aws_security_group.sg_web: Refreshing state... [id=sg-0c9b526ba6f89d910]
aws_instance.example: Refreshing state... [id=i-0b2fd8a0df19c215d]

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

Outputs:

instance_id = "i-0b2fd8a0df19c215d"
public_ip = "18.116.49.153"

Examine your instance in the state file to confirm that your drift_example tag is v2.

$ terraform state show aws_instance.example
##...
# aws_instance.example:
resource "aws_instance" "example" {
    tags                         = {
        "Name"          = "terraform-learn-state-ec2"
        "drift_example" = "v2"
    }
##...

When you are finished with this tutorial, destroy the resources you created. Enter yes when prompted to confirm your changes.

$ terraform destroy

aws_security_group.sg_web: Refreshing state... [id=sg-0c9b526ba6f89d910]
aws_instance.example: Refreshing state... [id=i-0b2fd8a0df19c215d]

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

##...
Plan: 0 to add, 0 to change, 2 to destroy.

Changes to Outputs:
  - instance_id = "i-0b2fd8a0df19c215d" -> null
  - public_ip   = "18.116.49.153" -> null

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes
aws_instance.example: Destruction complete after 1m11s
aws_security_group.sg_web: Destroying... [id=sg-0c9b526ba6f89d910]
aws_security_group.sg_web: Still destroying... [id=sg-0c9b526ba6f89d910, 10s elapsed]
aws_security_group.sg_web: Destruction complete after 11s

Destroy complete! Resources: 2 destroyed.

In this tutorial, you learned the different lifecycle management options you can use to prevent resource deletion. You also used lifecycle management to avoid downtime when Terraform recreates your infrastructure and to ignore changes to certain resource attributes.

For more information about Terraform lifecycle management and state drift, review the resources below:


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