Terraform Basics – AWS / GCP / Aliyun

What is Terraform?

It’s a tool to create, manage infrastructure as a code. Infrastructure includes not only servers but also network resources –e.g. DNS, loadbalancer. The benefit you can get is as follows:

  • Versioning of your changes
  • Management of all services as a whole (orchestration)
  • Single management of multi-cloud platform
  • and so on …

Let’s Try

I make two compute instances and make modifications, and finally delete all resources to demonstrate how to use Terraform.

  • on AWS (amazon web service), GCP (Google cloud platform) and Aliyun (Alibaba cloud)
  1. Install Terraform
  2. Get credentials
  3. Create servers
  4. Modify servers
  5. Delete all procured resources

Install Terraform


Terraform is distributed as a binary. Just download it and move it to wherever you like.

Download Terraform

$ wget https://releases.hashicorp.com/terraform/0.11.13/terraform_0.11.13_linux_amd64.zip
$ unzip terraform_0.11.13_linux_amd64.zip
$ sudo chmod +x terraform
$ sudo mv terraform /usr/local/bin/

Get credentials


To use cloud provider, you need to create a user credential in each cloud provider. You need to grant each users a sufficient privilege to carry out your tasks –e.g. create a compute instance.

Create servers


To demonstrate the procurement process, I create following resources in each cloud provider.

  • VPC … whole network range for this project
  • Subnets … sub network in VPC where services are installed
  • Compute instances … servers

In Terraform, configurations are defined in the text file with extension “.tf“.

First I create <cloud-provider>_sandbox.tf file for each provider.

AWS

aws_sandbox.tf
provider "aws" {
  region = "us-east-1"
  shared_credentials_file = "/home/k_shogo/.aws/credentials" # this is not necessary
  profile = "default" # this is not necessary
}

# create vpc
resource "aws_vpc" "sandbox_vpc" {
    cidr_block = "172.16.0.0/16"
}

# create internet gateway
resource "aws_internet_gateway" "sandbox_igw" {
    vpc_id = "${aws_vpc.sandbox_vpc.id}"
}

# create route table
resource "aws_route_table" "public" {
  vpc_id = "${aws_vpc.sandbox_vpc.id}"
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = "${aws_internet_gateway.sandbox_igw.id}"
  }
}

# create subnet
resource "aws_subnet" "sandbox_public" {
    vpc_id = "${aws_vpc.sandbox_vpc.id}"
    cidr_block = "172.16.0.0/24"
    availability_zone = "us-east-1a"
}

# associate route table with subnet
resource "aws_route_table_association" "sandbox_public_assoc" {
  subnet_id      = "${aws_subnet.sandbox_public.id}"
  route_table_id = "${aws_route_table.public.id}"
}

# register public key
resource "aws_key_pair" "tf_key" {
  key_name = "sandbox_tf_key"
  public_key = "${file("../tf_key.pub")}"
}

resource "aws_security_group" "sandbox_sg" {
  vpc_id      = "${aws_vpc.sandbox_vpc.id}"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port       = 0
    to_port         = 0
    protocol        = "-1"
    cidr_blocks     = ["0.0.0.0/0"]
  }
}

# procure servers
resource "aws_instance" "sandbox-server" {
  ami = "ami-0a313d6098716f372" # Ubuntu 18.04 LTS
  instance_type = "t2.micro"
  count = 2
  subnet_id = "${aws_subnet.sandbox_public.id}"
  key_name = "sandbox_tf_key"
  vpc_security_group_ids = ["${aws_security_group.sandbox_sg.id}"]
  associate_public_ip_address = true

  tags = {
    Name = "${format("sandbox%02d", count.index)}"
  }
}

GCP

gcp_sandbox.tf
# variables
variable "zone" {
  default = "us-east1-b"
}

provider "google" {
  credentials = "${file("sa.json")}"
  project = "my-project-id"
  region      = "us-east1"
}

# create vpc
resource "google_compute_network" "sandbox-vpc" {
  name = "sandbox-vpc"
  auto_create_subnetworks = "false"
}

# create a subnet resource
resource "google_compute_subnetwork" "sandbox-subnet" {
  name = "sandbox-subnet"
  ip_cidr_range = "172.16.0.0/24"
  network = "${google_compute_network.sandbox-vpc.name}"
}

# create firewall rule
resource "google_compute_firewall" "sandbox-sg" {
  name = "sandbox-sg"
  network = "${google_compute_network.sandbox-vpc.name}"

  allow {
    protocol = "tcp"
    ports = ["22"]
  }

  source_ranges = ["0.0.0.0/0"]
}

