Terraform: managing AWS Lightsail instances

preface

Terraform It is an open source infrastructure and code (IaC) tool that can provide a consistent CLI (command line interface) workflow to manage hundreds of cloud services, and encode the cloud API as a declarative configuration file for management.
This article creates a management AWS Lightsail Example to get started with the use of Terraform.

Installing Terraform CLI

To use Terraform, you must first install the Terraform command line tool on the local system. HashiCorp provides a pre compiled binary distribution package, which can be used through( https://www.terraform.com/dow... )Directly download the binary package of the corresponding platform, decompress it and put it in the corresponding execution path. You can also install it through some software package management tools, such as Linux brew / homebrew on Linux/OS X and chocolate on Windows.

Here, our example is installed on Linux using LinuxBrew

> brew install terraform

After the installation is complete, you can view its version

❯ terraform -version
Terraform v1.0.11
on linux_amd64

Use - help to view the available commands. After the installation is successful, we can use Terraform to create the corresponding infrastructure project.

AWS account preparation

This article will try Terraform by creating a project to manage AWS Lightsial instances, so you need an AWS account and access credentials to install and configure AWS CLI tools in the local environment.
To install and configure AWS CLI, refer to its documentation( https://docs.aws.amazon.com/c... )After configuration, you can access the corresponding AWS resources at the local command line terminal.

Create and initialize the Terraform project

Terraform manages the declarative code of an infrastructure project locally through folders. For example, we create a folder locally

> mkdir mylightsail
> cd mylightsail/

After entering the folder, create a file with. TF as the suffix, such as main.tf

> touch main.tf

Then use the editor to open the file for editing and write the following code block

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.65"
    }
  }
}

# Configure the AWS Provider
provider "aws" {
  region = "ap-southeast-1"
}

