ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 02. 테라폼 시작하기
    레거시/Terraform Up and Running 2021. 5. 26. 22:00
    반응형

    이 문서는 책 "테라폼 설치에서 운영까지"을 읽고 작성되었습니다. 최대한 요약해서 책 내용을 최소로 하는데 목표를 두고 있어서, 더 친절하고 정확한 내용을 원하신다면 책을 구매하시는 것을 추천드립니다. => 책 링크

    2장을 진행하기 위해 필요한 작업

    AWS 계정 설정하기

    위 내용은 다음 링크를 따라가기를 바란다.

    테라폼 설치하기

    위 내용은 다음 링크를 따라가기를 바란다.

    2장에서 배운 것

    terraform 구성 요소

    provider

    terraform 사용하기 위한 요소 중 첫 번째는 바로 provider이다. 정확히 인프라스트럭처를 구성하는 공급자를 의미한다.

    provider "aws" {
      region = "us-east-1"
    }

    위의 코드는 provider, 즉 공급자를 aws로 인프라스트럭처를 배포할 regionus-east-1로 지정한 것이다. terraform으로 인프라스트럭처를 구성하기 위해서는 이 코드가 반드시 필요하다. 보통 main.tf 파일에 이 코드를 작성하며 다른 프로그래밍 언어에서 main 함수 역할을 한다고 보면 된다.

     

    terraform으로 관리할 수 있는 provider의 종류는 다음 링크에서 더 자세하게 확인할 수 있다.

     

    resource

    resourceterraform으로 관리하는 인프라스트럭처를 구성하는 각 요소라고 보면 된다. aws로 보면 vpc, iam, ec2, rds, elb 등이라고 보면 된다. 다음은 resource의 예제이다.

    resource "aws_instance" "example" {
      image_id = "ami-0d5eff06f840b45e9"
      instance_type = "t2.micro"
    }

    다음은 aws ec2의 인스턴스 1개를 terraform으로 생성하는 코드이다. 인프라스트럭처의 각 구성 요소들은 대응하는 resource들이 존재한다. 모든 provider가 지원하는 resource들을 한 번에 보긴 힘드니까 aws만 살펴보자.

     

    awsresource들은 다음 링크에서 확인할 수 있다.  또한 각 resource의 간단한 사용법을 확인할 수 있으며, image_id, instance_type 등의 resource를 구성하는데 필요한 변수들을 확인할 수 있다.

     

    variable

    terraform은 프로그래밍 언어는 아니지만 프로그래밍 요소를 가지고 있다. 그 중 하나가 변수, variable이다. 선언 방법은 다음과 같다.

    variable "server_port" {
      description = "The port the server will use HTTP requests"
      default = 8080
    }

     

    variabledescription, default, type 등을 지정할 수 있다. type의 경우는 default 값을 보고 알아서 지정하며 default도 지정되지 않으면 string이 된다. variable의 사용법은 다음과 같다.

    resource "aws_security_group" "instance" {
      name = "terraform-example-instance"
      ingress {
        # var.server_port를 주목하자!  
        from_port = var.server_port
        to_port = var.server_port
        protocol = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    
      lifecycle {
        create_before_destroy = true
      }
    }

     

    var.VARIABLE_NAME으로 terraform 코드에서 변수를 사용할 수 있다. 이 경우 ingressfrom_port, to_port가 모두 변수 server_port의 값 8080으로 할당된다.

     

    data

    dataterraform의 메인 구성 요소는 아니고 코드를 줄이고 깔끔하게 관리할 수 있도록 provider가 제공하는 읽기 전용 정보라고 보면 된다. 선언은 다음과 같다.

    data "aws_availability_zones" "all" {}

     

    variable과 흡사하다. 사용 방법도 이와 비슷하다.

    resource "aws_autoscaling_group" "example" {
      launch_configuration = aws_launch_configuration.example.id
      # 여기를 주목!
      availability_zones = data.aws_availability_zones.all.names
    
      load_balancers = [aws_elb.example.name]
      health_check_type = "ELB"
    
      min_size = 2
      max_size = 10
    
      tag {
        key = "Name"
        value = "terraform-asg-example"
        propagate_at_launch = true
      }
    }

     

    역시 data.DATA_NAME으로 resource를 구성하는 변수들의 값을 할당할 수가 있다. 각 provider가 사용할 수 있는 data들도 역시 terraform registry에서 확인할 수 있다.

     

    다음 링크에서 왼쪽 부분에서 Data Sources를 살펴본다.

    terraform 명령어

    terraform init

    terraform init 명령어는 프로젝트를 terraform을 구동할 수 있는 환경으로 만들어준다. 보통 provider가 작성된 main.tf가 존재하는 경로에서 사용된다. terraform 최초 구동 시 반드시 필요한 명령어이다.

     

    terraform plan

    terraform plan은 현재 작성된 terraform 코드로 생성되고 변경되는 내역을 보여준다. 실제 환경에 적용하기 전 검증할 수 있게 하는 매우 중요한 명령어이다. 또한 terraform 코드의 문법적 오류가 없는지도 검증할 수 있다. 프로그래밍 언어에서 컴파일 단계로 보면 된다.

     

    terraform apply

    terraform apply는 실제로 인프라스트럭처를 구성한다. 역시 생성되고 변경되는 내역을 확인할 수 있다. 프로그래밍 언어로 치면 빌드 및 런타임 단계라고 보면 된다.

     

    참고로 런타임 오류처럼, 컴파일 단계인 terraform plan이 무사히 통과되더라도 provider의 제한으로 인해 terraform apply 명령어가 실패할 때가 아주 가끔 있다.

     

    terraform destroy

    terraform destroy는 이름 그대로 구성했던 인프라스트럭처의 resource를 모두 회수한다. 가끔 resource 설정으로 인해서 명령어가 안먹힐 때가 있는데, 그 때를 대비해서 terraform으로 강제로 삭제할 수 있도록 설정해두는 것이 좋다.

     

    terraform 명령어 cycle

    terraform 작업은 보통은 위의 4가지 명령어들로 구성된다. 일종의 순환 과정이 생성되는데 그림으로 보면 다음과 같다.

    2장 전체 코드

    2장을 진행하면 완성된 코드는 다음과 같다. 참고로, 책 코드 그대로 진행하면 안되는 부분들이 있기 때문에 책과는 완전 똑같지는 않다.

    src/ch02/main.tf

    provider "aws" {
      region = "us-east-1"
    }
    
    variable "server_port" {
      description = "The port the server will use HTTP requests"
      default = 8080
    }
    
    data "aws_availability_zones" "all" {}
    
    resource "aws_security_group" "instance" {
      name = "terraform-example-instance"
      ingress {
        from_port = var.server_port
        to_port = var.server_port
        protocol = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
      }
    
      lifecycle {
        create_before_destroy = true
      }
    }
    
    resource "aws_security_group" "elb" {
      name = "terraform-example-elb"
      ingress {
        from_port = 80
        to_port = 80
        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_launch_configuration" "example" {
      image_id = "ami-0d5eff06f840b45e9"
      instance_type = "t2.micro"
      security_groups = [aws_security_group.instance.id]
    
      user_data = <<-EOF
                #!/bin/bash
                echo "Hello, World" > index.html
                nohup python3 -m http.server ${var.server_port} &
                EOF
    
      lifecycle {
        create_before_destroy = true
      }
    }
    
    resource "aws_autoscaling_group" "example" {
      launch_configuration = aws_launch_configuration.example.id
      availability_zones = data.aws_availability_zones.all.names
    
      load_balancers = [aws_elb.example.name]
      health_check_type = "ELB"
    
      min_size = 2
      max_size = 10
    
      tag {
        key = "Name"
        value = "terraform-asg-example"
        propagate_at_launch = true
      }
    }
    
    resource "aws_elb" "example" {
      name = "terraform-asg-example"
      availability_zones = data.aws_availability_zones.all.names
      security_groups = [aws_security_group.elb.id]
    
      listener {
        lb_port = 80
        lb_protocol = "http"
        instance_port = var.server_port
        instance_protocol = "http"
      }
    
      health_check {
        healthy_threshold = 2
        unhealthy_threshold = 2
        timeout = 3
        interval = 30
        target = "HTTP:${var.server_port}/" 
      }
    }
    
    output "elb_dns_name" {
      value = aws_elb.example.dns_name  
    }
Designed by Tistory.