데이터 소스(data
)는 외부의 리소스 혹은 저장된 정보를 내부로 가져올 때 사용한다.
기본 사용법은 2기 스터디원 Ssoon님이 블로그에 잘 정리해주셨다.
아래와 같이 AMI나 AZ를 조회할 때 유용하다.
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "state"
values = ["available"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
data "aws_availability_zones" "available" {
group_names = [
"ap-northeast-2",
]
id = "ap-northeast-2"
names = [
"ap-northeast-2a",
"ap-northeast-2b",
"ap-northeast-2c",
"ap-northeast-2d",
]
state = "available"
zone_ids = [
"apne2-az1",
"apne2-az2",
"apne2-az3",
"apne2-az4",
]
}
변수는 Terrraform 코드를 동적으로 구성할 수 있게 한다. 테라폼에서는 이것을 입력 변수 Input Variables 로 정의한다.
variable "<이름>" {
<인수> = <값>
}
variable "image_id" {
type = string
}
위와 같이 변수를 정의할 때 다양한 메타인수를 넣을 수 있다. 관련 정보는 아래와 같다.
💡 변수 정의 시 사용 가능한 메타인수default : 변수 값을 전달하는 여러 가지 방법을 지정하지 않으면 기본값이 전달됨, 기본값이 없으면 대화식으로 사용자에게 변수에 대한 정보를 물어봄
type : 변수에 허용되는 값 유형 정의, string number bool list map set object tuple 와 유형을 지정하지 않으면 any 유형으로 간주
description : 입력 변수의 설명
validation : 변수 선언의 제약조건을 추가해 유효성 검사 규칙을 정의 - 링크
sensitive : 민감한 변수 값임을 알리고 테라폼의 출력문에서 값 노출을 제한 (암호 등 민감 데이터의 경우) - 링크
nullable : 변수에 값이 없어도 됨을 지정
우선순위
1번 부터 변수를 대입하며, 후 순위가 전 순위를 덮어쓰기 합니다. 결론적으로 아래에 있는 옵션이 우선순위가 높습니다.
Order | Option |
---|---|
1 | Environment Variables |
2 | terraform.tfvars |
3 | terraform.tfvars.json |
4 | *.auto.tfvars (alphabetical order) |
5 | -var or –var-file (command-line flags) |
local은 외부에서 입력되지 않고, 코드 내에서만 가공되어 동작하는 값이다. 외부에서 입력되진 않지만 Local 선언 자체에 일반 변수를 넣을 수 있다. (아래의 예시 참고)
local은 회사내의 클라우드 서비스를 이용할 때, 리소스에 태그를 걸어야한다. ex) Owner, Purpose 등
이 때 Local 변수를 사용하면 아래와 같이 편하게 리소스에 태그를 걸 수 있다.
locals {
additional_tags = {
Purpose = var.purpose
Owner = var.owner
}
}
...
resource "aws_instance" "app" {
...
tags = merge(
{
Name = "web-app"
},
local.additional_tags
)
}
도전과제2
: 위 3개 코드 파일 내용에 리소스의 이름(myvpc, mysubnet1 등)을 반드시! 꼭! 자신의 닉네임으로 변경해서 배포 실습해보세요!
resource "aws_vpc" "myvpc" {
cidr_block = "10.10.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "t101-study"
}
}
[도전과제1]
리전 내에서 사용 가능한 가용영역 목록 가져오기를 사용한 VPC 리소스 생성 실습 진행resource "aws_subnet" "mysubnet1" {
vpc_id = aws_vpc.myvpc.id
cidr_block = "10.10.1.0/24"
availability_zone = data.aws_availability_zones.available.names[2]
tags = {
Name = "t101-subnet1"
}
}
resource "aws_subnet" "mysubnet2" {
vpc_id = aws_vpc.myvpc.id
cidr_block = "10.10.2.0/24"
availability_zone = "ap-northeast-2c"
tags = {
Name = "t101-subnet2"
}
}
Vscode 에서 추출한 그림인데, 리소스가 많아 보기 조금 불편하다.
$ MYIP=$(terraform output -raw kane_ec2_public_ip)
$ echo $MYIP
3.35.173.67
$ while true; do curl --connect-timeout 1 http://$MYIP/ ; echo "------------------------------"; date; sleep 1; done
<h1>RegionAz(apne2-az1) : Instance ID(i-0ca40805a20604dbe) : Private IP(10.10.1.34) : Web Server</h1>
------------------------------
Mon Sep 4 00:50:56 KST 2023
<h1>RegionAz(apne2-az1) : Instance ID(i-0ca40805a20604dbe) : Private IP(10.10.1.34) : Web Server</h1>
------------------------------
Mon Sep 4 00:50:57 KST 2023
<h1>RegionAz(apne2-az1) : Instance ID(i-0ca40805a20604dbe) : Private IP(10.10.1.34) : Web Server</h1>
------------------------------
Mon Sep 4 00:50:58 KST 2023
terraform apply 이후 파일에 적힌 출력값을 콘솔에 출력해준다. 주로 Ec2의 퍼블릭 ip같이 꼭 확인해야 하는 것들을 주로 출력한다. 생성 후의 정보를 출력하기에 당연한 이야기지만 오로지, apply를 적용할 때만 출력한다. 또한 이런 값들은 추후 파이프라인 구성, shell script 혹은 ansible
에 사용할 수도 있다.
기본 예시
output "instance_ip_addr" {
value = aws_instance.server.private_ip
description = "The private IP address of the main server instance."
}
조건 검사 진행
output "api_base_url" {
value = "https://${aws_instance.example.private_dns}:8433/"
# The EC2 instance must have an encrypted root volume.
precondition {
condition = data.aws_ebs_volume.example.encrypted
error_message = "The server's root volume is not encrypted."
}
}
sensitive
: CLI 에서 출력되지 않게 할 수 있다.depends_on
: 선수관계를 정할 수 있다.(먼저, 출력되는 것을 결정할 수 있다.)output "instance_ip_addr" {
value = aws_instance.server.private_ip
description = "The private IP address of the main server instance."
depends_on = [
# Security group rule must be created before this IP address could
# actually be used, otherwise the services will be unreachable.
aws_security_group_rule.local_access,
]
}
count, count.index
로 접근variable "subnet_ids" {
type = list(string)
}
resource "aws_instance" "server" {
# Create one instance for each subnet
count = length(var.subnet_ids)
...
subnet_id = var.subnet_ids[count.index]
tags = {
Name = "Server ${count.index}"
}
}
resource "aws_instance" "example" {
# One VPC for each element of var.vpcs
for_each = var.instances
# each.value here is a value from var.vpcs
name = each.key
ami = each.value.ami
}
for
뒤에 If
를 통해 필터링 기능도 가능하다.(if 인 값만 사용)[for s in var.list : upper(s) if s != ""]
[for i, v in var.list : "${i} is ${v}"]
# object 형식일때
[for k, v in var.map : length(k) + length(v)]
특수한 목적의 Dynamic Block을 통해 동적으로 만들어지는 변수에 대해 반복 가능한 블럭을 만들 수 있다. 기존의 for_each, count 등 반복문은 리소스 block 등 자신의 바깥 블럭을 반복해서 찍어내는 것에 비해 dynamic block은 block자체를 정의하며 반복적으로 찍어낸다. (resource와 같은 단일블락이 아닌 내부 블락으로만 사용된다.) 사용방법은 Argument를 확인하면 된다.
resource "aws_security_group" "backend-sg" {
name = "backend-sg"
vpc_id = aws_vpc.backend-vpc.id
dynamic "ingress" {
for_each = var.ingress_ports
content {
from_port = ingress.value
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}
# 아래와 같이 하기 싫어서 위처럼 진행
resource "aws_security_group" "backend-sg" {
name = "backend-sg"
vpc_id = aws_vpc.backend-vpc.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
도전과제3
: 입력변수를 활용해서 리소스(어떤 리소스든지 상관없음)를 배포해보고, 해당 코드를 정리해주세요!
위에서 진행한 EC2 배포 코드를 이용한다. 변수를 통해 인스턴스의 타입을 동적으로 구성한다.
resource "aws_instance" "kane_ec2" {
depends_on = [
aws_internet_gateway.kane_igw
]
ami = data.aws_ami.amazonlinux2.id
associate_public_ip_address = true
// 아래의 내용을 수정!
instance_type = var.ec2_instance_type
vpc_security_group_ids = ["${aws_security_group.kane_sg.id}"]
subnet_id = aws_subnet.kane_subnet1.id
...
variable "ec2_instance_type" {
type = string
description = "The type of EC2 instance to launch"
}
ec2_instance_type = "t2.small"
이제 Terraform apply
명령어를 통해 인프라를 구축한다.
기존과는 다르게 t2.micro
가 아닌 t2.small
이 생성된 것을 확인할 수 있다.
도전과제4
: local를 활용해서 리소스(어떤 리소스든지 상관없음)를 배포해보고, 해당 코드를 정리해주세요!
local을 통해, EC2에 태깅 작업을 진행한다.
locals {
additional_tags = {
Environment = "Dev"
Purpose = "Test"
Owner = "Kane"
}
}
resource "aws_instance" "kane_ec2" {
depends_on = [
aws_internet_gateway.kane_igw
]
...
tags = merge({
Name = "t101-kane_ec2"
}
, local.additional_tags)
}
terraform apply
를 실행한다.
이제 AWS 콘솔에 들어가 EC2 > Tags 페이지를 확인하면 다음과 같이 태깅이 올바르게 된 것을 확인할 수 있다.