# procure global ip
resource "google_compute_address" "frontend-ip" {
  count = 2
  name = "frontend-ip-${count.index}"
}

# procure servers
resource "google_compute_instance" "sandbox-server" {
  boot_disk {
    initialize_params {
      image = "ubuntu-os-cloud/ubuntu-1804-lts"
    }
  }
  machine_type = "n1-standard-1"
  count = 2
  network_interface {
    subnetwork = "${google_compute_subnetwork.sandbox-subnet.name}"
    access_config {
        nat_ip = "${element(google_compute_address.frontend-ip.*.address, count.index)}"
    }
  }
  name = "${format("sandbox%02d", count.index)}"
  zone = "${var.zone}"

  metadata = {
    sshKeys = "tf-user:${file("../tf_key.pub")}"
  }
}

Aliyun

aliyun_sandbox.tf
provider "alicloud" {
  access_key = "${var.aliyun_access_key}"
  secret_key = "${var.aliyun_secret_key}"
  region = "us-east-1"
}

# create vpc
resource "alicloud_vpc" "vpc" {
  name       = "tf_sandbox_vpc"
  cidr_block = "172.16.0.0/12"
}

# create vswitch(subnet)
resource "alicloud_vswitch" "vsw" {
  vpc_id            = "${alicloud_vpc.vpc.id}"
  cidr_block        = "172.16.0.0/21"
  availability_zone = "us-east-1a"
}

# create security group
resource "alicloud_security_group" "sandbox_sg" {
  name = "sandbox_sg"
  vpc_id = "${alicloud_vpc.vpc.id}"
}

# create security rule and associate to security group
resource "alicloud_security_group_rule" "allow_ssh" {
  type              = "ingress"
  ip_protocol       = "tcp"
  policy            = "accept"
  port_range        = "22/22"
  security_group_id = "${alicloud_security_group.sandbox_sg.id}"
  cidr_ip           = "0.0.0.0/0"
}

# get compute instance type id
data "alicloud_instance_types" "1c1g" {
  cpu_core_count = 1
  memory_size = 1
}

# get image id
data "alicloud_images" "default" {
  name_regex = "^ubuntu_18_04"
  most_recent = true
  owners = "system"
}

# register ssh public key
resource "alicloud_key_pair" "tf_key" {
    key_name = "sandbox_tf_key"
    public_key = "${file("../tf_key.pub")}"
}

# create sandbox server
resource "alicloud_instance" "sandbox" {
  count = 2
  image_id = "${data.alicloud_images.default.images.0.id}"
  instance_type = "${data.alicloud_instance_types.1c1g.instance_types.0.id}"
  security_groups = ["${alicloud_security_group.sandbox_sg.id}"]
  instance_name = "${format("sandbox%02d", count.index)}"
  key_name = "sandbox_tf_key"
  internet_max_bandwidth_out = 10  # public ip is assigned by specifying this key
  vswitch_id = "${alicloud_vswitch.vsw.id}"
}

You can check if the syntax are correct.

AWS

$ 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.


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

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

Terraform will perform the following actions:

  + aws_instance.sandbox-server[0]
      ami:                                         "ami-0a313d6098716f372"
      associate_public_ip_address:                 "true"
      instance_type:                               "t2.micro"
      key_name:                                    "sandbox_tf_key"
      subnet_id:                                   "${aws_subnet.sandbox_public.id}"
      tags.Name:                                   "sandbox00"
...
  + aws_instance.sandbox-server[1]
      ami:                                         "ami-0a313d6098716f372"
      associate_public_ip_address:                 "true"
      instance_type:                               "t2.micro"
      key_name:                                    "sandbox_tf_key"
      subnet_id:                                   "${aws_subnet.sandbox_public.id}"
      tags.Name:                                   "sandbox01"
...
  + aws_internet_gateway.sandbox_igw
      vpc_id:                                      "${aws_vpc.sandbox_vpc.id}"
...
  + aws_key_pair.tf_key
      key_name:                                    "sandbox_tf_key"
      public_key:                                  "ssh-rsa AAAA***"
...
  + aws_route_table.public
      route.#:                                     "1"
      route.~2446290441.cidr_block:                "0.0.0.0/0"
      route.~2446290441.gateway_id:                "${aws_internet_gateway.sandbox_igw.id}"
      vpc_id:                                      "${aws_vpc.sandbox_vpc.id}"
