Terraformことはじめ

Terraform を学び始めました。基本的な箇所が中心ですが学習過程のメモとなります。

環境

$ terraform --version
Terraform v0.12.24
$ jq --version
jq-1.5-1-a5b5cbe

インストール

公式ではIntroductionという形で使用する流れを紹介しています。インストールではバイナリをダウンロード(+環境変数の更新)で対応しているようです。

今回はLinuxディストリビューションのパッケージ管理コマンド経由でインストールしました。最近は開発環境としてArchLinuxのdockerを使用することが多くpacmanを使用しています。

$ sudo pacman -Syu terraform

パッケージ (1) terraform-0.12.24-1

合計ダウンロード容量:  13.14 MiB
合計インストール容量:  55.89 MiB
(略)

インフラストラクチャの作成

プロバイダ

インフラストラクチャを定義するIaaSやPaaS、SaaSを記載します。AWSGCPAzureだけと思っていたのですが、普通にたくさん存在していました。今回はプロバイダをAWSとしています。

provider "aws" {
    profile = "default"
    region  = "ap-notrheast-1"
}

このように直接tfファイルに設定するのは避けて、通常はawscliや他のプロジェクトなどでも使用する.aws/profileに記載・管理して参照するのがスタンダードと思うので、providerをコメントアウトししたところ.aws/profileは参照せずにCLIパラメータとして指定するようになりました。

> terraform apply
provider.aws.region
  The region where AWS operations will take place. Examples
  are us-east-1, us-west-2, etc.

  Enter a value: ap-northeast-1
(略)

.aws/configから直接指定出来るような気もしているので、もう少し見てみたい。また、そのほかには.tfvarsファイルに変数を分離して、.tfファイルではvariableの宣言を行う方法もあるようです。このような機密情報の絡みは、暗号化(vault)考慮の必要性もあると思うので、その観点でも、もう少し詳しく見ていきたいところ。

リソース

リソースタイプを指定してリソースを作成します。これはVPCにサブネットを作成するリソースタイプを使用して、サブネットを作成しています。

resource "aws_subnet" "subnet" {
  vpc_id            = "vpc-1234567890"
  availability_zone = "ap-northeast-1a"
  cidr_block        = "172.31.0.0/24"
}

一度実行してみる

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

resource "aws_subnet" "subnet" {
  vpc_id            = "vpc-1234567890"
  availability_zone = "ap-northeast-1a"
  cidr_block        = "172.31.0.0/24"
}

terraform apply で実行する。

$ terraform apply

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_subnet.subnet will be created
  + resource "aws_subnet" "subnet" {
      + arn                             = (known after apply)
      + assign_ipv6_address_on_creation = false
      + availability_zone               = "ap-northeast-1a"
      + availability_zone_id            = (known after apply)
      + cidr_block                      = "172.31.0.0/24"
      + id                              = (known after apply)
      + ipv6_cidr_block                 = (known after apply)
      + ipv6_cidr_block_association_id  = (known after apply)
      + map_public_ip_on_launch         = false
      + owner_id                        = (known after apply)
      + vpc_id                          = "vpc-1234567890"
    }

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と入力して続けます。


  Enter a value: yes

aws_subnet.subnet: Creating...
aws_subnet.subnet: Creation complete after 1s [id=subnet-1234567890]

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

無事にVPCにサブネットが作成された。awscliコマンドでも確認してみる。

$ aws ec2 describe-subnets | jq -c .Subnets[].SubnetId
"subnet-1234567890"

破棄してみる

terraform destroy でリソースを破棄する。

$ terraform destroy

aws_subnet.subnet: Refreshing state... [id=subnet-1234567890]

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_subnet.subnet will be destroyed
  - resource "aws_subnet" "subnet" {
(略)
      - vpc_id                          = "vpc-1234567890" -> null
    }

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と入力して進める。


  Enter a value: yes

aws_subnet.subnet: Destroying... [id=subnet-1234567890]
aws_subnet.subnet: Destruction complete after 0s

Destroy complete! Resources: 1 destroyed.

awscliコマンドでも確認してみる。

$ aws ec2 describe-subnets | jq -c .Subnets[].SubnetId
 

引数設定について考える

上ではサブネットを作成しましたが、aws_instanceリソースタイプではインスタンスを作成することが出来ます。aws_instancesubnet_idでサブネットIDを指定する必要があるため、サブネットとインスタンスを一括で作成したい場合は、サブネットリソースからIDを取得してaws_instanceにパラメータとして指定したい。この辺は、AWS CDKを使用する場合も考える機会が多いところです。

以下のようにしました。

variable "cidr" {
  default = "172.31.0.0/24"
}

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

resource "aws_subnet" "subnet" {
  vpc_id            = "vpc-1234567890"
  availability_zone = "ap-northeast-1a"
  cidr_block        = var.cidr
}

resource "aws_instance" "instance" {
  ami           = "ami-1234567890"
  instance_type = "t2.micro"
  subnet_id     = aws_subnet.subnet.id
}

subnet_idはサブネットリソースからidを取得します。どのような内容が取得できるのかについては、applyのログにリソースとともに生成されているアトリビュートが記載されているので分かりやすいです。var.cidrvariableで変数を定義しています。

> terraform apply

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.instance will be created
(略)
  Only 'yes' will be accepted to approve.

  Enter a value:

yesと入力して続けます。

  Enter a value: yes

aws_subnet.subnet: Creating...
aws_subnet.subnet: Creation complete after 1s [id=subnet-1234567890]
aws_instance.instance: Creating...
aws_instance.instance: Still creating... [10s elapsed]
aws_instance.instance: Still creating... [20s elapsed]
aws_instance.instance: Still creating... [30s elapsed]
aws_instance.instance: Creation complete after 34s [id=i-1234567890]

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

完了しました。

> aws ec2 describe-subnets | jq -c .Subnets[].SubnetId
"subnet-1234567890"

> aws ec2 describe-instances | jq -c .Reservations[].Instances[].InstanceId
"i-1234567890"

問題なさそうです。

次は

初歩的なレベルではあるけれど、基本的な使い方は理解できたと思います。ただtfvarsなどの分離の考え方やmoduleの使用方法、より良い構成管理の方法など、まだ詳しく見ることが出来ていない箇所も多いのでその辺を見ていきたいところ。

独自言語(DSL)ということで少々怯えていたこともあり腰が重くなっていたのだけど、想定していたより遥かに簡単に書けて嬉しさあり悲しさありといったところ。悲しさ、というのは技術におけるそういう匂いを感じ取ることが出来ない自分自身に対してです。嗅覚を強くしたい。

© てっくらのーと/mkr-note 2024