Terraformでインフラを管理している場合、基本的には手動でリソースを作成することは避けた方が良いです。
Terraformで管理することで、コードによる一貫性やバージョン管理の利点を享受できます。
とはいえ、コードを書いてプロビジョニングするよりも、マネジメントコンソールから手で作ってしまった方が簡単に済む場合があります。特に、急ぎの対応が必要な場合や、複雑な設定を直感的に行いたい場合などです。しかし、この方法は後々管理が煩雑になるリスクを伴います。
そのようにして手動で作られたリソースも、Terraformの管理下に入れることが可能です。この方法を利用することで、既存のインフラをコード管理に移行できます。
今回はAWS上で手動で作成したリソースをTerraformにインポートする方法について解説します。
やること
以下の手順で、手動作成したAWSリソースをTerraform管理に移行します。
- 事前にTerraform実行用インスタンスを作成する。
- この手順は別の記事で解説しています。詳しくはこちらの記事をご覧ください。
- TerraformでVPCとサブネットを作成する。
- マネジメントコンソールから検証用のインスタンスを作成する。
- Terraform importで手動で作成したインスタンスをTerraformにインポートする。
- インポートしたインスタンスに変更を加えてみる。
今回は手順2から実施します。
構成図
インポート手順
TerraformでVPCとサブネットを作成する
VPC, サブネット,インターネットゲートウェイ, ルートテーブルとその関連付けを作成します。
下記のような.tf
ファイルを作成して、terraform apply
を実行してリソースをデプロイしましょう。
以下のファイルでは、AZ(アベイラビリティゾーン)やCIDR情報を外部のvarファイル
に設定しています。
※varファイル
の使い方については別の記事で解説しています。
# VPC
resource "aws_vpc" "terraform-vpc" {
cidr_block = var.vpc["cidr-vpc"]
enable_dns_hostnames = true
tags = {
Name = "terraform-vpc"
}
}
# Internet Gateway
resource "aws_internet_gateway" "terraform-igw" {
vpc_id = aws_vpc.terraform-vpc.id
tags = {
Name = "terraform-igw"
}
}
# Public Subnet
resource "aws_subnet" "terraform-sbn-pub-1a" {
vpc_id = aws_vpc.terraform-vpc.id
availability_zone = "${var.aws_region}a"
cidr_block = var.vpc["cidr-public-a"]
tags = {
"Name" = "terraform-sbn-pub-1a"
}
}
# Route Table for Public Subnet
resource "aws_route_table" "terraform-rtb-pub" {
vpc_id = aws_vpc.terraform-vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.terraform-igw.id
}
tags = {
"Name" = "terraform-rtb-pub"
}
}
resource "aws_route_table_association" "terraform-rtb-pub-1a" {
subnet_id = aws_subnet.terraform-sbn-pub-1a.id
route_table_id = aws_route_table.terraform-rtb-pub.id
}
マネジメントコンソールから検証用インスタンスを作成する
先ほど作成したVPCとサブネット上に、AWSマネジメントコンソールを使用してEC2インスタンスを作成します。
今回はAMIをAmazonLinux2023, インスタンスタイプをt2.microで作成してみます。
インポート用のtfファイルを作成する
Terraformを実行するディレクトリに、EC2をインポートするための.tf
ファイルを作成します。
$ touch ec2.tf
次にインポート用のブロックを用意します。最初はリソースタイプと識別名だけでOKで、中身は後で記述します。
resource "aws_instance" "imported_instance" {
}
terraform importを実行する
手動作成したEC2をTerraformにインポートします。インポートするにはterraform import
コマンドを実行します。
インポートの基本構文
terraform import {インポート先のアドレス} {リソースID}
インポート先のアドレスは、リソースタイプと識別名をピリオド(.
)で繋げたものです。先ほどの作成したec2.tfの例だと、aws_instance.imported_instance
がインポート先のアドレスになります。
リソースIDはインポート対象のリソースに固有のIDです。EC2インスタンスの場合、インスタンスID(例: i-xxxxxxxxxxxxxxxxx
)が該当します。
どのIDを使えばいいのかは、公式ドキュメントから確認することができます。
$ terraform import aws_instance.imported_instance i-xxxxxxxxxxxxxxxxx
aws_instance.imported_instance: Importing from ID "i-xxxxxxxxxxxxxxxxx"...
aws_instance.imported_instance: Import prepared!
Prepared aws_instance for import
aws_instance.imported_instance: Refreshing state... [id=i-xxxxxxxxxxxxxxxxx]
Import successful!
The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
Import successful!
と表示されればOKです。これで手動作成したEC2がTerraform管理下に入りました。
次に、TerraformのstateファイルにインポートしたEC2が登録されているか確認します。
以下のコマンドを実行して、aws_instance.imported_instance
が含まれていることを確認してください。
$ terraform state list
aws_instance.imported_instance
aws_internet_gateway.terraform-igw
aws_route_table.terraform-rtb-pub
aws_route_table_association.terraform-rtb-pub-1a
aws_subnet.terraform-sbn-pub-1a
aws_vpc.terraform-vpc
インポート用のtfファイルを修正する
先ほど作成したec2.tfに記述したインポート用のブロックを修正します。
現在は中身が空なので、terraform state show
コマンドを使用してインポートしたEC2インスタンスの属性を確認し、それに合わせて定義を記述します。
$ terraform state show aws_instance.imported_instance
# aws_instance.imported_instance:
resource "aws_instance" "imported_instance" {
ami = "ami-012967cc5a8c9f891"
arn = "arn:aws:ec2:us-east-1:123456789:instance/i-xxxxxxxxxxxxxxxxx"
associate_public_ip_address = true
availability_zone = "us-east-1a"
cpu_core_count = 1
cpu_threads_per_core = 1
disable_api_stop = false
disable_api_termination = false
ebs_optimized = false
get_password_data = false
hibernation = false
host_id = null
iam_instance_profile = null
id = "i-xxxxxxxxxxxxxxxxx"
instance_initiated_shutdown_behavior = "stop"
instance_lifecycle = null
instance_state = "running"
instance_type = "t2.micro"
(省略)
}
terraform state show
の出力内容から必要な情報を選び、ec2.tf
に記述します。
その後、terraform plan
を実行して状態の確認を行います。
resource "aws_instance" "imported_instance" {
★ここに定義を書く
}
terraform plan
を実行し、差分が表示されなくなれば成功です。具体的には以下のように出力されます。
No changes. Your infrastructure matches the configuration.
これが表示されたら、Terraformの状態ファイル(stateファイル)とコードが完全に一致していることを意味します。
インポートしたリソースの設定を変更する
Terraformへのインポートが完了したら、通常通りコードを編集してリソース設定を変更できます。
今回は、インスタンスタイプをt2.micro
からt2.small
に変更してみましょう。
instance_type = "t2.micro"
↓
instance_type = "t2.small"
修正後、terraform plan
コマンドで変更内容を確認します。
差分に問題がなければ、terraform apply
コマンドで変更を適用します。
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
~ update in-place
Terraform will perform the following actions:
# aws_instance.imported_instance will be updated in-place
~ resource "aws_instance" "imported_instance" {
id = "i-xxxxxxxxxxxxxxxxx"
~ instance_type = "t2.micro" -> "t2.small" ★インスタンスタイプが変更されている
tags = {
"Name" = "import-test-instance"
}
+ user_data_replace_on_change = false
# (37 unchanged attributes hidden)
# (8 unchanged blocks hidden)
}
Plan: 0 to add, 1 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 ★変更を適用する
applyが正常終了したら、マネジメントコンソールからインスタンスタイプが変更されていることを確認します。
おわりに
今回は手動で作成したリソースをTerraformにインポートする方法について解説しました。
これにより、すでに存在するインフラをTerraformの管理下に置くことができます。
コメント