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