...
  + aws_route_table_association.sandbox_public_assoc
      route_table_id:                              "${aws_route_table.public.id}"
      subnet_id:                                   "${aws_subnet.sandbox_public.id}"
...
  + aws_security_group.sandbox_sg
      egress.482069346.cidr_blocks.0:              "0.0.0.0/0"
      egress.482069346.protocol:                   "-1"
      ingress.2541437006.cidr_blocks.0:            "0.0.0.0/0"
      ingress.2541437006.from_port:                "22"
      ingress.2541437006.protocol:                 "tcp"
      ingress.2541437006.to_port:                  "22"
      vpc_id:                                      "${aws_vpc.sandbox_vpc.id}"
...
  + aws_subnet.sandbox_public
      availability_zone:                           "us-east-1a"
      cidr_block:                                  "172.16.0.0/24"
      vpc_id:                                      "${aws_vpc.sandbox_vpc.id}"
...
  + aws_vpc.sandbox_vpc
      cidr_block:                                  "172.16.0.0/16"
...

Plan: 9 to add, 0 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.

GCP

$ 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.


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

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

Terraform will perform the following actions:

  + google_compute_address.frontend-ip[0]
      address_type:                                        "EXTERNAL"
      name:                                                "frontend-ip-0"
...
  + google_compute_address.frontend-ip[1]
      address_type:                                        "EXTERNAL"
      name:                                                "frontend-ip-1"
...
  + google_compute_firewall.sandbox-sg
      allow.803338340.ports.0:                             "22"
      allow.803338340.protocol:                            "tcp"
      name:                                                "sandbox-sg"
      network:                                             "sandbox-vpc"
      source_ranges.1080289494:                            "0.0.0.0/0"
...
  + google_compute_instance.sandbox-server[0]
      boot_disk.0.initialize_params.0.image:               "ubuntu-os-cloud/ubuntu-1804-lts"
      machine_type:                                        "n1-standard-1"
      metadata.sshKeys:                                    "tf-user:ssh-rsa AAAA****"
      name:                                                "sandbox00"
      network_interface.0.subnetwork:                      "sandbox-subnet"
      zone:                                                "us-east1-b"
...
  + google_compute_instance.sandbox-server[1]
      boot_disk.0.initialize_params.0.image:               "ubuntu-os-cloud/ubuntu-1804-lts"
      machine_type:                                        "n1-standard-1"
      metadata.sshKeys:                                    "tf-user:ssh-rsa AAAA****"
      name:                                                "sandbox01"
      network_interface.0.access_config.0.nat_ip:          "${element(google_compute_address.frontend-ip.*.address, count.index)}"
      network_interface.0.subnetwork:                      "sandbox-subnet"
      zone:                                                "us-east1-b"
...
  + google_compute_network.sandbox-vpc
      name:                                                "sandbox-vpc"
...
  + google_compute_subnetwork.sandbox-subnet
      ip_cidr_range:                                       "172.16.0.0/24"
      name:                                                "sandbox-subnet"
      network:                                             "sandbox-vpc"
...

Plan: 7 to add, 0 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.

Aliyun

$ 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.

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

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

Terraform will perform the following actions:

  + alicloud_instance.sandbox[0]
      image_id:                   "ubuntu_18_04_64_20G_alibase_20190223.vhd"
      instance_name:              "sandbox00"
      instance_type:              "ecs.n1.tiny"
      internet_max_bandwidth_out: "10"
      key_name:                   "sandbox_tf_key"
      vswitch_id:                 "${alicloud_vswitch.vsw.id}"
...
  + alicloud_instance.sandbox[1]
      image_id:                   "ubuntu_18_04_64_20G_alibase_20190223.vhd"
      instance_name:              "sandbox01"
      instance_type:              "ecs.n1.tiny"
      internet_max_bandwidth_out: "10"
      key_name:                   "sandbox_tf_key"
      vswitch_id:                 "${alicloud_vswitch.vsw.id}"
...
  + alicloud_key_pair.tf_key
      key_name:                   "sandbox_tf_key"
      public_key:                 "ssh-rsa AAAA***"
...
  + alicloud_security_group.sandbox_sg
      name:                       "sandbox_sg"
      vpc_id:                     "${alicloud_vpc.vpc.id}"
