LAC WATCH

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

RSS

株式会社ラック

メールマガジン

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

サービス・製品 | 

5分で分かるTerraform(Infrastructure as Code)

さらに詳しく知るにはこちら

Terraform(テラフォーム)

HashiCorp社が提供するTerraformは、マルチクラウド上のコンピュータやネットワークの構築を自動化する、エンジニアにとても人気のあるツールです。

Terraformをご存じなかった方にも、その「成り立ち」と「何を目指しているのか」についてご理解いただけるよう、今回は「5分で分かるTerraform(Infrastructure as Code※1)」と題した記事を日本語訳してお届けします。著者のMehdi ZedはモントリオールでDevOpsバックエンド開発に携わっており、DevOpsについてSNSで積極的に発信しています。その発信内容は非常に分かりやすく、今回の記事についても本人の了解を得て日本語化しました。

さらに詳しく知るにはこちら

Terraform(テラフォーム)

※1 インフラの構築・運用に関わる作業をコード化、自動化するアプローチ。設定変更作業をコードで管理することで手作業による間違いを防ぎ、設定変更を履歴として管理できる。また、設定変更作業を自動化することで、大量のサーバーに迅速に設定変更を反映できる。


Terraformは、今の私にとって「ささやかな、ごちそう」です。今回はこのTerraformについてご紹介したいと思います。ご存じのとおり、ここ数年のDevOpsムーブメントの広がりに伴い、Infrastructure as Codeは今や誰もが取り組むべきものになってきました。そんな中でもTerraformはもっとも「クール」なソリューションです。

かつては

2006年の初めに、Amazonは少し知られたサービススイートであるAmazon Web Service(AWS)を発表しました。AWSについては皆さんご存じかと思います。

同じ年の8月25日、AWSはEC2のベータ版を米国でリリースしました。これにより開発者は初めて、クラウド上にサーバーを数分で起動できるようになりました。1年後、このサービスは世界中で一般公開されます。EC2のリリースはその後の全てを変えてしまうような出来事でした。

この革命以前は、アプリケーション用のサーバーを用意するのはかなり大変だったということを理解しておく必要があります。クラウドが登場する前は、社内でインフラサービスを用意するよう誰かに依頼しなくてはいけませんでした。オンプレミスのサーバーを手動で構築する必要があり、そのサーバーを構築している間はずっと待たなくてはなりません。

ところが現在では、数回のクリックでほとんど瞬時にサーバーを構築、変更、破棄することができます。これはこれで非常に良いことですが、これだけではサーバーを完全にコントロールするには不十分です。

それではコードを使って、クラウド上のインフラ環境を動的に構築し、管理できるとすればどうでしょうか。Amazonはこのアイデアを非常に気に入って、2010年5月15日にCloudFormationを発表します。

サービスとしてのインフラ(IaaS:Infrastructure as a Service)が生まれ、多くの人々に歓迎されました。そして現在最も話題になっているIaC(Infrastructure as Code)ツールTerraformがこの記事のテーマです。

Terraformとは

Terraformは、IaCを実現するツールです。Terraformはオープンソースであり、HashiCorpによってGo言語で開発されました。具体的にはTerraformではインフラの構成をコードで宣言します。構造化された構成ファイルでは、手動で操作することなくインフラ構成を自動で管理できます。インフラの初期プロビジョニング、更新、破棄、いずれもTerraformではコードにより宣言し、実行します。

IaCの世界では、インフラ構成を実現する方法がいくつかあります。Terraformは、いわゆる宣言型の方法を採用しており、インフラの望ましい状態を構成ファイルで宣言します。Terraformは、インフラの望ましい状態を達成するために最小限のことだけを行います。

例:あなたの管理する稼働中のインフラでは、すでにWebサーバーとデータベースが実行されています。コード内の構成はこれに完全に対応しています。次に2つのデータベースが必要になる構成を追加します。コミットするとTerraformは追加のデータベースを作成します。それ以外には何もしません。これによりコードで宣言された望ましい状態に達しました。あなたはこれを一見して「美しい」と感じるでしょう。

コードを見るだけでインフラの構成内容を理解できるということは素晴らしいことです。コードはGitでバージョン管理されます!つまり、あなたのインフラ環境もバージョン管理されるということです。

コードでインフラを構築する場合、本番環境を作る前にいくつかの環境でインフラ構築をテストできます。開発環境で同じコードをプッシュすると、インフラの変更を安全にテストできます。 同僚とインフラの状態をコードレビューすることも可能です。コードを数行変更するだけで、すばやく繰り返し重要な変更をすることができます。つまり、DevOpsで開発を進めるにあたり、最適な手段といえます。

