LAC WATCH

セキュリティとITの最新情報

RSS

株式会社ラック

メールマガジン

サイバーセキュリティや
ラックに関する情報をお届けします。

ラックピープル | 

Terraformerで既存AWS環境をIaC化してみた

DevSecOpsチームの前野です。

社内AWS開発環境の一部についてTerraformerを使いIaC化する検証を行いましたので、その手順や気付いたことを紹介します。

検証の背景

IaCとは、Infrastructure as Codeの略でインフラの構成管理をコードで行う手法を指します。そして、手動で作成したクラウドのインフラ環境をコードで表現し、バージョン管理ツールなどで管理可能な状態にすることを既存環境のIaC化と定義します。

利用している開発環境では、新規に作成するクラウドリソースはIaCを使って管理するのですが、昔からあるクラウドリソースは手動で作成しパラメーターもエクセルで管理していました。そのため、古いクラウドリソースもIaCによる運用を行いIaCのメリットを享受するべく今回の検証を行いました。IaCのメリットには、構築の自動化や設計の再利用、およびコードをバージョン管理することで、クラウドに対する変更履歴を保持できる等があります。

検証ではIaCツールとしてTerraformを対象としました。Terraformは、現在のインフラの状態を示すStateファイルとあるべきインフラの状態を定義するConfigurationファイル(.tfの拡張子を持つファイル群)で構成されます。そのため、Terraformによる既存インフラ環境のIaC化を達成するためには、StateファイルとConfigurationファイル双方を作成し、両者に差分がないことが必要です。

※ Terraformは、HashiCorp社のマルチクラウドに対応したIaCツールです。
ラックのTerraform紹介ページはこちら
Terraform(テラフォーム)

TerraformによるIaC化を達成するためには、ConfigurationファイルとStateファイルを作成し、両者に差分がない状況であることが必要

Stateファイルは、Terraformの標準コマンドである"terraform import"コマンドを使用して対象のインフラ環境から自動で抽出・生成できます。ただし対象のインフラリソースを特定する必要があり、数十のリソースが存在するインフラ環境をIaC化する場合には手間がかかります。例えば下記AWS VPCのStateファイルを生成するTerraformのコマンド実行例では、パラメーターにVPC IDの指定が必要です。

terraform import aws_vpc.test_vpc vpc-123xxxxx

またStateファイルに対応するConfigurationファイルは手動で作成しなければなりません。

そこでTerraformのStateファイルおよびConfigurationファイルを自動で抽出・生成するツールを探していたところ、Terraformerにたどり着き検証することになりました。

※ Waze SRE が作成したコマンドラインツール
GitHub - GoogleCloudPlatform/terraformer: CLI tool to generate terraform files from existing infrastructure (reverse Terraform). Infrastructure to Code

Terraformerは、下記コマンド実行例のように複数のサービスを指定して、含まれるインフラリソースを一括でインポートできます。

terraformer import aws --resources=vpc,subnet

また、Terraformerは対象のインフラリソースのConfigurationファイルを自動で生成できます。下記は、Terraformerで実際に生成したConfigurationファイルの例です。

ec2.tf

resource "aws_instance" "tfer--i-00XX-xxxxxxxxxxxxxxxxx_XX-XXXX-00000000-00XX-000000-00XX-XX-00XX-XX" {
  ami                         = "ami-00000000XXXXXXXXX"
  associate_public_ip_address = "false"
  availability_zone           = "ap-northeast-1a"
 
  capacity_reservation_specification {
    capacity_reservation_preference = "open"
  }
}

TerraformerによるIaC化の手順

Terraformerによる既存AWS環境のIaC化の具体的な手順を次の3つのステップで説明します。

  1. 事前準備
  2. コードの抽出・生成
  3. IaC実行環境への反映
TerraformerによるIaC化作業フロー概要

1. 事前準備

Terraformerを実行するためには、次の4つの作業が必要です。

  • (1)  実行環境の用意
  • (2)  権限の作成
  • (3)  Terraformのインストールと設定
  • (4)  Terraformerのインストール

(1)実行環境の用意

まず、Terraformerの実行環境を用意します。今回は検証目的のためローカルのWindows PC端末で作業を行いました。ただし、抽出するStateファイルにはクラウドの構成情報やシークレット等の機密情報が含まれるため、本番環境を対象とする場合には別途アクセスを制限した仮想マシン(AWSであれば特定の作業者のみログインできるEC2インスタンス)を用意してください。

以降は、ローカルのWindows PC端末上でAWS環境を対象にTerraformerを実行する想定で手順を記載します。

(2)権限の作成

Terraformerが対象インフラリソースの構成情報を取得する権限を作成します。

AWSの場合には、AWS管理ポリシー「ReadOnlyAccess」を付与したIAM Roleを作成して作業者のIAMユーザーに紐づけます。その後、IAMユーザーに紐づく資格情報(アクセスキーおよびシークレットキー)を発行します。なお「ReadOnlyAccess」は、対象のAWSアカウント内のすべてのクラウドリソースの読み取り権限のため、必要に応じて、参照可能な範囲を制限するポリシーを追加してください。

