sagantaf

メモレベルの技術記事を書くブログ。

Terraformを実際に使えるようになるためのTerraform入門+ちょっと実践

はじめに

AWSのリソース作成を参考にTerraformの基本的な使い方と、実際に開発する時に必要になるファイル構成や環境変数を使い方などを解説します。

目次

実行環境

  • Ubuntu:18.04
  • Terraform: v0.13.4

インストール

以下、公式ページに各環境でのインストール方法が記載されています。(英語)

Install Terraform | Terraform - HashiCorp Learn

今回は、Linux/Ubuntuなので以下のコマンドでインストールします。

$ curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
$ sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
$ sudo apt-get update && sudo apt-get install terraform
$ terraform -v

バージョンが表示されればインストール完了です。

タブ補完ができると非常に便利なので、以下のコマンドで有効化しておきます。

$ terraform -install-autocomplete

まずは使ってみる(QuickStart的な)

AWSのconfig設定

AWSリソースにアクセスするための~/.aws/ディレクトリ内にconfigが用意されている必要があります。 設定していない場合は、aws configureコマンドにてIAMユーザのアクセスキー /シークレットアクセスキー などを入力して設定してください。

参考:設定の基本 - AWS Command Line Interface

EC2インスタンスを作成する

以下2つのファイルを作成します。

provider.tf

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

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

ec2.tf

resource "aws_instance" "sample" {
    ami = "ami-02b658ac34935766f" # Ubuntu Server 18.04 LTS (HVM), SSD Volume Type(64bit x86)
    instance_type = "t2.micro"
    tags = {
        Name = "sample-instance"
    }
}

ここではt2.microのEC2インスタンスを1つ立ち上げる内容になっています。

では実際にTerraformコマンドを使って、定義した内容を適用していきます。

最初に初期化が必要です。初期化することで.terraformディレクトリが作成され、その中にいくつかterraform関連のファイルが作成されます。

$ terraform init

Initializing the backend...

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

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.

続いて、事前のドライランとして定義内容に問題がないかのチェックをします。どんなリソースが追加されるか一気に表示されます。(出力内容は長いので割愛します)

terraform plan

最後の方に

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

と表示されるため、想定通りの内容かどうかの確認ができます。

では実際にTFファイルを適用していきます。以下のコマンドを実行します。

terraform apply

ドライランの時と同じ出力が表示され、

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を入力します。

実際に適用が開始され、以下の表示が出ればOKです。

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

ここまで来たら、AWSコンソールを確認してみましょう。

実際にEC2インスタンスが作成されているはずです。

今回はネットワーク設定などは明記していないため、デフォルトの設定が適用されていると思いますが、必要であれば細かい設定を記述することができます。

また、terraform showコマンドにて「現在、どんな内容がAWSに適用されているのか」を確認できます。

EC2インスタンスの設定を変更する

さて次に、ec2.tfの中身を以下のように変更してみます。

resource "aws_instance" "sample" {
    ami = "ami-02b658ac34935766f" # Ubuntu Server 18.04 LTS (HVM), SSD Volume Type(64bit x86)
    instance_type = "t2.micro"
    tags = {
        Name = "changed-instance"
    }
}

インスタンスの名前を変更しているだけですが、これを適用してみます。

ドライランさせることで差分を確認できます。

terraform plan

差分は以下のように表示されます。

      ~ tags                         = {
          ~ "Name" = "sample-instance" -> "changed-instance"
        }

差分が想定通りであることを確認したら、インスタンスを作成する時と同様terraform applyコマンドを実行します。

この時の出力は、changedのみが1になっていると思います。このことから想定どおり変更されたことがわかります。

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

リソースの変更もリソース作成の時と同様に、terraform applyをするだけで実現できました。

全てのリソースを削除する

全てのリソースを削除するには、

terraform destroy

というコマンドを実行するだけです。

また、一部のリソースを削除したい場合は、TFファイルの削除したい部分をコメントアウトし、terraform applyするだけで実現できます。

Terraformの基本的な使い方

ここまでで超基本的なTerraformの使い方、使い勝手がわかったと思います。

ここからは実際にTerraformを使って様々なリソースを作成/変更するときに必要になる使い方を説明していきます。

基本的なフォルダ構成

  • provider.tf: プロバイダ設定ができるファイルです
  • variables.tf::変数設定ができるファイルです
  • main.tf:実際に作成したいAWSリソースを記載します(ファイル名はなんでもOKですが、mainとしておいた方がこのファイルが起点になっている、ということが分かると思います)

