どーも皆さまお久しぶりです!Technology Department(開発部)でインフラ周りを担当している山口です!
さて今回はインフラストラクチャ定義ツールで有名なTerraformを触ってみましたのでこちらについてご紹介していきます!
まずその前にInfrastructure as Codeについて少しご説明したいと思います。
Infrastructure as Code(IaC)とはインフラをコードで構成管理を行い、実際の構築やパラメータの等の変更も自動的に反映できるプロセスのことです。
AWSやGCPなどのパブリッククラウドを利用してインフラを構成することが多くなってきた中で、通常はコンソールから地道にインフラを構築しておりましたが、IaCはコードにインフラの構成が記述されていることからコマンド一つで同じ構成の環境を用意できたり、どのような構成なのかコード上で管理できるようになりインフラ特有の属人化の排除に繋げられるとメリットは様々です。
IaCを利用するツールとしてはAnsibleやchef等がありますが、今回はTechnology Departmentでも取り入れ始めているTerraformを使用してAWSのEC2インスタンスを作成してみました。
Terraformとは
TerraformはHashiCorp社によって開発されたインフラストラクチャ定義ツールです。
HCL(HashiCorp Configuration Language)という⾔語で構成されています。
AWSのみならずGCPやAzureといったパブリッククラウドやDatadogのような監視サービスなど幅広く対応している点が特徴です。
準備編
まずはTerraformが使えるように準備していきます。 HomebrewでTerraform のバージョンマネージャであるtfenvをインストールします。
$ brew install tfenv
次にtfenv経由でTerraform のバージョンを指定してインストールします。
$ tfenv install 0.12.24
Terraformがインストールが完了している確認します。
下記のようにバージョンが出力されたらインストール完了です。
$ terraform --version Terraform v0.12.24
今回はAWSのリソースを作成するためにアクセスキーとシークレットキーの設定を行います。
クレデンシャルを読み込む方法はいくつか方法はありますが、terraform.tfvars
を使う方法が推奨となっているため、今回はterraform.tfvars
に値を持たせファイルで値を渡すという方法をとります。こちらのファイルはgitignoreでGitの管理対象外にする方が良いでしょう。
access_key = "アクセスキー" secret_key = "シークレットキー"
構築編
続いて実際に構築に入ります。
今回作成するリソースはbg-test-ec2
というEC2インスタンス名でインスタンスタイプはt3.nano
で作成します。
基本的にはtfファイルに作成したいリソースを「resource」ブロックで定義しますが、Terraformもモジュールを定義することができ、今回はモジュールを利用することでインスタンスを作成しています。
モジュールを利用するファイル
module "ec2" { source = "../../modules/ec2" ami_id = "ami-XXXXXXXXXXXXXX" subnet_id = aws_subnet.public-subnet1a.id vpc_security_group_ids = [module.private-sg.security_group_id] instance_type = "t3.nano" iam_instance_profile = aws_iam_instance_profile.ec2-profile.name tag_name = "${var.tag_product}-${var.tag_env}-ec2" tag_env = var.tag_env tag_product = var.tag_product tag_type = "test" }
モジュール定義するファイル
resource "aws_instance" "ec2" { ami = var.ami_id instance_type = var.instance_type subnet_id = var.subnet_id vpc_security_group_ids = var.vpc_security_group_ids iam_instance_profile = var.iam_instance_profile ebs_optimized = true monitoring = true # disable_api_termination = true tags = { Name = var.tag_name env = var.tag_env product = var.tag_product type = var.tag_type } }
次にterraform init
コマンドでTerraform の実行に必要なバイナリをダウンロードします。
Terraform has been successfully initialized!
と表示されていれば成功です。
$ terraform init Initializing modules... Initializing the backend... Initializing provider plugins... 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 = "~> X.XX" 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
コマンドでtfファイルに記載したリソースがdry-runのように正常に作成できるか事前に確認できます。
こちらを見てみるとbg-test-ec2
というEC2インスタンス名でインスタンスタイプはt3.nano
で作成されることがわかります。
$ 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: ~省略〜 # module.ec2.aws_instance.ec2 will be created + resource "aws_instance" "ec2" { + ami = "ami-XXXXXXXXXXXXXX" + arn = (known after apply) + associate_public_ip_address = (known after apply) + availability_zone = (known after apply) + cpu_core_count = (known after apply) + cpu_threads_per_core = (known after apply) + ebs_optimized = true + get_password_data = false + host_id = (known after apply) + iam_instance_profile = "bg-test-ec2-role" + id = (known after apply) + instance_state = (known after apply) + instance_type = "t3.nano" + ipv6_address_count = (known after apply) + ipv6_addresses = (known after apply) + key_name = (known after apply) + monitoring = true + network_interface_id = (known after apply) + outpost_arn = (known after apply) + password_data = (known after apply) + placement_group = (known after apply) + primary_network_interface_id = (known after apply) + private_dns = (known after apply) + private_ip = (known after apply) + public_dns = (known after apply) + public_ip = (known after apply) + security_groups = (known after apply) + source_dest_check = true + subnet_id = (known after apply) + tags = { + "Name" = "bg-test-ec2" + "env" = "test" + "product" = "bg" + "type" = "test" } ~省略〜 Plan: 18 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
いよいよ実行移りますがterraform apply
コマンドで実際に実行してリソースを作成します。
実行するとterraform plan
コマンドの時と同様に作成される予定のリソースが出力後、本当に作成するか確認されyes
と打つと実際にAWSのリソースが作成されます。
最後にApply complete!
が出力されると成功となります。
$ 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: ~省略〜 Plan: 18 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_vpc.vpc: Creating... ~省略〜 module.ec2.aws_instance.ec2: Still creating... [10s elapsed] module.ec2.aws_instance.ec2: Still creating... [20s elapsed] module.ec2.aws_instance.ec2: Creation complete after 22s [id=i-0ffd188a384467fbc] ~省略〜 Apply complete! Resources: 18 added, 0 changed, 0 destroyed.
実際にAWSのコンソールを確認してみると、bg-test-ec2
というEC2インスタンス名でインスタンスタイプはt3.nano
で作成されていることを確認できました。
逆に削除したい場合は、terraform destroy
コマンドでTerraformで作成したリソースを削除することができます。
$ terraform destroy
このようにTerraformによりインフラをコード化することで、今までインフラにかけてたリソースを他の作業に割り当てることができたり、環境の差分による問題やヒューマンエラーが防げることは大変メリットと考えております。さらに実運用に向けて他のリソース作成やコードの構成を検証しながらインフラの自動化をどんどん進めていきたいと思います!