(3)Terraformのインストールと設定

Terraformerの実行には、Terraformが必要です。Terraformのインストール方法はHashiCorp社の公式ドキュメントを参照ください。

Install Terraform | Terraform | HashiCorp Developer

続いてTerraformの設定を行います。
作業ディレクトリに移動し、main.tfを作成します。

main.tf

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

次に下記コマンドを実行してprovider(各インフラに対応したTerraformのプラグイン)をインストールします。

terraform init

最後に、下記AWS CLIコマンドを実行してTerraformがAWSにアクセスする際の権限を設定します。

AWS CLIのインストール方法は、下記公式ドキュメントを参照ください。

AWS CLI の最新バージョンをインストールまたは更新します。 - AWS Command Line Interface

なおAWSの仮想マシン上で作業する場合には、インスタンスプロファイルにIAM Roleを紐づけることで本手順は不要になります。

> aws configure
 
AWS Access Key ID []: <前記手順「IAMの作成」で発行したaccess keyを入力>
AWS Secret Access Key []: <前記手順「IAMの作成」で発行したsecret keyを入力>
Default region name []: <IaC化対象のリージョンを入力 例:ap-northeast-1>
Default output format []: <出力データ形式を入力 例:json>

上記手順では、ローカルにシークレットを保持するため、セキュリティ強化の観点から必要に応じてMFAを使用してください。

AWS CLI 経由で MFA を使用してアクセスを認証する | AWS re:Post

(4)Terraformerのインストール

下記手順にしたがいTerraformerをインストールします。

GitHub - GoogleCloudPlatform/terraformer: CLI tool to generate terraform files from existing infrastructure (reverse Terraform). Infrastructure to Code

以上でTerraformerを実行するための事前準備が完了しました。

2. コードの抽出・生成

IaC化したいクラウドリソースを含むサービス名を指定して、Terraformerを実行します。
例えば、東京リージョンのVPCおよびサブネットのクラウドリソースを抽出する場合は下記コマンドを実行します。

terraformer import aws -resources=vpc,subnet -regions=ap-northeast-1

実行後に、作業ディレクトリにStateファイルおよび指定したサービス名ごとにConfigurationファイル含むディレクトリが作成されます。

3. IaC実行環境への反映

今回の検証では、IaC実行環境としてTerraform CloudとIaCのコードのバージョン管理システムとしてGitHubを使用しました。Terraform Cloudの基本的な使用方法について本稿では割愛しますが、記事内でHashiCorp社の公式チュートリアルのリンクを記載しますので適宜参照ください。

HashiCorp社が提供するTerraformのSaaS

(1)Terraform Cloudアカウントの作成

まず、Terraform Cloudのアカウントを作成します。

アカウントの作成手順は、下記公式ドキュメントを参照ください。

What is Terraform Cloud - Intro and Sign Up | Terraform | HashiCorp Developer

(2)Workspaceの作成およびGit連携

次に、Workspaceを作成し前記手順で生成したConfigurationファイルをコミットしたGitリポジトリと連携を行います。

Workspaceの作成手順は、下記公式ドキュメントを参照ください。

Create a Workspace | Terraform | HashiCorp Developer

Gitリポジトリとの連携手順は、下記公式ドキュメントを参照ください。

Use VCS-Driven Workflow | Terraform | HashiCorp Developer

(3)Stateファイルのアップロード

前記手順「Terraformのインストールと設定」で作成したmain.tfに下記を追記し、TerraformのStateファイルの保管場所にTerraform Cloudを指定します。

main.tf

terraform {
  backend "remote" {
    hostname = "app.terraform.io"
    organization = "<Organization名>"
    workspaces {
      name = "<Workspace名>"
    }
  }
}

下記コマンドを実行し、設定を反映します。

terraform init

前記手順「コードの抽出・生成」で生成したStateファイルについて、前記手順「Workspaceの作成およびGit連携」で作成したWorkspaceのStateファイル中のserialとlineageの値で更新します。

(Terraformerで生成した)terraform.state

{
  "version": 3,
  "terraform_version": "0.12.29",
  "serial": <Terraform CloudのStateファイルの値より大きい数値を設定>,
  "lineage": "<Terraform CloudのStateファイルの値で書き換え>",
(略)
}

CLIから下記コマンドを実行すると、ブラウザ経由でTerraform CloudのAPIトークン発行画面に遷移しますので、APIトークンを発行し、設定します。

> terraform login
 
Terraform will request an API token for app.terraform.io using your browser.
 
If login is successful, Terraform will store the token in plain text in  
the following file for use by subsequent commands:
    C:¥Users¥xxx¥ AppData ¥Roaming¥terraform.d¥credentials.tfrc.json
 
Do you want to proceed?
  Only 'yes' will be accepted to confirm.
 
  Enter a value: <yesと入力>
 
---------------------------------------------------------------------------------
 
Generate a token using your browser, and copy-paste it into this prompt.
 
Token for app.terraform.io:
  Enter a value: <発行したTerraform CloudのAPIトークンを入力>

下記コマンドを実行し、ローカルのStateファイルをTerraform Cloudにアップロードします。

terraform state push

