클라우드 엔지니어/클라우드 캠프과정

IaC - (terraform)

해아's 2022. 11. 1. 13:50
1. IaC
	IaC(Infrastructure as Code)란 코드 형태로 인프라를 작성, 정의, 배포, 업데이트하는 것을 의미
	인프라를 관리하는 모든 것을 코드 형태로 관리하는 것
  1) IaC의 종류
    (1) 애드 훅 스크립트
	Python, Ruby, Bash 등의 스크립트 언어
    (2) 구성 관리 도구
	Ansible, Puppet, Chef 등
	서버에 소프트웨어를 설치/관리하는 목적으로 사용
    (3) 서버 템플릿 도구
	Docker, Packer, Vargrant 등
    (4) 서버 프로비전 도구
	Terraform, CloudFormation 등의 기술
	*프로비전이란?
		프로비저닝(Provisioning) 이란 의미는 영어 직역한 그대로 "제공하는것"
		어떤 종류의 서비스든 사용자의 요구에 맞게 시스템 자체를 제공 하는 것을 프로비저닝이라고 하며 
		제공해줄 수 있는 것은 인프라 자원이나 서비스, 또는 장비가 될 수도 있다.
		Server Resource Provisioning : CPU, Memory, IO 등과 같은 실제 서버의 자원을 할당해주고 운영할 수 있게 제공해주는 것을 말한다.
		OS Provisioning : OS를 서버에 설치하고 구성작업을 해서 사용할 수 있도록 제공하는 것을 말한다.
		Software Provisioning : WAS, DBMS 등의 소프트웨어를 설치하고 세팅하여 실행할 수 있도록 제공하는 것을 말한다.
		Account Provisioning : 접근 권한을 가진 계정을 제공해주는 것을 말한다. 클라우드 인프라 쪽에서는 해당 업무를 담당하던 관리자가 변경된 경우 권한의 인계를 Account Provisioning 을 통해 하는 경우가 많다.
		Storage Provisioning : 데이터를 저장하고 관리할 수 있는 Storage 를 제공할 수 있다. 특히 클라우드에서는 제공하는 Storage 의 종류와 용도에 따라 다양한 방식의 제공이 이루어진다.
		클라우드를 도입하거나 클라우드 환경에서 사용하는 것은 클라우드 Vendor 로부터 서비스를 Provisioning 받아 사용한다고 보면 된다.
  2) IaC의 장점
	속도와 안정성
	문서화
	버전 관리
	확인 및 검사	
	재사용성
	IaC로 배포 작업을 자동화하게 되면 개발자가 원하는 시점에 배포할 수 있으며
	수작업보다 빠르고 안전하게 배포가 가능하다. 
	또한 코드이기 떄문에 그 자체로 문서화가 된다고 볼 수 있으며, 변경 사항과 커밋 이력이 남기 때문에 버전 관리도 할 수 있다. 
	코드 리뷰를 통해서 변경되는 인프라스트럭처를 확인할 수 있고 모듈 형태로 재사용할 수가 있다.

ec2 5대 에서 10대로 바꿀경우

Ansible : ec2 5대 + ec2 5대 (이미설정된 코드를 한번더실행)

Terraform: ec2 5대를 > 10대 (이미실행된 코드를 변경)

인프라관리는 테라폼이 상태관리가 된다.

설정은 엔서블이 좋다 엔서블은 상태관리가 안됨

 

Terraform:는 각종환경지원한다(쿠버,aws등등)

CloudFormation:는 aws만

오늘은 CloudFormation 를 가지고 aws를 해보고 내일부터는 Terraform를가지고 한다.

CloudFormation 에서 EC를 만들어보자

 

CloudFormation > 스택생성 > 준비된 템플릿 > 템플릿 파일 업로드(yml)

# !REF > 참조값 불러오기
AWSTemplateFormatVersion: 2010-09-09 #특정버전에서 사용하는 문법이다 라는 뜻
Resources:
    EC2Instance: #이름쓰는부분
        Type: AWS::EC2::Instance #AWS : 리소스 :
        Properties:
            ImageId: ami-068a0feb96796b48d  #생성할 이미지(AMI) 아이디
            KeyName: ec01 #!Ref KeyName 
            InstanceType: t2.micro  # !Ref InstanceType
            SecurityGroups: #보안그룹
            - default
            BlockDeviceMappings: # 저장장치 맵핍
            -
            DeviceName: /dev/sda1
            Ebs:
                VolumeSize: 8 #단위는 GB

이곳에서 AMI ID를 찾을수있다.

 

yml파일을 다만들고 업로드하면 우리는 지정하지않았지만 !REF 에서 적용한 파라미터를 이곳에서 매칭한다.

 

다음> 다음> 프로세스 실행

해보고 테라폼을 설치한다.

윈도우에서 설치하기

 

그냥 테라폼 exe다운받은후 배치설정한후

#이건 리눅스버전
apt update
aws
apt install awscli
aws --version
aws configure list
aws configure
aws configure list

#이건 윈도우버전

msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi
aws --version
aws configure list
aws configure
aws configure list

#거의동일하다

