본문 바로가기

study/AEWS 2기

AEWS 2기 8주차 첫번째

테라폼 기초 지식에 대해 공부해보겠습니다.

 

테라폼 소개 : 하시코프사에서 공개한 IaC 도구, Use infrastructure as code to provision and manage any infrastructure across your organization

 

 

AWS default VPC가 삭제되어 없을 경우, 아래처럼 default VPC를 생성 - 링크

# default VPC를 생성
aws ec2 create-default-vpc

# default Subnet 생성
aws ec2 create-default-subnet --availability-zone ap-northeast-2a
aws ec2 create-default-subnet --availability-zone ap-northeast-2b
aws ec2 create-default-subnet --availability-zone ap-northeast-2c
aws ec2 create-default-subnet --availability-zone ap-northeast-2d

 

 

Get Started AWS - Link

 

AWS | Terraform | HashiCorp Developer

Build, change, and destroy AWS infrastructure using Terraform. Step-by-step, command-line tutorials will walk you through the Terraform basics for the first time.

developer.hashicorp.com

mkdir learn-terraform
cd learn-terraform
touch main.tf

 

Amazon Linux 2 최신 ami id 찾기

#aws ec2 describe-images --owners self amazon
aws ec2 describe-images --owners self amazon --query 'Images[*].[ImageId]' --output text
aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=state,Values=available"
aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=state,Values=available" --query 'Images|sort_by(@, &CreationDate)[-1].[ImageId, Name]' --output text
ami-0217b147346e48e84	amzn2-ami-hvm-2.0.20240412.0-x86_64-gp2

aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=state,Values=available" --query 'Images|sort_by(@, &CreationDate)[-1].[ImageId]' --output text
ami-0217b147346e48e84

AL2ID=`aws ec2 describe-images --owners amazon --filters "Name=name,Values=amzn2-ami-hvm-2.0.*-x86_64-gp2" "Name=state,Values=available" --query 'Images|sort_by(@, &CreationDate)[-1].[ImageId]' --output text`
echo $AL2ID

 

 

  • 테라폼 코드 파일 작성 : HCL Hashicorp Configuration Language 코드 파일 생성, Block로 구성
    • provider : Terraform으로 정의할 Infrastructure Provider를 의미 - Docs
    • resource : 실제로 생성할 인프라 자원을 의미
cat <<EOT > main.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami           = "$AL2ID"
  instance_type = "t2.micro"
}
EOT

 

실행 확인

 

EC2 태그 정보 수정 : 코드 파일 수정

cat <<EOT > main.tf
provider "aws" {
  region = "ap-northeast-2"
}

resource "aws_instance" "example" {
  ami           = "$AL2ID"
  instance_type = "t2.micro"

  tags = {
    Name = "aews-study"
  }

}
EOT

 

확인

 

 

삭제

# 리소스 삭제
terraform destroy
 Enter a value: yes 입력

혹은
terraform destroy -auto-approve

 

 

테라폼 종속성 확인하기

  • 테라폼 종속성은 resource, module 선언으로 프로비저인되는 각 요소의 생성 순서를 구분짓는다.
  • 기본적으로 다른 리소스에서 값을 참조해 불러올 경우 생성 선후 관계에 따라 작업자가 의도하지는 않았지만 자동으로 연관 관계가 정의되는 암시적 종속성을 갖게 되고, 강제로 리소스 간 명시적 종속성을 부여할 경우에는 메타인수인 depends_on을 활용한다.
  • 코드 파일 수정
resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  content  = "456!"
  filename = "${path.module}/def.txt"
}

 

VS Code 확장 graphviz 설치

#
terraform apply -auto-approve
...
Plan: 2 to add, 0 to change, 0 to destroy.
local_file.def: Creating...
local_file.abc: Creating...
local_file.abc: Creation complete after 0s [id=5f30576af23a25b7f44fa7f5fdf70325ee389155]
local_file.def: Creation complete after 0s [id=b9fbde4d33ab9c450a7ce303fb4788c9d2db9aed]

# 리소스 확인
ls *.txt
terraform state list
local_file.abc
local_file.def

# graph 확인 > graph-1.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph
terraform graph > graph-1.dot