...
  + alicloud_security_group_rule.allow_ssh
      cidr_ip:                    "0.0.0.0/0"
      ip_protocol:                "tcp"
      policy:                     "accept"
      port_range:                 "22/22"
      priority:                   "1"
      security_group_id:          "${alicloud_security_group.sandbox_sg.id}"
      type:                       "ingress"
...
  + alicloud_vpc.vpc
      cidr_block:                 "172.16.0.0/12"
      name:                       "tf_sandbox_vpc"
...
  + alicloud_vswitch.vsw
      availability_zone:          "us-east-1a"
      cidr_block:                 "172.16.0.0/21"
      vpc_id:                     "${alicloud_vpc.vpc.id}"
...

Plan: 7 to add, 0 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.

Let’s apply and create servers.

AWS

$ terraform apply
...
Plan: 9 to add, 0 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_key_pair.tf_key: Creating...
...
aws_vpc.sandbox_vpc: Creating...
...
aws_key_pair.tf_key: Creation complete after 0s (ID: sandbox_tf_key)
aws_vpc.sandbox_vpc: Creation complete after 2s (ID: vpc-0fedb4b5c115339d8)
aws_internet_gateway.sandbox_igw: Creating...
...
aws_security_group.sandbox_sg: Creating...
...
aws_subnet.sandbox_public: Creating...
...
aws_subnet.sandbox_public: Creation complete after 0s (ID: subnet-0148f2919584b16d4)
aws_internet_gateway.sandbox_igw: Creation complete after 0s (ID: igw-08f522b62a6da0b69)
aws_route_table.public: Creating...
...
aws_route_table.public: Creation complete after 1s (ID: rtb-02a2a1ea215e6b516)
aws_route_table_association.sandbox_public_assoc: Creating...
...
aws_route_table_association.sandbox_public_assoc: Creation complete after 0s (ID: rtbassoc-0e28e80986f5e6025)
aws_security_group.sandbox_sg: Creation complete after 2s (ID: sg-02afb926fd9574f1a)
aws_instance.sandbox-server[0]: Creating...
...
aws_instance.sandbox-server[1]: Creating...
...
aws_instance.sandbox-server.0: Still creating... (10s elapsed)
aws_instance.sandbox-server.1: Still creating... (10s elapsed)
aws_instance.sandbox-server.0: Still creating... (20s elapsed)
aws_instance.sandbox-server.1: Still creating... (20s elapsed)
aws_instance.sandbox-server.0: Still creating... (30s elapsed)
aws_instance.sandbox-server.1: Still creating... (30s elapsed)
aws_instance.sandbox-server.0: Still creating... (40s elapsed)
aws_instance.sandbox-server.1: Still creating... (40s elapsed)
aws_instance.sandbox-server[0]: Creation complete after 42s (ID: i-0f9b44d71906330ce)
aws_instance.sandbox-server[1]: Creation complete after 42s (ID: i-05ddd9d6d4cdae4ca)

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

GCP

$ terraform apply
...
Plan: 7 to add, 0 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

google_compute_address.frontend-ip[0]: Creating...
...
google_compute_network.sandbox-vpc: Creating...
...
google_compute_address.frontend-ip[1]: Creating...
...
google_compute_address.frontend-ip[1]: Creation complete after 4s (ID: my-project-id/us-east1/frontend-ip-1)
google_compute_address.frontend-ip[0]: Creation complete after 4s (ID: my-project-id/us-east1/frontend-ip-0)
google_compute_network.sandbox-vpc: Still creating... (10s elapsed)
google_compute_network.sandbox-vpc: Creation complete after 16s (ID: sandbox-vpc)
google_compute_firewall.sandbox-sg: Creating...
...
google_compute_subnetwork.sandbox-subnet: Creating...
...
google_compute_firewall.sandbox-sg: Creation complete after 7s (ID: sandbox-sg)
google_compute_subnetwork.sandbox-subnet: Still creating... (10s elapsed)
google_compute_subnetwork.sandbox-subnet: Still creating... (20s elapsed)
google_compute_subnetwork.sandbox-subnet: Creation complete after 26s (ID: us-east1/sandbox-subnet)
google_compute_instance.sandbox-server[0]: Creating...
...
google_compute_instance.sandbox-server[1]: Creating...
...
google_compute_instance.sandbox-server.0: Still creating... (10s elapsed)
google_compute_instance.sandbox-server.1: Still creating... (10s elapsed)
google_compute_instance.sandbox-server[1]: Creation complete after 17s (ID: sandbox01)
google_compute_instance.sandbox-server.0: Still creating... (20s elapsed)
google_compute_instance.sandbox-server[0]: Creation complete after 27s (ID: sandbox00)

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