Terraform CloudのUI画面からPlanを実行し、変更が0件であること(StateファイルとConfigurationファイル差分がないこと)を確認します。この時、Plan実行前には対象のクラウドリソースの構築権限(ここではAWS IAM)をVariablesで設定している必要があります。

Variablesの設定方法は、下記公式ドキュメントを参照ください。

Create a Credentials Variable Set | Terraform | HashiCorp Developer

Terraform CloudのUI画面からPlanを実行し、変更が0件であること(StateファイルとConfigurationファイル差分がないこと)を確認

以上で既存AWS環境のIaC化が完了しました。

Terraformerを使用する際の注意点

Terraformerを使用した際に気付いた注意すべき2点を記載します。

  1. 出力されるStateファイルの対応バージョンが古い
  2. 出力されるConfigurationファイルは可読性の観点から修正が必要

1. 出力されるStateファイルの対応バージョンが古い

Terraformerが抽出するStateファイルは、Terraformバージョン0.12系の形式です(2023年6月1日執筆時点)。

Terraformは、バージョン1.0系にかけて(2023年6月1日執筆時点の最新バージョンは1.46)Stateファイルの構造が変化しているため、Terraformerを使用して、かつ0.12系より新しいバージョンのTerraformで実行する場合には、下記Stateファイルのアップデート作業が必要になります。

なお、アップデート作業中のTerraformのバージョンの切り替えはtfenvを使用しています。
tfenvのインストール方法は、下記手順を参照ください。

GitHub - tfutils/tfenv: Terraform version manager

まず、下記コマンドを実行して0.12系から0.13系へのアップデートを行います。

tfenv use 0.13.7
terraform init
terraform 0.13upgrade

次に、下記コマンドを実行して0.13系から0.14系へのアップデートを行います。

tfenv use 0.14.11
terraform init
terraform refresh

最後に、下記コマンドを実行して0.14系から1.0系へのアップデートを行います。

tfenv use 1.2.8
terraform init
terraform refresh

2. 出力されるConfigurationファイルは可読性の観点から修正が必要

Terraformerが生成するConfigurationファイルは、リソース名がランダムな文字列で、またフィールドの値が固定値です。そのため、運用では可読性の観点からリソース名の統一や、固定値の変数化が必要になります。

例えば、抽出したAWS EC2のConfigurationファイルは下記のようにリソース名にランダム文字列が含まれ、ami等のパラメーターが固定値となっています。

ec2.tf

resource "aws_instance" "tfer--i-00XX-xxxxxxxxxxxxxxxxx_XX-XXXX-00000000-00XX-000000-00XX-XX-00XX-XX" {
  ami                         = "ami-00000000XXXXXXXXX"
  associate_public_ip_address = "false"
  availability_zone           = "ap-northeast-1a"
 
  capacity_reservation_specification {
    capacity_reservation_preference = "open"
  }
}

なおConfigurationファイルのリソース名はStateファイルと紐づくため、リソース名を変更する場合には"terraform state mv"コマンドを実行してStateファイルも併せて修正する必要があります。

下記は、aws_instanceリソースについて、リソース名を「tfer--i-00XX...」から「sample」に変更する場合のコマンド実行例です。

terraform state mv aws_instance.tfer--i-00XX... aws_instance.sample

最後に

ここまでTerraformerによる具体的なIaC化の手順とTerraformerを使用する際の注意点を紹介しました。Terraformerは、既存インフラ環境のStateファイルとConfigurationファイルを自動で作成してくれる便利なツールです。しかし、生成したコードを基に頻繁に変更作業を行いたい、あるいは最新バージョンのTerraformで実行したい等、組織のIaC化の目的によっては出力したコードが直ちに利用できる完成されたコードとは言えず運用を考慮したリファクタリングが必要です。

これからIaC化に取り組まれる方は、まずなぜIaC化をしたいのかという目的を踏まえてTerraformerのツールの適否や適用範囲を検討してみてください。また、TerraformerもしくはTerraformについてお問い合わせ等ある方は、こちらからご相談ください

補足

本記事を執筆中にTerraformのバージョンv1.5.0-beta2がリリースされました(2023年5月24日)。

リリースには、既存インフラリソースからConfigurationファイルを自動生成するための新機能が含まれるため、上記で述べたTerraformerの2つの課題を解決する既存インフラ環境のIaC化のあらたな選択肢となり得ます。現在はまだベータ版なので、機能削除となる可能性もあります。ご利用にはご注意ください。

※ 下記Terraformリリースノートの「import blocks for importing infrastructure」および「Generating configuration for imported resources」の項目を参照
Release v1.5.0-beta2 · hashicorp/terraform · GitHub

「TerraformerおよびTerraform」に関するお問い合わせ

この記事は役に立ちましたか?

はい いいえ

関連記事

LAC WATCH

関連記事をご紹介します

  • Terraformに学ぶ、Infrastructure as Codeの導入と組織に起こる変化

  • Terraform+Snykで、セキュアなクラウドインフラ構築&運用自動化を実現しよう!

  • イチから学べるTerraform~基礎から実践を紹介するウェビナー動画を無料公開~