📌 Notice
본 블로깅은 아래의
24단계 실습으로 정복하는 쿠버네티스
책을 기준하여 정리하였습니다.출처 - 한빛출판네트워크
CloudNetaStudy
그룹에서 스터디한 내용입니다.
Hashicorp korea유형욱
님과 함께 스터디 하고 있습니다. 🙏
유형욱
님과윤서율
님께 다시한번 🙇 감사드립니다.
IaC와 테라폼을 이해하고 스터디에 필요한 실습 환경을 구성합니다.
테라폼 기본 명령 사용법을 알아봅니다.
HCL을 이해하고 기본 활용 방법을 학습합니다.
샘플코드 작성 및 배포를 실습합니다.
스터디에서 7.1~7.2 Git 관련 내용을 학습하였지만, Git을 사용한 개발환경에서는 기본적으로 숙지해야 하는 내용이므로 해당 블로그에서는 다루지 않습니다.
State 백엔드 소개
구성 목적(3가지)
7.3.1 Terraform Cloud (TFC) 백엔드
하시코프에서 프로비저닝 대상과 별개로 State를 관리할 수 있도록 SaaS 환경인 TFC를 제공하며 State 관리 기능은 무상을 제공 → 기존 Terraform CE 사용자가 가장 좋아하는 기능
HashiCorp Terraform: Enterprise Pricing, Packages & Features
- 제공 기능 : 기본 기능 무료, State 히스토리 관리, State lock 기본 제공, State 변경에 대한 비교 기능
- Free Plan 업데이트 : 사용자 5명 → 리소스 500개, 보안 기능(SSO, Sentinel/OPA로 Policy 사용) - 링크
테라폼 클라우드 가격정책 - [참고: Pricing, Feature]
- Free : 리소스 500개 까지 무료 → 커뮤니티 버전
- Standard : Free + 워크플로우 기능 추가 + 동시실행(Concurrency 개수 3개)
- Plus : 정책, 보안, 신뢰성, 확장성 등 기업형 고객에게 적합(대규모 사용자를 위한 비용모델)
- Enterprise : Plus와 대부분 유사하며 설치형 모델
개인 워크플로
개인이 테라폼으로 일하는 방식의 예
- Write : 프로비저닝하려는 목적에 따라 테라폼 코드를 작성
- 개인 작업이더라도 반복적인 사용성을 고려하자.
- 인수에 할당되는 값을 입력 변수화하고 반복적인 구조가 발생하는 경우 리소스 단위별로 반복문을 사용할지 다수의 리소스를 모듈화할지 결정한다.
- Plan : 적용하기 위한 실행 계획을 통해 리뷰
- 테라폼의 Plan뿐 아니라, terraform fmt를 통해 코드 형태를 포멧팅하고 변경되는 리소스를 리뷰한다.
- 또한 테라폼과 함께 동작하는 tfsec이나 terrascan 같은 보안 취약성 점검 툴 등을 활용하는 것도 좋은 방안이다.
- Apply : 코드로 실제 인프라를 프로비저닝
- 실행 계획상으로는 정상이지만 실제 프로비저닝하는 단계에서 인수 값, 생성 순서, 종속성에 따라 오류가 발생할 수 있다.
- 성공적인 완료를 위해 Write > Plan > Apply 단계를 반복하고 성공하는 경우 코드 관리를 위해 VCS에 코드를 병합한다.
다중 작업자 워크플로
- Write
- 여러 작업자의 테라폼 코드가 충돌하지 않도록 VCS와 같은 형상관리 도구에 익숙해져야 한다.
- 작업자는 작업 전에 미리 원격 저장소의 코드를 받고 깃에서는 브랜치를 활용해 개별적으로 작업한다.
- 개인의 워크플로에서 고려한 변수화와 더불어 패스워드와 인증서 같은 민감 데이터가 포함되지 않도록 코드를 설계한다.
- 또한 개인 작업 환경에서만 사용되는 변수는 공유하지 않는다.
- 깃을 사용한다면 작업자 개인의 변수는 terraform.tfvars 에 선언하고 .gitignore에 추가해 개별적으로 테스트할 수 있는 환경을 구성할 수 있다
- 이 단계에서 개별 작업자는 작은 단위의 개별 워크플로(Write > Plan > Apply)를 반복해야 한다.
- 개별 작업 환경과 별개로 병합되는 코드가 실제 운영 중인 인프라에 즉시 반영되면 실행 후 발생할 오류 예측이 어려워 부담이 될 수 있다.
- 이를 보완하기 위해 프로비저닝 대상의 환경을 검증과 운영, 또는 그 이상의 환경으로 구성 가능하도록 구조화한다.
- 이때 사용하는 방식은 디렉터리 기반 격리와 깃 기반의 브랜치 격리다.
- Plan
- 둘 이상의 작업자는 프로비저닝 이전에 팀원 간 리뷰를 거쳐 변경된 내역을 확인하고 공통 저장소에 병합해야 한다.
- 리뷰 단계에서는 추가, 삭제, 수정된 내역을 관련 작업자가 검증, 질의, 배움의 단계를 거쳐 복기함으로써 코드 상태를 개선 유지하고 작업자 간에 의도를 공유한다.
- 코드 자체 외에도 테라폼의 Plan 결과를 풀 리퀘스트 단계에 같이 제공하면 영향을 받는 리소스와 서비스 중단에 대한 예측이 더 쉬워진다.
- CI 툴과 연계하거나 Terraform Cloud/Enterprise의 VCS 통합 기능으로 자동화할 수 있다.
- Apply
- 코드가 최종 병합되면 인프라 변경이 수행됨을 알리고 변경되는 대상 환경의 중요도에 따라 승인이 필요할 수 있다.
- 또한 변경하는 코드가 특정 기능, 버그 픽스, 최종 릴리즈를 위한 병합인가에 따라 이 단계에 추가로 코드 병합이 발생할 수 있다.
- 관리하는 단위를 나누는 기준은 조직 R&R, 서비스, 인프라 종류 등으로 구분된다.
다수 팀의 워크플로
R&R이 분리된 다수 팀 또는 조직의 경우
- R&R이 분리된 다수 팀 또는 조직의 경우 테라폼의 프로비저닝 대상은 하나이지만 관리하는 리소스가 분리된다.
- 단일 팀의 워크플로가 유지되고 그 결과에 대해 공유해야 하는 핵심 워크플로가 필요하다.
- Write
- 대상 리소스가 하나의 모듈에서 관리되지 않고 R&R에 의해 워크스페이스가 분리된다.
- 서로 다른 워크스페이스에서 구성된 리소스 데이터를 권한이 다른 팀에게 공유하기 위해, 저장된 State 접근 권한을 제공하고 output을 통해 공유 대상 데이터를 노출한다.
- 테라폼 코드 작성 시 다른 워크스페이스에서의 변경 사항을 데이터 소스로 받아 오는 terraform_remote_state 또는 별도 KV-store를 활용하는 코드 구성이 요구된다.
- 또한 관리 주체가 다른 곳에서 생긴 변경 사항의 영향을 최소화하도록 리모트 데이터 소스의 기본값을 정의하거나 코드적인 보상 로직을 구현하는 작업이 필요하다.
- Plan
- 코드 기반으로 진행되는 리뷰는 반영되는 다른 팀의 인프라를 VCS상의 코드 리뷰만으로도 공유받고 영향도를 검토할 수 있다.
- 병합을 승인하는 단계에 영향을 받는 다른 팀의 작업자도 참여해야 한다.
- Apply
- 프로비저닝 실행과 결과에 대한 안내가 관련 팀에 알려져야 하므로 파이프라인 구조에서 자동화하는 것을 추천한다.
- 실행 후의 영향도가 여러 팀이 관리하는 리소스에 전파될 수 있으므로 코드 롤백 훈련이 필요하다.
- 생성된 결과에 다른 워크스페이스에서 참조되는 output 값의 업데이트된 내용을 다른 팀이 확인하는 권한 관리가 필요하다
테라폼 수준의 격리 목표
: State를 분리
테라폼은 파일이나 하위 모듈로 구분하더라고 동작 기준은 실행하는 루트 모듈에서 코드를 통합하고 하나의 State로 관리한다.
애플리케이션 구조가 모놀리식(+아키텍처)에서 MSA로 변화하는 과정은 테라폼의 IaC 특성과도 결부된다.
테라폼 또한 사용하는 리소스가 적고 구조가 단순하면 모놀리식 방식으로 구성하는 것이 인프라 프로비저닝 구축 속도는 빠를 수 있다.
하지만 유지 보수, 인수인계, 운영의 관점에서는 프로비저닝 단위별로 분류하는, 마치 MSA와도 같은 분산된 설계가 매몰 비용과 기술 부채를 줄이는 데 효과적이다.
규모가 큰 워크플로를 만들기 위해서는 간단하고 조합 가능한 부분들이 모여 집합을 이루어야 한다.
이러한 집합에서 발생하는 정보는 다른 집합과 교환할 수 있지만, 각 집합은 독립적으로 실행되며 다른 집합에 영향을 받지 않는 격리된 구조가 필요하다.
초기 테라폼 적용 단계에서 단일 또는 소수의 작업자는 단일 대상에 대해 IaC를 적용하고 하나의 루트 모듈에 많은 기능을 포함시킬 가능성이 높다.
루트 모듈 격리(파일/디렉터리)
- 단일 작업자가 테라폼으로 프로비저닝을 하는 많은 경우에 관리 편의성 및 배포 단순화를 위해 하나의 루트 디렉터리에 파일로 리소스들을 구분하거나, 디렉터리를 생성하고 하위에 구성 파일 묶음을 위치시켜 루트 모듈에서 하위 디렉터리를 모듈로 읽는 구조를 사용한다.
- 작업자가 관리하는 영역 또는 프로비저닝되는 리소스 묶음의 독립적인 실행을 위해 단일 루트 모듈 내의 리소스를 다수의 루트 모듈로 분리하고 각 모듈의 State를 참조하도록 격리한다.
- 관리적인 측면으로는 작업자들의 관리 영역을 분리시키고 깃 기준의 리모트 저장소도 접근 권한을 관리할 수 있다.
- 협업과 관련해 작업자별로 특정 루트 모듈을 선정해 구성 작업을 진행해 코드 충돌을 최소화하는 환경을 구성하고 인수인계 과정에서 리뷰하는 영역을 최소화할 수 있다.
목표
- 아래 깃허브 저장소를 복제해 아래 조건에 만족하는 코드를 작성
https://github.com/terraform101/terraform-aws-collaboration
조건
Workspace 이름 : terraform-edu-part1-assessment
실행 모드는 local
AWS 공통 Tag : Project = “workshop”
aws_instance는 반복문을 사용해 3개 구성
EIP를 제거하고 EC2에서 public ip를 자체 사용하도록 구성
placeholder 변수는 아래 3가지가 각각의 aws_instance에 적용되도록 구성
placekitten.com
placebear.com
placedog.net
1. TFC State 벡엔드 구성
별도의 워크스페이스를 생성하여 백엔드를 위한 리소스를 별도 생성합니다.
워크 스페이스 생성시 프로젝트에 반영할 수 있도록 가이드가 표시됩니다.
테라폼 작업을 Local에서 할 수 있도록 환경설정을 완료합니다.
2. AWS 공통 Tag : Project = "workshop"
프로바이더 항목에서 공통 태그를 선언하여 전체 리소스에 할당 할 수 있습니다.
provider "aws" { region = var.region default_tags { tags = { Project = "workshop" } } }
3. aws_instance 반복문 사용해 3개 구성
변수 placeholder의 개수만큼 ec2가 생성하고자 하므로 for_each 구문을 통해 변수(배열)에 할당된 값 만큼 반복하도록 하는 소스코드를 작성합니다.
resource "aws_instance" "hashicat" { for_each = toset(var.placeholder) ami = data.aws_ami.ubuntu.id instance_type = var.instance_type key_name = aws_key_pair.hashicat.key_name associate_public_ip_address = true subnet_id = aws_subnet.hashicat.id vpc_security_group_ids = [aws_security_group.hashicat.id] tags = { Name = "${var.prefix}-hashicat-instance" } }
4. EIP를 제거하고 EC2에서 public ip를 자체 사용하도록 구성
기존 소스코드에서 선언된 EIP 관련 소스코드를 삭제하여 EC2의 자체 Public ip를 사용하도록 구성합니다.
resource "aws_eip" "hashicat" { instance = aws_instance.hashicat.id vpc = true } resource "aws_eip_association" "hashicat" { instance_id = aws_instance.hashicat.id allocation_id = aws_eip.hashicat.id }
5. placeholder 변수 각각 적용 구성
variables.tf
인덱스에 따라 다른 변수가 선언 되어야 하므로 배열을 사용하여 변수를 선언합니다.variable "placeholder" { default = [ "placekitten.com", "placebear.com", "placedog.net" ] }
main.tf
선언된 변수를 사용하여 ec2의 count에 따라 다른 변수가 선언될 수 있도록 설정합니다.provisioner "remote-exec" { inline = [ "sudo apt -y update", "sleep 15", "sudo apt -y update", "sudo apt -y install apache2", "sudo systemctl start apache2", "sudo chown -R ubuntu:ubuntu /var/www/html", "chmod +x *.sh", "PLACEHOLDER=${var.placeholder[count.index]} WIDTH=${var.width} HEIGHT=${var.height} PREFIX=${var.prefix} ./deploy_app.sh", "sudo apt -y install cowsay", "cowsay Mooooooooooo!", ]