# 모든 리소스 제거
terraform destroy -auto-approve
ls *.txt
terraform state list

 

 

 

확인

 

 

리소스 참조값을 설정해 두 개의 리소스 간 암시적 종속성 부여

resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  content  = local_file.abc.content
  filename = "${path.module}/def.txt"
}

 

apply : 커맨드 생성에 순서가 발생한 종속성 있는 두 개의 리소스

#
terraform apply -auto-approve
...
Plan: 2 to add, 0 to change, 0 to destroy.
local_file.abc: Creating... <- 먼저 만들고
local_file.abc: Creation complete after 0s [id=5f30576af23a25b7f44fa7f5fdf70325ee389155]
local_file.def: Creating... <- 그 다음 만듬
local_file.def: Creation complete after 0s [id=5f30576af23a25b7f44fa7f5fdf70325ee389155]

ls *.txt
terraform state list
cat abc.txt
cat def.txt
diff abc.txt def.txt

# graph 확인 > graph-2.dot 파일 선택 후 오른쪽 상단 DOT 클릭
terraform graph
terraform graph > graph-2.dot

확인

 

 

리소스의 속성을 주입하지 않아도 두 리소스 간에 종속성이 필요한 경우에, depends_on 선언으로 적용 가능

resource "local_file" "abc" {
  content  = "123!"
  filename = "${path.module}/abc.txt"
}

resource "local_file" "def" {
  depends_on = [
    local_file.abc
  ]

  content  = "456!"
  filename = "${path.module}/def.txt"
}

 

확인

 

 

목표 : default VPC 대신 직접 VPC를 만들고, 해당 VPC내에 EC2 1대를 배포

VPC 배포 : vpc.tf

# 신규 디렉터리 생성
mkdir my-vpc-ec2
cd my-vpc-ec2

 

vpc.tf 파일 생성

provider "aws" {
  region  = "ap-northeast-2"
}

resource "aws_vpc" "myvpc" {
  cidr_block       = "10.10.0.0/16"

  tags = {
    Name = "aews-study"
  }
}
# 배포
terraform init && terraform plan && terraform apply -auto-approve
terraform state list
terraform state show aws_vpc.myvpc

# 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

 

확인

 

 

  • AWS 관리콘솔에서 VPC 생성 정보 확인 : DNS 옵션값 확인
  • vpc.tf 코드 내용 수정 : VPC DNS 옵션 수정
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 = "aews-study"
  }
}
# 배포
terraform plan && terraform apply -auto-approve

 

 

  • AWS 관리콘솔에서 VPC 생성 정보 확인 : DNS 옵션값 확인
  • vpc.tf 코드 내용 수정 : 서브넷 2개 생성 추가
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 = "aews-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 = "aews-subnet2"
  }
}

output "aws_vpc_id" {
  value = aws_vpc.myvpc.id
}
# 배포
terraform plan && terraform apply -auto-approve
terraform state list
aws_subnet.mysubnet1
aws_subnet.mysubnet2
aws_vpc.myvpc

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

확인

 

 

 

vpc.tf 코드 내용 수정 : 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
}

 

# 배포
terraform plan && terraform apply -auto-approve
terraform state list
aws_internet_gateway.myigw
aws_subnet.mysubnet1
aws_subnet.mysubnet2
aws_vpc.myvpc

 

vpc.tf 코드 내용 수정 : 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"
  }
}

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
}
# 배포
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

 

확인

 

 

보안그룹/EC2 배포 : sg.tf, ec2.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

 

 

ec2.tf 파일 생성 : EC2 생성

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
              echo "Web Server</h1>" > 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"
}

 

배포 실행 후 EC2 확인

# 
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"
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

 

삭제

terraform destroy -auto-approve

'study > AEWS 2기' 카테고리의 다른 글

AEWS 2기 스터디 마무리  (1) 2024.04.22
AEWS 2기 8주차 두번째  (0) 2024.04.22
AEWS 2기 7주차 두번째  (0) 2024.04.18
AEWS 2기 7주차 첫번째  (0) 2024.04.17
AEWS 2기 6주차 세번째  (0) 2024.04.10