zaki work log

作業ログやら生活ログやらなんやら

Terraformをv0.15に更新してAWSにEC2を作成するサンプルを動作

Terraformがv0.15にアップデートされたので、手元の環境も更新してみた。
以前お試しで作ったv0.12で動いていたソースでプロバイダ設定を新しい書式に更新すれば動作した。
zaki-hmkc.hatenablog.com

qiita.com

サンプルレベルだとおそらくv0.14 -> v0.15固有の更新は無く、v0.12からの飛び級更新のためいくつか修正が必要だったので、その内容について作業メモ。

既存環境

[zaki@cloud-dev terraform (master)]$ which terraform 
/usr/local/bin/terraform
[zaki@cloud-dev terraform (master)]$ terraform --version
Terraform v0.12.28

Your version of Terraform is out of date! The latest version
is 0.15.0. You can update by downloading from https://www.terraform.io/downloads.html

インストールした時の状況は過去記事のTerraform CLIツールのインストールの通り。

install

TerraformのCLIは、以前はバイナリファイルをダウンロードしてOSに展開する方式だったが、現在はパッケージマネージャを使ってインストールできるようになっている。

https://learn.hashicorp.com/tutorials/terraform/install-cli

以下はCentOS 7の場合。

[zaki@cloud-dev terraform (master)]$ sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
読み込んだプラグイン:fastestmirror
adding repo from: https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
grabbing file https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo to /etc/yum.repos.d/hashicorp.repo
repo saved to /etc/yum.repos.d/hashicorp.repo
[zaki@cloud-dev terraform (master)]$ sudo yum -y install terraform
読み込んだプラグイン:fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * epel: ftp.riken.jp
 * extras: ftp.riken.jp
 * updates: ftp.riken.jp
hashicorp                                                                                         | 1.4 kB  00:00:00     
hashicorp/7/x86_64/primary                                                                        |  41 kB  00:00:00     
hashicorp                                                                                                        271/271
依存性の解決をしています
--> トランザクションの確認を実行しています。
---> パッケージ terraform.x86_64 0:0.15.0-1 を インストール
--> 依存性解決を終了しました。

依存性を解決しました

=========================================================================================================================
 Package                      アーキテクチャー          バージョン                    リポジトリー                  容量
=========================================================================================================================
インストール中:
 terraform                    x86_64                    0.15.0-1                      hashicorp                     25 M

トランザクションの要約
=========================================================================================================================
インストール  1 パッケージ

総ダウンロード容量: 25 M
インストール容量: 76 M
Downloading packages:
警告: /var/cache/yum/x86_64/7/hashicorp/packages/terraform-0.15.0-1.x86_64.rpm: ヘッダー V4 RSA/SHA512 Signature、鍵 ID a3219f7b: NOKEY
terraform-0.15.0-1.x86_64.rpm の公開鍵がインストールされていません
terraform-0.15.0-1.x86_64.rpm                                                                     |  25 MB  00:00:11     
https://rpm.releases.hashicorp.com/gpg から鍵を取得中です。
Importing GPG key 0xA3219F7B:
 Userid     : "HashiCorp Security (HashiCorp Package Signing) <security+packaging@hashicorp.com>"
 Fingerprint: e8a0 32e0 94d8 eb4e a189 d270 da41 8c88 a321 9f7b
 From       : https://rpm.releases.hashicorp.com/gpg
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  インストール中          : terraform-0.15.0-1.x86_64                                                                1/1 
  検証中                  : terraform-0.15.0-1.x86_64                                                                1/1 

インストール:
  terraform.x86_64 0:0.15.0-1                                                                                            

完了しました!
[zaki@cloud-dev terraform (master)]$ 

旧バージョンの/usr/local/bin/terraformは削除してシェルを起動し直す。

[zaki@cloud-dev terraform (master)]$ terraform --version
Terraform v0.15.0
on linux_amd64

AWSVPCからEC2まで作成するサンプル(0.15版)

元ネタ

zaki-hmkc.hatenablog.com

このときに作った定義ファイルをv0.15対応する。
ちなみにこの定義ファイルで作成されるリソースはクラウド上には既に無いので、最悪tfstateを消してリセットする、も可能。(運用時はそうもいかないだろうけど)