문법체크편하게 하기위하여 테라폼은 VSCODE에서 작성하며 플러그인은 HashiCorp Terraform설치하여 작성하며 확장자는 *.tf이다.

 

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }

  required_version = ">= 1.2.0"
}

provider "aws" {
  region  = "ap-northeast-2" #리전명
}

resource "aws_instance" "app_server" {
  ami           = "ami-068a0feb96796b48d" #이미지명
  instance_type = "t2.micro"

  tags = {
    Name = "ExampleAppServerInstance"
  }
}

 

테라폼 명령어

테라폼 명령어 실행
	terraform init	초기화
	terraform validate	검증
	terraform plan	계획
	terraform apply	적용
	terraform destroy	제거
	terraform show	상태 확인
#ps terraform을 배치에 등록하기전에 vscode를 실행햇다면 vscode를 껏다켜야한다.

terraform init 초기화시

 

 

terraform plan 실행시

더보기

$ terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.app_server will be created
  + resource "aws_instance" "app_server" {
      + ami                                  = "ami-068a0feb96796b48d"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = (known after apply)
      + availability_zone                    = (known after apply)
      + cpu_core_count                       = (known after apply)
      + cpu_threads_per_core                 = (known after apply)
      + disable_api_stop                     = (known after apply)
      + disable_api_termination              = (known after apply)
      + ebs_optimized                        = (known after apply)
      + get_password_data                    = false
      + host_id                              = (known after apply)
      + host_resource_group_arn              = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_state                       = (known after apply)
      + instance_type                        = "t2.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = (known after apply)
      + monitoring                           = (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      + placement_partition_number           = (known after apply)
      + primary_network_interface_id         = (known after apply)
      + private_dns                          = (known after apply)
      + private_ip                           = (known after apply)
      + public_dns                           = (known after apply)
      + public_ip                            = (known after apply)
      + secondary_private_ips                = (known after apply)
      + security_groups                      = (known after apply)
      + source_dest_check                    = true
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Name" = "ExampleAppServerInstance"
        }
      + tags_all                             = {
          + "Name" = "ExampleAppServerInstance"
        }
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + user_data_replace_on_change          = false
      + vpc_security_group_ids               = (known after apply)

      + capacity_reservation_specification {
          + capacity_reservation_preference = (known after apply)

          + capacity_reservation_target {
              + capacity_reservation_id                 = (known after apply)
              + capacity_reservation_resource_group_arn = (known after apply)
            }
        }

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + tags                  = (known after apply)
          + throughput            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + enclave_options {
          + enabled = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + maintenance_options {
          + auto_recovery = (known after apply)
        }

      + metadata_options {
          + http_endpoint               = (known after apply)
          + http_put_response_hop_limit = (known after apply)
          + http_tokens                 = (known after apply)
          + instance_metadata_tags      = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_card_index    = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + private_dns_name_options {
          + enable_resource_name_dns_a_record    = (known after apply)
          + enable_resource_name_dns_aaaa_record = (known after apply)
          + hostname_type                        = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + tags                  = (known after apply)
          + throughput            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

terraform apply 실행시

정말실행할건지 : yes

더보기

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.app_server will be created
  + resource "aws_instance" "app_server" {
      + ami                                  = "ami-068a0feb96796b48d"
      + arn                                  = (known after apply)
      + associate_public_ip_address          = (known after apply)
      + availability_zone                    = (known after apply)
      + cpu_core_count                       = (known after apply)
      + cpu_threads_per_core                 = (known after apply)
      + disable_api_stop                     = (known after apply)
      + disable_api_termination              = (known after apply)
      + ebs_optimized                        = (known after apply)
      + get_password_data                    = false
      + host_id                              = (known after apply)
      + host_resource_group_arn              = (known after apply)
      + id                                   = (known after apply)
      + instance_initiated_shutdown_behavior = (known after apply)
      + instance_state                       = (known after apply)
      + instance_type                        = "t2.micro"
      + ipv6_address_count                   = (known after apply)
      + ipv6_addresses                       = (known after apply)
      + key_name                             = (known after apply)
      + monitoring                           = (known after apply)
      + outpost_arn                          = (known after apply)
      + password_data                        = (known after apply)
      + placement_group                      = (known after apply)
      + placement_partition_number           = (known after apply)
      + primary_network_interface_id         = (known after apply)
      + private_dns                          = (known after apply)
      + private_ip                           = (known after apply)
      + public_dns                           = (known after apply)
      + public_ip                            = (known after apply)
      + secondary_private_ips                = (known after apply)
      + security_groups                      = (known after apply)
      + source_dest_check                    = true
      + subnet_id                            = (known after apply)
      + tags                                 = {
          + "Name" = "ExampleAppServerInstance"
        }
      + tags_all                             = {
          + "Name" = "ExampleAppServerInstance"
        }
      + tenancy                              = (known after apply)
      + user_data                            = (known after apply)
      + user_data_base64                     = (known after apply)
      + user_data_replace_on_change          = false
      + vpc_security_group_ids               = (known after apply)

      + capacity_reservation_specification {
          + capacity_reservation_preference = (known after apply)

          + capacity_reservation_target {
              + capacity_reservation_id                 = (known after apply)
              + capacity_reservation_resource_group_arn = (known after apply)
            }
        }

      + ebs_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + snapshot_id           = (known after apply)
          + tags                  = (known after apply)
          + throughput            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }

      + enclave_options {
          + enabled = (known after apply)
        }

      + ephemeral_block_device {
          + device_name  = (known after apply)
          + no_device    = (known after apply)
          + virtual_name = (known after apply)
        }

      + maintenance_options {
          + auto_recovery = (known after apply)
        }

      + metadata_options {
          + http_endpoint               = (known after apply)
          + http_put_response_hop_limit = (known after apply)
          + http_tokens                 = (known after apply)
          + instance_metadata_tags      = (known after apply)
        }

      + network_interface {
          + delete_on_termination = (known after apply)
          + device_index          = (known after apply)
          + network_card_index    = (known after apply)
          + network_interface_id  = (known after apply)
        }

      + private_dns_name_options {
          + enable_resource_name_dns_a_record    = (known after apply)
          + enable_resource_name_dns_aaaa_record = (known after apply)
          + hostname_type                        = (known after apply)
        }

      + root_block_device {
          + delete_on_termination = (known after apply)
          + device_name           = (known after apply)
          + encrypted             = (known after apply)
          + iops                  = (known after apply)
          + kms_key_id            = (known after apply)
          + tags                  = (known after apply)
          + throughput            = (known after apply)
          + volume_id             = (known after apply)
          + volume_size           = (known after apply)
          + volume_type           = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_instance.app_server: Creating...
aws_instance.app_server: Still creating... [10s elapsed]
aws_instance.app_server: Still creating... [20s elapsed]
aws_instance.app_server: Still creating... [30s elapsed]
aws_instance.app_server: Creation complete after 31s [id=i-00b65e1ce56b3bc24]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

 

하면 ec2에 인스턴스가 생성된다.

 

테라폼 구성요소
	provider: 테라폼으로 생성할 인프라의 종류를 의미
	resource: 테라폼으로 실제로 생성할 인프라 자원을 의미
	state: 테라폼을 통해 생성한 자원의 상태를 의미
	output: 테라폼으로 만든 자원을 변수 형태로 state에 저장하는 것을 의미
	module: 공통적으로 활용할 수 있는 코드를 문자 그대로 모듈 형태로 정의하는 것을 의미
	remote: 다른 경로의 state를 참조하는 것을 의미, output 변수를 불러올때 주로 사용	

  4) 테라폼 작동 원리
	Local 코드 : 현재 개발자가 작성/수정하고 있는 코드
	AWS 실제 인프라 : 실제로 AWS에 배포되어 있는 인프라
	Backend에 저장된 상태 : 가장 최근에 배포한 테라폼 코드 형상

	테라폼은 실제 인프라와 Backend에 저장된 상태를 일치하도록 만드는 프로그램

    [1] Terraform init
	terraform init 명령어는 프로젝트를 terraform을 구동할 수 있는 환경으로 만들어준다. 
	보통 provider가 작성된 main.tf가 존재하는 경로에서 사용된다. terraform 최초 구동 시 반드시 필요한 명령어이다.
	
    [2] terraform plan
	현재 작성된 terraform 코드로 생성되고 변경될 내역을 보여준다. 
	실제 환경에 적용하기 전 검증할 수 있게 하는 매우 중요한 명령어이다. 
	또한 terraform 코드의 문법적 오류가 없는지도 검증할 수 있다.

    [3] terraform apply
	terraform apply는 실제로 인프라스트럭처를 구성한다.

    [4] terraform destroy
	구성했던 인프라스트럭처의 resource를 모두 회수한다. 

테라폼은 한번더 실행해도 EC2가 생기는게 아니다 수정된게 없기떄문이다.

 

provider: 테라폼으로 생성할 인프라의 종류를 의미
resource: 테라폼으로 실제로 생성할 인프라 자원을 의미
output: 테라폼으로 만든 자원을 변수 형태로 state에 저장하는 것을 의미

 

테라폼 리소스 코드 양식
	https://registry.terraform.io/providers/hashicorp/aws/latest/docs
	resource "리소스타입" "리소스이름" {
	  속성이름 = "속성값"
	}

그럼 기본소스에 resource를 하나 추가한다

리소스는 시큐리티 그룹이고 22번 포트를 오픈하는것이다.

 

#AWS에 리소스를 추가하는데 aws_security_group 라는것을 추가한다.
resource "aws_security_group" "ec2_allow_rule" {
  ingress {
    description = "SSH"
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    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_instance" "app_server" { #리소스
  ami           = "ami-068a0feb96796b48d" #이미지명
  instance_type = "t2.micro"
  vpc_security_group_ids = [ aws_security_group.ec2_allow_rule.id ] #resource "aws_security_group" "ec2_allow_rule" 를 가져와서 설정해준다
  tags = {
    Name = "ExampleAppServerInstance"
  }
}

 

결과

점심이후

테라폼의 변수

 

 

 

 

참고자료

더보기

 

 

 

728x90
반응형