T101-2주차(도전과제) [Terraform 101 Study]

cloudNet@ 팀의 가시다 님이 진행하는 테라폼 102 스터디 입니다. (테라폼으로 시작하는 IaC” (한빛미디어) 도서로 진행!)

  • 리전 내에서 사용 가능한 가용영역 목록 가져오기를 사용한 VPC 리소스 생성 실습 진행 혹은 아무거나 데이터 소스를 사용한 실습 진행
provider "aws" {
  region  = "ap-northeast-2"
}

data "aws_availability_zones" "available" {
  state = "available"
}

resource "aws_vpc" "monitoring-VPC" {
  cidr_block       = "10.10.0.0/16"
#dns확인 (원래 활성화 되어있음)
  enable_dns_support   = true
# dns호스트이름
  enable_dns_hostnames = true

  tags = {
    Name = "monitoring-VPC"
  }
}


resource "aws_subnet" "monitoring-pub-NAT-A-01" {
vpc_id     = aws_vpc.monitoring-VPC.id
cidr_block = "10.10.10.0/24"

availability_zone = data.aws_availability_zones.available.names[0] 

  tags = {
    Name = "monitoring-pub-NAT-A-01"
  }
}

resource "aws_subnet" "monitoring-pub-NAT-C-01" {
vpc_id     = aws_vpc.monitoring-VPC.id
cidr_block = "10.10.30.0/24"

availability_zone = data.aws_availability_zones.available.names[2] 

  tags = {
    Name = "monitoring-pub-NAT-C-01"
  }
}

  • 위 3개 코드 파일 내용에 리소스의 이름(myvpc, mysubnet1 등)을 반드시! 꼭! 자신의 닉네임으로 변경해서 배포 실습해보세요! (원본 코드는 2추자 내용 참고 부탁합니다.)
vpc.tf 생성
-----------------
provider "aws" {
  region  = "ap-northeast-2"
}

data "aws_availability_zones" "available" {
  state = "available"
}

resource "aws_vpc" "monitoring-VPC" {
  cidr_block       = "10.10.0.0/16"
#dns확인 (원래 활성화 되어있음)
  enable_dns_support   = true
# dns호스트이름
  enable_dns_hostnames = true

  tags = {
    Name = "monitoring-VPC"
  }
}


resource "aws_subnet" "monitoring-pub-NAT-A-01" {
vpc_id     = aws_vpc.monitoring-VPC.id
cidr_block = "10.10.10.0/24"

availability_zone = data.aws_availability_zones.available.names[0] 

  tags = {
    Name = "monitoring-pub-NAT-A-01"
  }
}

resource "aws_subnet" "monitoring-pub-NAT-C-01" {
vpc_id     = aws_vpc.monitoring-VPC.id
cidr_block = "10.10.30.0/24"

availability_zone = data.aws_availability_zones.available.names[2] 

  tags = {
    Name = "monitoring-pub-NAT-C-01"
  }
}

		# aws 프로바이더 유형이 aws_internet_gateway 이다
resource "aws_internet_gateway" "monitoring-igw" {
  vpc_id = aws_vpc.monitoring-VPC.id

  tags = {
    Name = "monitoring-igw"
  }
}

#별도의 라우팅 테이블 만든다.
resource "aws_route_table" "monitoring-pub-A-rt" {
  vpc_id = aws_vpc.monitoring-VPC.id

  tags = {
    Name = "monitoring-pub-A-rt"
  }
}

#  두개의 서브넷이 연동되는 리소스를 각각 만들어 준다. / aws_route_table_association = 라우팅 테이블 연동
resource "aws_route_table_association" "myrtassociation1" {
  subnet_id      = aws_subnet.monitoring-pub-NAT-A-01.id
  route_table_id = aws_route_table.monitoring-pub-A-rt.id
}
#  두개의 서브넷이 연동되는 리소스를 각각 만들어 준다. 
resource "aws_route_table_association" "myrtassociation2" {
  subnet_id      = aws_subnet.monitoring-pub-NAT-C-01.id
  route_table_id = aws_route_table.monitoring-pub-A-rt.id
}

resource "aws_route" "mydefaultroute" {
  route_table_id         = aws_route_table.monitoring-pub-A-rt.id
#destination_cidr_block은 목적지 IP 주소 범위를 CIDR 표기법으로 지정하는 속성
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.monitoring-igw.id
}
sg.tf 파일 생성: 보안그룹 생성 
------------------------------
resource "aws_security_group" "monitoring-ADMIN" {
  vpc_id      = aws_vpc.monitoring-VPC.id
  name        = "ADMIN"
  description = "monitoring-ADMIN"

 tags = {
    Name = "ADMIN"
  }

}

resource "aws_security_group_rule" "monitoring-ADMIN-inbound" {
											#인바운드
  type              = "ingress"
#시작하는 포트 번호
  from_port         = 80
#끝 포트 번호로, 이 경우에서도 80입니다. 따라서 이 규칙은 포트 80에서 시작해서 포트 80에서 끝나는 범위가 됩니다.
  to_port           = 80
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.monitoring-ADMIN.id
}