The terrain / required_providers block defines the providers required by the project. Terrain manages the corresponding infrastructure resources through different providers( https://registry.terraform.io )To find the required Providers, such as GCP, Azure and alicloud. Here, because the resources we want to manage are AWS Lightsail instances, we use the ones officially provided by Hashicorp hashicorp/aws .

Some options of the Provider are configured in the "AWS" section of the Provider. For example, the region is configured as ap-southeast-1. Therefore, please ensure that the AWS access credentials configured above can operate the resources of the region.

That is, here we define the Provider we need to use and its corresponding option configuration. Next, we need to use the terrain init command to initialize the project

> terraform init

Initializing provider plugins...
...
Terraform has been successfully initialized!

Initialization will start from( https://registry.terraform.io/ )Download the corresponding Provider plug-in to the. Terraform / providers / directory for the next command.
At the same time, a. Terrain.lock.hcl file will be generated to record the specific Provider version used. Its function is similar to the package lock file of NPM. It can be submitted to the code version management warehouse, and other collaborative members can keep using the same plug-in version.

Create infrastructure resources

After the initialization of the project, we can write the declarative configuration of the resources to be created. We can directly write the corresponding configuration into the main.tf file or create a new file with. TF as the suffix. Here we create a new file named resources.tf and write the definition of the resources we need

## LightSail Resources

resource "aws_lightsail_static_ip" "Example-sig-ip" {
  name = "Example-EIP"
}

resource "aws_lightsail_instance" "Example-sig" {
  name              = "Example-Sig"
  availability_zone = "ap-southeast-1c"
  blueprint_id      = "ubuntu_20_04"
  bundle_id         = "nano_2_0"
  key_pair_name     = "LightsailDefaultKeyPair"
  tags = {
    Example = ""
  }
}

resource "aws_lightsail_static_ip_attachment" "Example-sig-ip-attache" {
  static_ip_name = aws_lightsail_static_ip.Example-sig-ip.id
  instance_name  = aws_lightsail_instance.Example-sig.id
}

resource "aws_lightsail_instance_public_ports" "Example-sig-public-ports" {
  instance_name = aws_lightsail_instance.Example-sig.name

  port_info {
    protocol  = "tcp"
    from_port = 0
    to_port   = 65535
    cidrs = [
      "0.0.0.0/0"
    ]
  }
  port_info {
    protocol  = "udp"
    from_port = 0
    to_port   = 65535
    cidrs = [
      "0.0.0.0/0"
    ]
  }
}

The format of the defined resource is resource "[Provider_resource _type]" resource_name ". The first parameter is the resource type name supported by the corresponding Provider, and the second parameter is the resource name defined by ourselves (which can be used for other resource references). For example, we first define a static IP resource of Lightsail, where the parameter name specifies the name of AWS resource.

In the above definition, we declare the following resources

  • A Lightsail static IP address
  • A Lightsail calculation instance and bind the SSH key named LightsailDefaultKeyPair
  • Binding of static IP address and calculation instance
  • Open network port group of the instance (similar to the security group definition of AWS EC2 instance)

After saving the file, we can use the terrain FMT command to format the file format and terrain validate to check for syntax errors.

After defining the resources we want, we first execute the plan by commanding the terrain plan command to view the specific execution changes (the plan will not actually operate the corresponding resources)

❯ terraform plan                    

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_lightsail_instance.Example-sig will be created
  + resource "aws_lightsail_instance" "Example-sig" {
      + arn                = (known after apply)
      + availability_zone  = "ap-southeast-1c"
      + blueprint_id       = "ubuntu_20_04"
      + bundle_id          = "nano_2_0"
      + cpu_count          = (known after apply)
      + created_at         = (known after apply)
      + id                 = (known after apply)
      + ipv6_address       = (known after apply)
      + ipv6_addresses     = (known after apply)
      + is_static_ip       = (known after apply)
      + key_pair_name      = "LightsailDefaultKeyPair"
      + name               = "Example-Sig"
      + private_ip_address = (known after apply)
      + public_ip_address  = (known after apply)
      + ram_size           = (known after apply)
      + tags               = {
          + "Example" = ""
        }
      + tags_all           = {
          + "Example" = (known after apply)
        }
      + username           = (known after apply)
    }

  # aws_lightsail_instance_public_ports.Example-sig-public-ports will be created
  + resource "aws_lightsail_instance_public_ports" "Example-sig-public-ports" {
      + id            = (known after apply)
      + instance_name = "Example-Sig"

      + port_info {
          + cidrs     = [
              + "0.0.0.0/0",
            ]
          + from_port = 0
          + protocol  = "tcp"
          + to_port   = 65535
        }
      + port_info {
          + cidrs     = [
              + "0.0.0.0/0",
            ]
          + from_port = 0
          + protocol  = "udp"
          + to_port   = 65535
        }
    }

  # aws_lightsail_static_ip.Example-sig-ip will be created
  + resource "aws_lightsail_static_ip" "Example-sig-ip" {
      + arn          = (known after apply)
      + id           = (known after apply)
      + ip_address   = (known after apply)
      + name         = "Example-EIP"
      + support_code = (known after apply)
    }

  # aws_lightsail_static_ip_attachment.Example-sig-ip-attache will be created
  + resource "aws_lightsail_static_ip_attachment" "Example-sig-ip-attache" {
      + id             = (known after apply)
      + instance_name  = (known after apply)
      + ip_address     = (known after apply)
      + static_ip_name = (known after apply)
    }

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

+Indicates the resources to be added, (know after apply) means to only want to (apply) in the specific After that, AWS will create the specific value that will be returned only after the corresponding resource is created according to the definition. Next, you can use terrain apply to perform the operation. After successful execution, a. Terrain / terrain.state file will be generated to record the resource status after execution, or you can view it through the command terrain show

❯ terraform show
# aws_lightsail_instance.Example-sig:
resource "aws_lightsail_instance" "Example-sig" {
    arn                = "arn:aws:lightsail:ap-southeast-1:090767794770:Instance/21cb0ea5-e814-4307-8606-01348d98be15"
    availability_zone  = "ap-southeast-1c"
    blueprint_id       = "ubuntu_20_04"
    bundle_id          = "nano_2_0"
    cpu_count          = 1
    created_at         = "2021-11-08T05:49:05Z"
    id                 = "Example-Sig"
    ipv6_address       = "2406:da18:8ae:4b02:1f2:4ff1:daa1:6a8c"
    ipv6_addresses     = [
        "2406:da18:8ae:4b02:1f2:4ff1:daa1:6a8c",
    ]
    is_static_ip       = true
    key_pair_name      = "LightsailDefaultKeyPair"
    name               = "Example-Sig"
    private_ip_address = "172.26.45.249"
    public_ip_address  = "54.220.33.133"
    ram_size           = 0.5
    tags               = {
        "Example" = ""
    }
    tags_all           = {
        "Example" = ""
    }
    username           = "ubuntu"
}

# aws_lightsail_instance_public_ports.Example-sig-public-ports:
resource "aws_lightsail_instance_public_ports" "Example-sig-public-ports" {
    id            = "Example-Sig-987241840"
    instance_name = "Example-Sig"

    port_info {
        cidrs     = [
            "0.0.0.0/0",
        ]
        from_port = 0
        protocol  = "tcp"
        to_port   = 65535
    }
    port_info {
        cidrs     = [
            "0.0.0.0/0",
        ]
        from_port = 0
        protocol  = "udp"
        to_port   = 65535
    }
}

# aws_lightsail_static_ip.Example-sig-ip:
resource "aws_lightsail_static_ip" "Example-sig-ip" {
    arn          = "arn:aws:lightsail:ap-southeast-1:090767794770:StaticIp/3f0298e0-efeb-4429-9574-156fef12a48f"
    id           = "Example-EIP"
    ip_address   = "54.220.33.133"
    name         = "Example-EIP"
    support_code = "313963776615/54.220.33.133"
}

# aws_lightsail_static_ip_attachment.Example-sig-ip-attache:
resource "aws_lightsail_static_ip_attachment" "exmaple-sig-ip-attache" {
    id             = "Example-EIP"
    instance_name  = "Example-Sig"
    ip_address     = "54.220.33.133"
    static_ip_name = "Example-EIP"
}

Then we can update the resources on the cloud by updating the resource definition file and executing plan & apply. If the resources are no longer needed, we can also destroy all resources through a command of terrain destroy.

summary

Taking the simple AWS Lightsail resource management as an example, this paper shows how to use Terraform to manage resources on the cloud. We define the resources we need through a declarative code. At the same time, the resource definition code can be versioned through the version management tool to further realize the working mode of IaC.

In this way, we use the local execution mode of Terraform. In addition to local execution, Terraform also provides the function of back-end execution, so that execution can be placed in some execution environments on the cloud. The management of resource status will also be maintained on the back-end, so as to realize CI/CD Pipeline and GitOps. Among them, Hashicorp Terraform Cloud It is a Backend. The next article will put the example on the terrain cloud for execution.

Keywords: DevOps

Added by crowezr on Tue, 23 Nov 2021 12:21:11 +0200