Week2
Github를 통해 코드 관리
1. Data 소스
Data 소스의 경우 외부 리소스 또는 저장된 정보를 테라폼 내에서 참조할 때 사용함
기존에 Console 상에서 만들었던 리소스들을 Terraform code 내에서 활용하고 싶을때 data 를 통해 가져올 있음
- 예시) ec2 중 lee 라는 이름의 instance 에대한 정보를 가져오기
- 이제 data.aws_instance.example.[원하는 값] 을 통해 해당 인스턴스에 대한 정보를 사용할 수 있음
data "aws_instance" "example" { filter { name = "tag:Name" values = ["lee"] } }
2. Variable
1) 변수 읽어들이는 순서
Env → terraform.tfvars → terraform.tfvars.json → *.auto.tfvars / *.auto.tfvars.json
→ CLI comment -var -var-file
2) 변수 종류
- type 미 지정 시 default 값을 보고 어느정도 맞춰줌
(1) string
variable "변수 이름" {
type = string
description = "var String" // 해당 변수가 어떤 의미인지 설명하는 것
default = "myString" // 변수의 기본 값
}
(2) number
variable "변수 이름" {
type = number
default = 123
}
(3) boolean
variable "변수 이름" {
default = true
}
(4) list
variable "변수 이름" {
default = [
"google",
"vmware",
"amazone",
"microsoft"
}
사용 예시
0 번 인덱스 출력
output "list_index_0" {
value = var.list.0
}
리스트 내부 모두 출력
output "list_all" {
value = [
for name in var.list :
name
]
}
(5) map
- 모두 출력 시 키 값을 기준으로 정렬되어 출력
variable = "변수 이름" {
default = {
azure = "microsoft",
gcp = "google",
aws = "amazon"
}
}
사용 예시
value 값 출력
output "map_key" {
value = var.map.aws
}
모든 값 출력
output = "map_all" {
value = var.map
}
(6) set
- list와 달리 정렬하여 출력
- map 과 달리 값이 하나
variable = "변수 이름" {
type = set(string)
default = [
"google",
"vmware",
"amazone",
"microsoft"
]
}
(7) object
- 서로 다른 type을 묶어 사용할 수 있게 해
variable "obejct" {
type = object({ name = string, age= number })
default = {
name = "abc"
age = 12
}
}
(8) tuple
variable "tuple" {
type = tuple([string, number, bool])
default = ["abc", 123, true]
}
(9) 변수의 유효성 체크 가능
하단에 있는 코드로 활성화 가능
terraform {
experiments = [variable_validation]
}
예시)
- myVar의 길이가 4보다 커야함
variable "myVar" {
type = string
default = "myVar"
validation {
condition = length(var.myVar) > 4
error_message = "에러 메세지 등록"
}
}
- yourVar 변수는 앞에 your로 시작해야함
variable "yourVar" {
type = string
default = "yourVar"
validation {
condition = can(regex("^your", var.yourVar))
error_message = "에러 메세지 출력"
}
}
3. Local
코드내에서 가공하여 사용하는 변수라고 이해하면 쉬움. 이미 선언한 여러변수를 조합하여 새로운 변수를 만들어 사용할 때 적절함
- 예시) 두 변수를 조합하여 활용
variable "homepage" {
type = string
default = "leechanghwan"
}
variable "index" {
type = list(string)
default = [ "_0", "_1", "_2"]
}
locals {
name = ["${var.homepage}${var.index[0]}", "${var.homepage}${var.index[1]}", "${var.homepage}${var.index[2]}"]
}
- locals.name 이라는 변수에 var.hompage, var.index 를 활용하여 조합하여 사용
4. 반복문
1) Count
- 리소스 블록내 주어진 정수값 만큼 같은 리소스를 생성함
- 예시) count를 사용하여 ec2를 3개 생성
resource "aws_instance" "Challange4" {
ami = "ami-0676d41f079015f32"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.Challange4-sg.id]
count = 3
user_data = <<-EOF
#!/bin/bash
sudo yum update -y
sudo yum install httpd -y
sudo systemctl start httpd
sudo systemctl enable httpd
sleep 10
sudo echo "${count.index}" > /var/www/html/index.html
sudo systemctl restart httpd
EOF
tags = { Name = local.name[count.index] }
}
2)for_each
- 리소스 블록내 선언된 key 개수만큼 리소스를 생성
- count 와 차이점 : for_each는 key와 vaule 값이 존재하여 해당 값으로 리소스 블록내 요소 값들에 key와 value 값을 전달 가능
- count 도 해당 기능이 구현가능하나 list, map 등의 variable을 활용하여 count.index를 통해 접근 해야함
- 예시)
resource "aws_instance" "Challange3" {
ami = "ami-0676d41f079015f32"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.Challange3-sg.id]
for_each = {
index1 = var.homepage[0]
index2 = var.homepage[1]
index3 = var.homepage[2]
}
user_data = <<-EOF
#!/bin/bash
sudo yum update -y
sudo yum install httpd -y
sudo systemctl start httpd
sudo systemctl enable httpd
sleep 10
#each.value를 활용하여 value 값을 전달하고 있다.
sudo echo "${each.value}" > /var/www/html/index.html
sudo systemctl restart httpd
EOF
tags = { Name = each.value}
}
3) for
- 리소스 , 블록 단위가 아닌 한 줄 정도의 반복문을 사용할 때 사용한다
- 예시) ingress 블록내 cidr 블록내 반복문을 사용하여 값 지정
variable "allow" {
variable "allow" {
type = list(string)
default = [ "172.31.50.0/24", "172.31.70.0/24", "172.31.90.0/24"]
}
resource "aws_security_group" "example-sg" {
name = "example-sg"
ingress {
from_port = 22
to_port = 22
protocol = "TCP"
cidr_blocks = [for x in var.allow : x]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
4) dynamic
- 리소스 내부에 블록에 대해서 반복문을 사용할 시 사용
- 보통 sg 를 선언 시 정책을 설정할때 dynamic 구문을 사용한다.
- 예시) 443, 80 포트에 대해서 ingress 를 dynamic 구문을 통해 선언
variable "ingresses" {
default = [
{
from_port : 443
to_port : 443
},
{
from_port : 80
to_port : 80
}
]
}
resource "aws_security_group" "example-sg" {
name = "example-sg"
dynamic "ingress" {
for_each = var.ingresses
content {
from_port = ingress.value["from_port"]
to_port = ingress.value["to_port"]
protocol = "tcp"
cidr_blocks = [0.0.0.0/0]
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
5. 도전과제
1) 리전 내에서 사용 가능한 가용영역 목록을 가져와 VPC 리소스 생성하기
(1) data 소스를 통해 리전내에 존재하는 az를 가져옴
#data.tf
#data 소스를 활용하여 사용가능한 az 가져오기
data "aws_availability_zones" "available" {
state = "available"
}
(2) terraform state show 명령어를 활용하여 data 소스 확인
terraform state show data.aws_availability_zones.available
# data.aws_availability_zones.available:
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",
]
}
(3) 해당 data 소스를 availability_zone에 기입
#vpc.tf
#vpc 선언
resource "aws_vpc" "Challange1_vpc" {
cidr_block = "192.168.0.0/16"
tags = {
Name = "Challange1"
}
}
#ap-northeast-2a 에 subnet 선언
resource "aws_subnet" "Challange1_subnet_a" {
vpc_id = aws_vpc.Challange1_vpc.id
cidr_block = "192.168.0.0/24"
#가져온 데이터 소스 활용
availability_zone = data.aws_availability_zones.available.names[0]
tags = {
Name = "Challange1_subnet_a"
}
}
#ap-northeast-2b 에 subnet 선언
resource "aws_subnet" "Challange1_subnet_b" {
vpc_id = aws_vpc.Challange1_vpc.id
cidr_block = "192.168.1.0/24"
#가져온 데이터 소스 활용
availability_zone = data.aws_availability_zones.available.names[1]
tags = {
Name = "Challange1_subnet_b"
}
}
#ap-northeast-2c 에 subnet 선언
resource "aws_subnet" "Challange1_subnet_c" {
vpc_id = aws_vpc.Challange1_vpc.id
cidr_block = "192.168.2.0/24"
#가져온 데이터 소스 활용
availability_zone = data.aws_availability_zones.available.names[2]
tags = {
Name = "Challange1_subnet_c"
}
}
(4) console 확인
2) 노션 내의 Terraform 코드의 리소스를 자신의 닉네임으로 변경하여 배포 실습하기
- (Option) 선행조건
- 리소스에 대한 이해
// 리소스 종류가 EC2일때 resource "aws_instance" "my-ec2" { ami = "ami-코드 입력" instance_type = "t2.micro" associate_public_ip_address = true }
resource "리소스 종류" "리소스 이름" { //리소스 종류에 따른 내부 구성요소 입력 }
- 리소스에 대한 이해
(1) data 소스를 통해 리전내에 존재하는 az를 가져옴
#data.tf
#data 소스를 활용하여 사용가능한 az 가져오기
data "aws_availability_zones" "available" {
state = "available"
}
(2) vpc 선언
resource "aws_vpc" "Challange2_vpc" {
cidr_block = "192.168.0.0/16"
tags = {
Name = "Challange2"
}
}
(3) subnet 선언
#availability_zones_a 에 subnet 영역 생성
resource "aws_subnet" "Challange2_subnet_a" {
vpc_id = aws_vpc.Challange2_vpc.id
cidr_block = "192.168.0.0/24"
availability_zone = data.aws_availability_zones.available.names[0]
tags = {
Name = "Challange2_subnet_a"
}
}
#availability_zones_b 에 subnet 영역 생성
resource "aws_subnet" "Challange2_subnet_b" {
vpc_id = aws_vpc.Challange2_vpc.id
cidr_block = "192.168.1.0/24"
availability_zone = data.aws_availability_zones.available.names[1]
tags = {
Name = "Challange2_subnet_b"
}
}
#availability_zones_c 에 subnet 영역 생성
resource "aws_subnet" "Challange2_subnet_c" {
vpc_id = aws_vpc.Challange2_vpc.id
cidr_block = "192.168.2.0/24"
availability_zone = data.aws_availability_zones.available.names[2]
tags = {
Name = "Challange2_subnet_c"
}
}
(4) internet gateway 생성
resource "aws_internet_gateway" "Challange2_igw" {
vpc_id = aws_vpc.Challange2_vpc.id
tags = {
Name = "Challange2_igw"
}
}
(5) 라우팅 테이블 생성
#라우팅 테이블 생성
resource "aws_route_table" "Challange2_rtb" {
vpc_id = aws_vpc.Challange2_vpc.id
tags = {
Name = "Challange2_rtb_Public_a"
}
}
(6) 라우팅 테이블과 서브넷 연결
#라우팅 테이블 과 subnet_a 와 연결
resource "aws_route_table_association" "asso_with_subnet_a" {
subnet_id = aws_subnet.Challange2_subnet_a.id
route_table_id = aws_route_table.Challange2_rtb.id
}
#라우팅 테이블 과 sbunet_b 와 연결
resource "aws_route_table_association" "asso_with_subnet_b" {
subnet_id = aws_subnet.Challange2_subnet_b.id
route_table_id = aws_route_table.Challange2_rtb.id
}
#라우팅 테이블 과 sbunet_c 와 연결
resource "aws_route_table_association" "asso_with_sub_a" {
subnet_id = aws_subnet.Challange2_subnet_c.id
route_table_id = aws_route_table.Challange2_rtb.id
}
(7) 보안 그룹 생성과 보안그룹 룰 생성
resource "aws_security_group" "Challange2_sg" {
vpc_id = aws_vpc.Challange2_vpc.id
name = "Challange2_sg"
}
resource "aws_security_group_rule" "Challange2_inbound" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.Challange2_sg.id
}
resource "aws_security_group_rule" "Challange2_outbound" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.Challange2_sg.id
}
(8) data 소스를 활용하여 ami 이미지 가져오기
data "aws_ami" "Challange2_amazonlinux2" {
most_recent = true
filter {
name = "owner-alias"
values = ["amazon"]
}
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-ebs"]
}
owners = ["amazon"]
}
(9) (8)에서 생성한 data 소스를 활용하여 ec2 생성
resource "aws_instance" "Challange2_ec2" {
depends_on = [
aws_internet_gateway.Challange2_igw
]
ami = data.aws_ami.Challange2_amazonlinux2.id
associate_public_ip_address = true
instance_type = "t2.micro"
vpc_security_group_ids = ["${aws_security_group.Challange2_sg.id}"]
subnet_id = aws_subnet.Challange2_subnet_a.id
user_data = <<-EOF
#!/bin/bash
wget https://busybox.net/downloads/binaries/1.31.0-defconfig-multiarch-musl/busybox-x86_64
mv busybox-x86_64 busybox
chmod +x busybox
RZAZ=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone-id)
IID=$(curl 169.254.169.254/latest/meta-data/instance-id)
LIP=$(curl 169.254.169.254/latest/meta-data/local-ipv4)
echo "<h1>RegionAz($RZAZ) : Instance ID($IID) : Private IP($LIP) : Web Server</h1>" > index.html
nohup ./busybox httpd -f -p 80 &
EOF
user_data_replace_on_change = true
tags = {
Name = "Challange2_ec2"
}
}
(10) Console 확인
a. terraform state list
b. aws_console : vpc
3)입력변수를 활용해서 리소스를 배포
(1) 변수 생성
#variable.tf
variable "homepage" {
type = list(string)
default = [ "lee", "chang", "hwan" ]
}
(2) 보안그룹과 ec2 생성
#main.tf
resource "aws_instance" "Challange3" {
ami = "ami-0676d41f079015f32"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.Challange3-sg.id]
#(a)for_each 에서 사용할 key, vaule 선언 value는 변수에서 가져옴
for_each = {
index1 = var.homepage[0]
index2 = var.homepage[1]
index3 = var.homepage[2]
}
#(b) 홈페이지 문구와 ec2이름을 for_each문에서의 value로 사용함
user_data = <<-EOF
#!/bin/bash
sudo yum update -y
sudo yum install httpd -y
sudo systemctl start httpd
sudo systemctl enable httpd
sleep 10
sudo echo "${each.value}" > /var/www/html/index.html
sudo systemctl restart httpd
EOF
tags = { Name = each.value}
}
resource "aws_security_group" "Challange3-sg" {
name = "Challange3-sg"
ingress {
from_port = 22
to_port = 22
protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
- (a) for_each 에서 사용할 key, vaule 선언 value는 변수에서 가져옴
- (b) 홈페이지 문구와 ec2이름을 for_each문에서의 value로 사용함
(3) console 확인 및 홈페이지 확인
a. aws_console : ec2
b. curl을 통한 홈페이지 확인
4) local을 활용해서 리소스를 배포
(1) 변수 생성 - local 활용 확인
variable "homepage" {
type = string
default = "leechanghwan"
}
variable "index" {
type = list(string)
default = [ "_0", "_1", "_2"]
}
# (a) [local.name](http://local.name) 내에서 homepage 변수와, index 변수를 가공하여 활용함
locals {
name = ["${var.homepage}${var.index[0]}", "${var.homepage}${var.index[1]}", "${var.homepage}${var.index[2]}"]
}
- (a) local.name 내에서 homepage 변수와, index 변수를 가공하여 활용함
(2) 보안그룹과 ec2 생성 - local 활용 확인
resource "aws_instance" "Challange4" {
ami = "ami-0676d41f079015f32"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.Challange4-sg.id]
# (a) count 를 활용하여 반복문 실행
count = 3
# (b) count.index가 홈페이지의 문구로 등록됨
user_data = <<-EOF
#!/bin/bash
sudo yum update -y
sudo yum install httpd -y
sudo systemctl start httpd
sudo systemctl enable httpd
sleep 10
sudo echo "${count.index}" > /var/www/html/index.html
sudo systemctl restart httpd
EOF
# (c) local.name 에 있는 요소들을 ec2 이름으로 등록
tags = { Name = local.name[count.index] }
}
resource "aws_security_group" "Challange4-sg" {
name = "Challange4-sg"
ingress {
from_port = 22
to_port = 22
protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
- (a) count 를 활용하여 반복문 실행
- (b) count.index가 홈페이지의 문구로 등록됨
- c) local.name 에 있는 요소들을 ec2 이름으로 등록
(3) console 확인 및 홈페이지 확인
a. aws_console : ec2
b. curl 을 통한 홈페이지 확인
5) count, for_each, for문, dynamic 문 활용
- for_each 는 3번 도전과제, count는 4번 도전과제에서 사용했으므로 for문, dynamic문 활용을 정리
(1) 변수 선언
#variable.tf
# (a) ingressess - ingress로 등록할 포트들을 저장한 변수
variable "ingresses" {
default = [
{
from_port : 443
to_port : 443
},
{
from_port : 80
to_port : 80
}
]
}
# (b) allow - 허용할 cidr 목록을 저장한 변수
variable "allow" {
type = list(string)
default = [ "172.31.50.0/24", "172.31.70.0/24", "172.31.90.0/24"]
}
- (a) ingressess - ingress로 등록할 포트들을 저장한 변수
- (b) allow - 허용할 cidr 목록을 저장한 변수
(2) sg 생성 - for문, dynamic 문 활용 확인
resource "aws_security_group" "Challange5-sg" {
name = "Challange5-sg"
# (a) dynamic 블록을 활용하여 ingress 다수 생성
dynamic "ingress" {
for_each = var.ingresses
content {
from_port = ingress.value["from_port"]
to_port = ingress.value["to_port"]
protocol = "tcp"
# (b) cidr_blockd을 allow 변수에 있는 목록을 가져와 등록
cidr_blocks = [for x in var.allow : x]
}
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
- (a) dynamic 블록을 활용하여 ingress 다수 생성
- (b) cidr_blockd을 allow 변수에 있는 목록을 가져와 등록
(3) console 확인
'Terraform > Study' 카테고리의 다른 글
Terraform-101-Study Week7 - [워크플로] (0) | 2023.08.19 |
---|---|
Terraform-101-Study Week6 - [협업, TFC] (0) | 2023.08.13 |
Terraform-101-Study Week4 - [State, 모듈] (0) | 2023.07.29 |
Terraform-101-Study Week3 - [조건문, 함수, 프로비저너, terraform_data, moved, 프로바이더] (0) | 2023.07.22 |