<1> 데이터 소스 1 테라폼으로 정의되지 않은 외부 리소스 또는 저장된 정보를 테라폼 내에서 참조할 때 사용 mkdir 35 cd 35 2 data 소스 = data로 시작함. vi main.tf data "local_file" "abc" { filename = "${path.module}/abc.txt" } data 정보를 참조. local 프로바이이더를 씀. file을 소스로 사용함. 이름 abc 3 # 실습 확인을 위해서 abc.txt 파일 생성 echo "t101 study - 2 week" > abc.txt 4 terraform init && terraform plan && terraform apply -auto-approve 5 terraform state list data.local_file.abc // 데이터 블록, 로컬 프로바이더, 파일, abc라는 리소스 유형 6 // 테라폼 콘솔로 변수 값 확인 가능함 // 대화형으로 확인 가능. 전체 상태 정보를 확인가능하다. terraform console > data.local_file.abc { "content" = <<-EOT t101 study - 2 week EOT "content_base64" = "dDEwMSBzdHVkeSAtIDJ3ZWVrCg==" "content_base64sha256" = "GTJyISrUCoLsNeCTz8=" "content_base64sha512" = "tp0cRC/xBlJH4txY6Skb/FmexTrlNXgAeSYPtmPhvYhgwsXTWJ2jpTJkkiqclybnVu8MA==" "content_md5" = "983a604da71f3b8291" "content_sha1" = "75a47c30031f170e9539324f95c87" "content_sha256" = "193272212ad40a8542a782893b0564bb0d7824f3f" "content_sha512" = "b69d1c442ff106520994c99248aa725c9b9d5bbc30" "filename" = "./abc.txt" "id" = "75a47c30031f5f39324f95c87" } // 특정 내용만 보고 싶을때는 ? data.local_file.abc.filename data.local_file.abc.content data.local_file.abc.id exit > data.local_file.abc.filename "./abc.txt" > data.local_file.abc.content < data.local_file.abc.id "75a47c30031f5fb5170e9539324f95c87" <2> 데이터 속성 참조 - 실제 써보자. 1 # Terraform Code data "<리소스 유형>" "<이름>" { <인수> = <값> } # 데이터 소스 참조 data.<리소스 유형>.<이름>.<속성> 2 예시) AWS 가용 영역 정보를 가져오고 싶을때 ? ap-northeast-2a 정보를 가져와 보자~ # Declare the data source data "aws_availability_zones" "available" { state = "available" } resource "aws_subnet" "primary" { availability_zone = data.aws_availability_zones.available.names[0] # e.g. ap-northeast-2a } resource "aws_subnet" "secondary" { availability_zone = data.aws_availability_zones.available.names[1] # e.g. ap-northeast-2b } // 가용 영역 정보를 가져오고 싶다. // data소스를 활용한다. // data.aws_availability_zones.available.names[0] // data.프로바이더 aws . 가용영역 . 이름 . names는 속성이다. 3 속성 참고 Attribute Reference https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones <3> 데이터 소스 참조 실습1 1 vi main.tf resource "local_file" "abc" { content = "123!" filename = "${path.module}/abc.txt" } data "local_file" "abc" { filename = local_file.abc.filename } resource "local_file" "def" { content = data.local_file.abc.content filename = "${path.module}/def.txt" } // abc라는 파일을 만듬 // def 파일의 컨텐츠에 data사용. 123! 들어감. 2 // data는 1개 // resource는 2개 # terraform state list data.local_file.abc local_file.abc local_file.def // content = data.local_file.abc.content // def의 콘텐츠 내용이 def.txt 파일에 들어간다. // 123! 이 들어간다. 동일하게 콘텐츠가 123!로 들어간다. // more abc.txt // more def.txt <4> az.tf 파일 생성 = AZ(가용영역)를 변수로 확인하기 1 vi az.tf data "aws_availability_zones" "available" { state = "available" } // aws를 만들거니 init 한번 해줘야 함. aws 프로바이더 관련 파일을 다운로드된다. 2 # terraform init -upgrade && terraform apply -auto-approve terraform state list # terraform state list data.aws_availability_zones.available data.local_file.abc local_file.abc local_file.def // 데이터 소스 관련해 1개가 추가 되었다. data.aws_availability_zones.available 3 # // 명령어로 보기 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", ] } 4 // 테라폼 콘솔로도 필터링해서 볼 수 있다. terraform console > data.aws_availability_zones.available data.aws_availability_zones.available.names data.aws_availability_zones.available.names[0] data.aws_availability_zones.available.names[1] data.aws_availability_zones.available.zone_ids[0] data.aws_availability_zones.available.zone_ids[1] exit <5> 입력 변수, input variable 1 입력 변수는 인프라를 구성하는 데 필요한 속성 값을 정의해 코드의 변경 없이 여러 인프라를 생성하는 데 목적이 있다. 2 cd mkdir 36 cd 36 3 변수는 variable로 시작되는 블록으로 구성된다. 변수 블록 뒤의 이름값은 동일 모듈 내 모든 변수 선언에서 고유해야 하며, 이 이름으로 다른 코드 내에서 참조된다 variable 블록으로 선언한다. 4 예) # variable 블록 선언의 예 variable "<이름>" { <인수> = <값> } variable "image_id" { type = string } 5 예제) vi main.tf variable "string" { type = string description = "var String" default = "myString" } variable "number" { type = number default = 123 } variable "boolean" { default = true } variable "list" { default = [ "google", "vmware", "amazon", "microsoft" ] } output "list_index_0" { value = var.list.0 } output "list_all" { value = [ for name in var.list : upper(name) ] } variable "map" { # Sorting default = { aws = "amazon", azure = "microsoft", gcp = "google" } } variable "set" { # Sorting type = set(string) default = [ "google", "vmware", "amazon", "microsoft" ] } variable "object" { type = object({ name = string, age = number }) default = { name = "abc" age = 12 } } variable "tuple" { type = tuple([string, number, bool]) default = ["abc", 123, true] } variable "ingress_rules" { # optional ( >= terraform 1.3.0) type = list(object({ port = number, description = optional(string), protocol = optional(string, "tcp"), })) default = [ { port = 80, description = "web" }, { port = 53, protocol = "udp" }] } // 확인 terraform init && terraform plan && terraform apply -auto-approve terraform state list # terraform output list_all = [ "GOOGLE", "VMWARE", "AMAZON", "MICROSOFT", ] list_index_0 = "google" 설명 // output "list_all" { value = [ for name in var.list : upper(name) // output "list_index_0" { 은 리스트의 0을 가져온다. google을 가져온다. <6> 유효성 검사 1 입력되는 변수 타입 지정 외에, 사용자 지정한 값에 대한 유효성 검사가 가능하다. 변수 브럭 내에 validation 블럭에서 조건인 condition내에 규칙이 true 또는 false를 반환해야 하면 false 인 경우 출력 되는 메시지를 정의한다. 예제) vi main.tf variable "image_id" { type = string description = "The id of the machine image (AMI) to use for the server." validation { condition = length(var.image_id) > 4 error_message = "The image_id value must exceed 4." } validation { # regex(...) fails if it cannot find a match condition = can(regex("^ami-", var.image_id)) error_message = "The image_id value must starting with \"ami-\"." } } // id 가 최소 4글자 이상이여야 한다. ami 이미지를 잘못 넣은것을 검사할때 사용한다. // ami 이미지 이름이 ami- 로 시작해야 한다.고 컨티션을 정의한다. # terraform apply -auto-approve var.image_id The id of the machine image (AMI) to use for the server. Enter a value: ami (3글자만 입력했다) ... 에러가 나온다!!! # terraform apply -auto-approve var.image_id The id of the machine image (AMI) to use for the server. Enter a value: ami- (ami- 이나 4글자이상이 아니다.) ... │ The image_id value must exceed 4. # terraform apply -auto-approve var.image_id The id of the machine image (AMI) to use for the server. Enter a value: ami-12345678 // 4자 이상이 되어야 한다. // ami- 로 시작되어야 한다. // 실행시켜봄 , 입력 변수를 지정하지 않았으니 대화형으로 물어봄. // ami-11111111 넣어봄 = 성공 <7> 변수 선언하고 참조 해보자 1 입력을 변수로 받아보자. 8080 포트 사용하다 9090으로 변경할 경우 사용가능하다. vi main.tf variable "my_password" {} resource "local_file" "abc" { content = var.my_password filename = "${path.module}/abc.txt" } # terraform init -upgrade terraform apply -auto-approve var.my_password Enter a value: qwe123 ... // 변수를 입력 안했으니 입력 값을 받는다. qwe123 입력. # 확인 terraform state list local_file.abc # 상세 보기 terraform state show local_file.abc cat abc.txt ; echo qwe123 2 # 해당 파일에 다른 내용으로 변경해 보기 terraform apply -auto-approve var.my_password Enter a value: t101mypss ... # 확인 cat abc.txt ; echo t101mypss 3 민감한 변수 취급? passwd 노출하면 안된다. 출력할 때 암호화 되어 보이도록 한다. variable "my_password" { default = "password" sensitive = true } resource "local_file" "abc" { content = var.my_password filename = "${path.module}/abc.txt" } 4 확인? # 출력 부분에 내용 안보임! terraform apply -auto-approve 5 terraform state show local_file.abc # 결과물 파일 확인 cat abc.txt ; echo 6 # terraform.tfstate 파일 확인 상태 저장 파일에는 저장이 되어 있다. 상태정보 파일은 보안에 유의해야 한다. cat terraform.tfstate | grep '"content":' "content": "password", <8> 변수 입력 방법과 우선순위? https://spacelift.io/blog/terraform-tfvars 7이 가장 우선순위가 높다. 1 우선순위 ? 가장 낮은 우선 순위? 대화형으로 입력하는것 main.tf variable "my_var" {} resource "local_file" "abc" { content = var.my_var filename = "${path.module}/abc.txt" } 실행 후 입력 # 실행 terraform apply -auto-approve var.my_var Enter a value: var1 ... # 확인 terraform state show local_file.abc cat abc.txt ; echo 2 번째 ? variable 블록의 default 값 variable "my_var" { default = "var2" } resource "local_file" "abc" { content = var.my_var filename = "${path.module}/abc.txt" } # 실행 terraform apply -auto-approve # 확인 terraform state show local_file.abc cat abc.txt ; echo var2 3 번째 ? 환경 변수 (TF_VAR 변수 이름) 환경 변수의 접두사에 TF_VAR_ 가 포함되면 그 뒤의 문자열을 변수 이름으로 인식 환경 변수가 디폴트 값보다 우선된다!!! # Linux/macOS export TF_VAR_my_var=var3 terraform apply -auto-approve # 확인 cat abc.txt ; echo var3 4 우선 순위 ? terraform.tfvars에 정의된 변수 선언 # echo 'my_var="var4"' > terraform.tfvars cat terraform.tfvars var4 # terraform apply -auto-approve # 확인 cat abc.txt ; echo var4 5 우선 순위? *.auto.tfvars에 정의된 변수 선언 a. 보다 b.이 우선순위가 높다. # a.auto.tfvars 파일 생성 echo 'my_var="var5_a"' > a.auto.tfvars ls *.tfvars # terraform apply -auto-approve # 확인 cat abc.txt ; echo # b.auto.tfvars 파일 생성 echo 'my_var="var5_b"' > b.auto.tfvars ls *.tfvars a.auto.tfvars b.auto.tfvars terraform.tfvars # terraform apply -auto-approve # 확인 cat abc.txt ; echo var5_b 6. 우선 순위 ? *.auto.tfvars.json에 정의된 변수 선언 # a.auto.tfvars.json 파일 생성 cat < a.auto.tfvars.json { "my_var" : "var6_a" } EOF ls *.tfvars ; ls *.json # terraform apply -auto-approve # 확인 cat abc.txt ; echo var5_b # c.auto.tfvars.json 파일 생성 cat < c.auto.tfvars.json { "my_var" : "var6_c" } EOF ls *.tfvars ; ls *.json # terraform apply -auto-approve # 확인 cat abc.txt ; echo var6_c // a보다 c가 우선 순위가 높다!! 7 최우선 순위 ? CLI 실행 시 -var 인수에 지정 또는 -var-file로 파일 지정 최우선 순위로 반영 된다!!! # terraform apply -auto-approve -var=my_var=var7 cat abc.txt ; echo var7 # terraform apply -auto-approve -var=my_var=var7 -var=my_var=var8 cat abc.txt ; echo var8 # var9.txt 파일 생성 echo 'my_var="var9"' > var9.txt # terraform apply -auto-approve -var=my_var=var7 -var-file="var9.txt" cat abc.txt ; echo var9 <9> VPC 배포 직접 VPC를 만들어보자!!! 1 cd mkdir vpc cd vpc vi vpc.tf provider "aws" { region = "ap-northeast-2" } resource "aws_vpc" "myvpc" { cidr_block = "10.10.0.0/16" tags = { Name = "t101-study" } } 2 # 배포, 확인 terraform init && terraform plan && terraform apply -auto-approve terraform state list terraform state show aws_vpc.myvpc 3 terraform console aws_vpc.myvpc.id 로 정보를 볼수 있다. 4 # VPC 확인 export AWS_PAGER="" aws ec2 describe-vpcs | jq aws ec2 describe-vpcs --filter 'Name=isDefault,Values=false' | jq aws ec2 describe-vpcs --filter 'Name=isDefault,Values=false' --output yaml // default vpc 는 조회 안하도록 필터링해서 조회하자. 5 vpc dns 옵션 수정 vi main.tf provider "aws" { region = "ap-northeast-2" } resource "aws_vpc" "myvpc" { cidr_block = "10.10.0.0/16" enable_dns_support = true enable_dns_hostnames = true tags = { Name = "t101-study" } } // 콘솔 vpc 에서 확인하자. // 콘솔 vpc > Resource map에서 확인하자. 서브넷이 없다. 6 // subnet 만들기 provider "aws" { region = "ap-northeast-2"oo } resource "aws_vpc" "myvpc" { cidr_block = "10.10.0.0/16" enable_dns_support = true enable_dns_hostnames = true tags = { Name = "t101-study" } } resource "aws_subnet" "mysubnet1" { vpc_id = aws_vpc.myvpc.id cidr_block = "10.10.1.0/24" availability_zone = "ap-northeast-2a" 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" } } output "aws_vpc_id" { value = aws_vpc.myvpc.id } // vpc_id 는 aws_vpc.myvpc,id 를 가져와서 사용한다. // 콘솔 > vpc Resource map에서 확인하자. 7 # 배포 terraform plan && terraform apply -auto-approve terraform state list aws_subnet.mysubnet1 aws_subnet.mysubnet2 aws_vpc.myvpc // vpc 1개, 서브넷 1,2가 있다. terraform state show aws_subnet.mysubnet1 terraform output terraform output aws_vpc_id terraform output -raw aws_vpc_id # graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭 terraform graph > graph.dot # 서브넷 확인 aws ec2 describe-subnets --output text # 참고 : aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-<자신의 VPC ID>" VPCID=$(terraform output -raw aws_vpc_id) aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" | jq aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPCID" --output table 8 igw 추가 ? provider "aws" { region = "ap-northeast-2" } resource "aws_vpc" "myvpc" { cidr_block = "10.10.0.0/16" enable_dns_support = true enable_dns_hostnames = true tags = { Name = "t101-study" } } resource "aws_subnet" "mysubnet1" { vpc_id = aws_vpc.myvpc.id cidr_block = "10.10.1.0/24" availability_zone = "ap-northeast-2a" 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" } } resource "aws_internet_gateway" "myigw" { vpc_id = aws_vpc.myvpc.id tags = { Name = "t101-igw" } } output "aws_vpc_id" { value = aws_vpc.myvpc.id } 9 # 배포 terraform plan && terraform apply -auto-approve terraform state list aws_internet_gateway.myigw aws_subnet.mysubnet1 aws_subnet.mysubnet2 aws_vpc.myvpc 10 디폴트 라우팅 추가 ? provider "aws" { region = "ap-northeast-2" } resource "aws_vpc" "myvpc" { cidr_block = "10.10.0.0/16" enable_dns_support = true enable_dns_hostnames = true tags = { Name = "t101-study" } } resource "aws_subnet" "mysubnet1" { vpc_id = aws_vpc.myvpc.id cidr_block = "10.10.1.0/24" availability_zone = "ap-northeast-2a" 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" } } resource "aws_internet_gateway" "myigw" { vpc_id = aws_vpc.myvpc.id tags = { Name = "t101-igw" } } resource "aws_route_table" "myrt" { vpc_id = aws_vpc.myvpc.id tags = { Name = "t101-rt" } } resource "aws_route_table_association" "myrtassociation1" { subnet_id = aws_subnet.mysubnet1.id route_table_id = aws_route_table.myrt.id } resource "aws_route_table_association" "myrtassociation2" { subnet_id = aws_subnet.mysubnet2.id route_table_id = aws_route_table.myrt.id } resource "aws_route" "mydefaultroute" { route_table_id = aws_route_table.myrt.id destination_cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.myigw.id } output "aws_vpc_id" { value = aws_vpc.myvpc.id } // 라우팅 테이블을 만들고, 연결 한다. 11 # 배포 terraform plan && terraform apply -auto-approve terraform state list aws_internet_gateway.myigw aws_route.mydefaultroute aws_route_table.myrt aws_route_table_association.myrtassociation1 aws_route_table_association.myrtassociation2 aws_subnet.mysubnet1 aws_subnet.mysubnet2 aws_vpc.myvpc terraform state show aws_route.mydefaultroute # graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭 terraform graph > graph.dot # 라우팅 테이블 확인 #aws ec2 describe-route-tables --filters 'Name=tag:Name,Values=t101-rt' --query 'RouteTables[].Associations[].SubnetId' aws ec2 describe-route-tables --filters 'Name=tag:Name,Values=t101-rt' --output table 12 보안그룹 = sg.tf ec2 = ec2.tf vi sg.tf resource "aws_security_group" "mysg" { vpc_id = aws_vpc.myvpc.id name = "T101 SG" description = "T101 Study SG" } resource "aws_security_group_rule" "mysginbound" { type = "ingress" from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] security_group_id = aws_security_group.mysg.id } resource "aws_security_group_rule" "mysgoutbound" { type = "egress" from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] security_group_id = aws_security_group.mysg.id } # 배포 ls *.tf terraform plan && terraform apply -auto-approve terraform state list aws_security_group.mysg aws_security_group_rule.mysginbound aws_security_group_rule.mysgoutbound ... terraform state show aws_security_group.mysg terraform state show aws_security_group_rule.mysginbound # graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭 terraform graph > graph.dot 13 ec2 배포 vi ec2.tf data "aws_ami" "my_amazonlinux2" { most_recent = true filter { name = "owner-alias" values = ["amazon"] } filter { name = "name" values = ["amzn2-ami-hvm-*-x86_64-ebs"] } owners = ["amazon"] } resource "aws_instance" "myec2" { depends_on = [ aws_internet_gateway.myigw ] ami = data.aws_ami.my_amazonlinux2.id associate_public_ip_address = true instance_type = "t2.micro" vpc_security_group_ids = ["${aws_security_group.mysg.id}"] subnet_id = aws_subnet.mysubnet1.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 "

