代々木で働く19歳エンジニアのブログ

思ったこととか、技術的なこと書きます。

Overview of terraform

Getting Started

Install

$ brew install terraform

Configuration

provider "aws" {
  access_key = "ACCESS_KEY_HERE"
  secret_key = "SECRET_KEY_HERE"
  region     = "us-east-1"
}
resource "aws_instance" "example" {
  ami           = "ami-2757f631"
  instance_type = "t2.micro"
}

Execution Plan and Apply

$ terraform plan

# create real resources
$ terraform apply

# the terraform.tfstate file maps various resource metadata to actual resource IDs so that Terraform knows what it is managing.
# You can inspect the state using terraform show

$ terraform show

Change Infrastructure

resource "aws_instance" "example" {
+ ami           = "ami-2757f631" 
- ami           = "ami-b374d5a5"
  instance_type = "t2.micro"
}

Destroy Infrastructure

# verify exactly what resources Terraform is managing and will destroy
$ terraform plan -destroy

# destroy the infrastructure
$ terraform destroy

Resource Dependencies

resource "aws_instance" "example" {
  ami           = "ami-b374d5a5"
  instance_type = "t2.micro"
}

# This resource type allocates and associates an elastic IP to an EC2 instance. 
# The only parameter for aws_eip is "instance" which is the EC2 instance to assign the IP to.

resource "aws_eip" "ip" {
  instance = "${aws_instance.example.id}"
}

Implicit and Explicit Dependencies

#  you can also specify explicit dependencies with the depends_on parameter which is available on any resource.

resource "aws_eip" "ip" {
  instance   = "${aws_instance.example.id}"
  depends_on = ["aws_instance.example"]
}
# If you're ever unsure about the dependency chain that Terraform is creating, you can use the terraform graph
$ terraform graph

Defining a Provisioner

Provisioners are used to execute scripts on a local or remote machine as part of resource creation or destruction.

resource "aws_instance" "example" {
  ami           = "ami-b374d5a5"
  instance_type = "t2.micro"

  provisioner "local-exec" {
    command = "echo ${aws_instance.example.public_ip} > ip_address.txt"
  }
}
$ cat ip_address.txt
54.192.26.128

Defining Variables

variable "access_key" {}
variable "secret_key" {}

# If a default value is set, the variable is optional.
variable "region" {
  default = "us-east-1"
}
# Using Variables in Configuration
provider "aws" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region     = "${var.region}"
}

Assigning Variables

# Command-line flags
$ terraform plan \
  -var 'access_key=foo' \
  -var 'secret_key=bar'
access_key = "foo"
secret_key = "bar"
$ terraform plan \
  -var-file="secret.tfvars" \
  -var-file="production.tfvars"

Lists

# implicitly by using brackets [...]
variable "cidrs" { default = [] }

# explicitly
variable "cidrs" { type = "list" }
cidrs = [ "10.0.0.0/16", "10.1.0.0/16" ]

Maps Maps are a way to create variables that are lookup tables.

variable "amis" {
  # A variable can have a map type assigned explicitly, or it can be implicitly declared as a map by specifying a default value that is a map.
  type = "map"
  default = {
    "us-east-1" = "ami-b374d5a5"
    "us-west-2" = "ami-4b32be2b"
  }
}
resource "aws_instance" "example" {
  ami           = "${lookup(var.amis, var.region)}"
  instance_type = "t2.micro"
}

Assigning Maps

$ terraform plan -var 'amis={ us-east-1 = "foo", us-west-2 = "bar" }'
variable "region" {}
variable "amis" {
  type = "map"
}
amis = {
  "us-east-1" = "ami-abc123"
  "us-west-2" = "ami-def456"
}
$ terraform apply -var region=us-west-2

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

Outputs:

  ami = ami-def456

Defining Outputs

Outputs are a way to tell Terraform what data is important. This data is outputted when apply is called, and can be queried using the terraform output command.

output "ip" {
  value = "${aws_eip.ip.public_ip}"
}

Viewing Outputs

$ terraform apply
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

  ip = 50.17.232.209
$ terraform output ip
50.17.232.209

Modules

provider "aws" {
  access_key = "AWS ACCESS KEY"
  secret_key = "AWS SECRET KEY"
  region     = "AWS REGION"
}

# The module block tells Terraform to create and manage a module.
module "consul" {
 # The source configuration is the only mandatory key for modules. It tells Terraform where the module can be retrieved.
 source = "github.com/hashicorp/consul/terraform/aws"

  key_name = "AWS SSH KEY NAME"
  key_path = "PATH TO ABOVE PRIVATE KEY"
  region   = "us-east-1"
  servers  = "3"
}
# Prior to running any command such as plan with a configuration that uses modules, you'll have to get the modules.

$ terraform get

# The terraform get command is used to download and update modules mentioned in the root module.
https://www.terraform.io/docs/commands/get.html

Remote Backends - In production environments it is more responsible to run Terraform remotely and store a master Terraform state remotely. - Terraform Enterprise allows teams to easily version, audit, and collaborate on infrastructure changes. - functions as a Terraform backend as well as enabling many other features such as remote apply, run history, state history, state diffing, and more

githubのterraform版みたいな感じ?

# configure the backend in your configuration
terraform {
  backend "consul" {
    address = "demo.consul.io"
    path    = "getting-started-RANDOMSTRING"
    lock    = false
  }
}
# After configuring a backend, run terraform init to setup Terraform.

$ terraform init 
$ terraform plan

# ...

No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, Terraform
doesn't need to do anything.

# Terraform is now storing your state remotely in Consul.

Terraform Enterprise

$ export ATLAS_TOKEN=ATLAS_ACCESS_TOKEN
terraform {
  backend "atlas" {
    name = "USERNAME/getting-started"
  }
}

# Note that the backend name is "atlas" for legacy reasons and will be renamed soon.
$ terraform init
$ git init
$ git add example.tf
$ git commit -m "init commit"

# push your Terraform configuration to Terraform Enterprise

$ terraform push

This will automatically trigger a terraform plan, which you can review in the Terraform page. If the plan looks correct, hit “Confirm & Apply” to execute the infrastructure changes.

所感

  • consul使ってみたい
  • Modules, Terraform Enterprise, Provisioner使ってみたい
  • でもこの辺使い出したらもう仕事関係ないんだよなー笑
  • Terraform Enterpriseのページがかっこよかった

Reference from