티스토리 뷰

T101 study

[5주차] Module & Runner

haru224 2024. 7. 13. 21:41

lCloudNet@ 가시다님이 진행하는 Terraform 101 Study 4기 스터디 내용 참고.

스터디 교재 : ‘테라폼으로 시작하는 IaC’ (한빛 미디어, 김민수 외 지금) 책의 내용 참고

 -. https://www.aladin.co.kr/m/mproduct.aspx?ItemId=317519064

 

1. 모듈


1. 모듈소개 Link 

 

Modules Overview - Configuration Language | Terraform | HashiCorp Developer

Modules are containers for multiple resources that are used together in a configuration. Find resources for using, developing, and publishing modules.

developer.hashicorp.com

  • 테라폼으로 인프라와 서비스를 관리하면 시간이 지날수록 구성이 복잡해지고 관리하는 리소스가 늘어나게 된다. 테라폼의 구성 파일과 디렉터리 구성에는 제약이 없기 때문에 단일 파일 구조상에서 지속적으로 업데이트할 수 있지만, 다음과 같은 문제가 발생한다.
    • 테라폼 구성에서 원하는 항목을 찾고 수정하는 것이 점점 어려워짐
    • 리소스들 간의 연관 관계가 복잡해질수록 변경 작업의 영향도를 분석하기 위한 노력이 늘어남
    • 개발/스테이징/프로덕션 환경으로 구분된 경우 비슷한 형태의 구성이 반복되어 업무 효율이 줄어듦
    • 새로운 프로젝트를 구성하는 경우 기존 구성에서 취해야 할 리소스 구성과 종속성 파악이 어려움
  • 모듈은 루트 모듈과 자식 모듈로 구분된다
    • 루트 모듈 Root Module : 테라폼을 실행하고 프로비저닝하는 최상위 모듈
    • 자식 모듈 Chile Module : 루트 모듈의 구성에서 호출되는 외부 구성 집합
  • 모듈은 테라폼 구성의 집합이다. 테라폼으로 관리하는 대상의 규모가 커지고 복잡해져 생긴 문제를 보완하고 관리 작업을 수월하게 하기 위한 방안으로 활용
    • 관리성 : 모듈은 서로 연관 있은 구성의 묶음이다. 원하는 구성요소를 단위별로 쉽게 찾고 업데이트할 수 있다. 모듈은 다른 구성에서 쉽게 하나의 덩어리로 추가하거나 삭제할 수 있다. 또한 모듈이 업데이트되면 이 모듈을 사용하는 모든 구성에서 일관된 변경 작업을 진행할 수 있다.
    • 캡슐화 : 테라폼 구성 내에서 각 모듈은 논리적으로 묶여져 독립적으로 프로비저닝 및 관리되며, 그 결과는 은닉성을 갖춰 필요한 항목만을 외부에 노출시킨다.
    • 재사용성 : 구성을 처음부터 작성하는 것에는 시간과 노력이 필요하고 작성 중간에 디버깅과 오류를 수정하는 반복 작업이 발생한다. 테라폼 구성을 모듈화하면 이후에 비슷한 프로비저닝에 이미 검증된 구성을 바로 사용할 수 있다.
    • 일관성표준화 : 테라폼 구성 시 모듈을 활용하는 워크플로는 구성의 일관성을 제공하고 서로 다른 환경과 프로젝트에도 이미 검증한 모듈을 적용해 복잡한 구성과 보안 사고를 방지할 수 있다.

 

 

1.1 모듈 작성 기본 원칙


  • 기본 원칙 : 모듈은 대부분의 프로그래밍 언어에서 쓰이는 라이브러리나 패키지와 역할이 비슷하다
    • 모듈 디렉터리 형식을 terraform-<프로바이더 이름>-<모듈 이름> 형식을 제안한다. 이 형식은 Terraform Cloud, Terraform Enterprise에서도 사용되는 방식으로 1) 디렉터리 또는 레지스트리 이름이 테라폼을 위한 것이고, 2) 어떤 프로바이더의 리소스를 포함하고 있으며, 3) 부여된 이름이 무엇인지 판별할 수 있도록 한다.

