서론
- 프로덕션 수준 인프라 구축은 어렵다. 여기서 말하는 인프라란 서버, 데이터 저장소, 로드 밸런서, 보안 기능, 모니터링 및 경고 도구, 파이프라인 구축 및 비즈니스 운영에 필요한 기타 모든 기술을 의미한다.
- 매니지드 서비스를 사용하더라도 작업은 꽤 오래걸리며 깊은 전문성을 갖춘 인력이 팀에 없거나, 끌려다녀 집중할 시간을 갖지 못한다면 시간은 훨씬 더 오래 걸릴 수 있다.
1. 프로덕션 수준 인프라 구축에 오랜 시간이 걸리는 이유
호프스태터의 법칙
- “호프스태터의 법칙을 계산에 넣어도 항상 예상한 것보다 더 오래 걸린다.”
- SW 프로젝트에 걸리는 시간 추정치는 아주 부정확하다.
- 데브옵스 프로젝트에는 예상 시간보다 2배가 더 소요될 수 있다.
1.1. 데브옵스 산업이 아직 초기 단계이다
- 테라폼, 도커, 패커 및 쿠버네티스와 같은 도구가 모두 2010년 중반 혹은 중반에 출시되었으며 계속 빠르게 변하고 있다.
1.2 야크 털 깎기에 취약하다
- 야크 털 깎기
- 원래 하고 싶었던 작업을 수행하기 전 해야하는 하찮고, 겉으로 볼때는 관련 없는 작업들.
- 예
- 앱을 배포하는데 갑자기 TLS 인증서 문제가 발생하는 경우
1.3 본질적인 복잡성
- 우발적인 복잡성
- 알고리즘 작성하는데 메모리 할당 버그를 처리하는 것
- 본질적인 복잡성
- 본질적인 문제 (언어, 환경과 상관 없음)
본질적인 복잡성을 평가할 때 시간이 많이 걸리는 세부 사항을 잊어먹는다.
2. 프로덕션 수준 인프라 체크 리스트
- 모든 항목이 인프라에 필요하지는 않지만 어떤 항목을 구현했는지, 어떤 항목을 건너 뛰기로 결정했는지, 그 이유는 무엇인지를 의식적으로 명시적으로 문서화해야한다
3. 프로덕션 수준 인프라 모듈
3.1 소형 모듈
모든 인프라를 단일 파일 또는 단일 모듈러 정의하는 대형 모듈의 단점
- 속도가 느림
- plan 이 5~6분이상 걸리는 등 명령 실행에 걸리는 시간이 오래 걸린다.
- 안전하지 않음
- 취소 권한 원칙에 위배.
- 위험성이 높음
- 달걀을 한 바구니에 담는 행위임으로 전부 깨질 수 있다.
- 스테이징 변경사항이 프로덕션에 반영되는 건 이상핟,
- 이해하기 어려움
- 코드가 한 곳에 뭉쳐있으면 이해하기 어렵다.
- 리뷰하기 어려움
- 4번과 연결되는데 수천 글의 코드로 구성된 모듈 리뷰는 거의 불가능함
- 테스트하기 어려움
- 많은 양의 인프라 코드를 테스트하는 것은 거의 불가능
로버트 C. 마틴 “함수는 작게” → 인프라도 모두 모듈로 나누자
로버트 C.마틴 “함수의 첫 번째 규칙은 작아야 한다는 것입니다. 함수의 두 번째 규칙은 그보다 더 작아야 한다는 것입니다.”
3.2 합성 가능한 모듈
- 재사용 가능하고 합성 가능한 모듈(composable module)을 구축하자
- 유닉스 도구 개발자 더그 매클로이 “한 가지 일을 잘 해내는 프로그램을 여러 개 작성하세요. 그리고 그 프로그램이 함께 작동하게 하세요. 이것이 바로 유닉스 철학입니다.
- 함수 합성 방식을 적용
- add, sub 을 구현해 calculation 내부에서 사용하는 것
- 모듈 2개로 구분한다
- Generic module
- alb, asg-rolling-deploy 같은 코드의 기본 구성 요소며 재사용할 수 있는 것
- 사용 사례별 모듈
- 특정 앱같이 여러 개의 일반 모듈을 결합하여 앱을 배포하는 경우
- Generic module
3.3 테스트 가능한 모듈
- 수동 테스트 장치
- apply, destory 실행하여 반복적으로 배포, 최소함으로써 작동 테스트
- 자동화된 테스트 장치
- 모듈에 대한 자동화 테스트 작성
- 실행 가능한 문서
- README 등 팀의 다른 구성원이 이를 찾아서 모듈 작동 방식을 이해하여 모듈 고체할 수 있다.
디렉토리
- modules/modules
- modules/examples: 예제
- modules/test: 테스트
버전 고정하자
- 시멘틱 버전 특성이 그대로 나타난다. 공급자 버전을 고정하는 것을 권장한다
- version = “~> 2.0”
- 공급자에 따라 다르다. 신뢰할 수 있는 공급자라면 더 유연하게 관리?
3.4 릴리스 가능한 모듈
1. 깃을 이용
module "{module}" {
source = "github.com/brikis98/terraform-up-and-running-code//code/terraform/04-terraform-module/module-example/modules/services/webserver-cluster?ref=v0.1.0"
...
- 모듈 url과 버전을 명시
2. 테라폼 레지스트리
- 테라폼 엔터프라이즈면 개인 깃 레포르 사용할 수 있다.
- 요구사항이 있으니 주의하자
- 모듈이 공개 깃허브 리포지토리에 있어야 한다.
- 리포지토리 이름은 terraform-<PROVIDER>-<NAME> 과 같은 형태로 부여해야 한다.
- provider → AWS 와 같은 공급자 이름
- name → vault 와 같은 모듈 이름
- 모듈은 리포지토리의 루트에 테라폼 코드를 정의하고 README.md를 제공하고, main.tf, variables.tf, output.tf 규칙을 파일 이름으로 사용하는 것을 포함하는 지정된 파일 구조르 따라야 합니다.
- 시멘틱 버전과 함께 깃 태그를 사용해야 합니다.
3.5 테라폼 모듈을 넘어서
테라폼 모듈 폴더에는 비테라폼 코드가 포함될 수 있다
- 부팅에 필요한 배시 스크립트
- 테라폼의 한계 극복할 수 있는 비상구
프로비저너
- 테라폼 실행할 때 부트스트랩, 구성 관리 또는 정리 작업을 수행하기 위해 로컬 시스템이나 원격 시스템에서 스크립트를 실행하는데 사용된다
- provisioner 블록을 사용한다.
- 종류
- local-exec: 로컬 시스템에서 실행
- remote-exec: 원격 리소스에서 실행
- 예
- 원격 리소스로 파일을 복사하는 file 등
- 기타 키워드
- 기본적으로는 creation-time 프로비저너이다.
- when=”destory” 인수 설정하면 destory-time 프로비저너가 된다. (desyory 실행 후 리소스 삭제 전 실행)
- on_failure 사용해 오류 처리할 수 있음 → continue: 오류 무시, abort: 중단
local-exec 예시
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
provisioner "local-exec" {
command = "echo \\"Hello, World from $(uname -smp)\\""
}
}
remote-exec 예시
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.instance.id]
key_name = aws_key_pair.generated_key.key_name
provisioner "remote-exec" {
inline = ["echo \\"Hello, World from $(uname -smp)\\""]
}
connection {
type = "ssh"
host = self.public_ip
user = "ubuntu"
private_key = tls_private_key.example.private_key_pem
}
}
- 네트워크를 통해 EC2인스턴스와 통신하고 SSH 구성한다.
null_resource 이용해서 실제 리소스에 연결하지 않는 프로비저너
resource "null_resource" "example" {
# Use UUID to force this null_resource to be recreated on every
# call to 'terraform apply'
triggers = {
uuid = uuid()
}
provisioner "local-exec" {
command = "echo \\"Hello, World from $(uname -smp)\\""
}
}
외부 데이터 소스 사용하는 프로토콜
data "external" "echo" {
program = ["bash", "-c", "cat /dev/stdin"]
query = {
foo = "bar"
}
}
output "echo" {
value = data.external.echo.result
}
output "echo_foo" {
value = data.external.echo.result.foo
}
- 배시에 의존하는 코드여서 조심해야함. → 윈도우에서 배포 불가능.
결론
- 인프라 체크리스트를 통해 건너뛸 항목을 명시적으로 구분하자.
- 예제 코드와 테스트 코드를 작성하자.
- 버전은 최대한 고정하자.
- external 데이터 소스, 다른 비상구를 사용하면 코드 이식성이 저하되고 코드를 불안정하게 만들기 때문에 신중하게 사용하자
'DevOps > Terraform' 카테고리의 다른 글
[Terraform] 테라폼의 팁과 요령: 반복문, if문, 배포 및 주의사항 (0) | 2023.04.02 |
---|---|
[Terraform] 테라폼의 팁과 요령: 반복문 (0) | 2023.03.27 |
댓글