6.30

w0nyyy·2022년 7월 1일
0

IaC

Cloud Formation 클라우드 포메이션

VPC 생성 YAML

# 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에 남아있으므로 내가 지워야됨

스택 생성 클릭

VPC

DNS 호스트이름 편집 :
DNS 확인 편집 :

EC2 YAML

# 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는 생성과는 거리가 멀다. 설정, 구성과 가깝.

  1. 코딩 규칙 - 내장 함수, 두칸 띄우기 이런것들
  2. 멱등성 - 설치되지않은 경우에 설치하고, 동작하지 않는 경우에만 동작하도록 하는 것. 실행 횟수에 관계없이 파일 사용
    ex) yum install -y httpd - > Nothing to do 이렇게 뜸. 이미 설치된 경우 cpu memory 같은 것들이 낭비되지않게 하기 위해.
  3. 분산형 구조 - 네트워크에 연결되어있는 모든 서버들을 ip통신으로 관리할 수 있는 분산형 구조. hosts 파일을 인벤토리라고 함. 플레이북 - 스크립트 (aws에서 yaml)

서버 템플릿 도구

도커, 패커, 베이그런트 같은 것들. 운영체제, 소프트웨어, 파일 및 기타 모든 내용을 포함 한 스냅샷으로 이미지를 생성하여 모든 서버에 이미지를 설치함. 실행은 서버에 이미지를 배포하고 할 수 있음
ex) ova,AMI

오케스트레이션 도구

서버 템플릿 도구는 vm이나 컨테이너를 생성하기엔 좋은 도구, 그러나 관리부분이 부족하다.
이를 보완하기 위한 것이 쿠버네티스
자동 복구(복제), 롤백(복원 - 스냅샷), 업데이트, 오토스케일링(자동 확장)

쿠버네티스도 코드로 정의하니까 IaC 도구로 봄. 도커 자체는 ad-hoc과 닮았음

* 클러스터 - 마스터, 워커 뭉탱이
가용성을 높이고, 오토스케일링 등등을 하기 위해 클러스터를 구성함. 자원 공유 가능

프로비전 도구

앤서블은 서버를 못 만들었음. 레거시한 물리적 서버(이미 만들어진 서버)를 앤서블이 연결해서 인벤토리내에 있는 머신들을 remote에서 구성만 해주는 도구였다. 클라우드로 오면서 모듈이 발달하면서 클라우드 환경에서도 ec2를 생성하는 기능이 추가됨.

앤서블과 테라폼의 격차가 줄어듬. 테라폼은 처음부터 클라우드 네이티브였기 때문에 퍼포먼스가 좋다. 앤서블은 범용. 특화된게 없음.

IaC 장점

  1. 자급식 배포
    2.속도와 안정성 - 휴먼에러 방지
  2. 문서화
  3. 버전 관리 - 주 목적은 rollback
  4. 유효성 검증
  5. 재사용성 - 검증된 모듈로 일관되게 배포가능

테라폼 작동 방식

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 주요 명령어

  • terraform init : terraform 명령어에는 테라폼의 기본 기능이 포함되어 있지만 모든 공급자(AWS, Azure, GCP 등)에 대한 코드가 포함되어 있지 않습니다. 그렇게 때문에 terraform init 명령어를 실행하여 테라폼에 코드를 스캔하도록 지시하고 어느 공급자인지 확인하고, 필요한 코드를 다운로드하도록 해야 합니다. 기본적으로 공급자 코드는 테라폼의 .terraform 폴더에 다운로드됩니다.

  • terraform plan : 테라폼이 구성 파일을 사용하여 작업을 수행하기 전에 코드의 온전성을 검사할 수 있습니다. plan 명령어는 리눅스에서 쓰이는 diff 명령의 결괏값과 유사합니다. + 가 있는 항목은 추가되고, - 가 있는 항목은 삭제된다는 뜻입니다. ~ 가 있는 항목은 수정됩니다.

  • terraform apply : 테라폼의 구성 파일을 실행하려면 terraform apply 명령어를 실행합니다.

Terraform 설치

--- 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 인스턴스 생성

--- 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의 줄임말이다. 주로 이것은 백준 문제를 풀 때 최대 몇개의 입력이 들어오는지 모르는 문제에서 사용된다.

0개의 댓글