如何用Terraform在AWS ECS Fargate部署HashiCorp Vault?
在AWS ECS Fargate通过Terraform部署HashiCorp Vault的配置方案
一、你的任务定义分析与优化
你提供的任务定义基本可行,但存在几个生产环境下的风险点,需要调整优化:
核心问题与修正:
- 镜像标签风险:
vault:latest会自动拉取最新镜像,可能导致版本不一致或意外更新,建议指定具体稳定版本(如vault:1.15.3)。 - 存储持久化缺失:当前
file后端存储在容器本地路径/vault/file,Fargate容器重启后数据会彻底丢失,必须挂载EFS文件系统持久化Vault数据。 - VAULT_ADDR配置优化:容器内可直接设置为
http://0.0.0.0:8200,不影响内部访问,外部访问通过后续服务的网络配置实现。
优化后的任务定义(包含EFS挂载):
resource "aws_ecs_task_definition" "vault" { family = "vault-task" container_definitions = <<DEFINITION [ { "name": "vault", "image": "vault:1.15.3", "essential": true, "portMappings": [ { "containerPort": 8200, "hostPort": 8200, "protocol": "tcp" } ], "environment": [ { "name": "VAULT_ADDR", "value": "http://0.0.0.0:8200" }, { "name": "VAULT_LOCAL_CONFIG", "value": "{ \"backend\": {\"file\": {\"path\": \"/vault/file\"}}, \"default_lease_ttl\": \"168h\", \"max_lease_ttl\": \"720h\", \"listener\": [{ \"tcp\": { \"address\": \"0.0.0.0:8200\", \"tls_disable\": true }}] }" } ], "memory": 512, "cpu": 256, "mountPoints": [ { "sourceVolume": "vault-storage", "containerPath": "/vault/file", "readOnly": false } ] } ] DEFINITION requires_compatibilities = ["FARGATE"] network_mode = "awsvpc" memory = 512 cpu = 256 execution_role_arn = aws_iam_role.ecs_task_execution_role.arn task_role_arn = aws_iam_role.ecs_task_role.arn # 用于访问EFS/KMS等资源 volume { name = "vault-storage" efs_volume_configuration { file_system_id = aws_efs_file_system.vault.id root_directory = "/vault-data" transit_encryption = "ENABLED" } } }
二、ECS服务定义
通过以下Terraform代码定义ECS服务,管理Vault任务的运行:
resource "aws_ecs_service" "vault" { name = "vault-service" cluster = aws_ecs_cluster.vault_cluster.id task_definition = aws_ecs_task_definition.vault.arn desired_count = 1 # Vault单节点部署,集群需额外配置Raft后端 launch_type = "FARGATE" network_configuration { subnets = [aws_subnet.private_subnet_1.id, aws_subnet.private_subnet_2.id] # 推荐用私有子网,通过ALB暴露服务 security_groups = [aws_security_group.vault_sg.id] assign_public_ip = false # 私有子网无需公网IP } # 可选:配置负载均衡(外部访问Vault时需添加) load_balancer { target_group_arn = aws_lb_target_group.vault_tg.id container_name = "vault" container_port = 8200 } deployment_controller { type = "ECS" } lifecycle { ignore_changes = [desired_count] # 避免terraform apply时重置实例数 } }
三、关键配套资源配置
1. EFS文件系统(持久化存储)
resource "aws_efs_file_system" "vault" { creation_token = "vault-storage" tags = { Name = "vault-storage" } } resource "aws_efs_mount_target" "vault" { count = length(aws_subnet.private_subnet) file_system_id = aws_efs_file_system.vault.id subnet_id = aws_subnet.private_subnet[count.index].id security_groups = [aws_security_group.efs_sg.id] }
2. 安全组配置
- Vault安全组:仅允许负载均衡或指定IP访问8200端口
resource "aws_security_group" "vault_sg" { name = "vault-sg" description = "Allow Vault traffic" vpc_id = aws_vpc.main.id ingress { from_port = 8200 to_port = 8200 protocol = "tcp" security_groups = [aws_security_group.alb_sg.id] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } }
3. IAM角色配置
- 任务执行角色:需具备拉取镜像、访问EFS的权限
resource "aws_iam_role" "ecs_task_execution_role" { name = "ecs-task-execution-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ecs-tasks.amazonaws.com" } } ] }) } resource "aws_iam_role_policy_attachment" "ecs_task_execution_role_policy" { role = aws_iam_role.ecs_task_execution_role.name policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" } resource "aws_iam_role_policy" "efs_access_policy" { name = "efs-access-policy" role = aws_iam_role.ecs_task_execution_role.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = ["elasticfilesystem:ClientMount", "elasticfilesystem:ClientWrite"] Effect = "Allow" Resource = aws_efs_file_system.vault.arn } ] }) }
四、Vault初始化与Unseal
Fargate启动Vault后,需手动完成初始化:
- 进入容器终端:
aws ecs execute-command --cluster <集群名> --task <任务ID> --container vault --interactive --command "/bin/sh" - 初始化Vault:
vault operator init,保存生成的根令牌和unseal密钥 - Unseal Vault:
vault operator unseal <unseal密钥>(默认需执行3次)
若需自动Unseal,可配置AWS KMS作为后端,修改VAULT_LOCAL_CONFIG中的seal节点:
"seal": { "awskms": { "kms_key_id": "<你的KMS密钥ARN>" } }
内容的提问来源于stack exchange,提问作者Benjamin Volk
相关产品推荐
相关产品推荐