테라폼 구성은 궁극적으로 모듈화가 가능한 구조로 작성할 것을 제안한다. 처음부터 모듈화를 가정하고 구성파일을 작성하면 단일 루트 모듈이라도 후에 다른 모듈이 호출할 것을 예상하고 구조화할 수 있다. 또한 작성자는 의도한 리소스 묶음을 구상한 대로 논리적인 구조로 그룹화할 수 있다.

    • 각각의 모듈을 독립적으로 관리하기를 제안한다. 리모트 모듈을 사용하지 않더라도 처음부터 모듈화가 진행된 구성들은 떄로 루트 모듈의 하위 파일 시스템에 존재하는 경우가 있다. 하위 모듈 또한 독립적인 모듈이므로 루트 모듈 하위에 두기보다는 동일한 파일 시스템 레벨에 위치하거나 별도 모듈만을 위한 공간에서 불러오는 것을 권장한다. 이렇게 하면 VCS를 통해 관리하기가 더 수월하다.
    • 공개된 테라폼 레지스트리의 모듈을 참고하기를 제안한다. 대다수의 테라폼 모듈은 공개된 모듈이 존재하고 거의 모든 인수에 대한 변수 처리, 반복문 적용 리소스, 조건에 따른 리소스 활성/비활성 등을 모범 사례로 공개해두었다. 물론 그대로 가져다 사용하는 것보다는 프로비저닝하려는 상황에 맞게 참고하는 것을 권장한다.
    • 작성된 모듈은 공개 또는 비공개로 게시해 팀 또는 커뮤니티와 공유하기를 제안한다. 모듈의 사용성을 높이고 피드백을 통해 더 발전된 모듈을 구성할 수 있는 자극이 된다.
    • 모듈을 독립적으로 관리하기 위해 디렉터리 구조를 생성할 때 모듈을 위한 별도 공간을 생성하는 방식으로 진행한다. 특정 루트 모듈 하위에 자식 모듈을 구성하는 경우 단순히 복잡한 코드를 분리하는 요도로 명시되며 종속성이 발생하므로 루트 모듈 사이에 모듈 디렉터리를 지정한다. 

 

 

1.2 모듈화 해보기


  • 모듈화 소개
    • 모듈의 기본적 구조는 테라폼 구성으로 입력 변수를 구성하고 결과를 출력하기 위한 구조로 구성한다.
    • 모듈화’라는 용어는 이런 구조재활용하기 위한 템플릿 작업을 말한다.
    • 애플리케이션 개발시에도 자주 사용되는 용어로 테라폼은 작성된 모듈을 다른 루트 모듈에서 가져다 사용하며 이를 통해 재사용성과 표준화 구조를 구성할 수 있다.
    • 기존에 작성된 모듈은 다른 모듈에서 참조해 사용할 수 있다. 사용 방식은 리소스와 비슷하다.
    • 모듈에서 필요한 값은 variable로 선언해 설정하고, 모듈에서 생성된 값 중 외부 모듈에서 참조하고 싶은 값은 output으로 설정한다. 마치 자바 개발 시 getter, setter로 캡슐화된 클래스를 활용하는 것과 비슷한다.
  • 모듈 작성 실습
    • 하나의 프로비저닝에서 사용자와 패스워드를 여러 번 구성해야 하는 경우를 가상의 시나리오로 삼아 모듈화를 진행해보겠다.
      • random_pet는 이름을 자동으로 생성하고, random_password는 사용자의 패스워드를 설정한다 - random_pet
      • random_password는 random 프로바이더 리소스로 난수 형태로 패스워드를 만들 수 있다

## 자식모듈 작성

mkdir -p 06-module-traning/modules/terraform-random-pwgen
cd 06-module-traning/modules/terraform-random-pwgen
touch main.tf variable.tf output.tf

## main.tf

resource "random_pet" "name" {
  keepers = {
    ami_id = timestamp()
  }
}

resource "random_password" "password" {
  length           = var.isDB ? 16 : 10
  special          = var.isDB ? true : false
  override_special = "!#$%*?"
}


## variable.tf

variable "isDB" {
  type        = bool
  default     = false
  description = "패스워드 대상의 DB 여부"
}

## output.tf
output "id" {
  value = random_pet.name.id
}

output "pw" {
  value = nonsensitive(random_password.password.result) 
}


## 실행: 자식모듈 동작 테스트