resource "aws_security_group_rule" "monitoring-ADMIN-outbound" {
											#아웃바운드
  type              = "egress"
  from_port         = 0
  to_port           = 0
#해당 규칙이 적용되는 프로토콜을 지정합니다. 여기서는 "-1"을 사용하고 있어 모든 프로토콜이 해당 규칙에 대해 허용됩니다.
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.monitoring-ADMIN.id
}
ec2생성 (ec2.tf 생성)
---------------------
#데이터 소스 블록이 있으며 ami 유형이 있다 my_amazonlinux2 이건 이름이므로 자기 마음대로
data "aws_ami" "my_amazonlinux2" {
#최신 AMI를 사용하려면 true로 설정합니다
  most_recent = true
#원하는 AMI를 찾기 위한 필터를 정의합니다
  filter {
#첫 번째 필터에서 owner-alias를 "amazon"으로 설정하여 Amazon 소유의 이미지만 검색합니다.
    name   = "owner-alias"
    values = ["amazon"]
  }
#두 번째 필터에서 name을 "amzn2-ami-hvm-*-x86_64-ebs"로 설정하여 Amazon Linux 2의 특정 이미지를 검색합니다
  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-ebs"]
  }
#이미지 소유자를 지정합니다. 여기서는 "amazon"만 포함됩니다.
  owners = ["amazon"]
}
#위에라인들이 속성 값들이며, 데이터 소스를 선언하였다.


resource "aws_instance" "my" {

#리소스의 속성을 주입하지 않아도 두 리소스 간에 종속성이 필요한 경우에, depends_on 선언으로 적용 가능
#인터넷 게이트웨이가 있어야지만 그뒤로 넘어감
  depends_on = [
    aws_internet_gateway.monitoring-igw
  ]

	#위에 속성 값들을 이용하여 하드 코딩안하고 data 값을 참하여 가져온다 (ami 직접 안적음)
  #검색한 Amazon Linux 2 AMI ID를 사용합니다.
  ami                         = data.aws_ami.my_amazonlinux2.id

#인스턴스에 공용 IP 주소를 연결하려면 true로 설정합니다.
  associate_public_ip_address = true
  instance_type               = "t2.micro"

#시큐리티 그룹 id 가져옴
  vpc_security_group_ids      = ["${aws_security_group.monitoring-ADMIN.id}"]
# 서브넷은 두 개인대 1번 가져옴 
  subnet_id                   = aws_subnet.monitoring-pub-NAT-A-01.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
#ec2 메타데이터 이용해서 현제 ec2에 배포된 az와 인스턴스 id 프라이빗 ip 을 변수에 넣어주고 index.html 넣는다 
              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

#인스턴스 사용자 데이터가 변경될 때 인스턴스를 다시 생성하려면 true로 설정합니다.
  user_data_replace_on_change = true

  tags = {
    Name = "monitoring-pri-web-A-01"
  }
}

#출력 섹션 output "myec2_public_ip": 생성된 인스턴스의 공용 IP 주소를 출력합니다. 이를 통해 생성된 인스턴스에 접근하거나 연결할 수 있습니다.
output "myec2_public_ip" {
  value       = aws_instance.my.public_ip
  description = "The public IP of the Instance"
}

  • 입력변수를 활용해서 리소스(어떤 리소스든지 상관없음)를 배포해보고, 해당 코드를 정리해주세요
#입력을 통하여 원하는 버킷을 생성합니다.
provider "aws" {
  region = "ap-northeast-2"
}

# 변수 선언
variable "sr-aws_s3_bucket" {
  type = string
}

resource "aws_s3_bucket" "test_bucket" {
  bucket = "test-bucket-${var.sr-aws_s3_bucket}"
}



----
root@DESKTOP-9HBHD7U:/home/minho/3.3# terraform apply -auto-approve
var.sr-aws_s3_bucket
  Enter a value: minho2

하지만 이러한 식으로 할경우 단점이 있습니다 아래를 볼경우

root@DESKTOP-9HBHD7U:/home/minho/3.3# terraform destroy -auto-approve
var.sr-aws_s3_bucket
  Enter a value: minho2

삭제를 할때도 변수를 입력하여 주어야 합니다(변수값이 없기때문) 그럼으로 입력을 통하여 생성을 하기보다는 변수를 선언하고 참조 하는 방식을 권장 드립니다

수정본

main.tf  [입력변수]
--------------------
provider "aws" {
  region = "ap-northeast-2"
}


variable "sr-aws_s3_bucket" {
  type = string
  default = "minho2"
}
s3.tf 입력 변수를 참조하는 S3 리소스 생성
------------------------------------------
resource "aws_s3_bucket" "test_bucket" {
  bucket = "test-bucket-${var.sr-aws_s3_bucket}"
}

