01 - Terraform Basic

最後更新: 2023-05-22

目錄

 


Install

 

yum install -y yum-utils

yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo

yum -y install terraform    # 會安 git, perl-Git

terraform -v

terraform -install-autocomplete     # Install the TAB autocomplete package

# 它會在 .bashrc 加入

complete -C /usr/bin/terraform terraform

vim syntax highlighting

https://github.com/hashivim/vim-terraform

  1. yum install p7zip -y
  2. mkdir ~/.vim
  3. cd /usr/src
  4. wget https://github.com/hashivim/vim-terraform/zipball/master -O hashivim-`date +%Y%m%d`.zip
  5. 7za x hashivim-`date +%Y%m%d`.zip
  6. mv hashivim-vim-*/{autoload,ftdetect,ftplugin,indent,syntax} ~/.vim

Help

terraform -help init          # Main commands: init, validate, plan, apply, destroy

 


Basic Usage

 

mkdir lab1; cd !$

建立 "main.tf"

terraform fmt          # 格式好 main.tf

terraform init          # 建建 provider 所而資料 (.terraform, .terraform.lock.hcl)

terraform validate   # 要 init 後才可以 validate

# 匯出 AWS 登入資料

export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...

P.S.

unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY

terraform plan              # Preview 有什麼變動

terraform apply

terraform destroy         # 刪除一切

說明

fmt

Rewrite Terraform configuration files to a canonical format and style.

執行後, 它會 Output 它修改過的檔案名

validate

Check whether the configuration is valid

init

initializes a "working directory" containing Terraform configuration files.
installs all providers and modules referred to in the Terraform project
upgrade the providers and modules for your project

terraform block does not include a cloud or backend block, Terraform defaults to the local backend.

validate

 * 要 initialize 後才可以 validate config

使用情況: Update provider / module versions 時很有用

 


File & Directory 結構

 

lock file - .terraform.lock.hcl

The lock file ensures that Terraform uses the same provider versions across your team

.terraform directory

store the project's providers and modules.

terraform.tfstate

Terraform to map real world resources to your configuration, keep track of metadata

Terraform uses state to determine which changes to make to your infrastructure.
Prior to any operation, Terraform does a refresh to update the state with the real infrastructure.

 


CLI Configuration File

 

.terraformrc

# disables upgrade and security bulletin checks (會連到 HashiCorp)

disable_checkpoint = true

# disable the use of an anonymous signature in checkpoint requests
# (allow check for security bulletins)

disable_checkpoint_signature = true

 


Plugin cache

 

Enables plugin caching

mkdir /root/.terraform.d/plugin-cache

~/.terraformrc

plugin_cache_dir = "$HOME/.terraform.d/plugin-cache"

By default, terraform init downloads plugins into a subdirectory of the working directory
  so that each working directory is self-contained.

if you have multiple configurations that use the same provider
  then a separate copy of its plugin will be downloaded for each configuration.

If the selected plugin is not already in the cache, Terraform will download it into the cache first and then
  symbolic links under your current working directory

.terraform/providers/registry.terraform.io/hashicorp/aws/4.66.1 ->
  /root/.terraform.d/plugin-cache/registry.terraform.io/hashicorp/aws/4.66.1/linux_amd64

清垃圾

Over time, as plugins are upgraded, the cache directory may grow to contain several unused versions

which you must delete manually.

 


Cloud Provider AWS

 

Prerequisites

  • Terraform CLI (1.2.0+)
  • AWS CLI
  • AWS account and associated credentials that allow you to create resources.
    (aws configure)
  • AWS plugin

AWS Plugin

/root/.terraform.d/plugin-cache/registry.terraform.io/hashicorp/aws

343M    4.66.1
346M    4.67.0

Step1: Login 到 AWS

除了 "export" login 外, 另外可以用其他方式 login

[1] Hard-coded

provider "aws" {
  access_key = "my-access-key"
  secret_key = "my-secret-key"
}

 * Hard-coded credentials are not recommended in any Terraform configuration

[2] Load awscli configure