#
ls *.tf
terraform init && terraform plan

# 테스트를 위해 apply 시 변수 지정
terraform apply -auto-approve -var=isDB=true
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
id = "knowing-aardvark"
pw = "Y5eeP0i2KLLE9gBa"

# 확인
terraform state list

terraform state show random_pet.name
echo "random_pet.name.id" | terraform console
echo "random_pet.name.keepers" | terraform console

terraform state show random_password.password
echo "random_password.password.length" | terraform console
echo "random_password.password.special" | terraform console
cat terraform.tfstate| grep result

# tfstate에 모듈 정보 확인 : VSCODE에서 terraform.tfstate 파일 확인
cat terraform.tfstate | grep module

# graph 확인
terraform graph > graph.dot

아직까지 모듈은 아님

 

자식 모듈 호출 실습

  • 다수의 리소스를 같은 목적으로 여러 번 반복해서 사용하려면 리소스 수만큼 반복해 구성 파일을 정의해야 하고 이름도 고유하게 설정해줘야 하는 부담이 있지만, 모듈을 활용하면 반복되는 리소스 묶음을 최소화할 수 있다.
mkdir -p 06-module-traning/06-01-basic
cd 06-module-traning/06-01-basic
touch main.tf

## main.tf

module "mypw1" {
  source = "../modules/terraform-random-pwgen"
}

module "mypw2" {
  source = "../modules/terraform-random-pwgen"
  isDB   = true
}

output "mypw1" {
  value  = module.mypw1
}

output "mypw2" {
  value  = module.mypw2
}


## 실행

#
terraform init && terraform plan && terraform apply -auto-approve
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
mypw1 = {
  "id" = "equipped-mustang"
  "pw" = "OXST1EYqQc"
}
mypw2 = {
  "id" = "diverse-impala"
  "pw" = "y8mEbOJhS6dCTiK#"
}

# 확인
terraform state list

# tfstate에 모듈 정보 확인 : VSCODE에서 terraform.tfstate 파일 확인
cat terraform.tfstate | grep module

# terraform init 시 생성되는 modules.json 파일 확인
tree .terraform
.terraform
├── modules
│   └── modules.json
...

## 모듈로 묶여진 리소스는 module이라는 정의를 통해 단순하게 재활용하고 반복 사용할 수 있다.
## 모듈의 결과 참조 형식은 module.<모듈 이름>.<output 이름>으로 정의된다.
cat .terraform/modules/modules.json | jq
{
  "Modules": [
    {
      "Key": "",
      "Source": "",
      "Dir": "."
    },
    {
      "Key": "mypw1",
      "Source": "../modules/terraform-random-pwgen",
      "Dir": "../modules/terraform-random-pwgen"
    },
    {
      "Key": "mypw2",
      "Source": "../modules/terraform-random-pwgen",
      "Dir": "../modules/terraform-random-pwgen"
    }
  ]
}

# graph 확인
terraform graph > graph.dot

 

 

1. 3 모듈 사용 방식


  • 모듈과 프로바이더
    • 모듈에서 사용되는 모든 리소스는 관련 프로바이더의 정의가 필요하다. 여기서 사용자는 프로바이더 정의를 모듈 안 or 밖 고민
      • provider를 child module에 각각 정의할 것인지, root module에 정의하고 사용하는 것인지

 

유형 1. 자식 모듈에서 프로바이더 정의

  • 모듈에서 사용하는 프로바디어 버전과 구성 상세를 자식 모듈에서 고정하는 방법이다.
    • 프로바이더 버전과 구성에 민감하거나, 루트 모듈에서 프로바이더 정의 없이 자식 모듈이 독립적인 구조일 때 고려할 방법이다
    • 하지만 동일한 프로바이더가 루트와 자식 양쪽에 또는 서로 다른 자식 모듈에 버전 조건 합의가 안 되면, 오류가 발생하고 모듈에 반복문을 사용할 수 없다는 단점이 있으므로 잘 사용하지 않는다.

