Terraform 대 CloudFormation: 최종 가이드
게시 됨: 2022-03-11저처럼 인터넷을 뒤져 다음 IaC(Infrastructure-as-code) 도구로 CloudFormation과 Terraform 중에서 선택하는 데 도움이 되는 확실한 답을 찾지 못한 경우, 저는 오랫동안 고통을 공유했습니다. 이제 두 도구 모두에 상당한 경험이 있으며 어느 도구를 사용할지 정보에 입각한 결정을 내릴 수 있습니다.
TL;DR
AWS의 IaC 프로젝트의 경우 다음과 같은 이유로 CloudFormation을 선택합니다.
- CloudFormation은 코드(즉, 템플릿)와 코드의 인스턴스화(즉, 스택)를 구분합니다. Terraform에서는 그러한 구분이 없습니다. 다음 섹션에서 이에 대해 자세히 설명합니다.
- Terraform은 기본 종속성 관리를 잘 처리하지 않습니다. 이후 섹션에서 더 자세히 설명합니다.
코드와 인스턴스화 구별하기
CloudFormation과 Terraform의 한 가지 차이점은 코드와 인스턴스화가 각 서비스 내에서 서로 관련되는 방식입니다.
CloudFormation에는 템플릿의 인스턴스화인 스택 개념이 있습니다. 동일한 템플릿은 지정된 계정의 지정된 클라이언트, 여러 계정 또는 다른 클라이언트에 의해 무한대 로 인스턴스화될 수 있습니다.
Terraform에는 그러한 개념이 없으며 코드와 해당 인스턴스화 간의 일대일 관계가 필요합니다. 실행하려는 서버마다 웹 서버의 소스 코드를 복제하거나 컴파일된 버전을 실행하는 대신 응용 프로그램을 실행해야 할 때마다 코드를 복제하는 것과 비슷합니다.
이 점은 간단한 설정의 경우 매우 사소하지만 중대형 운영의 경우 금세 주요 골칫거리가 됩니다. Terraform에서는 기존 코드에서 새 스택을 실행해야 할 때마다 코드를 복제해야 합니다. 스크립트 파일을 복사/붙여넣기하는 것은 자신을 방해하고 의도하지 않은 리소스를 손상시키는 매우 쉬운 방법입니다.
Terraform에는 실제로 CloudFormation과 같은 스택 개념이 없습니다. 이는 Terraform이 처음부터 코드와 코드가 관리하는 리소스 간에 일대일 일치를 갖도록 구축되었음을 분명히 보여줍니다. 이것은 나중에 환경 개념(이후 "작업 공간"으로 이름이 변경됨)에 의해 부분적으로 수정되었지만, 이를 사용하는 방법은 원치 않는 환경에 배포하기가 엄청나게 쉽습니다. 이는 배포하기 전에 terraform workspace select
을 실행해야 하고 이 단계를 잊어버리면 이전에 선택한 작업 공간에 배포되기 때문입니다.
실제로 이 문제는 Terraform 모듈을 사용하여 완화되는 것이 사실이지만 최상의 경우에도 상당한 양의 상용구 코드가 필요합니다. 사실, 이 문제는 너무 심각해서 사람들이 이 문제를 해결하기 위해 Terraform 주변에 래퍼 도구인 Terragrunt를 만들어야 했습니다.
상태 관리 및 권한
CloudFormation과 Terraform의 또 다른 중요한 차이점은 각각 상태와 권한을 관리하는 방식입니다.
CloudFormation은 스택 상태를 관리하며 어떠한 옵션도 제공하지 않습니다. 그러나 CloudFormation 스택 상태는 내 경험상 견고했습니다. 또한 CloudFormation을 사용하면 권한이 낮은 사용자가 스택 자체에 필요한 모든 권한 없이도 스택을 관리할 수 있습니다. CloudFormation은 스택 작업을 실행하는 사용자의 권한이 아니라 스택에 연결된 서비스 역할의 권한을 얻을 수 있기 때문입니다.
Terraform은 상태를 관리하기 위해 일부 백엔드를 제공해야 합니다. 기본값은 다음과 같이 완전히 만족스럽지 않은 로컬 파일입니다.
- 상태 파일의 견고성은 파일이 저장된 시스템의 견고성과 완전히 연결됩니다.
- 이는 팀워크를 거의 불가능하게 만듭니다.
따라서 AWS에서는 일반적으로 S3 버킷을 사용하여 상태 파일을 저장하고 동시성을 처리하는 DynamoDB 테이블을 사용하여 이를 달성하는 강력한 공유 상태가 필요합니다.
즉, 인스턴스화하려는 각 스택에 대해 수동으로 S3 버킷과 DynamoDB 테이블을 생성하고 이러한 두 객체에 대한 권한을 수동으로 관리하여 권한이 낮은 사용자가 액세스해서는 안 되는 데이터에 액세스하지 못하도록 제한해야 합니다. 스택이 몇 개뿐이라면 큰 문제가 되지 않지만 관리해야 할 스택이 20개라면 매우 번거로워집니다.
그건 그렇고, Terraform 작업 공간을 사용할 때 작업 공간당 하나의 DynamoDB 테이블을 가질 수는 없습니다. 즉, 배포를 수행할 수 있는 최소 권한을 가진 IAM 사용자를 원하는 경우 DynamoDB 권한이 항목 수준으로 세분화되지 않기 때문에 해당 사용자는 모든 작업 공간의 잠금을 조작할 수 있습니다.
종속성 관리
이 점에서 CloudFormation과 Terraform은 모두 약간 까다로울 수 있습니다. 리소스의 논리적 ID(예: 이름)를 변경하면 둘 다 이전 리소스를 삭제하고 새 리소스를 생성해야 한다고 간주합니다. 따라서 일반적으로 두 도구, 특히 CloudFormation의 중첩 스택에서 리소스의 논리적 ID를 변경하는 것은 좋지 않습니다.
첫 번째 섹션에서 언급했듯이 Terraform은 기본 종속성을 처리하지 않습니다. 불행히도 Terraform 개발자는 해결 방법의 명백한 부족에도 불구하고 오랜 문제에 많은 관심을 기울이지 않습니다.
적절한 종속성 관리가 IaC 도구에 절대적으로 중요하다는 점을 감안할 때 Terraform의 이러한 문제는 프로덕션 환경에 배포하는 것과 같은 비즈니스 크리티컬 작업이 관련된 즉시 적합성에 의문을 제기합니다. CloudFormation은 훨씬 더 전문적인 느낌을 제공하며 AWS는 항상 고객에게 프로덕션 수준의 도구를 제공하는 데 매우 세심한 주의를 기울입니다. CloudFormation을 사용해 온 수년 동안 저는 종속성 관리에 문제를 본 적이 없습니다.
CloudFormation을 사용하면 스택에서 일부 출력 변수를 내보낼 수 있으며, 이 변수는 다른 스택에서 재사용할 수 있습니다. 솔직히 말해서 이 기능은 지역당 둘 이상의 스택을 인스턴스화할 수 없으므로 제한적입니다. 이름이 같은 두 개의 변수를 내보낼 수 없고 내보낸 변수에 네임스페이스가 없기 때문입니다.
Terraform은 그러한 시설을 제공하지 않으므로 덜 바람직한 옵션이 남아 있습니다. Terraform을 사용하면 다른 스택의 상태를 가져올 수 있지만 상태에 저장된 많은 비밀을 포함하여 해당 스택의 모든 정보에 액세스할 수 있습니다. 또는 스택이 S3 버킷에 저장된 JSON 파일 형식으로 일부 변수를 내보낼 수 있지만 이 옵션은 더 번거롭습니다. 사용할 S3 버킷을 결정하고 적절한 권한을 부여하고 모든 작성자 측과 독자 측 모두에서 직접 코드를 작성하십시오.
Terraform의 한 가지 장점은 데이터 소스가 있다는 것입니다. 따라서 Terraform은 Terraform에서 관리하지 않는 리소스를 쿼리할 수 있습니다. 그러나 실제로는 대상 계정에 대해 아무 것도 가정하지 않기 때문에 일반 템플릿을 작성하려는 경우 관련성이 거의 없습니다. CloudFormation에서 이에 상응하는 것은 템플릿 매개변수를 더 추가하는 것이므로 반복과 오류 가능성이 있습니다. 그러나 내 경험상 이것은 결코 문제가 되지 않았습니다.
Terraform의 종속성 관리 문제로 돌아가서 또 다른 예는 로드 밸런서에 대한 설정을 업데이트하고 다음을 얻으려고 할 때 오류가 발생하는 것입니다.
Error: Error deleting Target Group: ResourceInUse: Target group 'arn:aws:elasticloadbalancing:us-east-1:723207552760:targetgroup/strategy-api-default-us-east-1/14a4277881e84797' is currently in use by a listener or a rule status code: 400, request id: 833d8475-f702-4e01-aa3a-d6fa0a141905
예상되는 동작은 Terraform이 대상 그룹이 삭제되지 않는 다른 리소스의 종속성을 감지하고 결과적으로 삭제를 시도해서는 안 되지만 오류가 발생해서는 안 된다는 것을 감지하는 것입니다.
운영
Terraform은 명령줄 도구이지만 매우 대화식이므로 사람이 실행할 것으로 예상합니다. 배치 모드(예: 스크립트에서)로 실행할 수 있지만 몇 가지 추가 명령줄 인수가 필요합니다. Terraform이 기본적으로 사람에 의해 실행되도록 개발되었다는 사실은 IaC 도구의 목적이 자동화라는 점을 감안할 때 상당히 당혹스럽습니다.
Terraform은 디버그하기 어렵습니다. 오류 메시지는 종종 매우 기본적이며 무엇이 잘못되고 있는지 이해하지 못하게 합니다. 이 경우 TF_LOG=debug
와 함께 Terraform을 실행해야 합니다. 그러면 트롤링할 엄청난 양의 출력이 생성됩니다. 이를 복잡하게 하는 것은 Terraform이 때때로 실패하는 AWS에 대한 API 호출을 수행하지만 실패는 Terraform의 문제가 아니라는 점입니다. 대조적으로 CloudFormation은 문제가 어디에 있는지 이해할 수 있도록 충분한 세부 정보와 함께 합리적으로 명확한 오류 메시지를 제공합니다.
Terraform 오류 메시지의 예:
Error: error reading S3 bucket Public Access Block: NoSuchBucket: The specified bucket does not exist status code: 404, request id: 19AAE641F0B4AC7F, host id: rZkgloKqxP2/a2F6BYrrkcJthba/FQM/DaZnj8EQq/5FactUctdREq8L3Xb6DgJmyKcpImipv4s=
위의 오류 메시지는 기본 문제(이 경우 권한 문제)를 실제로 반영하지 않는 명확한 오류 메시지를 보여줍니다.

