2&>1

AWSとかGCPとかGolangとかとか

TerraformでAWSを試す

IaC( Infrastructure as Code )が叫ばれる昨今ようやく「Terraform」触りました。IaCってなに?ていうのはググればすぐのなの任せます。

Terraformのインストール

環境(GCPに構築)
Red Hat Enterprise Linux Server release 7.6 (Maipo)

1.Terraformのダウンロード
  ここから環境にあったものをダウンロード
2.インストール
  ダウンロードしたものを/usr/local/srcなんかに移動

unzip terraform_0.11.11_linux_amd64.zip

解凍したら/usr/local/binなんかに移動してパス追加

[root@terraform terraform_work]# export PATH=/usr/local/bin:$PATH

##ついでにprofileにも追記
[root@terraform terraform_work]# vi ~/bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin:/usr/local/bin   ##ココに追加

export PATH

するとこうなる

[root@terraform ~]# terraform
Usage: terraform [-version] [-help] <command> [args]

The available commands for execution are listed below.
The most common, useful commands are shown first, followed by
less common or more advanced commands. If you're just getting
started with Terraform, stick with the common commands. For the
other commands, please read the help and docs before usage.

Common commands:
    apply              Builds or changes infrastructure
    console            Interactive console for Terraform interpolations
    destroy            Destroy Terraform-managed infrastructure
    env                Workspace management
    fmt                Rewrites config files to canonical format
    get                Download and install modules for the configuration
    graph              Create a visual graph of Terraform resources
    import             Import existing infrastructure into Terraform
    init               Initialize a Terraform working directory
    output             Read an output from a state file
    plan               Generate and show an execution plan
    providers          Prints a tree of the providers used in the configuration
    push               Upload this Terraform module to Atlas to run
    refresh            Update local state file against real resources
    show               Inspect Terraform state or plan
    taint              Manually mark a resource for recreation
    untaint            Manually unmark a resource as tainted
    validate           Validates the Terraform files
    version            Prints the Terraform version
    workspace          Workspace management

All other commands:
    debug              Debug output management (experimental)
    force-unlock       Manually unlock the terraform state
    state              Advanced state management

AWS環境向けに作ってみる

とりあえず作業ディレクトリを作って移動

1.コード書く
  単純にインスタンスを作成するだけのやつです

[root@terraform terraform_work]# vi example.tf

provider "aws" {
  access_key = "xxxxhogexxxxxx"
  secret_key = "xxxxhogexxxxxxxxxxhogexxxxxx"
  region     = "ap-northeast-1"
}

resource "aws_instance" "example" {
  ami           = "ami-05cd6c87a37390178"
  instance_type = "t3.nano"
}

事前にアクセスキーを作成してシークレットキーとともに控える
(これって直接書くしかないのかな。。なんか別ファイルにキーだけ置いとくのもできそうな気がするがまだちゃんと調べてない。。)

2.コードをイニシャライズする

[root@terraform terraform_work]# terraform init

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "aws" (1.60.0)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = "~> 1.60"

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

3.コードを実行
  途中作っていい?と聞かれるので"yes"と答える

[root@terraform terraform_work]# terraform apply
aws_instance.example: Refreshing state... (ID: i-0c933621e39daa09b)

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.example
      id:                           <computed>
      ami:                          "ami-05cd6c87a37390178"
      arn:                          <computed>
      associate_public_ip_address:  <computed>
      availability_zone:            <computed>
      cpu_core_count:               <computed>
      cpu_threads_per_core:         <computed>
      ebs_block_device.#:           <computed>
      ephemeral_block_device.#:     <computed>
      get_password_data:            "false"
      host_id:                      <computed>
      instance_state:               <computed>
      instance_type:                "t3.nano"
      ipv6_address_count:           <computed>
      ipv6_addresses.#:             <computed>
      key_name:                     <computed>
      network_interface.#:          <computed>
      network_interface_id:         <computed>
      password_data:                <computed>
      placement_group:              <computed>
      primary_network_interface_id: <computed>
      private_dns:                  <computed>
      private_ip:                   <computed>
      public_dns:                   <computed>
      public_ip:                    <computed>
      root_block_device.#:          <computed>
      security_groups.#:            <computed>
      source_dest_check:            "true"
      subnet_id:                    <computed>
      tenancy:                      <computed>
      volume_tags.%:                <computed>
      vpc_security_group_ids.#:     <computed>