유형 2. 루트 모듈에서 프로바이더 정의(실습)

  • 자식 모듈루트 모듈프로바이더 구성에 종속되는 방식이다.
  • 디렉터리 구조로는 분리되어 있지만 테라폼 실행 단계에서 동일 계층으로 해석되므로 프로바이더 버전과 구성은 루트 모듈의 설정이 적용된다. 프로바이더를 모듈 내 리소스와 데이터 소스에 일괄 적용하고, 자식 모듈에 대한 반복문 사용에 자유로운 것이 장점이다. 자식 모듈에 특정 프로바이더 구성의 종속성은 반영할 수 없으므로 자식 모듈을 프로바이더 조건에 대해 기록하고, 자식 모듈을 사용하는 루트 모듈에서 정의하는 프로바이더에 맞게 업데이트 해야 한다.
  • 다음은 동일한 모듈에 사용되는 프로바이더 조건이 다른 경우 각 모듈별로 프로바이더를 맵핑하는 방안이다.
  • 리소스와 데이터 소스에 provider 메타인수로 지정하는 방식과 비슷하나 모듈에는 다수의 프로바이더가 사용될 가능성이 있으므로 map 타입으로 구성하는 provider로 정의한다. 실습을 위한 디렉터리 구성의 예는 다음과 같다.

## 자식 모듈 디렉토리 생성

mkdir -p 06-module-traning/modules/terraform-aws-ec2/
cd 06-module-traning/modules/terraform-aws-ec2/
touch main.tf variable.tf output.tf

# main.tf

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

resource "aws_default_vpc" "default" {}

data "aws_ami" "default" {
  most_recent = true
  owners      = ["amazon"]

  filter {
    name   = "owner-alias"
    values = ["amazon"]
  }

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm*"]
  }
}

resource "aws_instance" "default" {
  depends_on    = [aws_default_vpc.default]
  ami           = data.aws_ami.default.id
  instance_type = var.instance_type

  tags = {
    Name = var.instance_name
  }
}

## variable.tf

variable "instance_type" {
  description = "vm 인스턴스 타입 정의"
  default     = "t2.micro"
}

variable "instance_name" {
  description = "vm 인스턴스 이름 정의"
  default     = "my_ec2"
}


## 루트 모듈 디렉토리 생성

mkdir -p 06-module-traning/multi_provider_for_module/
cd 06-module-traning/multi_provider_for_module/
touch main.tf output.tf


## main.tf

provider "aws" {
  region = "ap-southeast-1"  
}

provider "aws" {
  alias  = "seoul"
  region = "ap-northeast-2"  
}

module "ec2_singapore" {
  source = "../modules/terraform-aws-ec2"
}

module "ec2_seoul" {
  source = "../modules/terraform-aws-ec2"
  providers = {
    aws = aws.seoul
  }
  instance_type = "t3.small"
}


## output.tf

output "module_output_singapore" {
  value = module.ec2_singapore.private_ip
}

output "module_output_seoul" {
  value = module.ec2_seoul.private_ip
}



## 실행

#
cd 06-module-traning/multi_provider_for_module/
terraform init
cat .terraform/modules/modules.json | jq

#
terraform apply -auto-approve
terraform output
terraform state list
terraform state show module.ec2_seoul.data.aws_ami.default
terraform state show module.ec2_singapore.data.aws_ami.default

# tfstate에 모듈 정보 확인 : VSCODE에서 terraform.tfstate 파일 확인
cat terraform.tfstate | grep module

# graph 확인
terraform graph > graph.dot

# aws cli로 ec2 확인
aws ec2 describe-instances --region ap-northeast-2 --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text
aws ec2 describe-instances --region ap-southeast-1 --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text

# 실습 완료 후 리소스 삭제
terraform destroy -auto-approve

 

 

 

 

자식 모듈에서 필요로 하는 프로바이더의 버전이 루트 모듈의 정의와 다른 경우, 테라폼 구성에서 정의한 내용이 서로 호환되지 않아 오류가 발생할 수 있다.

 

모듈의 반복문

  • 모듈 또한 리소스에서 반복문을 사용하듯 구성할 수 있다.
  • 모듈이라는 리소스 정의 묶음을 원하는 수량으로 프로비저닝할 수 있으므로 모듈 없이 구성하는 것과 대비해 리소스 종속성 관리와 유지 보수에 장점이 있다. count를 사용한 반복문 사용은 리소스에서의 사용 방식처럼 module 블록 내에 선언한다.
## 반복문 (count)

mkdir -p 06-module-traning/module_loop_count/
cd 06-module-traning/module_loop_count/
touch main.tf

