Terraform으로 ECS에서 서비스 자동 등록
Terraform으로 ECS에서 서비스 자동 등록 (Register Services on ECS Automatically with Terraform)
이 주제는 ECS 클러스터 워크로드에 Consul 서비스 메시를 배포하는 Terraform 구성을 만드는 방법을 설명해요. Consul 서버 에이전트는 ECS에서 실행되지 않으므로 EKS 같은 다른 런타임에 배포하고 ECS 워크로드에 연결해야 해요.
출처: 문서
본문
이 주제는 ECS 클러스터 워크로드에 Consul 서비스 메시를 배포하는 Terraform 구성을 만드는 방법을 설명해요. Consul 서버 에이전트는 ECS에서 실행되지 않으므로 EKS 같은 다른 런타임에 배포하고 ECS 워크로드에 연결해야 해요. 추가 정보는 Consul on AWS Elastic Container Service 개요를 참고해요.
개요 (Overview)
ECS 태스크 정의와 Consul 서비스 메시 구성 요소를 구축하는 Terraform 모듈을 포함하는 Terraform 구성 파일을 만들어요. 태스크 정의는 AWS의 소프트웨어 서비스에 대한 ECS 청사진이에요. 추가 정보는 ECS task definitions 문서를 참고해요.
Terraform 구성에 다음 모듈과 리소스를 추가할 수 있어요:
mesh-task모듈: 애플리케이션 컨테이너와 함께 태스크 정의에 Consul ECS control-plane 및 Consul dataplane 컨테이너를 추가해요. Envoy는 Consul dataplane 컨테이너 내에서 하위 프로세스로 실행돼요.aws_ecs_service리소스: 태스크 인스턴스를 실행하고 유지하는 ECS 서비스를 추가해요.gateway-task모듈: 클러스터에 메시 게이트웨이 컨테이너를 추가해요. 메시 게이트웨이는 서로 다른 유형의 네트워크 영역 간 서비스 간 통신을 가능하게 해요.
프로덕션 워크로드에 Consul 보안 기능을 활성화하려면 서비스 메시 태스크용 ACL 토큰을 프로비저닝하는 controller 모듈도 배포해야 해요.
Terraform 구성을 정의한 후 terraform apply를 사용해 ECS 클러스터에 Consul을 배포해요.
요구 사항 (Requirements)
- Terraform 구성 파일을 만드는 방법에 익숙해야 해요. Terraform 시작 방법에 대한 정보는 Terraform 문서를 참고해요.
- AWS ECS에 익숙해야 해요. 추가 정보는 Amazon AWS 문서의 What is Amazon Elastic Container Service를 참고해요.
gateway-task모듈을 사용해 메시 게이트웨이를 배포하려면 TLS를 활성화해야 해요. 추가 정보는 Configure the ECS controller를 참고해요.
보안 구성 요구 사항 (Secure configuration requirements)
Consul 서비스 메시에서 보안 기능을 활성화하려면 다음 요구 사항과 사전 요구 사항을 충족해야 해요:
- Consul 서버에서 gRPC를 통해 Consul 컨테이너와 안전하게 통신할 수 있도록 TLS 암호화를 활성화해요.
- Consul 서버에서 접근 제어 목록(ACL)을 활성화해요. ACL은 메시에서 Consul 서버에 대한 접근의 인증 및 권한 부여를 제공해요.
- ECS에서 민감한 데이터를 지정하는 방법에 익숙해야 해요. 추가 정보는 AWS 문서의 Passing sensitive data to a container를 참고해요.
또한 Consul은 각 ECS 태스크 패밀리(task family)에 대해 고유한 IAM 역할을 요구해요. 태스크 IAM 역할은 각 Consul 서비스에 태스크 패밀리가 고유하므로 서로 다른 태스크 패밀리가 공유할 수 없어요.
ACL 토큰 및 정책 생성 방법을 포함해 Consul의 보안 기능 구성에 익숙해야 해요. 추가 정보는 다음 리소스를 참고해요:
태스크 정의 생성 (Create the task definition)
Terraform 구성 파일을 만들고 ECS 태스크 정의를 추가해요. 태스크 정의에는 애플리케이션 컨테이너, Consul control-plane 컨테이너, dataplane 컨테이너, controller 컨테이너가 포함돼요. 서비스 메시를 여러 Consul 데이터 센터 또는 파티션에 피어링하려면 네트워크 영역 간 연결을 가능하게 하는 게이트웨이 컨테이너를 배포하는 gateway-task 모듈을 추가해요.
mesh task 모듈 구성 (Configure the mesh task module)
Terraform 구성에 module 블록을 추가하고 다음 필드를 지정해요:
source:mesh-task모듈의 위치를 지정해요. 이 필드는hashicorp/consul-ecs/aws//modules/mesh-task로 설정해야 해요.mesh-task모듈은 Terraform 구성을 적용할 때 Consul 서비스 메시 인프라를 자동으로 추가해요.version: 사용할mesh-task모듈의 버전을 지정해요.family: ECS 태스크 정의 패밀리를 지정해요. Consul은 기본적으로family값을 Consul 서비스 이름으로도 사용해요.container_definitions: 태스크 정의에 대한 컨테이너 정의 목록을 지정해요. 이 필드에 애플리케이션 컨테이너를 포함해요.
구성할 수 있는 모든 옵션에 대한 정보는 Terraform 레지스트리의 mesh-task 모듈 참조 문서를 참고해요.
Consul 서버에서 ACL 및 암호화 설정이 활성화되어 있다면 해당 설정도 구성해야 해요. 추가 정보는 보안 배포 활성화를 참고해요.
다음 예시에서 Terraform 구성 파일 mesh-task.tf는 example-client-app이라는 애플리케이션 컨테이너가 있는 태스크 정의를 만들어요:
mesh-task.tf:
module "my_task" {
source = "hashicorp/consul-ecs/aws//modules/mesh-task"
version = "<latest version>"
family = "my_task"
container_definitions = [
{
name = "example-client-app"
image = "docker.io/org/my_task:v0.0.1"
essential = true
portMappings = [
{
containerPort = 9090
hostPort = 9090
protocol = "tcp"
}
]
cpu = 0
mountPoints = []
volumesFrom = []
}
]
port = 9090
}
다음 필드는 필수예요. 전체 참조는 모듈 참조 문서를 참고해요.
Consul 서버 설정 구성 (Configure Consul server settings)
control-plane 및 ECS controller 컨테이너가 서버에 연결되도록 구성할 수 있도록 mesh task 모듈에 Consul 서버 연결 설정을 제공해요.
variables.tf파일에서 gRPC 및 HTTP 트래픽에 대한 호스트 URL과 TLS 설정에 대한 변수를 정의해요. 정의할 수 있는 변수에 대한 정보는 mesh task module reference를 참고해요. 다음 예시에서 Consul 서버 주소는consul_server_hosts변수에 정의돼요:
variable "consul_server_hosts" {
description = "Address of Consul servers."
type = string
}
- control-plane 및 ECS controller 컨테이너 정의에
environment블록을 추가해요. environment.name필드를CONSUL_ECS_CONFIG_JSON환경 변수로 설정하고 값은local.encoded_config로 설정해요.
environment = [
{
name = "CONSUL_ECS_CONFIG_JSON",
value = local.encoded_config
}
]
구성을 적용하면 mesh task 모듈이 서버 구성 변수를 보간하고 config.tf 파일을 만든 다음 해당 설정을 적절한 컨테이너에 주입해요. config.tf 파일에 대한 추가 정보는 JSON schema 참조 문서를 참고해요.
태스크 인스턴스를 실행하는 ECS 서비스 구성 (Configure an ECS service to run your task instances)
태스크 정의를 사용해 태스크를 시작하려면 ECS 서비스를 만들기 위해 구성에 aws_ecs_service 리소스를 추가해요. ECS 서비스는 태스크 정의를 사용해 태스크를 시작하는 가장 일반적인 방법 중 하나예요.
aws_ecs_service 리소스에서 mesh-task 모듈의 task_definition_arn 출력 값을 참조해요. 다음 예시는 module.my_task.task_definition_arn으로 참조되는 태스크 정의에 대한 ECS 서비스를 추가해요:
mesh-task.tf:
module "my_task" {
source = "hashicorp/consul-ecs/aws//modules/mesh-task"
...
}
resource "aws_ecs_service" "my_task" {
name = "my_task_service"
task_definition = module.my_task.task_definition_arn
launch_type = "FARGATE"
propagate_tags = "TASK_DEFINITION"
...
}
전체 구성 참조는 Terraform 레지스트리의 aws_ecs_service를 참고해요.
ECS 애플리케이션의 테스트 인스턴스를 배포하는 경우 Terraform에서 구성을 적용할 수 있어요. 지침은 구성 실행을 참고해요. 프로덕션 환경에 배포를 구성하려면 ECS controller 모듈도 배포해야 해요. 지침은 Configure the ECS controller를 참고해요.
WAN 페더레이션 및 클러스터 피어링 같은 다중 데이터 센터 Consul 기능을 활용하려면 네트워크의 각 Consul 데이터 센터에 대해 gateway-task 모듈을 추가해야 해요. 지침은 gateway task 모듈 구성을 참고해요.
gateway task 모듈 구성 (Configure the gateway task module)
gateway-task 모듈은 네트워크 영역 간 서비스 간 통신을 가능하게 하는 메시 게이트웨이를 배포해요. 메시 게이트웨이는 서비스 메시 세션에서 SNI(서버 이름 표시) 헤더를 감지하고 연결을 적절한 대상으로 라우팅해요.
추가 정보는 다음 문서를 참고해요:
메시 게이트웨이를 사용하려면 클러스터에서 TLS가 활성화되어야 해요. 추가 정보는 요구 사항 섹션을 참고해요.
- Terraform 구성 파일에
module블록을 추가하고 레이블을 지정해요. 레이블은 게이트웨이의 고유 식별자예요. module에source를 추가하고gateway-task의 위치를 지정해요. 값은hashicorp/consul-ecs/aws//modules/gateway-task여야 해요.- 다음 필수 입력을 지정해요:
ecs_cluster_arn: 게이트웨이용 ECS 클러스터의 ARN.family: 태스크의 여러 버전에 대한 이름을 지정해요. 자세한 내용은 AWS 문서를 참고해요.kind:mesh-gateway로 설정해요.subnets: 게이트웨이 태스크가 배포되어야 하는 서브넷 ID 목록을 지정해요.
- 프로덕션 환경에 배포하는 경우
acl및tls구성을 추가해야 해요. 자세한 내용은 Configure the ECS controller를 참고해요. - 환경에 필요한 추가 매개변수를 구성해요. 모든 매개변수에 대한 정보는 모듈 참조 문서를 참고해요.
다음 예시는 my-gateway라는 메시 게이트웨이 태스크를 정의해요:
mesh-gateway.tf:
module "my_mesh_gateway" {
source = "hashicorp/consul-ecs/aws//modules/gateway-task"
version = "<latest version>"
kind = "mesh-gateway"
family = "my-gateway"
ecs_cluster_arn = "<ECS cluster ARN>"
subnets = ["<subnet ID>"]
consul_server_hosts = "<address of the Consul server>"
tls = true
consul_ca_cert_arn = "<Secrets manager secret ARN>"
}
전체 참조는 Terraform 레지스트리의 gateway-task 모듈을 참고해요.
추가 구성 예시는 gateway task 구성 예시를 참고해요.
ECS controller 구성 (Configure the ECS controller)
클러스터의 자체 ECS 태스크에 ECS controller 컨테이너를 배포해요. 컨테이너에 대한 자세한 내용은 ECS controller 컨테이너를 참고해요.
보안 구성 요구 사항에서 설명한 사전 요구 사항을 완료했는지 확인하고 다음 단계를 완료해 controller 컨테이너를 구성해요.
controller용 ACL 토큰 생성 (Create a an ACL token for the controller)
-
Consul 서버에서 controller에 대해 다음 접근을 부여하는 정책을 만들어요:
이 정책을 통해 Consul은 정책에 연결된 토큰을 생성할 수 있어요. 지침은 서비스 토큰 생성을 참고해요.
- 토큰을 만들고 ACL controller 정책에 연결해요. 지침은 ACL 토큰 문서를 참고해요.
AWS secrets manager 시크릿 구성 (Configure an AWS secrets manager secret)
Terraform 구성에 aws_secretsmanager_secret 리소스를 추가하고 CA 및 TLS 인증서 검색 값을 지정해요. 이 리소스는 서비스가 TLS로 통신하고 ACL 토큰을 제시할 수 있게 해요. ECS controller는 bootstrap 토큰 값을 검색하기 위해 시크릿 관리자도 사용해요.
다음 예시에서 Terraform은 gRPC 및 HTTPS용 CA 인증서를 시크릿 관리자에 만들어요. Consul은 시크릿 관리자에서 CA 인증서 PEM 파일을 검색해 mesh task가 HTTP 및 gRPC 트래픽에 TLS를 사용할 수 있게 해요:
secret.tf:
resource "tls_private_key" "ca" {
algorithm = "ECDSA"
ecdsa_curve = "P384"
}
resource "tls_self_signed_cert" "ca" {
private_key_pem = tls_private_key.ca.private_key_pem
subject {
common_name = "Consul Agent CA"
organization = "HashiCorp Inc."
}
// 5 years.
validity_period_hours = 43800
is_ca_certificate = true
set_subject_key_id = true
allowed_uses = [
"digital_signature",
"cert_signing",
"crl_signing",
]
}
resource "aws_secretsmanager_secret" "ca_key" {
name = "${var.name}-${var.datacenter}-ca-key"
recovery_window_in_days = 0
}
resource "aws_secretsmanager_secret_version" "ca_key" {
secret_id = aws_secretsmanager_secret.ca_key.id
secret_string = tls_private_key.ca.private_key_pem
}
resource "aws_secretsmanager_secret" "ca_cert" {
name = "${var.name}-${var.datacenter}-ca-cert"
recovery_window_in_days = 0
}
resource "aws_secretsmanager_secret_version" "ca_cert" {
secret_id = aws_secretsmanager_secret.ca_cert.id
secret_string = tls_self_signed_cert.ca.cert_pem
}
두 변수 모두에 단일 CERT PEM을 사용할 수 있다는 점에 유의해요. consul_ca_cert_arn은 두 프로토콜 모두에 적용되는 기본 ARN이에요. consul_https_ca_cert_arn 및 consul_grpc_ca_cert_arn 변수를 사용해 프로토콜별 인증서 PEM을 사용할 수도 있어요.
다음 Terraform 구성은 생성된 CA 인증서 ARN을 mesh-task 모듈에 전달하고 HTTPS 및 gRPC 통신 모두에 CA 인증서 및 PEM 변수가 설정되도록 해요.
secret.tf:
module "my_task" {
source = "hashicorp/consul-ecs/aws//modules/mesh-task"
version = "<version>"
...
tls = true
consul_ca_cert_arn = aws_secretsmanager_secret.ca_cert.arn
}
보안 배포 활성화 (Enable secure deployment)
보안 배포를 활성화하려면 태스크 모듈에 다음 구성을 추가해요.
secret.tf:
module "my_task" {
source = "hashicorp/consul-ecs/aws//modules/mesh-task"
version = "<version>"
...
tls = true
consul_grpc_ca_cert_arn = aws_secretsmanager_secret.ca_cert.arn
acls = true
consul_server_hosts = "https://consul-server.example.com"
consul_https_ca_cert_arn = aws_secretsmanager_secret.ca_cert.arn
}
전체 구성 예시 (Complete configuration examples)
terraform-aws-consul-ecs GitHub 리포지토리에는 ECS 워크로드에 Consul 서비스 메시를 배포하는 데 도움이 되는 참조할 수 있는 예시가 포함되어 있어요.
Terraform 구성 적용 (Apply your Terraform configuration)
태스크 정의를 만들기 위해 Terraform을 실행해요.
태스크 정의용 Terraform 구성을 mesh-task.tf 같은 파일에 저장해요. 이 파일은 프로젝트의 다른 Terraform 구성 파일과 함께 디렉터리에 배치해야 해요.
mesh-task 모듈은 AWS Terraform 공급자를 요구해요. 다음 예시는 provider.tf라는 파일에 AWS 공급자를 포함하고 구성하는 방법을 보여줘요. 추가 문서 및 사양은 Terraform 레지스트리의 AWS provider를 참고해요.
provider.tf:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "<latest version>"
}
}
}
provider "aws" {
region = "<AWS region>"
...
}
프로젝트에 필요한 추가 AWS 리소스를 같은 디렉터리의 Terraform 구성 파일에 지정해요. 다음 예시는 기본적인 프로젝트 디렉터리를 보여줘요:
$ ls
mesh-task.tf
provider.tf
...
다음 명령을 실행해 구성을 실행해요:
terraform init: 이 명령은 Terraform 공급자 같은 종속성을 다운로드해요.terraform apply: 이 명령은mesh-task모듈의 태스크 정의 같은 AWS 리소스를 만들도록 Terraform에 지시해요.
Terraform은 현재 디렉터리의 .tf 파일 확장자를 가진 모든 파일을 읽어요. 자세한 내용 및 Terraform 모범 사례는 Terraform 문서를 참고해요.
다음 단계 (Next steps)
Consul 서비스 메시 인프라를 배포한 후에는 서비스 인스턴스 간 경로를 정의하고 애플리케이션의 바인드 주소를 구성해 애플리케이션이 메시를 통해서만 트래픽을 수신하도록 해야 해요. 다음 주제를 참고해요:
gateway task 구성 예시 (Gateway task configuration examples)
다음 예시는 다양한 사용 사례에 대한 gateway-task 구성 방법을 보여줘요.
수신 (Ingress)
메시 게이트웨이는 데이터 센터 간 트래픽을 라우팅하기 위해 WAN을 통해 도달 가능해야 해요. 메시 게이트웨이를 통한 수신(ingress)을 활성화하려면 gateway-task 모듈에서 다음 옵션을 구성해요.
| 입력 변수 | 유형 | 설명 |
|---|---|---|
lb_enabled |
Boolean | 메시 게이트웨이에 대한 수신을 위해 네트워크 로드 밸런서를 자동으로 배포하고 구성하려면 true로 설정해요. |
lb_vpc_id |
string | 로드 밸런서를 시작할 VPC를 지정해요. |
lb_subnets |
list of strings | 로드 밸런서와 연결할 하나 이상의 공용 서브넷을 지정해요. |
mesh-gateway.tf:
module "my_mesh_gateway" {
...
lb_enabled = true
lb_vpc_id = "<VPC ID>"
lb_subnets = ["<public subnet IDs>"]
}
또는 gateway-task 모듈에 wan_address 및 wan_port 입력을 제공해 메시 게이트웨이에 대한 수신을 수동으로 구성할 수 있어요. wan_port 필드는 선택사항이에요. 기본적으로 포트 8443이 사용돼요.
mesh-gateway.tf:
module "my_mesh_gateway" {
...
wan_address = "<public WAN address>"
wan_port = <public WAN port>
}
메시 게이트웨이는 L4 TCP 연결을 라우팅하며 mTLS 세션을 종료하지 않아요. 메시 게이트웨이에 대한 수신을 위해 AWS Elastic Load Balancing을 수동으로 구성하는 경우 AWS Network Load Balancer 또는 Classic Load Balancer를 사용해야 해요.
ACL
ACL이 활성화된 경우 gateway-task 모듈에서 다음 옵션을 구성해요.
| 옵션 | 유형 | 설명 |
|---|---|---|
acl |
Boolean | ACL이 활성화된 경우 true로 설정해요. |
consul_server_hosts |
string | Consul 서버의 HTTP address를 지정해요. 메시 게이트웨이 태스크가 IAM 인증 방법을 사용해 Consul에 로그인하여 클라이언트 및 서비스 토큰을 얻는 데 필요해요. |
consul_https_ca_cert_arn |
string | Consul HTTPS API용 인증서가 포함된 Secrets Manager 시크릿의 ARN을 지정해요. |
mesh-gateway.tf:
module "my_mesh_gateway" {
...
acls = true
consul_server_hosts = "<HTTP address of the Consul server>"
tls = true
consul_https_ca_cert_arn = "<Secrets Manager secret ARN>"
}
WAN 페더레이션 (WAN federation)
메시 게이트웨이를 통한 WAN 페더레이션을 활성화하려면 gateway-task에서 다음 옵션을 구성해요.
| 옵션 | 유형 | 설명 |
|---|---|---|
consul_datacenter |
string | 로컬 Consul 데이터 센터의 이름을 지정해요. |
consul_primary_datacenter |
string | 기본 Consul 데이터 센터의 이름을 지정해요. |
enable_mesh_gateway_wan_federation |
Boolean | WAN 페더레이션을 활성화하려면 true로 설정해요. |
enable_acl_token_replication |
Boolean | ACL 토큰 복제를 활성화하고 보조 데이터 센터에서 로컬 토큰 생성을 허용하려면 true로 설정해요. |
다음 예시는 gateway-task 모듈 구성 방법을 보여줘요.
mesh-gateway.tf:
module "my_mesh_gateway" {
...
enable_mesh_gateway_wan_federation = true
}
ACL이 활성화된 상태에서 WAN을 통해 Consul 데이터 센터를 페더레이션할 때 모든 데이터 센터의 모든 서버 및 클라이언트 에이전트에서 ACL 토큰 복제를 활성화해요.