#s3버전관리
resource "aws_s3_bucket_versioning" "var_bucket" {
  bucket = aws_s3_bucket.test_bucket.id
  versioning_configuration {
    status = "Enabled"
  }
}

  • local를 활용해서 리소스(어떤 리소스든지 상관없음)를 배포해보고, 해당 코드를 정리해주세요
# 로컬 변수 값 정의
locals {
  db_engine              = "mysql"                # 데이터베이스 엔진 (MySQL)
  db_engine_version      = "5.7"                   # 데이터베이스 엔진 버전
  db_instance_class      = "db.t3.micro"           # 데이터베이스 인스턴스 클래스 (RDS 인스턴스 유형)
  db_parameter_group_name = "default.mysql5.7"     # 데이터베이스 파라미터 그룹 이름
}

# AWS RDS 인스턴스 리소스 생성
resource "aws_db_instance" "default" {
  allocated_storage    = 10                       # 할당된 스토리지 크기 (GB)
  db_name              = "mtest23213"                   # 생성할 데이터베이스 이름
  engine               = local.db_engine          # 로컬 변수에서 데이터베이스 엔진값 가져오기
  engine_version       = local.db_engine_version  # 로컬 변수에서 엔진 버전값 가져오기
  instance_class       = local.db_instance_class  # 로컬 변수에서 인스턴스 클래스값 가져오기
  username             = "foo"                    # 데이터베이스 사용자 이름
  password             = "foobarbaz"              # 데이터베이스 비밀번호
  parameter_group_name = local.db_parameter_group_name  # 로컬 변수에서 파라미터 그룹 이름 가져오기
  skip_final_snapshot  = true                     # 인스턴스 삭제 시 최종 스냅샷 생략
}

생성할경우 아래와 같이 rds는 생성되지만 name이상 합니다 그 이유는 Terraform에서 aws_db_instance 리소스 사용 시, db_name 속성에 설정한 값이 실제 데이터베이스 이름에 반영되지 않는 경우라서 입니다 그럼으로 아래의 코드를 추가 및 재배포 합니다.

수정본

# 로컬 변수 값 정의
locals {
  db_engine              = "mysql"                # 데이터베이스 엔진 (MySQL)
  db_engine_version      = "5.7"                   # 데이터베이스 엔진 버전
  db_instance_class      = "db.t3.micro"           # 데이터베이스 인스턴스 클래스 (RDS 인스턴스 유형)
  db_parameter_group_name = "default.mysql5.7"     # 데이터베이스 파라미터 그룹 이름
}

# AWS RDS 인스턴스 리소스 생성
resource "aws_db_instance" "default" {
  allocated_storage    = 10                       # 할당된 스토리지 크기 (GB)
identifier  = "mtest23213-ss3d3e3-bb-db-name"  # 이렇게 설정하면 RDS 인스턴스 식별자가 생성됩니다.
  db_name              = "mtest23213"                   # 생성할 데이터베이스 이름
  engine               = local.db_engine          # 로컬 변수에서 데이터베이스 엔진값 가져오기
  engine_version       = local.db_engine_version  # 로컬 변수에서 엔진 버전값 가져오기
  instance_class       = local.db_instance_class  # 로컬 변수에서 인스턴스 클래스값 가져오기
  username             = "foo"                    # 데이터베이스 사용자 이름
  password             = "foobarbaz"              # 데이터베이스 비밀번호
  parameter_group_name = local.db_parameter_group_name  # 로컬 변수에서 파라미터 그룹 이름 가져오기
  skip_final_snapshot  = true                     # 인스턴스 삭제 시 최종 스냅샷 생략
}

  • count, for_each 반복문, for문, dynamic문 을 활용해서 리소스(어떤 리소스든지 상관없음)를 배포해보고, 해당 코드를 정리해주세요

count

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

resource "aws_instance" "test-ins" {
  count = 2
  ami           = "ami-0b7c737f668580ff1"
  instance_type = "t2.micro"
  tags = {
    Name = "test-ins - ${count.index}"
  }
}

for_each

variable "instances" {
  type = list(string)
  default = [
    "test-ins-1",
    "test-ins-2",
  ]
}

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

resource "aws_instance" "test-ins" {
  for_each      = toset(var.instances)       # for_each를 적용하여 var.instances에 있는 각 항목 별로 리소스를 반복하도록 설정
  ami           = "ami-0b7c737f668580ff1"
  instance_type = "t2.micro"
  tags = {
    Name = "${each.key}"                     # 각 반복 별에 해당하는 인스턴스 이름을 사용
  }
}

for

variable "instances" {
  type = list(string)
  default = [
    "test-ins-1",
    "test-ins-2",
  ]
}

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

resource "aws_instance" "test-ins" {
  for_each      = { for s in var.instances : s => upper(s) } # var.instances의 각 문자열을 대문자로 변환한 값을 사용하여 인스턴스 생성
  ami           = "ami-0b7c737f668580ff1"
  instance_type = "t2.micro"
  tags = {
    Name = "${each.value}"                 # each.value를 사용하여 대문자로 변환된 인스턴스 이름을 사용
  }
}

소문자를 대문자로 변환 하였습니다

위로 스크롤