しかし実際にTerraformはどのように機能しているのでしょうか?Terraformはインフラ構成の一部を、どのように構築、変更、破棄を管理しているのでしょうか?

どのように機能しているのか?

Terraformは構成ファイルで宣言した状態を取得し、変更内容を宛先のプロバイダーにプッシュします。AWS上にサーバーを構築する場面をイメージしてください。サーバーの構成を宣言し、それをプッシュすることでAWSアカウント上にサーバーが現れます。

TerraformはGo言語で書かれたAWS SDKを使用しています。このSDKを介して、サーバーをクラウド上に直接構築しました。ですが、SDKコードに煩わされたり、背後で何が起こっているのかを本当に理解したりする必要はありません。Terraformがそのような面倒なことを吸収してくれますので、コードだけチェックすればOKです。これにより、インフラの更新フローが非常にシンプルかつ高速になります。

Terraform使用してクラウド上にサーバーを構築する構成図

そして重要なのは、Terraformが1つのプロバイダー(AWS)やクラウド一般に限定されないことです。ほとんどすべてのタイプのインフラをTerraformのリソースとして表すことができます。そう考えるとTerraformの素晴らしさが伝わると思います。

ローカルマシンのDockerコンテナからDigitalOceanのクラウドアカウントに至るまで、Terraformによってインフラをどこにでも再現できます。この記事では、利用可能プロバイダーの全リストを提供するつもりはありませんが、たとえばこちらを参照ください。そしてこの利用可能プロバイダーが多数あるという事実はTerraformの有用性を高めます。

さて、理論はこれで十分ですので、次は実際に手を動かしてやってみましょう。

コードを見る

それでは、設定から始めてみましょう。ここでは、Linuxディストリビューションを使用しているものと想定して話を進めます。そうでない場合はこちらをご覧ください。

# dependencies
sudo apt-get install wget unzip

# download last version
wget
https://releases.hashicorp.com/terraform/0.12.20/terraform_0.12.20_linux_amd64.zip

# unzip in bin folder
sudo unzip ./terraform_0.12.20_linux_amd64.zip -d /usr/local/bin/

# check its working
terraform -v

次に最初の構成ファイルを作成します。まず簡単なところから始めましょう。AWS上にEC2サーバーとPostgresデータベースを作成します。管理者のクレデンシャルを発行できるAWSアカウントも持っているものと想定しています。最初のステップでは、プロバイダーを定義するmain.tfファイルを作成します。

main.tf

# definition provider
provider "aws" {
  version = "~> 2.0"
  region = "${var.provider_region}"
  access_key = "${var.secret_access_key}"
  secret_key = "${var.secret_key}"
}

ここでは、AWSを利用すること、及びバージョンとリージョンを指定します。AWSにアクセスするにはクレデンシャル情報を指定します。指定する値は変数を介して参照されます。これらの変数はすべて、この後に見るファイルに格納されます。

これでAWSの利用するバージョン、リージョンを宣言したので、次は構築するものを宣言します。いつものように、どこから始めればよいかわからないときは、ドキュメントを調べましょう。UbuntuとPostgresデータベースを宣言するresource.tfファイルを作成してみましょう。

resource.tf

resource "aws_instance" "web" {
  ami = "${data.aws_ami.ubuntu.id}"
  instance_type = "${var.server_instance_type}"

  tags = {
    Name = "${var.server_tag_name}"
  }
}

data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
  }

  owners = ["099720109477"]
}

resource "aws_db_instance" "default" {
  allocated_storage = "${var.db_allocated_storage}"
  storage_type = "${var.db_storage_type}"
  engine = "${var.db_engine}"
  engine_version = "${var.db_engine_version}"
  instance_class = "${var.db_instance_class}"
  name = "${var.db_database_name}"
  username = "${var.db_database_username}"
  password = "${var.secret_db_database_password}"
  final_snapshot_identifier = "${var.db_snapshot_identifier}"
}

必要なすべてを定義したので、これに対応する変数を入力します。専用のvariables.tfファイルを作成します。シークレットは本来ファイル内で平文であることは望ましくありませんが※2、今回はデモを簡単に見せるために、このようにします。

※2 訳注:Terraformで使うシークレットを安全に管理するには、Vaultと組み合わせることを推奨したい。
LAC WATCH:Vaultの動的シークレットでTerraformのセキュリティレベルを向上させるには

