Pages

Wednesday, October 3, 2018

Understanding Terraform state

Once we successfully create a aws instance by running the “terraform apply” command, we will also see another file generated by terraform with the name “terraform.tfstate”

This file is called state file. What terraform does is not just to create the resource but also save everything it knows about the resource in this special file with “tfstate” extension file. This file is a Json file with all details regarding the resource terraform has created.

The terraform state file is quite explanatory

"version": 3,
"terraform_version": "0.11.7",
"serial": 1,
"lineage": "bda22195-37ed-a63a-cfd3-54e1804fcadf",

The version:3 talks about the version of the state file. This is not a terraform version or the resource version that we created.

The terraform_version:0.11.7 talks about the version of the terraform that this state file is created. 

The serial:1 talks about the version of the of the state file. This value gets increased when ever we change the state. 

The next lines that start from modules talk about the resource specific details.
    "modules": [
        {
            "path": [
                "root"
            ],
            "outputs": {},
            "resources": {
                "aws_instance.first-instance": {
                    "type": "aws_instance",
                    "depends_on": [],
                    "primary": {
                        "id": "i-0363a956cb5a76b37",
                        "attributes": {
                            "ami": "ami-9c0638f9",
                            "arn": "arn:aws:ec2:us-east-2:161598355066:instance/i-0363a956cb5a76b37",
                            "associate_public_ip_address": "true",
                            "availability_zone": "us-east-2c",
                            "cpu_core_count": "1",
                            "cpu_threads_per_core": "1",
                            "credit_specification.#": "1",
                            "credit_specification.0.cpu_credits": "standard",
                            "disable_api_termination": "false",
                            "ebs_block_device.#": "0",
                            "ebs_optimized": "false",
      ****************

This state file is considered to be very important coz terraform uses this file not just for creating but also for updating and destroying the infrastructure. Terraform knows if the actual state of resources has changed and if parameters in a template have changed, and then it intelligently figures out what the final state should look like and gets your infrastructure to that state.

Terraform provides command line options where we can edit the state file. The below command list all the resources in the state file

jagadishfirstTemplate$Sun Sep 30@ terraform state list
aws_instance.first-instance

The terraform show command will print the state information in a human readable format

jagadishfirstTemplate$Sun Sep 30@ terraform show
aws_instance.first-instance:
  id = i-0363a956cb5a76b37
  ami = ami-9c0638f9
  arn = arn:aws:ec2:us-east-2:161598355066:instance/i-0363a956cb5a76b37
  associate_public_ip_address = true
  availability_zone = us-east-2c
  cpu_core_count = 1
  cpu_threads_per_core = 1
  credit_specification.# = 1
  credit_specification.0.cpu_credits = standard
  disable_api_termination = false
  ebs_block_device.# = 0
  ebs_optimized = false
  ephemeral_block_device.# = 0
  get_password_data = false
  iam_instance_profile = 
  instance_state = running
  instance_type = t2.micro
  ipv6_addresses.# = 0
  key_name = 
  monitoring = false
  network_interface.# = 0
  network_interface_id = eni-08b7d1faa00bbc6fa
  password_data = 
  placement_group = 
  primary_network_interface_id = eni-08b7d1faa00bbc6fa
  private_dns = ip-172-31-38-85.us-east-2.compute.internal
  private_ip = 172.31.38.85
  public_dns = ec2-18-219-108-48.us-east-2.compute.amazonaws.com
  public_ip = 18.219.108.48
  root_block_device.# = 1
  root_block_device.0.delete_on_termination = false
  root_block_device.0.iops = 100
  root_block_device.0.volume_id = vol-0a3175a45d18b7c88
  root_block_device.0.volume_size = 8
  root_block_device.0.volume_type = gp2
  security_groups.# = 1
  security_groups.3814588639 = default
  source_dest_check = true
  subnet_id = subnet-c861a484
  tags.% = 1
  tags.Name = first-instance
  tenancy = default
  volume_tags.% = 0
  vpc_security_group_ids.# = 1
  vpc_security_group_ids.1322522975 = sg-1a83ef77

Updating the ResourceNow lets see how we can update a resource. 

jagadishfirstTemplate$Sun Sep 30@ cat template.tf 
provider "aws" 
{
     region = "us-east-2"
}

resource "aws_instance" "first-instance" 
{
    instance_type = "t2.micro"
    ami = "ami-9c0638f9"

    tags {
      Name = "first-instance-change"
    }

}

I just changed the tag name from “first-instance” to “first-instance-change”. Now before running the “terraform apply” , lets see what happens if we run this. Luckily terraform provides a “terraform plan” command which will give you the state changes that will happen.

jagadishfirstTemplate$Sun Sep 30@ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_instance.first-instance: Refreshing state... (ID: i-0363a956cb5a76b37)
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  ~ aws_instance.first-instance
      tags.Name: "first-instance" => "first-instance-change"


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

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

If we see the action that terraform will do from the below lines,
Terraform will perform the following actions:

  ~ aws_instance.first-instance
      tags.Name: "first-instance" => "first-instance-change"

We can see that it is going to change the tag name from “first-instance” to “first-instance-change”

Terraform also provides ways to validate the template using “terraform validate”. This will validate the file and display any errors

Another nice command provided by terraform is “terraform fmt” which will format the template file to best practices, 

jagadishfirstTemplate$Sun Sep 30@ terraform fmt
template.tf

jagadishfirstTemplate$Sun Sep 30@ cat template.tf 
provider "aws" {
  region = "us-east-2"
}

resource "aws_instance" "first-instance" {
  instance_type = "t2.micro"
  ami           = "ami-9c0638f9"

  tags {
    Name = "first-instance-change"
  }
}

Now apply the changes
jagadishfirstTemplate$Sun Sep 30@ terraform apply
aws_instance.first-instance: Refreshing state... (ID: i-0363a956cb5a76b37)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  ~ aws_instance.first-instance
      tags.Name: "first-instance" => "first-instance-change"


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

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_instance.first-instance: Modifying... (ID: i-0363a956cb5a76b37)
  tags.Name: "first-instance" => "first-instance-change"
aws_instance.first-instance: Still modifying... (ID: i-0363a956cb5a76b37, 10s elapsed)
aws_instance.first-instance: Modifications complete after 12s (ID: i-0363a956cb5a76b37)

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

If you check the state it will changed some thing as below,
jagadishfirstTemplate$Sun Sep 30@ cat terraform.tfstate | head -n 10
{
    "version": 3,
    "terraform_version": "0.11.7",
    "serial": 2,
    "lineage": "bda22195-37ed-a63a-cfd3-54e1804fcadf",
    "modules": [
        {
            "path": [
                "root"
            ],

The serial version is changed if you observe.

Destroy the Instance - To destroy the resource we created, we can just call “terraform destroy” or we can delete the template.tf file and run the “terraform apply” command. Terraform will automatically identify state that we want to destroy and will destroy the instance

jagadishfirstTemplate$Sun Sep 30@ terraform destroy
aws_instance.first-instance: Refreshing state... (ID: i-0363a956cb5a76b37)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - aws_instance.first-instance


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

Do you really want to destroy?
  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.first-instance: Destroying... (ID: i-0363a956cb5a76b37)
aws_instance.first-instance: Still destroying... (ID: i-0363a956cb5a76b37, 10s elapsed)
aws_instance.first-instance: Still destroying... (ID: i-0363a956cb5a76b37, 20s elapsed)
aws_instance.first-instance: Still destroying... (ID: i-0363a956cb5a76b37, 30s elapsed)
aws_instance.first-instance: Still destroying... (ID: i-0363a956cb5a76b37, 40s elapsed)
aws_instance.first-instance: Destruction complete after 46s

Destroy complete! Resources: 1 destroyed.

More to Come, Happy learning :-)

No comments :

Post a Comment