## main.tf

provider "aws" {
  region = "ap-northeast-2"  
}

module "ec2_seoul" {
  count  = 2
  source = "../modules/terraform-aws-ec2"
  instance_type = "t3.small"
}

output "module_output" {
  value  = module.ec2_seoul[*].private_ip   
}


## 실행 

#
cd 06-module-traning/module_loop_count/
terraform init
cat .terraform/modules/modules.json | jq

#
terraform apply -auto-approve
terraform output
terraform state list

# tfstate에 모듈 정보 확인 : VSCODE에서 terraform.tfstate 파일 확인
cat terraform.tfstate | grep module

# graph 확인
terraform graph > graph.dot

# aws cli로 ec2 확인
aws ec2 describe-instances --region ap-northeast-2 --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text

# 실습 완료 후 리소스 삭제
terraform destroy -auto-approve

모듈 묶음에 일관된 구성과 구조로 프로비저닝이 되는 경우라면 count가 간편한 방안이지만, 동일한 모듈 구성에 필요한 인수 값이 다르다 for_each를 활용한다.

 

  • 예를 들어 동일한 모듈에 개발과 상용에 대한 입력 변수를 다르게 처리하는 방식을 실습해보시기 바랍니다.
## 반복문 (for_each)

## main.tf

locals {
  env = {
    dev = {
      type = "t3.micro"
      name = "dev_ec2"
    }
    prod = {
      type = "t3.medium"
      name = "prod_ec2"
    }
  }
}

module "ec2_seoul" {
  for_each = local.env
  source = "../modules/terraform-aws-ec2"
  instance_type = each.value.type
  instance_name = each.value.name
}

output "module_output" {
  value  = [
    for k in module.ec2_seoul: k.private_ip
  ]
}

## 실행

#
terraform plan
terraform apply -auto-approve
terraform output
terraform state list

# tfstate에 모듈 정보 확인 : VSCODE에서 terraform.tfstate 파일 확인
cat terraform.tfstate | grep module

# graph 확인
terraform graph > graph.dot

# aws cli로 ec2 확인
aws ec2 describe-instances --region ap-northeast-2 --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output text

# 실습 완료 후 리소스 삭제
terraform destroy -auto-approve

 

 

 

1.4 모듈 소스 관리


  • 모듈 소스 관리
    • Module 블록에 정의된 소스 구성으로 모듈의 코드 위치를 정의한다. terraform init을 수행할 때 지정된 모듈을 다운로드해 사용한다 - Link 
      • 로컬 디렉터리 경로
      • 테라폼 레지스트리 Terraform Registry
      • 깃허브 Github
      • 비트버킷 Bitbucket
      • 깃 Generic Git Repository
      • HTTP URLs
      • S3 Bucket
      • GCS Bucket google cloud storage
    • 테라폼 공식 문서 안내와 같이 루트 경로에 모듈을 배치하는 것 외에 패키지 하위 디렉터리 경로를 참조하는 것도 하나의 방안이다.
    로컬 디렉터리 경로
    • 로컬 경로를 지정할 때는 테라폼 레지스트리와 구분하기 위해 하위 디렉터리는 ./로, 상위 디렉터리는 ../로 시작한다.
    • 대상 모듈은 이미 같은 로컬 파일 시스템에 존재하므로 다운로드 없이 바로 사용한다. 앞서 언급한 대로 재사용성이 고려된다면 상위 디렉터리에 별도 관리하는 것을 권장하고, 항상 루트 모듈과 함께 동작해야 하는 경우 하위 디렉터리에 모듈을 정의한다.
    • 코드 예시) 작업 환경을 기준으로 하는 로컬 경로 상위에 위치한 모듈 경로 선언
module "local_module" {
  source = "../modules/my_local_module"
}
  •     테라폼 레지스트리
    • 테라폼 모듈 레지스트리는 테라폼의 프로토콜을 사용해 모듈을 사용하는 방식이다.
    • 공개된 테라폼 모듈을 사용하거나 Terraform Cloud, Terraform Enterprise에서 제공되는 비공개 테라폼 모듈을 사용할 때 설정하는 소스 지정 방식이다.
    • 공개된 모듈 - Link     
    • 공개된 테라폼 모듈을 source에 선언할 때는 <네임스페이스>/<이름>/<프로바이더> 형태로 설정한다.
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.1.0"
}

 

