AWS Terraform Section3 - Input and Output

Terraform output

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
resource "aws_subnet" "dev-subnet-1" {
# 指定subnet所属的VPC
# 目前VPC还没创建,所以需要动态引用定义的资源
vpc_id = aws_pvc.development-vpc.id

# 定义VPC地址范围的子集
cidr_block = "10.0.10.0/24"

availability_zone = "eu-west-3a"
}

...

output "dev-subnet-id" {
value = aws_subnet.dev-subnet-1.id
}

执行

1
terraform plan

可以看到控制台输出了output​中定义的值

image

*可以使用vscode编写Terraform code,该工具支持打开终端

image

Terraform input

在Terraform中引用变量

  • 通过default​给定默认值
  • 通过type​设置变量类型,如list(string), string, object等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
variable "subnet_cidr_block" {
description = "subnet cidr block"
default="10.0.10.0/24"
type = string

}

...

resource "aws_subnet" "dev-subnet-1" {
vpc_id = aws_pvc.development-vpc.id
cidr_block = var.subnet_cidr_block

availability_zone = "eu-west-3a"
}

Object示例

terraform.tfvars

1
2
3
4
cidr_blocks = [
{cidr_block-="10.0.0.0/16", name="dev-vpc"},
{cidr_block-="10.0.0.0/16", name="dev-vpc"}
]

变量定义方式

1
2
3
4
5
6
variable "cidr_blocks" {
type = list(object({
cidr_block = string
name = string
}))
}

引用方式

1
2
3
4
5
6
7
8
resource "aws_pvc" "development-vpc" {

cider_block = var.cider_block[0].cider_block
tags = {
Name: var.cider_block[0].name
}

}

变量的赋值方式

通过控制台输入

直接执行

1
terraform apply

然后在控制台输入内容

image

命令行传参数

在控制台执行

1
terraform -var "subnet_cidr_block=10.0.30.0/24"

(常用)定义变量文件

当执行如下命令时

1
terraform apply -var-file terraform-dev.tfvars --target=module.xxx

变量传递链路如下

*.tfvars​ -> variable.tf -> main.tf -> output.tf

例如:

创建一个*.tfvars​的文件,例如terraform.tfvars

Terraform能自动找到tfvars​并识别为变量文件

image

执行

1
terraform apply

此时不需要额外输入变量的值,Terraform会自动找到变量并且赋值

推荐把变量文件根据环境来命名

例如 terraform-dev.tfvars

image

指定变量文件

1
terraform apply -var-file terraform-dev.tfvars

AWS Credential

不推荐以下方式明文写入access key

1
2
3
4
5
6
7
8
9
provider "aws" {
region = "eu-west-3" # 取决于购买的EC2实例所属的区域

/**
不推荐hardcode明文的key
**/
access_key = ""
secret_key = ""
}

1.可以使用环境变量的方式

1
2
export AWS_SECRET_ACCESS = "XXXX"
export AWS_ACCESS_KEY_ID = "XXXX"

然后直接执行terraform命令,会自动连接到AWS

image

2.在文件中存储以便全局调用

存储位置: ~/.aws/credentials

可以直接输入 aws configure进行配置,自动存储到 ~/.aws/credentials

image

也可以设置AWS_DEFAULT_REGION指定默认的区域

image

3.可以通过安装adfs登录AWS

1
python install adf-assume

执行以下脚本一键连接到AWS

1
2
3
4
5
6
7
#!/bin/bash

source [python_env]
echo -n "Input AWS password: "
read -s AWS_PASSWORD
export AWS_PROFILE=saml
adfs-assume -u $ACCOUNT --domain=$DOMAIN

Global Variable

命名规则必须为:TF_VAR_xxx

例如,需要引用操作系统当前环境下的某个变量

image

在Terraform中引用

1
2
3
4
5
6
7
variable avail_zone {}

...

resource "aws_subnet" "dev-subnet-1" {
availability_zone = var.avail_zone
}

执行结果

可以看到自动识别到了变量 avail_zone 自动匹配到了 TF_VAR_avail_zone

image

Terraform Module

通过模块的方式编写,而不是将所有的代码都放在同一个tf​文件中

一个module应该将多个resource整合起来,方便相同的组件重用

例如VPC、Subnet、Route table、Internate gateway都应该放到同一个module中,方便创建EC2时直接调用

image

同时Terraform也有一些现成的module方便参考,不需要重复创造功能相同的模块

https://registry.terraform.io/browse/modules

Terraform state

Terraform plan会根据state文件生成执行计划

最好把tfstate​存放起来远程访问,确保Jenkins和团队成员本地执行都能读取到最新的状态

AWS可以使用S3存储

image

例如

1
2
3
4
5
6
7
8
9
# 创建S3
terraform {
required_version = ">=0.12"
backend "s3" {
bucket = "myapp-bucket"
key = "myapp/state.tfstate"
region = "eu-west-3"
}
}

在创建的时候会询问是否把状态存储到S3image

此时state文件将交给AWS控制,Jenkins和开发人员本地会自动使用S3的state文件

image

使用如下命令验证,不同的环境执行应该得到相同的结果

1
terraform state list
0%