provider "aws" {
  shared_config_files      = ["/root/.aws/config"]
  shared_credentials_files = ["/root/.aws/credentials"]
  region                   = "ap-east-1"
}

 * 當沒有 export 及 Hard-Code 設定時, Default 會用 [~/.aws/config] 及 [~/.aws/credentials]

相當於

provider "aws" {
  region                   = "ap-east-1"
}

Profile 設定

provider "aws" {
  shared_config_files      = ["/root/.aws/config"]
  shared_credentials_files = ["/root/.aws/credentials"]
  profile                  = "customprofile"
}

 * If no named profile is specified, the default profile is used.

[default]

Step2: 準備 Project Folder 及 tf 檔

lab1.tf


// Comment
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.67.0"            // providers 的版本
    }
  }
  required_version = ">= 1.2.0"      // terraform 的版本
}

provider "aws" {
  region  = "ap-east-1"
  default_tags {
    tags = {
      Terraform   = "true"
      Environment = "Lab1"
    }
  }
}

/*
resource {...}
*/

Block

  • terraform {} Terraform settings # 非必須
  • provider{} Configures the specified provider # 必須
  • resource {} Define components of your infrastructure (VPC, Instance ...)

terraform{}

當前最新機是 4.67.0

  • version = "~> 4.66.0"   // 符號 "~>" 表示只升級小版本號, 它只會安 4.66.1
  • version = ">= 4.66.0"   // 會直接安裝最新版

provider{}

  • tags 是非必要的

resource{}

 

AWS Provider Documentation

https://registry.terraform.io/providers/hashicorp/aws/latest

 


Good structure

 

在同一  Folder 內的 *.tf 檔都當作一個整體

  • main.tf - call modules, locals, and data sources to create all resources
  • variables.tf - declarations of variables used in main.tf
  • outputs.tf - outputs from the resources created in main.tf
  • terraform.tfvars - 存放 variables 的值

versions.tf

variable "cidr" {
  description = "The CIDR block for the VPC. Default value is a valid CIDR, but not acceptable by AWS and should be overriden"
  type        = string
  default     = "0.0.0.0/0"
}

terraform.tfvars

cidr = "10.10.0.0/16"

*.tfvars

variable.tf are files where all variables are declared;

these might or might not have a default value.

variable.tfvars are files where the variables are provided/assigned a value.

main.tf

resource "aws_vpc" "this" {
  cidr_block = var.cidr
}

 


outputs.tf

 

建議格式: {name}_{type}_{attribute}

outputs.tf

output "app_instance_id" {
  description = "ID of the EC2 instance"
  value       = aws_instance.app_server.id
}

output "app_instance_public_ip" {
  description = "Public IP address of the EC2 instance"
  value       = aws_instance.app_server.public_ip
}

更新 outputs.tf 後要 "terraform apply" 才看到的 output

之後再想看就使用 "terraform output"

output - to extract the value of an output variable from the state file.

 


Inspect state

 

When you applied your configuration, Terraform wrote data into a file called terraform.tfstate

The Terraform state file is the only way Terraform can track which resources it manages,
and often contains sensitive information,
so you must store your state file securely and restrict access.

# human-readable output from a state or plan file

terraform show

Advanced state management (state)

terraform [global options] state <subcommand> [options] [args]

Subcommands:

    list                      List resources in the state
    mv                      Move an item in the state
    pull                     Pull current state and output to stdout
    push                    Update remote state from a local state file
    replace-provider   Replace provider in the state
    rm                      Remove instances from the state
    show                   Show a resource in the state

# list resources within a Terraform state

terraform state list

aws_internet_gateway.lab1-igw
aws_route_table.lab1-rt
aws_route_table_association.lab1-subnet-a
aws_subnet.lab1-subnet-a
aws_vpc.lab1-vpc

# show the attributes of a single resource in the state file that matches the given address.

terraform state show ADDRESS

i.e.

terraform state show aws_vpc.lab1-vpc

 


Destroy infrastructure

 

 * It does not destroy resources running elsewhere that are not managed by the current Terraform project.
   (This command is the inverse of "terraform apply")

terraform destroy

 

Creative Commons license icon Creative Commons license icon