2. Terraform Runner


참고 링크


[국내]

  • Terraform을 GitOps 방식으로 사용하기 위한 도구 선택 - Link
  • Atlantis 란? (Terraform Pull Request Automation) - Link
  • 펫프렌즈가 DevOps 조직없이 인프라를 관리하는 방법 - Link
  • Atlantis 배포하기 - Link
  • Github에서 Atlantis를 이용한 Terraform 협업 환경 구축 - Link Github
  • Jenkins + terraform + tfsec 로 정적 분석 자동화 구성 하기 - Link

[해외]

  • install-atlantis-docker-container-in-amazon-linux-integrate - Link Github
  • Hacking Atlantis - Youtube
  • [CNCF] How Breaking up Our Infrastructure Monorepos Saved Us from Pul... Donnie Laughton - Youtube

 

Atlantis


소개 : Terraform Pull Request Automation - Running Terraform Workflows with Ease - Link 

 

Atlantis

Atlantis Terraform Pull Request Automation Running Terraform Workflows with Ease

www.runatlantis.io

이미지 출처: https://isn-t.tistory.com/46

 

설명: Atlantis 공식 홈페이지 참조 : https://www.runatlantis.io/guide#overview-%E2%80%93-what-is-atlantis

 

개요 – 아틀란티스란 무엇인가?

Atlantis는 풀 리퀘스트를 통해 Terraform을 자동화하는 애플리케이션입니다. 인프라에 독립형 애플리케이션으로 배포됩니다. 제3자가 귀하의 자격 증명에 액세스할 수 없습니다.

Atlantis는 Terraform 풀 리퀘스트에 대한 GitHub, GitLab 또는 Bitbucket 웹훅을 수신합니다. 그런 다음 실행하여 terraform plan풀 리퀘스트에 대한 출력으로 주석을 달고 있습니다.

적용하고 싶을 때, atlantis apply풀 리퀘스트에 댓글을 남기면 Atlantis가 실행되어 terraform apply결과를 댓글로 다시 알려 줍니다.

 

왜 아틀란티스를 운영하시나요?

가시성 증가

모두가 자신의 컴퓨터에서 Terraform을 실행하고 있을 때 인프라의 현재 상태를 아는 것은 어렵습니다.

  • 지점 에 배포된 것이 있나요 main?
  • 누군가 최신 변경 사항에 대한 풀 리퀘스트를 만드는 것을 잊었나요?
  • 마지막 작업의 결과는 무엇이었나요 terraform apply?

Atlantis를 사용하면 모든 것이 풀 리퀘스트에 표시됩니다. 인프라에 수행된 모든 작업의 ​​기록을 볼 수 있습니다.

 

모든 사람과의 협업을 활성화하세요

엔지니어링 조직의 모든 사람에게 Terraform 자격 증명을 배포하고 싶지는 않겠지만, 이제 누구나 Terraform 풀 리퀘스트를 열 수 있습니다.

풀 리퀘스트가 적용되기 전에 승인을 요청하면 실수로 아무 일도 일어나지 않습니다.

 

Terraform 풀 리퀘스트를 더 잘 검토하세요

.의 출력을 보지 않고는 Terraform 변경 사항을 완전히 검토할 수 없습니다 terraform plan. 이제 해당 출력이 자동으로 풀 리퀘스트에 추가됩니다.

 

워크플로우 표준화

Atlantis는 풀 리퀘스트가 병합되거나 잠금이 수동으로 삭제될 때까지 디렉토리/작업 공간을 잠급니다. 이렇게 하면 변경 사항이 예상 순서대로 적용됩니다.

Atlantis가 실행하는 정확한 명령은 구성 가능합니다. 사용자 정의 스크립트를 실행하여 이상적인 워크플로를 구성할 수 있습니다.

 

 

실습 따라하기


 

AWS EC2 생성 : atlantis 서버 역할

# CloudFormation yaml 파일 다운로드

# CloudFormation 스택 배포
#각자 자신의 AWS EC2 서울 리전 Keypair 이름
MYKEYNAME=kp-gasida
aws cloudformation deploy --template-file t101-atlantis-ec2.yaml --stack-name t101 --parameter-overrides KeyName=$MYKEYNAME SgIngressSshCidr=$(curl -s ipinfo.io/ip)/32 --region ap-northeast-2