Plan: 1 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_instance.example: Creating...
  ami:                          "" => "ami-05cd6c87a37390178"
  arn:                          "" => "<computed>"
  associate_public_ip_address:  "" => "<computed>"
  availability_zone:            "" => "<computed>"
  cpu_core_count:               "" => "<computed>"
  cpu_threads_per_core:         "" => "<computed>"
  ebs_block_device.#:           "" => "<computed>"
  ephemeral_block_device.#:     "" => "<computed>"
  get_password_data:            "" => "false"
  host_id:                      "" => "<computed>"
  instance_state:               "" => "<computed>"
  instance_type:                "" => "t3.nano"
  ipv6_address_count:           "" => "<computed>"
  ipv6_addresses.#:             "" => "<computed>"
  key_name:                     "" => "<computed>"
  network_interface.#:          "" => "<computed>"
  network_interface_id:         "" => "<computed>"
  password_data:                "" => "<computed>"
  placement_group:              "" => "<computed>"
  primary_network_interface_id: "" => "<computed>"
  private_dns:                  "" => "<computed>"
  private_ip:                   "" => "<computed>"
  public_dns:                   "" => "<computed>"
  public_ip:                    "" => "<computed>"
  root_block_device.#:          "" => "<computed>"
  security_groups.#:            "" => "<computed>"
  source_dest_check:            "" => "true"
  subnet_id:                    "" => "<computed>"
  tenancy:                      "" => "<computed>"
  volume_tags.%:                "" => "<computed>"
  vpc_security_group_ids.#:     "" => "<computed>"
aws_instance.example: Still creating... (10s elapsed)
aws_instance.example: Creation complete after 13s (ID: i-028e10437889aeeca)

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

4.コードの内容

[root@terraform terraform_work]# terraform show
aws_instance.example:
  id = i-028e10437889aeeca
  ami = ami-05cd6c87a37390178
  arn = arn:aws:ec2:ap-northeast-1:363717127291:instance/i-028e10437889aeeca
  associate_public_ip_address = true
  availability_zone = ap-northeast-1a
  cpu_core_count = 1
  cpu_threads_per_core = 2
  credit_specification.# = 1
  credit_specification.0.cpu_credits = unlimited
  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 = t3.nano
  ipv6_addresses.# = 0
  key_name =
  monitoring = false
  network_interface.# = 0
  network_interface_id = eni-0e09848f22985016b
  password_data =
  placement_group =
  primary_network_interface_id = eni-0e09848f22985016b
  private_dns = ip-172-31-17-100.ap-northeast-1.compute.internal
  private_ip = 172.31.17.100
  public_dns = ec2-3-112-72-247.ap-northeast-1.compute.amazonaws.com
  public_ip = 3.112.72.247
  root_block_device.# = 1
  root_block_device.0.delete_on_termination = true
  root_block_device.0.iops = 100
  root_block_device.0.volume_id = vol-09e1eadc149aa8700
  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-e7ce5eae
  tags.% = 0
  tenancy = default
  volume_tags.% = 0
  vpc_security_group_ids.# = 1
  vpc_security_group_ids.1170673366 = sg-ca8649b3

これでAWS側にEC2インスタンスが作成されています

コードを変更して再作成

1.使用するAMIを変更

[root@terraform terraform_work]# vi example.tf

provider "aws" {
  access_key = "xxxxhogexxxxxx"
  secret_key = "xxxxhogexxxxxxxxxxhogexxxxxx"
  region     = "ap-northeast-1"
}

resource "aws_instance" "example" {
  ami           = "ami-00a5245b4816c38e6"
  instance_type = "t3.nano"
}

2.そのまま実行

[root@terraform terraform_work]# terraform apply
aws_instance.example: Refreshing state... (ID: i-028e10437889aeeca)

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

Terraform will perform the following actions:

-/+ aws_instance.example (new resource required)
      id:                           "i-028e10437889aeeca" => <computed> (forces new resource)
      ami:                          "ami-05cd6c87a37390178" => "ami-00a5245b4816c38e6" (forces new resource)
      arn:                          "arn:aws:ec2:ap-northeast-1:363717127291:instance/i-028e10437889aeeca" => <computed>
      associate_public_ip_address:  "true" => <computed>
      availability_zone:            "ap-northeast-1a" => <computed>
      cpu_core_count:               "1" => <computed>
      cpu_threads_per_core:         "2" => <computed>
      ebs_block_device.#:           "0" => <computed>
      ephemeral_block_device.#:     "0" => <computed>
      get_password_data:            "false" => "false"
      host_id:                      "" => <computed>
      instance_state:               "running" => <computed>
      instance_type:                "t3.nano" => "t3.nano"
      ipv6_address_count:           "" => <computed>
      ipv6_addresses.#:             "0" => <computed>
      key_name:                     "" => <computed>
      network_interface.#:          "0" => <computed>
      network_interface_id:         "eni-0e09848f22985016b" => <computed>
      password_data:                "" => <computed>
      placement_group:              "" => <computed>
      primary_network_interface_id: "eni-0e09848f22985016b" => <computed>
      private_dns:                  "ip-172-31-17-100.ap-northeast-1.compute.internal" => <computed>
      private_ip:                   "172.31.17.100" => <computed>
      public_dns:                   "ec2-3-112-72-247.ap-northeast-1.compute.amazonaws.com" => <computed>
      public_ip:                    "3.112.72.247" => <computed>
      root_block_device.#:          "1" => <computed>
      security_groups.#:            "1" => <computed>
      source_dest_check:            "true" => "true"
      subnet_id:                    "subnet-e7ce5eae" => <computed>
      tenancy:                      "default" => <computed>
      volume_tags.%:                "0" => <computed>
      vpc_security_group_ids.#:     "1" => <computed>


Plan: 1 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.example: Destroying... (ID: i-028e10437889aeeca)
aws_instance.example: Still destroying... (ID: i-028e10437889aeeca, 10s elapsed)
aws_instance.example: Still destroying... (ID: i-028e10437889aeeca, 20s elapsed)
aws_instance.example: Destruction complete after 29s
aws_instance.example: Creating...
  ami:                          "" => "ami-00a5245b4816c38e6"
  arn:                          "" => "<computed>"
  associate_public_ip_address:  "" => "<computed>"
  availability_zone:            "" => "<computed>"
  cpu_core_count:               "" => "<computed>"
  cpu_threads_per_core:         "" => "<computed>"
  ebs_block_device.#:           "" => "<computed>"
  ephemeral_block_device.#:     "" => "<computed>"
  get_password_data:            "" => "false"
  host_id:                      "" => "<computed>"
  instance_state:               "" => "<computed>"
  instance_type:                "" => "t3.nano"
  ipv6_address_count:           "" => "<computed>"
  ipv6_addresses.#:             "" => "<computed>"
  key_name:                     "" => "<computed>"
  network_interface.#:          "" => "<computed>"
  network_interface_id:         "" => "<computed>"
  password_data:                "" => "<computed>"
  placement_group:              "" => "<computed>"
  primary_network_interface_id: "" => "<computed>"
  private_dns:                  "" => "<computed>"
  private_ip:                   "" => "<computed>"
  public_dns:                   "" => "<computed>"
  public_ip:                    "" => "<computed>"
  root_block_device.#:          "" => "<computed>"
  security_groups.#:            "" => "<computed>"
  source_dest_check:            "" => "true"
  subnet_id:                    "" => "<computed>"
  tenancy:                      "" => "<computed>"
  volume_tags.%:                "" => "<computed>"
  vpc_security_group_ids.#:     "" => "<computed>"
aws_instance.example: Still creating... (10s elapsed)
aws_instance.example: Creation complete after 13s (ID: i-0aad086be18339bfd)

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

変更点がわかりやすく表示されます。
また先に作成したインスタンスは削除されたのち新しいものが作成されるのは注意です!別で作成したい場合は新しいコードファイルにしましょう!!

3.作成したインスタンスの削除

[root@terraform terraform_work]# terraform destroy
aws_instance.example: Refreshing state... (ID: i-0aad086be18339bfd)

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


Plan: 0 to add, 0 to change, 1 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_instance.example: Destroying... (ID: i-0aad086be18339bfd)
aws_instance.example: Still destroying... (ID: i-0aad086be18339bfd, 10s elapsed)
aws_instance.example: Still destroying... (ID: i-0aad086be18339bfd, 20s elapsed)
aws_instance.example: Still destroying... (ID: i-0aad086be18339bfd, 30s elapsed)
aws_instance.example: Destruction complete after 40s

Destroy complete! Resources: 1 destroyed.

これで削除完了です。

まとめ

運用する場合はVPCやらDiskやら設定するものはたくさんあるのでコードも長くなりますが触りとしてはこんなもんで。
こういうのをコード化して残しておくと再作成も楽だしいいですね。学習コストはそこそこありますが。。