[zaki@cloud-dev practice (master)]$ find .terraform/
.terraform/
.terraform/plugins
.terraform/plugins/linux_amd64
.terraform/plugins/linux_amd64/terraform-provider-aws_v2.70.0_x4
.terraform/plugins/linux_amd64/lock.json

reinitialization

まずはそのまま実行してみる。

[zaki@cloud-dev practice (master)]$ terraform plan
╷
│ Warning: Version constraints inside provider configuration blocks are deprecated
│ 
│   on provider.tf line 2, in provider "aws":
│    2:   version = "~> 2.8"
│ 
│ Terraform 0.13 and earlier allowed provider version constraints inside the provider configuration block, but that is
│ now deprecated and will be removed in a future version of Terraform. To silence this warning, move the provider
│ version constraint into the required_providers block.
╵
╷
│ Error: Could not load plugin
│ 
│ 
│ Plugin reinitialization required. Please run "terraform init".
│ 
│ Plugins are external binaries that Terraform uses to access and manipulate
│ resources. The configuration provided requires plugins which can't be located,
│ don't satisfy the version constraints, or are otherwise incompatible.
│ 
│ Terraform automatically discovers provider requirements from your
│ configuration, including providers used in child modules. To see the
│ requirements and constraints, run "terraform providers".
│ 
│ failed to instantiate provider "registry.terraform.io/hashicorp/aws" to obtain schema: unknown provider
│ "registry.terraform.io/hashicorp/aws"
│ 
╵

警告はいったん置いといて、エラーがでてる。
terraform initの再実行が必要ということ。

[zaki@cloud-dev practice (master)]$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 2.8"...
- Installing hashicorp/aws v2.70.0...
- Installed hashicorp/aws v2.70.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

╷
│ Warning: Version constraints inside provider configuration blocks are deprecated
│ 
│   on provider.tf line 2, in provider "aws":
│    2:   version = "~> 2.8"
│ 
│ Terraform 0.13 and earlier allowed provider version constraints inside the provider configuration block, but that is
│ now deprecated and will be removed in a future version of Terraform. To silence this warning, move the provider
│ version constraint into the required_providers block.
╵

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.

init自体は成功して以下のとおりファイルが追加される。
ディレクトリ構成が変わっており、旧バージョンで使っていたplugins/ではなくproviders/以下にファイルが作成される模様。

[zaki@cloud-dev practice (master)]$ find .terraform/
.terraform/
.terraform/plugins
.terraform/plugins/linux_amd64
.terraform/plugins/linux_amd64/terraform-provider-aws_v2.70.0_x4
.terraform/plugins/linux_amd64/lock.json
.terraform/providers
.terraform/providers/registry.terraform.io
.terraform/providers/registry.terraform.io/hashicorp
.terraform/providers/registry.terraform.io/hashicorp/aws
.terraform/providers/registry.terraform.io/hashicorp/aws/2.70.0
.terraform/providers/registry.terraform.io/hashicorp/aws/2.70.0/linux_amd64
.terraform/providers/registry.terraform.io/hashicorp/aws/2.70.0/linux_amd64/terraform-provider-aws_v2.70.0_x4

が、バージョンの警告が出ているのでそれを修正する。

Docs overview | hashicorp/aws | Terraform Registry

前回はv0.12でやっていたので「awsプロバイダ指定とバージョン・リージョン指定」をセットで書く書式だったが、v0.13以降は以下のように「プロバイダ指定とバージョン」「awsプロバイダの指定とリージョン指定」と別々に記述するようになっている。

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

provider "aws" {
  region  = "ap-northeast-1"
}

これでinitを再実行すると、

[zaki@cloud-dev practice (master)]$ terraform init

Initializing the backend...

Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
╷
│ Error: Failed to query available provider packages
│ 
│ Could not retrieve the list of available versions for provider hashicorp/aws: locked provider
│ registry.terraform.io/hashicorp/aws 2.70.0 does not match configured version constraint ~> 3.0; must use terraform
│ init -upgrade to allow selection of new versions
╵

ぬぁ、アップグレードは-upgradeオプションが必要。

[zaki@cloud-dev practice (master)]$ terraform init -upgrade

