카테고리 없음

Terraform 실습

서머스 2022. 7. 4. 17:58

 

VM에 터미널로 접속한 뒤, asg 디렉터리를 만들고 아래의 파일을 생성한다.

 

vi variables.tf

variable "instance_security_group_name" {
  description = "The name of the security group for the EC2 Instances"
  type        = string
  default     = "terraform-example-instance"
}

variable "http_port" {
  description = "The port the server will use for HTTP requests"
  type        = number
  default     = 80
}

variable "ssh_port" {
  description = "The port the server will use for SSH requests"
  type        = number
  default     = 22
}

variable "alb_name" {
  description = "The name of the ALB"
  type        = string
  default     = "terraform-asg-example"
}

variable "alb_security_group_name" {
  description = "The name of the security group for the ALB"
  type        = string
  default     = "terraform-example-alb"
}

 

vi user-data.sh

#!/bin/bash
yum install -y httpd
systemctl enable --now httpd
echo "Hello AWS Terraform" > /var/www/html/index.html
timedatectl set-timezone Asia/Seoul
rdate -s time.bora.net
echo $(date +"%H:%M:%S") >> /var/www/html/index.html
sleep 600
yes > /dev/null &

httpd 설치, 시간 설정, 과부하 동시에 주도록 한다.

 

vi main.tf

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

### new-vpc ###