# [모니터링] CloudFormation 스택 상태
while true; do 
  date
  AWS_PAGER="" aws cloudformation list-stacks \
    --stack-status-filter CREATE_IN_PROGRESS CREATE_COMPLETE CREATE_FAILED DELETE_IN_PROGRESS DELETE_FAILED \
    --query "StackSummaries[*].{StackName:StackName, StackStatus:StackStatus}" \
    --output table
  sleep 1
done

# EC2 공인 IP 확인
aws cloudformation describe-stacks --stack-name t101 --query 'Stacks[*].Outputs[0].OutputValue' --output text

 

AWS EC2 SSH 접속 : 기본 정보 확인

# ubuntu EC2에 SSH 접속
ssh -i ~/.ssh/kp-gasida.pem ubuntu@$(aws cloudformation describe-stacks --stack-name t101 --query 'Stacks[*].Outputs[0].OutputValue' --output text)
---------------------------
# 계정 확인
whoami

# aws 자격증명 설정 : (옵션) IAM profile로 설정 -> 단 이경우 tf 파일에 설정 필요
aws --version
aws configure
AWS Access Key ID [None]: ####
AWS Secret Access Key [None]: ####
Default region name [None]: ap-northeast-2
Default output format [None]: 

# aws 자격증명 확인
aws s3 ls

# 테라폼 버전 확인
terraform version

#
git version

#
ls -l
./atlantis version

 

 

공인 IP 혹은 도메인 노출 설정

Atlantis needs to be accessible somewhere that github.com/gitlab.com/bitbucket.org or your GitHub/GitLab Enterprise installation can reach.

One way to accomplish this is with ngrok, a tool that forwards your local port to a random public hostname.

# URL 변수 지정
URL="http://$(curl -s ipinfo.io/ip):4141"
echo $URL

 

 

Git Repo (Private) 생성

Git Token 생성

Github → Settings → Developer settings ⇒ Personal access tokens : Tokens (classic) ← Repo 제한 가능 Fine-grained tokens 사용 권장

환경변수 세팅

TOKEN="ghp_XXXXXXXXXXXXXXXXXXXXXXXXXX"

 

[권장] Create a webhook secret so Atlantis can validate webhooks - See Creating a Webhook Secret

Webhook secrets are actually optional. However they're highly recommended for security.

Atlantis uses Webhook secrets to validate that the webhooks it receives from your Git host are legitimate.

One way to confirm this would be to allowlist requests to only come from the IPs of your Git host but an easier way is to use a Webhook Secret.

Generating A Webhook Secret

You can use any random string generator to create your Webhook secret. It should be > 24 characters.

For example:

 

Create a Webhook Secret

 

GitHub and GitLab use webhook secrets so clients can verify that the webhooks came from them.

# Create a random string of any length (you can use random.org) and set an environment variable:
SECRET="XXXXXXXXXXXXXXXXX"

 

Create a Webhook Secret

 

Take the URL that ngrok output and create a webhook in your GitHub, GitLab or Bitbucket repo:

GitHub or GitHub Enterprise Webhook

서버 정상 실행 후

 

Start Atlantis

You're almost ready to start Atlantis, just set two more variables:

USERNAME="{the username of your GitHub, GitLab or Bitbucket user}"
REPO_ALLOWLIST="$YOUR_GIT_HOST/$YOUR_USERNAME/$YOUR_REPO"
# ex. REPO_ALLOWLIST="github.com/runatlantis/atlantis"
# If you're using Bitbucket Server, $YOUR_GIT_HOST will be the domain name of your
# server without scheme or port and $YOUR_USERNAME will be the name of the **project** the repo
# is under, **not the key** of the project.

 

Now you can start Atlantis. The exact command differs depending on your Git host:

#
URL="http://$(curl -s ipinfo.io/ip):4141"
USERNAME=###
TOKEN='###'
SECRET='###'
REPO_ALLOWLIST="github.com/###/t101-cicd"

# 변수 설정 확인
echo $URL $USERNAME $TOKEN $SECRET $REPO_ALLOWLIST