Aliyun

$ terraform apply
~same output as in `$ terraform apply`.~
Plan: 7 to add, 0 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

alicloud_vpc.vpc: Creating...
...
alicloud_key_pair.tf_key: Creating...
...
alicloud_key_pair.tf_key: Creation complete after 4s (ID: sandbox_tf_key)
alicloud_vpc.vpc: Still creating... (10s elapsed)
alicloud_vpc.vpc: Creation complete after 17s (ID: vpc-0xiq50c8jea8rr9opqd58)
alicloud_security_group.sandbox_sg: Creating...
...
alicloud_vswitch.vsw: Creating...
...
alicloud_security_group.sandbox_sg: Creation complete after 3s (ID: sg-0xi1lk7w3kj3khcv7nzt)
alicloud_security_group_rule.allow_ssh: Creating...
...
alicloud_security_group_rule.allow_ssh: Creation complete after 4s (ID: sg-0xi1lk7w3kj3khcv7nzt:ingress:tcp:22/22::0.0.0.0/0:accept:1)
alicloud_vswitch.vsw: Still creating... (10s elapsed)
alicloud_vswitch.vsw: Creation complete after 12s (ID: vsw-0xij7wju82bvfy7k55bye)
alicloud_instance.sandbox[1]: Creating...
...
alicloud_instance.sandbox[0]: Creating...
...
alicloud_instance.sandbox.0: Still creating... (10s elapsed)
alicloud_instance.sandbox.1: Still creating... (10s elapsed)
alicloud_instance.sandbox.1: Still creating... (20s elapsed)
alicloud_instance.sandbox.0: Still creating... (20s elapsed)
alicloud_instance.sandbox.1: Still creating... (30s elapsed)
alicloud_instance.sandbox.0: Still creating... (30s elapsed)
alicloud_instance.sandbox.1: Still creating... (40s elapsed)
alicloud_instance.sandbox.0: Still creating... (40s elapsed)
alicloud_instance.sandbox[0]: Creation complete after 49s (ID: i-0xihi71f0f04ryc3bbjj)
alicloud_instance.sandbox[1]: Creation complete after 50s (ID: i-0xiepsafguau2phhv6rw)

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

To confirm these servers are correctly procured, log in to the servers using local private key.

AWS

$ terraform show | grep public_ip
  associate_public_ip_address = true
  public_ip = 18.212.64.**
  associate_public_ip_address = true
  public_ip = 34.201.242.**
  map_public_ip_on_launch = false
$ ssh -i ../tf_key ubuntu@18.212.64.**
The authenticity of host '18.212.64.** (18.212.64.**)' can't be established.
ECDSA key fingerprint is SHA256:MfoKB6BxJlIEZ4l9jbMMXiBE65zRwi0O0TLhaexhuRo.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '18.212.64.**' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-1032-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri Apr 19 20:27:19 UTC 2019

  System load:  0.1               Processes:           86
  Usage of /:   13.6% of 7.69GB   Users logged in:     0
  Memory usage: 14%               IP address for eth0: 172.16.0.107
  Swap usage:   0%

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

To run a command as administrator (user "root"), use "sudo ".
See "man sudo_root" for details.

ubuntu@ip-172-16-0-107:~$ 

GCP

$ terraform show | grep nat_ip
  network_interface.0.access_config.0.assigned_nat_ip = 
  network_interface.0.access_config.0.nat_ip = 35.243.181.**
  network_interface.0.access_config.0.assigned_nat_ip = 
  network_interface.0.access_config.0.nat_ip = 35.237.183.**
k_shogo@ubuntu16-nso:~/sandbox_novmillan/gcp_infra_base$ ssh -i ../tf_key tf-user@35.243.181.**
The authenticity of host '35.243.181.** (35.243.181.**)' can't be established.
ECDSA key fingerprint is SHA256:eNX9w+0N+uhzUuy8dOvE2DVGhUkasahWdSFPsqMVXXc.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '35.243.181.**' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-1029-gcp x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri Apr 19 21:55:01 UTC 2019

  System load:  0.58              Processes:           91
  Usage of /:   11.8% of 9.52GB   Users logged in:     0
  Memory usage: 5%                IP address for ens4: 172.16.0.3
  Swap usage:   0%

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.



The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

tf-user@sandbox00:~$ 

Aliyun