RegionAz($RZAZ) : Instance ID($IID) : Private IP($LIP) : Web Server

" > index.html nohup ./busybox httpd -f -p 80 & EOF user_data_replace_on_change = true tags = { Name = "t101-myec2" } } output "myec2_public_ip" { value = aws_instance.myec2.public_ip description = "The public IP of the Instance" } // ami = data.aws_ami.my_amazonlinux2.id ami를 가져 온다. // subnet_id = aws_subnet.mysubnet1.id 서브넷 id를 확인한다. # ls *.tf terraform plan && terraform apply -auto-approve terraform state list data.aws_ami.my_amazonlinux2 aws_instance.myec2 ... terraform state show data.aws_ami.my_amazonlinux2 terraform state show aws_instance.myec2 # 데이터소스 값 확인 terraform console > data.aws_ami.my_amazonlinux2.id "ami-01c81850a6167bb81" // ami 정보가 나온다. data.aws_ami.my_amazonlinux2.image_id data.aws_ami.my_amazonlinux2.name data.aws_ami.my_amazonlinux2.owners data.aws_ami.my_amazonlinux2.platform_details data.aws_ami.my_amazonlinux2.hypervisor data.aws_ami.my_amazonlinux2.architecture exit # graph 확인 > graph.dot 파일 선택 후 오른쪽 상단 DOT 클릭 terraform graph > graph.dot # 출력된 EC2 퍼블릭IP로 cul 접속 확인 terraform output -raw myec2_public_ip 52.79.154.3 MYIP=$(terraform output -raw myec2_public_ip) while true; do curl --connect-timeout 1 http://$MYIP/ ; echo "------------------------------"; date; sleep 1; done Mon Jul 10 17:03:00 KST 2023

RegionAz(apne2-az1) : Instance ID(i-064948a0afaa3a969) : Private IP(10.10.1.109) : Web Server

------------------------------ Mon Jul 10 17:03:01 KST 2023

RegionAz(apne2-az1) : Instance ID(i-064948a0afaa3a969) : Private IP(10.10.1.109) : Web Server

------------------------------ Mon Jul 10 17:03:02 KST 2023 14 삭제 terraform destroy -auto-approve