이 오류 메시지는 또한 Terraform이 때때로 자신을 구석에 칠할 수 있는 방법을 보여줍니다. 예를 들어, 해당 버킷에 S3 버킷과 aws_s3_bucket_public_access_block
리소스를 생성하고 어떤 이유로든 해당 버킷을 파괴하는 Terraform 코드를 일부 변경하는 경우(예: 위에서 설명한 "변경은 삭제 및 생성을 의미합니다"에서) Terraform은 aws_s3_bucket_public_access_block
을 로드하려고 시도하지만 계속해서 위의 오류와 함께 실패합니다. Terraform의 올바른 동작은 aws_s3_bucket_public_access_block
을 적절하게 교체하거나 삭제하는 것입니다.
마지막으로 Terraform과 함께 CloudFormation 도우미 스크립트를 사용할 수 없습니다. 이는 특히 EC2 인스턴스가 자체 초기화를 완료하고 요청을 처리할 준비가 되었음을 CloudFormation에 알리는 cfn-signal을 사용하려는 경우 성가실 수 있습니다.
구문, 커뮤니티 및 롤백
구문 면에서 Terraform은 CloudFormation에 비해 루프를 지원하는 좋은 이점이 있습니다. 그러나 내 경험상 이 기능은 다소 위험할 수 있습니다. 일반적으로 루프는 동일한 리소스를 여러 개 만드는 데 사용됩니다. 그러나 스택을 다른 개수로 업데이트하려는 경우 이전 리소스와 새 리소스를 연결해야 할 수도 있습니다(예: zipmap()
을 사용하여 현재 발생하는 두 배열의 값을 결합합니다. 하나의 배열은 이전 루프 크기의 크기를 갖고 다른 배열은 새 루프 크기의 크기를 갖기 때문에 크기가 다릅니다. 이러한 문제가 루프 없이 발생할 수 있는 것은 사실이지만 루프가 없으면 스크립트를 작성하는 사람에게 문제가 훨씬 더 분명할 것입니다. 이러한 경우 루프를 사용하면 문제가 난독화됩니다.
Terraform의 구문 또는 CloudFormation의 구문이 더 나은지 여부는 대부분 기본 설정의 문제입니다. CloudFormation은 처음에 JSON만 지원했지만 JSON 템플릿은 읽기가 매우 어렵습니다. 다행히 CloudFormation은 훨씬 읽기 쉽고 주석을 허용하는 YAML도 지원합니다. 그러나 CloudFormation의 구문은 상당히 장황한 경향이 있습니다.
Terraform의 구문은 일종의 JSON 파생물이며 상당히 특이한 HCL을 사용합니다. Terraform은 CloudFormation보다 더 많은 기능을 제공하며 일반적으로 이해하기 쉽습니다. 따라서 Terraform이 이 점에서 약간의 이점이 있다고 주장할 수 있습니다.
Terraform의 또 다른 장점은 커뮤니티에서 유지 관리하는 모듈을 쉽게 사용할 수 있다는 점이며 이는 템플릿 작성을 단순화합니다. 한 가지 문제는 그러한 모듈이 조직의 요구 사항을 준수할 만큼 충분히 안전하지 않을 수 있다는 것입니다. 따라서 높은 수준의 보안이 필요한 조직의 경우 이러한 모듈(및 향후 추가 버전)을 검토하는 것이 필요할 수 있습니다.
일반적으로 Terraform 모듈은 CloudFormation 중첩 스택보다 훨씬 유연합니다. CloudFormation 중첩 스택은 그 아래에 있는 모든 것을 숨기는 경향이 있습니다. 중첩 스택에서 업데이트 작업은 중첩 스택이 업데이트됨을 보여주지만 중첩 스택 내에서 무슨 일이 일어날지는 자세히 보여주지 않습니다.
실제로 논쟁의 여지가 있을 수 있는 마지막 요점은 CloudFormation이 실패한 배포를 롤백하려고 시도한다는 것입니다. 이것은 상당히 흥미로운 기능이지만 불행히도 매우 길 수 있습니다(예: CloudFormation에서 Elastic Container Service에 대한 배포가 실패했다고 결정하는 데 최대 3시간이 걸릴 수 있음). 반대로, 오류가 발생하면 Terraform은 그 위치에서 그냥 멈춥니다. 롤백 기능이 좋은 것인지 아닌지는 논란의 여지가 있지만, 더 오래 기다려야 하는 상황에서 받아들일 수 있는 트레이드오프가 발생했을 때 스택이 가능한 한 작동 상태로 유지된다는 사실에 감사하게 되었습니다.
Terraform 대 CloudFormation 방어
Terraform은 CloudFormation보다 장점이 있습니다. 제 생각에 가장 중요한 것은 업데이트를 적용할 때 Terraform이 사용 중인 모든 모듈에 대한 드릴다운을 포함하여 수행하려는 모든 변경 사항을 표시한다는 것입니다. 대조적으로 CloudFormation은 중첩 스택을 사용할 때 중첩 스택을 업데이트해야 한다는 것만 표시하지만 세부 정보를 드릴다운하는 방법은 제공하지 않습니다. 이러한 유형의 정보는 "이동" 버튼을 누르기 전에 알아야 하는 매우 중요하기 때문에 답답할 수 있습니다.
CloudFormation과 Terraform 모두 확장을 지원합니다. CloudFormation에서는 자체 생성한 AWS Lambda 함수를 백엔드로 사용하여 소위 "커스텀 리소스"를 관리할 수 있습니다. Terraform의 경우 확장을 훨씬 쉽게 작성하고 코드의 일부를 구성할 수 있습니다. 따라서 이 경우 Terraform에 이점이 있습니다.
Terraform은 많은 클라우드 공급업체를 처리할 수 있습니다. 이를 통해 Terraform은 여러 클라우드 플랫폼 간에 주어진 배포를 통합할 수 있는 위치에 있습니다. 예를 들어 AWS와 Google Cloud Platform(GCP) 간에 단일 워크로드가 분산되어 있다고 가정해 보겠습니다. 일반적으로 워크로드의 AWS 부분은 CloudFormation을 사용하여 배포되고 GCP 부분은 GCP의 Cloud Deployment Manager를 사용하여 배포됩니다. Terraform을 사용하면 대신 단일 스크립트를 사용하여 해당 클라우드 플랫폼에서 두 스택을 모두 배포하고 관리할 수 있습니다. 이런 식으로 두 개가 아닌 한 개의 스택만 배포하면 됩니다.
Terraform 대 CloudFormation에 대한 비인수
인터넷에 계속해서 떠돌고 있는 논증이 아닌 것이 꽤 있습니다. 가장 큰 문제는 Terraform이 멀티 클라우드이기 때문에 수행되는 클라우드 플랫폼에 관계없이 하나의 도구를 사용하여 모든 프로젝트를 배포할 수 있다는 것입니다. 기술적으로 이것은 사실이지만 특히 일반적인 단일 클라우드 프로젝트를 관리할 때 그렇게 보일 수 있는 큰 이점은 아닙니다. 현실은 (예를 들어) CloudFormation에서 선언된 리소스와 Terraform 스크립트에서 선언된 동일한 리소스 간에 거의 일대일 대응 관계가 있다는 것입니다. 어느 쪽이든 클라우드 관련 리소스의 세부 정보를 알아야 하기 때문에 차이점은 구문으로 귀결되며, 이는 배포 관리에서 가장 큰 문제는 아닙니다.
일부에서는 Terraform을 사용하면 공급업체 종속을 피할 수 있다고 주장합니다. 이 주장은 CloudFormation을 사용하여 AWS에 의해 잠긴 것과 같은 방식으로 Terraform을 사용하여 HashiCorp(Terraform의 창시자)에 의해 잠긴다는 의미에서 성립하지 않습니다. 플랫폼.
Terraform 모듈이 사용하기 더 쉽다는 사실은 나에게 덜 중요합니다. 우선, AWS는 사용자가 만든 보안 허점 및 다양한 규정 준수 프로그램 위반에 대한 인식된 책임 때문에 커뮤니티 기반 CloudFormation 템플릿에 대한 단일 리포지토리를 호스팅하는 것을 의도적으로 피하려고 한다고 생각합니다.
좀 더 개인적인 차원에서, 저는 소프트웨어 개발의 경우 라이브러리를 사용하는 이점을 충분히 이해합니다. 라이브러리는 수만 줄의 코드로 쉽게 실행될 수 있기 때문입니다. 그러나 IaC의 경우 일반적으로 코드의 크기가 훨씬 작으며 이러한 모듈은 일반적으로 수십 줄입니다. 복사/붙여넣기를 사용하는 것은 호환성을 유지하고 보안을 알 수 없는 사람에게 위임하는 문제를 피한다는 점에서 실제로 그렇게 나쁜 생각은 아닙니다.
복사/붙여넣기를 사용하는 것은 많은 개발자와 DevOps 엔지니어에게 눈살을 찌푸리게 하며 여기에는 그럴만한 이유가 있습니다. 그러나 내 관점은 코드 조각에 복사/붙여넣기를 사용하면 필요에 맞게 쉽게 조정할 수 있고 라이브러리를 만들 필요가 없고 일반화하는 데 많은 시간을 할애할 필요가 없다는 것입니다. 코드가 예를 들어 12개 이상의 템플릿에서 중복되지 않는 한 이러한 코드 스니펫을 유지 관리하는 수고는 일반적으로 매우 낮습니다. 이러한 경우 코드를 사용하고 중첩 스택으로 사용하는 것이 합리적이며, 반복하지 않는 이점은 업데이트를 수행할 때 중첩 스택 내부에서 업데이트될 내용을 볼 수 없다는 성가심보다 아마도 더 클 것입니다. 작업.
CloudFormation 대 Terraform 결론
AWS는 CloudFormation을 통해 고객에게 항상 의도한 대로 작동하는 견고한 도구를 제공하고자 합니다. 물론 Terraform의 팀도 그렇게 하지만 도구의 중요한 측면인 종속성 관리는 불행히도 우선순위가 아닌 것 같습니다.
Terraform은 특히 다중 클라우드 아키텍처가 있는 경우 프로젝트에 위치할 수 있습니다. 이 경우 Terraform 스크립트는 사용 중인 다양한 클라우드 공급업체의 리소스 관리를 통합하는 한 가지 방법입니다. 그러나 이 경우에는 각각의 클라우드별 IaC 도구를 사용하여 이미 구현된 스택을 관리하는 데만 Terraform을 사용함으로써 Terraform의 단점을 피할 수 있습니다.
Terraform과 CloudFormation의 전반적인 느낌은 CloudFormation이 비록 불완전하지만 더 전문적이고 안정적이라는 것입니다. 특히 멀티 클라우드가 아닌 모든 프로젝트에 이 제품을 추천합니다.