resource "aws_vpc" "new_vpc" {
  cidr_block  = "192.168.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support = true
  instance_tenancy = "default"

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

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

resource "aws_subnet" "new_public_subnet_2a" { #2a 가용영역에 만들어지게 될 public subnet
  vpc_id = aws_vpc.new_vpc.id
  cidr_block = "192.168.0.0/20"
  map_public_ip_on_launch = true
  availability_zone = data.aws_availability_zones.available.names[0] # name : a,b,c,d
  tags = {
    Name = "NEW-PUBLIC-SUBNET-2A"
  }
}

resource "aws_subnet" "new_public_subnet_2b" {
  vpc_id = aws_vpc.new_vpc.id
  cidr_block = "192.168.16.0/20"
  map_public_ip_on_launch = true
  availability_zone = data.aws_availability_zones.available.names[1] # 2b
  tags = {
    Name = "NEW-PUBLIC-SUBNET-2B"
  }
}

resource "aws_subnet" "new_public_subnet_2c" {
  vpc_id = aws_vpc.new_vpc.id
  cidr_block = "192.168.32.0/20"
  map_public_ip_on_launch = true
  availability_zone = data.aws_availability_zones.available.names[2] # 2c
  tags = {
    Name = "NEW-PUBLIC-SUBNET-2C"
  }
}

resource "aws_subnet" "new_public_subnet_2d" {
  vpc_id = aws_vpc.new_vpc.id
  cidr_block = "192.168.48.0/20"
  map_public_ip_on_launch = true
  availability_zone = data.aws_availability_zones.available.names[3] # 2d
  tags = {
    Name = "NEW-PUBLIC-SUBNET-2D"
  }
}

resource "aws_internet_gateway" "new_igw" {
  vpc_id = aws_vpc.new_vpc.id  # igw가 vpc에 바로 attachment된다.
  tags = {
    Name = "NEW-IGW"
  }
}

resource "aws_route_table" "new_public_rtb" {
  vpc_id = aws_vpc.new_vpc.id

  route {
    cidr_block = "0.0.0.0/0" # 목적지
    gateway_id = aws_internet_gateway.new_igw.id
  }
  tags = {
    Name = "NEW-PUBLIC-RTB"
  }
}

resource "aws_route_table_association" "new_public_subnet_2a_association" {
  subnet_id = aws_subnet.new_public_subnet_2a.id
  route_table_id = aws_route_table.new_public_rtb.id
}

resource "aws_route_table_association" "new_public_subnet_2b_association" {
  subnet_id = aws_subnet.new_public_subnet_2b.id
  route_table_id = aws_route_table.new_public_rtb.id
}

resource "aws_route_table_association" "new_public_subnet_2c_association" {
  subnet_id = aws_subnet.new_public_subnet_2c.id
  route_table_id = aws_route_table.new_public_rtb.id
}

resource "aws_route_table_association" "new_public_subnet_2d_association" {
  subnet_id = aws_subnet.new_public_subnet_2d.id
  route_table_id = aws_route_table.new_public_rtb.id
}

### asg ###

# 보안그룹 만들기
resource "aws_security_group" "instance" {
  name   = var.instance_security_group_name
  vpc_id = aws_vpc.new_vpc.id #보안 그룹을 어느 vpc에 둘 것인지?

  ingress {
    from_port   = var.http_port
    to_port     = var.http_port
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"] # curl ipconfig.io 한 아이피 넣으면 됨
  }
  ingress {
    from_port   = -1 # icmp는 포트의 개념이 없음
    to_port     = -1
    protocol    = "icmp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_launch_configuration" "example" {
  image_id        = "ami-0fd0765afb77bcca7"
  instance_type   = "t2.micro"
  security_groups = [aws_security_group.instance.id] # 복수 개가 들어갈 수 있어서 []로
  key_name        = "aws_key"	
  user_data       = file("user-data.sh")

  # Required when using a launch configuration with an auto scaling group.
  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_autoscaling_group" "example" {
  launch_configuration = aws_launch_configuration.example.name
  vpc_zone_identifier  = [
    aws_subnet.new_public_subnet_2a.id,
    aws_subnet.new_public_subnet_2b.id,
    aws_subnet.new_public_subnet_2c.id,
    aws_subnet.new_public_subnet_2d.id
  ]

  target_group_arns = [aws_lb_target_group.asg.arn] # 타겟 그룹 생성 -> 로드밸런서 이용, arn : amazon resource number
  health_check_type = "ELB"

  min_size         = 2
  desired_capacity = 2
  max_size         = 4

  tag {
    key                 = "Name"
    value               = "terraform-asg-example"
    propagate_at_launch = true
  }
}

resource "aws_lb" "example" { # lb : 로드 밸런서

  name               = var.alb_name

  load_balancer_type = "application"
  subnets            = [
    aws_subnet.new_public_subnet_2a.id,
    aws_subnet.new_public_subnet_2b.id,
    aws_subnet.new_public_subnet_2c.id,
    aws_subnet.new_public_subnet_2d.id
  ]
  security_groups    = [aws_security_group.alb.id]
}

resource "aws_lb_listener" "http" { 
  load_balancer_arn = aws_lb.example.arn
  port              = var.http_port
  protocol          = "HTTP"

  # By default, return a simple 404 page
  default_action {
    type = "fixed-response"

    fixed_response {
      content_type = "text/plain"
      message_body = "404: page not found"
      status_code  = 404
    }
  }
}

resource "aws_lb_target_group" "asg" {

  name = var.alb_name

  port     = var.http_port
  protocol = "HTTP"
  vpc_id   = aws_vpc.new_vpc.id

  health_check {
    path                = "/"
    protocol            = "HTTP"
    matcher             = "200" # 성공 코드
    interval            = 15
    timeout             = 3
    healthy_threshold   = 2
    unhealthy_threshold = 2
  }
}

resource "aws_lb_listener_rule" "asg" {
  listener_arn = aws_lb_listener.http.arn
  priority     = 100

  condition {
    path_pattern {
      values = ["*"]
    }
  }

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.asg.arn
  }
}

resource "aws_security_group" "alb" {
  vpc_id = aws_vpc.new_vpc.id
  name   = var.alb_security_group_name

  # Allow inbound HTTP requests
  ingress {
    from_port   = var.http_port
    to_port     = var.http_port
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    from_port   =443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  # Allow all outbound requests
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
resource "aws_autoscaling_policy" "scale_in" {
  name                   = "ScaleInPolicy"
  autoscaling_group_name = aws_autoscaling_group.example.name
  adjustment_type        = "ChangeInCapacity"
  scaling_adjustment     = -1
  cooldown               = 300 # ScaleIn 후 cooldown 시간이 필요함
}

resource "aws_cloudwatch_metric_alarm" "scale_in" {
  alarm_description   = "Monitors CPU utilization for Terramino ASG"
  alarm_actions       = [aws_autoscaling_policy.scale_in.arn]
  alarm_name          = "ScaleInAlarm"
  comparison_operator = "LessThanOrEqualToThreshold" # 비교연산자(임계값과 비교했을 때)
  namespace           = "AWS/EC2"
  metric_name         = "CPUUtilization"
  threshold           = "30" # 30% 이하의 값이 보이면 알람이 울린다.
  evaluation_periods  = "1" # 5분마다 한번씩, 평균 값이
  period              = "300" # 300초 동안 평균시간
  statistic           = "Average"

  dimensions = {
    AutoScalingGroupName = aws_autoscaling_group.example.name
  }
}
resource "aws_autoscaling_policy" "scale_out" {
  name                   = "ScaleOutPolicy"
  autoscaling_group_name = aws_autoscaling_group.example.name
  adjustment_type        = "ChangeInCapacity"
  scaling_adjustment     = 1
  cooldown               = 300
}

resource "aws_cloudwatch_metric_alarm" "scale_out" {
  alarm_description   = "Monitors CPU utilization for Terramino ASG"
  alarm_actions       = [aws_autoscaling_policy.scale_out.arn]
  alarm_name          = "ScaleOutAlarm"
  comparison_operator = "GreaterThanOrEqualToThreshold"
  namespace           = "AWS/EC2"
  metric_name         = "CPUUtilization" # cpu 사용률이 70보다 크면 알람을 울린다.
  threshold           = "70"
  evaluation_periods  = "1"
  period              = "300" # 5분 평균
  statistic           = "Average"

  dimensions = {
    AutoScalingGroupName = aws_autoscaling_group.example.name
  }
}

 

vi outputs.tf

output "alb_dns_name" {
  value       = aws_lb.example.dns_name
  description = "The domain name of the load balancer"
}

 

terraform init
terraform validate
terraform plan
terraform apply

이후 CloudWatch로 가 보면 알람이 두개 생성되어 있다.

 

 

2. Github에서 클론하기

일일이 쓰지 않고, 깃허브에서 폴더화하여 다운로드 받아 쓴다.

git clone https://github.com/hali-linux/aws_set.git
terraform apply

curl 해 보면

잘 나온다.

 

Azure CLI

azure_cli 디렉터리를 만든 뒤 들어간다.

 

echo -e "[azure-cli]
name=Azure CLI
baseurl=https://packages.microsoft.com/yumrepos/azure-cli
enabled=1
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc" | sudo tee /etc/yum.repos.d/azure-cli.repo

그대로 복붙 후

yum install -y azure-cli
az login

azure 설치한 후, 로그인한다.

 

해당 사이트에 접속한 뒤, 코드 입력 후 [다음] 클릭

로그인 완료

 

# resourceGroup=VMTutorialResources
# location=koreacentral
# az group create --name $resourceGroup --location $location # 리소스 그룹 만들기
# vnetName=TutorialVNet1
# subnetName=TutorialSubnet1
# vnetAddressPrefix=10.129.0.0/16
# subnetAddressPrefix=10.129.0.0/24
# az network vnet create \
--name $vnetName \
--resource-group $resourceGroup \
--address-prefixes $vnetAddressPrefix \
--subnet-name $subnetName \
--subnet-prefixes $subnetAddressPrefix

# az network vnet list
# az vm image list
# vmName=TutorialVM1
# vi httpd.txt
#!/bin/bash
apt update
apt install -y apache2
echo "<h1>Hello Azure CLI</h1>" > /var/www/html/index.html

# az vm create \
--resource-group $resourceGroup \
--name $vmName \
--image UbuntuLTS \
--vnet-name $vnetName \
--subnet $subnetName \
--size Standard_B1s \
--custom-data httpd.txt \
--admin-username azureuser \
--generate-ssh-keys \
--output json \
--verbose
#http의 경로를 굳이 쓸 필요 x
#ssh key를 만든다.


# az network nsg rule create \
--resource-group $resourceGroup \
--nsg-name TutorialVM1NSG \
--name myNetworkSecurityGroupRule \
--protocol tcp \
--priority 900 \
--destination-port-range 80

# az vm open-port -n $vmName -g $resourceGroup --port 443
# 이 방법은 포트 번호를 여는 방법이 좀더 간단하다

# az vm list-ip-addresses
# ssh -i .ssh/id_rsa azureuser@20.214.201.208
# az vm delete --resource-group $resourceGroup --name $vmName --yes
# az group delete -n $resourceGroup
# az group delete -n NetworkWatcherRG