# Atlantis 서버 실행
./atlantis server \
--atlantis-url="$URL" \
--gh-user="$USERNAME" \
--gh-token="$TOKEN" \
--gh-webhook-secret="$SECRET" \
--repo-allowlist="$REPO_ALLOWLIST"

# [신규 터미널] 기본 tcp 4141 포트 오픈
ss -tnlp
State      Recv-Q     Send-Q         Local Address:Port         Peer Address:Port    Process                                       
LISTEN     0          4096                       *:4141                    *:*        users:(("atlantis",pid=2089,fd=7))
...

# 웹 접속 확인
URL="http://$(curl -s ipinfo.io/ip):4141"
echo $URL
http://54.180.226.134:4141

 

 

 

Local 에서 Git 코드 작업

# git clone
git clone https://github.com/$USERNAME/t101-cicd && cd t101-cicd && tree

# feature branch 생성
git branch test && git checkout test && git branch

# main.tf 파일 작성
echo 'resource "null_resource" "example" {}' > main.tf

# add commit push
git add main.tf && git commit -m "add main.tf" && git push origin test

 

 

Github(Create a pull request) → Atlantis 확인

  • [신규 터미널] 서버 모니터링
watch -d tree .atlantis/

 

  • Compare & pull request 클릭

  • Create pull request : title ( create null resource )

 

  • Plan 자동 수행 확인 → 하단 plan Details 클릭 확인

 

  • Lock 상태 일 경우

  • 서버 모니터링
# terraform plan 수행 결과 파일 확인
watch -d tree .atlantis/
.atlantis/
├── atlantis.db
├── bin
├── plugin-cache
│   └── registry.terraform.io
│       └── hashicorp
│           └── null
│               └── 3.2.2
│                   └── linux_amd64
│                       └── terraform-provider-null_v3.2.2_x5
└── repos
    └── gasida
        └── t101-cicd
            └── 1
                └── default
                    ├── README.md
                    ├── default.tfplan
                    └── main.tf

# Github Repo 코드를 가져 온 것을 확인
cat .atlantis/repos/$USERNAME/t101-cicd/1/default/main.tf

 

  • Add a comment ⇒ apply 결과 화면 확인
# 
atlantis plan -d .
atlantis apply -d .

 

 

  • Merge pull request → Confirm merge
# repos 에서 디렉터리 삭제
watch -d tree .atlantis/
.atlantis/
├── atlantis.db
├── bin
├── plugin-cache
│   └── registry.terraform.io
│       └── hashicorp
│           └── null
│               └── 3.2.2
│                   └── linux_amd64
│                       └── terraform-provider-null_v3.2.2_x5
└── repos
    └── gasida
        └── t101-cicd

 

  • 웹 확인

 

 

  • Local Git
#
git checkout main
ls
git pull
ls
cat main.tf

 

 

 

Atlantis : Autoplan, Manual Plan, Apply

 

Create a pull request so you can test Atlantis.

# [TIP] You could add a null resource as a test:
resource "null_resource" "example" {}

# Or just modify the whitespace in a file.

 

Autoplan

You should see Atlantis logging about receiving the webhook and you should see the output of terraform plan on your repo.

Atlantis tries to figure out the directory to plan in based on the files modified.

If you need to customize the directories that Atlantis runs in or the commands it runs if you're using workspaces or .tfvars files, see atlantis.yaml Reference.

 

Manual Plan

To manually plan in a specific directory or workspace, comment on the pull request using the -d or -w flags:

 

atlantis plan -d mydir   # 디렉터리
atlantis plan -w staging # 워크스페이스

 

To add additional arguments to the underlying terraform plan you can use:

atlantis plan -- -target=resource -var 'foo=bar'

 

Apply

If you'd like to apply, type a comment: atlantis apply. You can use the -d or -w flags to point Atlantis at a specific plan.

Otherwise it tries to apply the plan for the root directory.

'T101 study' 카테고리의 다른 글

[8주차] OpenTofu  (0) 2024.08.03
[7주차] 테라폼으로 AWS EKS 배포  (0) 2024.07.27
[4주차] Provider & State  (0) 2024.06.30
[3주차] 기본 사용 3/3  (0) 2024.06.29
[2주차] 기본 사용 2/3  (0) 2024.06.22
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함