$ terraform show | grep public_ip
  public_ip = 47.90.215.**
  public_ip = 47.89.190.**
$ ssh -i ../tf_key root@47.90.215.**
The authenticity of host '47.90.215.** (47.90.215.**)' can't be established.
ECDSA key fingerprint is SHA256:4ru0cC70b7i4liKzwO7mqpjoCsUWtCtWUYAJGL/CELs.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '47.90.215.**' (ECDSA) to the list of known hosts.
Welcome to Ubuntu 18.04.2 LTS (GNU/Linux 4.15.0-45-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage


Welcome to Alibaba Cloud Elastic Compute Service !

root@iZ0xiik0m7h8m34653q7x0Z:~# 

Modify servers


Procured resources can be modified by modifying the tf file, and apply it again.

Add tags on the procured servers.

AWS

aws_sandbox.tf
resource "aws_instance" "sandbox-server" {
  tags = {
    Tier = "frontend"
  }
$ terraform apply
...
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.sandbox-server[0]
      tags.%:    "1" => "2"
      tags.Tier: "" => "frontend"

  ~ aws_instance.sandbox-server[1]
      tags.%:    "1" => "2"
      tags.Tier: "" => "frontend"


Plan: 0 to add, 2 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.sandbox-server[1]: Modifying... (ID: i-05ddd9d6d4cdae4ca)
...
aws_instance.sandbox-server[0]: Modifying... (ID: i-0f9b44d71906330ce)
...
aws_instance.sandbox-server[1]: Modifications complete after 2s (ID: i-05ddd9d6d4cdae4ca)
aws_instance.sandbox-server[0]: Modifications complete after 2s (ID: i-0f9b44d71906330ce)

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

GCP

gcp_sandbox.tf
resource "google_compute_instance" "sandbox-server" {
  tags = ["frontend"]
}
$ terraform apply
...
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:

  ~ google_compute_instance.sandbox-server[0]
      tags.#:          "0" => "1"
      tags.3423674012: "" => "frontend"

  ~ google_compute_instance.sandbox-server[1]
      tags.#:          "0" => "1"
      tags.3423674012: "" => "frontend"


Plan: 0 to add, 2 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

google_compute_instance.sandbox-server[0]: Modifying... (ID: sandbox00)
...
google_compute_instance.sandbox-server[1]: Modifying... (ID: sandbox01)
...
google_compute_instance.sandbox-server[0]: Modifications complete after 3s (ID: sandbox00)
google_compute_instance.sandbox-server[1]: Modifications complete after 8s (ID: sandbox01)

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

Aliyun

aliyun_sandbox.tf
# create sandbox server
resource "alicloud_instance" "sandbox" {
  tags = {
    tier = "frontend"
  }
$ terraform apply
...
Terraform will perform the following actions:

  ~ alicloud_instance.sandbox[0]
      tags.%:    "0" => "1"
      tags.Tier: "" => "frontend"

  ~ alicloud_instance.sandbox[1]
      tags.%:    "0" => "1"
      tags.Tier: "" => "frontend"


Plan: 0 to add, 2 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

alicloud_instance.sandbox[0]: Modifying... (ID: i-0xihi71f0f04ryc3bbjj)
  tags.%:    "0" => "1"
  tags.Tier: "" => "frontend"
alicloud_instance.sandbox[1]: Modifying... (ID: i-0xiepsafguau2phhv6rw)
  tags.%:    "0" => "1"
  tags.Tier: "" => "frontend"
alicloud_instance.sandbox[0]: Modifications complete after 7s (ID: i-0xihi71f0f04ryc3bbjj)
alicloud_instance.sandbox[1]: Modifications complete after 7s (ID: i-0xiepsafguau2phhv6rw)

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

Delete one server.

AWS

aws_sandbox.tf
resource "aws_instance" "sandbox-server" {
  tags = {
    Tier = "frontend"
  }
$ terraform apply
...
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.sandbox-server[1]


Plan: 0 to add, 0 to change, 1 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.sandbox-server[1]: Destroying... (ID: i-05ddd9d6d4cdae4ca)
aws_instance.sandbox-server.1: Still destroying... (ID: i-05ddd9d6d4cdae4ca, 10s elapsed)
aws_instance.sandbox-server.1: Still destroying... (ID: i-05ddd9d6d4cdae4ca, 20s elapsed)
aws_instance.sandbox-server[1]: Destruction complete after 30s

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

GCP

gcp_sandbox.tf
resource "google_compute_instance" "sandbox-server" {
  count = 1
}
$ terraform apply
...
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:

  - google_compute_instance.sandbox-server[1]


Plan: 0 to add, 0 to change, 1 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

google_compute_instance.sandbox-server[1]: Destroying... (ID: sandbox01)
google_compute_instance.sandbox-server.1: Still destroying... (ID: sandbox01, 10s elapsed)
google_compute_instance.sandbox-server.1: Still destroying... (ID: sandbox01, 20s elapsed)
google_compute_instance.sandbox-server.1: Still destroying... (ID: sandbox01, 30s elapsed)
google_compute_instance.sandbox-server.1: Still destroying... (ID: sandbox01, 40s elapsed)
google_compute_instance.sandbox-server.1: Still destroying... (ID: sandbox01, 50s elapsed)
google_compute_instance.sandbox-server.1: Still destroying... (ID: sandbox01, 1m0s elapsed)
google_compute_instance.sandbox-server[1]: Destruction complete after 1m6s

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

Aliyun

aliyun_sandbox.tf
# create sandbox server
resource "alicloud_instance" "sandbox" {
  count = 1
}
$ terraform apply
...
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:

  - alicloud_instance.sandbox[1]


Plan: 0 to add, 0 to change, 1 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

alicloud_instance.sandbox[1]: Destroying... (ID: i-0xiepsafguau2phhv6rw)
alicloud_instance.sandbox.1: Still destroying... (ID: i-0xiepsafguau2phhv6rw, 10s elapsed)
alicloud_instance.sandbox.1: Still destroying... (ID: i-0xiepsafguau2phhv6rw, 20s elapsed)
alicloud_instance.sandbox[1]: Destruction complete after 23s

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

Delete all resources


Once you played with cloud resources, it is important to remove all resources you have procured. Otherwise it keeps charging you bills.

AWS

$ terraform destroy
...
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.sandbox-server

  - aws_internet_gateway.sandbox_igw

  - aws_key_pair.tf_key

  - aws_route_table.public

  - aws_route_table_association.sandbox_public_assoc

  - aws_security_group.sandbox_sg

  - aws_subnet.sandbox_public

  - aws_vpc.sandbox_vpc


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

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_route_table_association.sandbox_public_assoc: Destroying... (ID: rtbassoc-0e28e80986f5e6025)
aws_instance.sandbox-server: Destroying... (ID: i-0f9b44d71906330ce)
aws_key_pair.tf_key: Destroying... (ID: sandbox_tf_key)
aws_route_table_association.sandbox_public_assoc: Destruction complete after 0s
aws_key_pair.tf_key: Destruction complete after 0s
aws_route_table.public: Destroying... (ID: rtb-02a2a1ea215e6b516)
aws_route_table.public: Destruction complete after 1s
aws_internet_gateway.sandbox_igw: Destroying... (ID: igw-08f522b62a6da0b69)
aws_instance.sandbox-server: Still destroying... (ID: i-0f9b44d71906330ce, 10s elapsed)
aws_internet_gateway.sandbox_igw: Still destroying... (ID: igw-08f522b62a6da0b69, 10s elapsed)
aws_instance.sandbox-server: Still destroying... (ID: i-0f9b44d71906330ce, 20s elapsed)
aws_internet_gateway.sandbox_igw: Still destroying... (ID: igw-08f522b62a6da0b69, 20s elapsed)
aws_internet_gateway.sandbox_igw: Destruction complete after 24s
aws_instance.sandbox-server: Destruction complete after 30s
aws_security_group.sandbox_sg: Destroying... (ID: sg-02afb926fd9574f1a)
aws_subnet.sandbox_public: Destroying... (ID: subnet-0148f2919584b16d4)
aws_subnet.sandbox_public: Destruction complete after 0s
aws_security_group.sandbox_sg: Destruction complete after 1s
aws_vpc.sandbox_vpc: Destroying... (ID: vpc-0fedb4b5c115339d8)
aws_vpc.sandbox_vpc: Destruction complete after 0s

Destroy complete! Resources: 8 destroyed.

GCP

$ terraform destroy
...
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:

  - google_compute_address.frontend-ip[0]

  - google_compute_address.frontend-ip[1]

  - google_compute_firewall.sandbox-sg

  - google_compute_instance.sandbox-server

  - google_compute_network.sandbox-vpc

  - google_compute_subnetwork.sandbox-subnet


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

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

google_compute_instance.sandbox-server: Destroying... (ID: sandbox00)
google_compute_firewall.sandbox-sg: Destroying... (ID: sandbox-sg)
google_compute_instance.sandbox-server: Still destroying... (ID: sandbox00, 10s elapsed)
google_compute_firewall.sandbox-sg: Still destroying... (ID: sandbox-sg, 10s elapsed)
google_compute_firewall.sandbox-sg: Destruction complete after 15s
google_compute_instance.sandbox-server: Still destroying... (ID: sandbox00, 20s elapsed)
google_compute_instance.sandbox-server: Still destroying... (ID: sandbox00, 30s elapsed)
google_compute_instance.sandbox-server: Still destroying... (ID: sandbox00, 40s elapsed)
google_compute_instance.sandbox-server: Still destroying... (ID: sandbox00, 50s elapsed)
google_compute_instance.sandbox-server: Destruction complete after 56s
google_compute_address.frontend-ip[1]: Destroying... (ID: my-project-id/us-east1/frontend-ip-1)
google_compute_address.frontend-ip[0]: Destroying... (ID: my-project-id/us-east1/frontend-ip-0)
google_compute_subnetwork.sandbox-subnet: Destroying... (ID: us-east1/sandbox-subnet)
google_compute_address.frontend-ip[0]: Destruction complete after 3s
google_compute_address.frontend-ip[1]: Destruction complete after 3s
google_compute_subnetwork.sandbox-subnet: Still destroying... (ID: us-east1/sandbox-subnet, 10s elapsed)
google_compute_subnetwork.sandbox-subnet: Destruction complete after 15s
google_compute_network.sandbox-vpc: Destroying... (ID: sandbox-vpc)
google_compute_network.sandbox-vpc: Still destroying... (ID: sandbox-vpc, 10s elapsed)
google_compute_network.sandbox-vpc: Destruction complete after 15s

Destroy complete! Resources: 6 destroyed.

Aliyun

$ terraform destroy
...
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:

  - alicloud_instance.sandbox

  - alicloud_key_pair.tf_key

  - alicloud_security_group.sandbox_sg

  - alicloud_security_group_rule.allow_ssh

  - alicloud_vpc.vpc

  - alicloud_vswitch.vsw


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

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

alicloud_security_group_rule.allow_ssh: Destroying... (ID: sg-0xi1lk7w3kj3khcv7nzt:ingress:tcp:22/22::0.0.0.0/0:accept:1)
alicloud_key_pair.tf_key: Destroying... (ID: sandbox_tf_key)
alicloud_instance.sandbox: Destroying... (ID: i-0xihi71f0f04ryc3bbjj)
alicloud_key_pair.tf_key: Destruction complete after 3s
alicloud_security_group_rule.allow_ssh: Destruction complete after 6s
alicloud_instance.sandbox: Still destroying... (ID: i-0xihi71f0f04ryc3bbjj, 10s elapsed)
alicloud_instance.sandbox: Still destroying... (ID: i-0xihi71f0f04ryc3bbjj, 20s elapsed)
alicloud_instance.sandbox: Destruction complete after 27s
alicloud_vswitch.vsw: Destroying... (ID: vsw-0xij7wju82bvfy7k55bye)
alicloud_security_group.sandbox_sg: Destroying... (ID: sg-0xi1lk7w3kj3khcv7nzt)
alicloud_vswitch.vsw: Still destroying... (ID: vsw-0xij7wju82bvfy7k55bye, 10s elapsed)
alicloud_security_group.sandbox_sg: Still destroying... (ID: sg-0xi1lk7w3kj3khcv7nzt, 10s elapsed)
alicloud_security_group.sandbox_sg: Destruction complete after 14s
alicloud_vswitch.vsw: Still destroying... (ID: vsw-0xij7wju82bvfy7k55bye, 20s elapsed)
alicloud_vswitch.vsw: Destruction complete after 22s
alicloud_vpc.vpc: Destroying... (ID: vpc-0xiq50c8jea8rr9opqd58)
alicloud_vpc.vpc: Destruction complete after 2s

Destroy complete! Resources: 6 destroyed.

Terraform is especially useful for me whenever I need to create a temporary lab in the cloud. Previously I did all the provisioning and house keeping manually(and some scripting), and it is not only a couple of times that I got unexpected charge because I forgot to delete resources.

Since Terraform is specialized in infrastructure orchestration, the other tools are also required to have a life cycle management of services –e.g. CI/CD, which I will introduce them in separate post.