# provider variables
variable "provider_region" {
 description = "Provider region"
 default = "us-east-1"
}

variable "secret_access_key" {
 description = "Provider access key"
 default = "YOUR-ACCESS-KEY"
}

variable "secret_key" {
 description = "Provider secret key"
 default = "YOUR-SECRET-KEY"
}

# instance web variables
variable "server_instance_type" {
  description = "Server instance type"
  default = "t2.micro"
}

variable "server_tag_name" {
  description = "Server tag name"
  default = "JeSuisUnDev"
}

# instance base de données RDS postgres variables
variable "db_allocated_storage" {
  description = "Allocated storage"
  default = 20
}
variable "db_storage_type" {
  description = "Storage type"
  default = "gp2"
}

variable "db_engine" {
  description = "Storage engine"
  default = "postgres"
}

variable "db_engine_version" {
  description = "Storage engine version"
  default = "11.5"
}

variable "db_instance_class" {
  description = "Storage instance class"
  default = "db.t2.micro"
}

variable "db_database_name" {
  description = "Storage database name"
  default = "postgres"
}

variable "db_database_username" {
  description = "Storage database name"
  default = "postgres"
}

variable "secret_db_database_password" {
  description = "Storage database secret password"
  default = "postgres"
}

variable "db_snapshot_identifier" {
  description = "Storage database snapshot identifier"
  default = "postgres"
}

これで設定終了です!それでは実際に動かしてみましょう。まずTerraformを初期化、ファイルを検証し、アクションを計画(plan)して、最後に変更を適用(apply)します。Terraform CLI(Terraformが用意するコマンドライン)を使用してやってみましょう!

はじめに、Terraform初期化コマンドを入力してみましょう。これは先程ファイルを作成したフォルダで行う必要があります。

> terraform init

Initializing the backend...

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "aws" (hashicorp/aws) 2.48.0...

Terraform has been successfully initialized!

構成ファイルの記述がすべて正常であることを検証します。

> terraform validate

Success! The configuration is valid.

次の段階ではPlanを行います。今回は新しいインフラを構築するため、作成の操作のみ実行されます。

> terraform plan

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_db_instance.default will be created
  # aws_instance.web will be created

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

そして今、まさにIaCの魔法がかかる瞬間です。Terraformで行った計画(plan)を実行(apply)します。これにより実際にインフラをクラウドに構築します。

> terraform apply

aws_instance.web: Creating...
aws_db_instance.default: Creating...
aws_instance.web: Still creating... [10s elapsed]
aws_instance.web: Still creating... [30s elapsed]
aws_instance.web: Creation complete after 43s [id=i-0f285230749e69a67]
aws_db_instance.default: Still creating... [50s elapsed]
aws_db_instance.default: Still creating... [1m50s elapsed]
aws_db_instance.default: Still creating... [2m50s elapsed]
aws_db_instance.default: Still creating... [3m50s elapsed]
aws_db_instance.default: Still creating... [4m0s elapsed]
aws_db_instance.default: Creation complete after 4m8s [id=terraform-20200208064624729700000001]

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

コードでインフラが出来上がりました。美しいですよね?さて構築が完了したので、terraform showコマンドでステータスを確認してみましょう。そして最も重要なのは、インフラを新規構築するのと同じくらい簡単にインフラを破棄できることです。

> terraform destroy

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

aws_instance.web: Destroying... [id=i-0f285230749e69a67]
aws_db_instance.default: Destroying... [id=terraform-20200208064624729700000001]
aws_instance.web: Destruction complete after 30s
aws_db_instance.default: Destruction complete after 50s

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

これでインフラ全体をコードで完全に制御できます。そして、すべてをCI/CDパイプラインに入れると、何もあなたを止めることはできません。

最後に

もっと詳しく知りたい方はTerraformのドキュメントをご確認ください。とても分かりやすく作られているので、参考になると思います。また、HashiCorpが作成したチュートリアルもあり、初心者にはとても役立ちます。こちらもぜひ、楽しみながら試してみてください!

お問合せ

Terraformに関するお問い合わせ

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

はい いいえ

関連記事

LAC WATCH

関連記事をご紹介します

  • 人的ミスによる情報漏えいを回避!TerraformとSentinelでAWS S3のセキュリティベストプラクティスを実現

  • 技術者でない人のためのTerraform入門

  • Vaultの動的シークレットでTerraformのセキュリティレベルを向上させるには