Initializing the backend...

Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 3.0"...
- Installing hashicorp/aws v3.37.0...
- Installed hashicorp/aws v3.37.0 (signed by HashiCorp)

Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file. Review those changes and commit them to your
version control system if they represent changes you intended to make.

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.

正常に動作しました。

plan

プロバイダ定義以外の定義ファイルはそのままで、terraform plan(dry run)を実行。

[zaki@cloud-dev practice (master)]$ 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_instance.bastion will be created
  + resource "aws_instance" "bastion" {
      + ami                          = (sensitive)
      + arn                          = (known after apply)
      + associate_public_ip_address  = true
      + availability_zone            = (known after apply)

:
:

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

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if
you run "terraform apply" now.

とくに問題無し。

apply

[zaki@cloud-dev practice (master)]$ time terraform apply -auto-approve
aws_key_pair.my_key: Creating...
aws_vpc.practice: Creating...
aws_key_pair.my_key: Creation complete after 0s [id=deployer-key]
aws_vpc.practice: Still creating... [10s elapsed]
aws_vpc.practice: Creation complete after 12s [id=vpc-033ac6df503e91040]
aws_internet_gateway.gw: Creating...
aws_subnet.prac_priv2: Creating...
aws_security_group.allow_ssh_icmp: Creating...
aws_subnet.prac_priv1: Creating...
aws_subnet.prac_public: Creating...
aws_subnet.prac_priv2: Creation complete after 1s [id=subnet-0623f3cc8dca00879]
aws_internet_gateway.gw: Creation complete after 1s [id=igw-08d2b30675b10dbd5]
aws_route_table.public_route: Creating...
aws_subnet.prac_priv1: Creation complete after 1s [id=subnet-0761a961e0049ac32]
aws_subnet.prac_public: Creation complete after 1s [id=subnet-023d30a65d6a5fe9f]
aws_route_table.public_route: Creation complete after 1s [id=rtb-038e5ea5f48545c62]
aws_route_table_association.public_subnet: Creating...
aws_security_group.allow_ssh_icmp: Creation complete after 2s [id=sg-043174961474ad348]
aws_security_group_rule.egress: Creating...
aws_security_group_rule.icmp: Creating...
aws_security_group_rule.ssh: Creating...
aws_instance.bastion: Creating...
aws_route_table_association.public_subnet: Creation complete after 0s [id=rtbassoc-09bb5298f44359358]
aws_security_group_rule.egress: Creation complete after 1s [id=sgrule-3339993613]
aws_security_group_rule.icmp: Creation complete after 1s [id=sgrule-366981081]
aws_security_group_rule.ssh: Creation complete after 2s [id=sgrule-3333037129]
aws_instance.bastion: Still creating... [10s elapsed]
aws_instance.bastion: Creation complete after 13s [id=i-0a64360f7c3300544]

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

real    0m31.964s
user    0m2.115s
sys     0m0.280s

できた。

ssh access

はい。

[zaki@cloud-dev practice (master)]$ ssh ec2-user@*.*.*.* -i ~/.ssh/id_aws_sample
The authenticity of host '*.*.*.* (*.*.*.*)' can't be established.
ECDSA key fingerprint is SHA256:gUKCdxBnkvEt1R0K0DjgiASoiH2XdpnVCccgH5kH+vU.
ECDSA key fingerprint is MD5:1d:df:5e:a7:55:9a:a2:5a:15:64:e9:63:0b:ff:e8:a2.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '*.*.*.*' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
No packages needed for security; 2 packages available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-172-26-10-12 ~]$ uptime
 00:35:04 up 3 min,  1 user,  load average: 0.02, 0.04, 0.01

後始末

terraform destroy -auto-approve

追加ファイル

www.terraform.io

バージョンが新しくなり、新たに .terraform.lock.hcl というファイルが作成されるようになっている。
以下の記事で詳しく解説されている。
参考: Terraform職人再入門2020 - Qiita

なるほど、init-upgradeが必要だったのはこれも影響してたっぽい。

このロックファイルが存在すると、 terraform init が前回と同じバージョンを選択します。更新する場合は terraform init -upgrade を実行します。

また、このファイルもバージョン管理の対象にするとのこと。

サンプルコード

github.com

手元はmasterなのにGitHubリポジトリ作ったらmainになってて差異を解消できずに朝からgit push --forceを発動してしまった()