provider.tf

AWSのアクセス先などの基本的な情報を格納します。

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

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

詳細は公式ページを確認ください。

直接AWSのアクセスキーとシークレットアクセスキー を指定することもできますが、セキュリティ上は避けた方が良いです。

variables.tf

TFファイルで環境変数を利用するには、variables.tfにて定義する必要があります。

書き方は、

variable 変数名 {
    type: 変数の型 stringなど
    description: 説明
    default: デフォルト値 
}

です。

使い方は、var.変数名を指定するだけです。

例えば、

variable aws_instance_type {
  type        = string
  description = "AWSインスタンス種別"
  default     = "t2.micro"
}

という環境変数を定義した場合、

resource "aws_instance" "sample" {
    count = 1
    ami = "ami-02b658ac34935766f" # Ubuntu Server 18.04 LTS (HVM), SSD Volume Type(64bit x86)
    instance_type = var.aws_instance_type
    tags = {
        Name = "instance-${var.aws_instance_type}" # 文字列内で使いたい場合は${}で囲むだけ
    }
}

といった使い方ができます。

変数への値の設定方法

変数を設定する方法は、3通りあります。

  1. オプションで渡す: terraform apply -var 'aws_instance_type=t2.large'のように-varを使う
  2. 環境変数で渡す:TF_VAR_変数名として環境変数を設定しておくことで、terraformコマンド実行時に自動的に読み込まれる
  3. ファイルで渡す:terraform.tfvarsという名前でファイルを作成し変数名 = 値を書いておくことで、自動的に読み込まれる

上記の方法で変数の値を設定しなかった場合は、デフォルト値が設定されます。デフォルト値が設定されていなければ、terraformコマンド実行時にエラーになります。

リソースの書き方

基本的な書き方は、

resource "リソースの種類" "リソース名" {
        (リソースの設定値)
}

のように、リソースの種類とリソース名(任意の文字列)を設定し、設定値を中に記載していく形になります。

リソースの種類は、Terraformであらかじめ定義されており、AWSであればaws_という接頭語が付けられています。(EC2はaws_instance、S3はaws_s3、など)

リソースの種類やブロック内の各リソースの設定項目は、公式ページにまとまっていますので、実際に作成する時に参考になります。例えば、ECSクラスターの設定項目は以下のArgument Referenceに記載されています。

terraform ECS reference

他リソースの属性を参照する

QuickStartではEC2のみを定義して作成しましたが、実施に利用する時には複数のリソースを定義することが多いと思います。

その時に、「同時に複数リソースを定義してapplyしたいけど、その時に作成されるリソースの情報が他のリソースで必要、、、」となる時があります。例えば、「セキュリティグループにVPCを指定したいけど、VPC自体も今回作成するため識別子がわからない、、、」といった時です。

そんな時は、他リソースの属性をリソースの種類.リソース名.属性名と指定して参照することできます。

以下はVPCとセキュリティグループの定義です。

resource "aws_vpc" "sampleVPC" {
    cidr_block = "10.1.0.0/16"
    instance_tenancy = "default"
    enable_dns_support = "true"
    enable_dns_hostnames = "false"
    tags {
      Name = "sampleVPC"
    }
}

resource "aws_security_group" "admin" {
    name = "admin"
    description = "Allow SSH"
    vpc_id = aws_vpc.sampleVPC.id # ここで同時に作成するvpcの属性を指定
    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"]
    }
}

もし、他のリソースから上記のセキュリティグループを参照したい場合は、aws_security_group.admin.idといった具合に利用できます。

リソース間の依存関係は自動で解決してくれるため、適用順序は基本的には気にしないでOKです。depends_onを使って明記することもできます。

resource "aws_security_group" "admin" {
    name = "admin"
    description = "Allow SSH"
    vpc_id = aws_vpc.sampleVPC.id
    depends_on = aws_vpc.sampleVPC.id # vpcが作成されてから作成することを明記
    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"]
    }
}

参考

10分で理解するTerraform - Qiita

TerraformAWS事始め - Qiita

Terraform Registry

さらに細かく理解したい人は

以下のサイトや本に実用的な使い方が細かくまとまっていますので、一読し、Referenceとして使うと良いと思います。

Terraform職人入門: 日々の運用で学んだ知見を淡々とまとめる - Qiita