# vi new-vpc.yaml // 두 칸씩 들여쓰기 해서 층층이 정리해주는 형태 yaml
AWSTemplateFormatVersion: 2010-09-09
Resources:
VPC: // 논리적 id. 지정 가능
Type: AWS::EC2::VPC // 필드. : <- 붙여져있는 것들
Properties:
CidrBlock: 192.168.0.0/16
EnableDnsSupport: true // true를 안넣어주면 ec2인스턴스가 ping이 안나감.
EnableDnsHostnames: true
InstanceTenancy: default // 공용이 아닌 전용을 쓰니까 default
Tags:
- Key: Name
Value: NEW-VPC
SubnetA: // 지정 가능. 참조 id로 쓰임
Type: AWS::EC2::Subnet // 정확히 지정해주어야함 토씨하나 안틀리고
Properties:
AvailabilityZone: ap-northeast-2a
VpcId: !Ref VPC // VPC 안에 있으니까 VPC id가 필요함.
CidrBlock: 192.168.0.0/20
MapPublicIpOnLaunch: true // 퍼블릭 ip 자동할당 활성화
Tags:
- Key: Name
Value: NEW-PUBLIC-SUBNET-2A
SubnetB:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-2b
VpcId: !Ref VPC
CidrBlock: 192.168.16.0/20
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: NEW-PUBLIC-SUBNET-2B
SubnetC:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-2c
VpcId: !Ref VPC
CidrBlock: 192.168.32.0/20
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: NEW-PUBLIC-SUBNET-2C
SubnetD:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: ap-northeast-2d
VpcId: !Ref VPC
CidrBlock: 192.168.48.0/20
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: NEW-PUBLIC-SUBNET-2D
InternetGateway: // 지정 가능. 직관적으로 할려고
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: NEW-IGW
VPCGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
RouteTableA:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: NEW-PUBLIC-RTB
InternetRoute:
Type: AWS::EC2::Route
DependsOn: InternetGateway // 생성 순서 dependson 인터넷 게이트웨이가 만들어진 후에 인터넷라우트를 해주어야함.
Properties:
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
RouteTableId: !Ref RouteTableA
SubnetARouteTableAssociation: // 서브넷과 RTB를 연결해주는 작업. 4개의 서브넷과 연결해주는 것
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTableA
SubnetId: !Ref SubnetA
SubnetBRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTableA
SubnetId: !Ref SubnetB
SubnetCRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTableA
SubnetId: !Ref SubnetC
SubnetDRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref RouteTableA
SubnetId: !Ref SubnetD
s3에 버킷이 만들어지면서 저장됨. 클라우드 포메이션은 저장기능 자체는 없음. -> 리소스들을 지워도 yaml은 s3에 남아있으므로 내가 지워야됨
스택 생성 클릭
DNS 호스트이름 편집 :
DNS 확인 편집 :
# vi new-ec2.yaml
AWSTemplateFormatVersion: 2010-09-09
Mappings:
RegionMap:
ap-northeast-2:
AMIID: ami-0fd0765afb77bcca7
ap-northeast-1:
AMIID: ami-0b7546e839d7ace12
Parameters:
InstanceTypeParameter:
Type: String
Default: t2.micro
Description: Enter instance size. Default is t2.micro
VPC:
Type: String
Default: vpc-01a276b266db7833b
Description: VPC ID.
Subnet:
Type: String
Default: subnet-01132b9dddcf71d3d
Description: Subnet ID.
AMI:
Type: String
Default: AMIID
Description: The Linux AMI to use.
Key:
Type: String
Default: new-key
Description: The key used to access the instance.
Resources:
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: "NEW-SG-WEB"
GroupDescription: "SSH and web traffic in, all traffic out."
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: '80'
ToPort: '80'
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: '22'
ToPort: '22'
CidrIp: 123.142.252.25/32
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
Linux:
Type: 'AWS::EC2::Instance'
Properties:
SubnetId: !Ref Subnet
# ImageId: !Ref AMI
ImageId: !FindInMap [ RegionMap, !Ref "AWS::Region", !Ref AMI ] // mappings 에서 정보를 가져오겠다.
InstanceType:
Ref: InstanceTypeParameter
KeyName: !Ref Key
SecurityGroupIds:
- Ref: InstanceSecurityGroup
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeSize: 8
Tags:
- Key: Name
Value: NEW-EC2
UserData:
Fn::Base64: |
#cloud-boothook
#!/bin/bash
yum install -y httpd
systemctl enable --now httpd
echo "Hello World!" > /var/www/html/index.html
Outputs:
PublicIp:
Description: PublicIp Output
Value: {"Fn::GetAtt": ["Linux","PublicIp"]}
bash 명령어들이다. 리눅스 환경에서 이용하고 있기 때문.
셰프, 퍼핏, 앤서블, 솔트 스택 등
config는 생성과는 거리가 멀다. 설정, 구성과 가깝.
도커, 패커, 베이그런트 같은 것들. 운영체제, 소프트웨어, 파일 및 기타 모든 내용을 포함 한 스냅샷으로 이미지를 생성하여 모든 서버에 이미지를 설치함. 실행은 서버에 이미지를 배포하고 할 수 있음
ex) ova,AMI
서버 템플릿 도구는 vm이나 컨테이너를 생성하기엔 좋은 도구, 그러나 관리부분이 부족하다.
이를 보완하기 위한 것이 쿠버네티스
자동 복구(복제), 롤백(복원 - 스냅샷), 업데이트, 오토스케일링(자동 확장)
쿠버네티스도 코드로 정의하니까 IaC 도구로 봄. 도커 자체는 ad-hoc과 닮았음
* 클러스터 - 마스터, 워커 뭉탱이
가용성을 높이고, 오토스케일링 등등을 하기 위해 클러스터를 구성함. 자원 공유 가능
앤서블은 서버를 못 만들었음. 레거시한 물리적 서버(이미 만들어진 서버)를 앤서블이 연결해서 인벤토리내에 있는 머신들을 remote에서 구성만 해주는 도구였다. 클라우드로 오면서 모듈이 발달하면서 클라우드 환경에서도 ec2를 생성하는 기능이 추가됨.
앤서블과 테라폼의 격차가 줄어듬. 테라폼은 처음부터 클라우드 네이티브였기 때문에 퍼포먼스가 좋다. 앤서블은 범용. 특화된게 없음.
Target API가 없으면 아무것도 안됨.
CSP가 제공해주는 API 를 이용해서 클라우드를 생성하고 관리함.
테라폼 프로바이더로 각각의 CSP사의 API를 쉽게 사용할 수 있음
프로비전 도구 - 리소스 생성 & 관리
쓰기 : 작성, 리소스 정의
계획 : plan 명령어를 통해서 인프라 및 구성을 생성, 업데이트 또는 destroy 할 수 있음. 실제 적용에 앞서서 테스트, 검증함.
적용 : apply, 승인시 테라폼은 리소스 종속성을 고려하여 제안된 작업을 올바른 순서로 수행.
--- Terraform 작동 방식
테라폼은 해시코프사에서 Go언어로 개발한 오픈소스도구입니다. 운영체제마다 바이너리 파일이 존재하는데 Go 코드는 하나의 바이너리 파일로 컴파일되며 Terraform이라는 명령어로 실행할 수 있습니다. 이 Terraform 명령어를 사용하여 노트북, 데스크탑, 빌드 서버 또는 다른 컴퓨터에서든 인프라를 배포할 수 있으며 이를 위해 추가 인프라(마스터, 에이전트)를 생성할 필요가 없습니다. 즉 Terraform 명령어가 AWS, Azure, GCP, Openstack 등의 Provider를 대신해 API를 호출하여 리소스를 생성합니다.
테라폼은 생성하려는 인프라 정보가 담겨 있는 텍스트로 이루어진 테라폼 구성 파일을 생성하여 API를 호출합니다. 이러한 구성 값들이 '코드형 인프라'를 만드는 바로 그 '코드'입니다. 팀의 누군가가 인프라를 수정하고자 할 때, 서버에 직접 접속하여 작업하거나 수작업으로 수정하는 대신 테라폼을 사용하여 구성 파일을 수정할 있습니다.
# vi main.tf
provider "aws" { # aws를 공급자로 사용하여
region = "ap-northeast-2" # 서울 리전에 인프라를 배포한다는 의미
}
resource "aws_instance" "example" {
ami = "ami-0fd0765afb77bcca7"
instance_type = "t2.micro"
}
resource"<PROVIDER>_<TYPE>" "<NAME>" { # PROVIDER는 aws 같은 공급자의 이름이고 TYPE은 instance 같이 해당 공급자에서 생성할 리소스 유형입니다. NAME은 테라폼 코드에서 이 리소스를 참조하기 위해 사용할 수 있는 example과 같은 '식별자'입니다. CONFIG는 특정 리소스에 대한 하나 이상의 인수(argument)로 구성됩니다.
[CONFIG ...]
}
--- Terraform 주요 명령어
terraform init : terraform 명령어에는 테라폼의 기본 기능이 포함되어 있지만 모든 공급자(AWS, Azure, GCP 등)에 대한 코드가 포함되어 있지 않습니다. 그렇게 때문에 terraform init 명령어를 실행하여 테라폼에 코드를 스캔하도록 지시하고 어느 공급자인지 확인하고, 필요한 코드를 다운로드하도록 해야 합니다. 기본적으로 공급자 코드는 테라폼의 .terraform 폴더에 다운로드됩니다.
terraform plan : 테라폼이 구성 파일을 사용하여 작업을 수행하기 전에 코드의 온전성을 검사할 수 있습니다. plan 명령어는 리눅스에서 쓰이는 diff 명령의 결괏값과 유사합니다. + 가 있는 항목은 추가되고, - 가 있는 항목은 삭제된다는 뜻입니다. ~ 가 있는 항목은 수정됩니다.
terraform apply : 테라폼의 구성 파일을 실행하려면 terraform apply 명령어를 실행합니다.
--- Terraform 설치
# wget https://releases.hashicorp.com/terraform/1.2.3/terraform_1.2.3_linux_amd64.zip
# unzip terraform_1.2.3_linux_amd64.zip
# mv terraform /usr/local/bin/
# terraform -version
--- AWS Terraform ec2 인스턴스 생성
# mkdir aws && cd $_
# vi main.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
ami = "ami-0fd0765afb77bcca7"
instance_type = "t2.micro"
}
# terraform init
# terraform plan
# terraform apply
# terraform destroy
plan 시 오류가 나면, timedatectl을 해서 확인해본다. 안맞으면 맞춰줘야함
rdate -s time.bora.net
--- ec2 인스턴스 정보 추가
# vi main.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "example" {
ami = "ami-0fd0765afb77bcca7"
instance_type = "t2.micro"
tags = {
Name = "terraform-example"
}
}
# terraform init
# terraform plan
# terraform apply
# terraform destroy
인스턴스 정보변경
plan 시 변경 사항이 ~ 뒤에 뜬다
--- ec2 인스턴스 웹서버 배포
# vi main.tf
provider "aws" {
region = "ap-northeast-2"
}
resource "aws_instance" "alb-vm-01" {
ami = "ami-0fd0765afb77bcca7"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.instance.id] // 내가 만든 aws 보안그룹. 이름이 instance인 보안그룹의 id 참조
key_name = "new-key"
user_data = <<-EOF
#! /bin/bash
yum install -y httpd
systemctl enable --now httpd
echo "Hello, Terraform" > /var/www/html/index.html
EOF
tags = {
Name = "terraform-example"
}
}
resource "aws_security_group" "instance" {
name = var.security_group_name
ingress {
from_port = 80
to_port = 80
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"]
}
ingress {
from_port = -1
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"]
}
tags = {
Name = "terraform-sg"
}
}
EOF? EOF는 end of file의 줄임말이다. 주로 이것은 백준 문제를 풀 때 최대 몇개의 입력이 들어오는지 모르는 문제에서 사용된다.