跨VPC通过AWS Privatelink从Atlantis访问EC2上ElasticSearch的配置问题
跨VPC通过AWS Privatelink访问EC2上ElasticSearch的解决方案
问题核心
你的配置方向完全错误:直接使用AWS官方服务的service_name(比如com.amazonaws.us-east-2.ec2)创建的VPC端点,仅用于访问AWS EC2自身的API(比如查询实例信息),根本无法暴露你自己EC2上部署的ElasticSearch服务。要跨VPC通过Privatelink访问自定义服务,必须采用VPC端点服务(VPC Endpoint Service)+ 客户端VPC端点的组合,而非直接创建指向AWS官方服务的端点。
正确实现步骤
1. 服务端(ElasticSearch所在VPC)配置
Privatelink的端点服务必须绑定Network Load Balancer(NLB),无法直接关联EC2实例,因此需先完成以下配置:
- 创建NLB,监听9200端口,目标组指向你的ES EC2实例(端口9200)
- 创建VPC端点服务,关联该NLB,并允许Atlantis所在VPC访问
- 配置安全组规则:
- NLB安全组允许Atlantis VPC的子网访问9200端口
- ES EC2安全组允许NLB的安全组访问9200端口
2. 客户端(Atlantis所在VPC)配置
- 创建接口型VPC端点,指向服务端创建的自定义端点服务名称(格式类似
com.amazonaws.vpce.us-east-2.vpce-svc-xxxxxx) - 配置Atlantis所在ECS的安全组,允许访问该VPC端点的9200端口
- 可选:启用私有DNS,让Atlantis通过自定义域名访问ES
修正后的Terraform代码示例
服务端(ES所在VPC)代码
# 变量定义 variable "elasticsearch_vpc_id" { type = string } variable "elastic_dev_subnet_ids" { type = list(string) } variable "elastic_ec2_instance_id" { type = string } variable "atlantis_vpc_id" { type = string } # 创建NLB目标组,指向ES EC2实例 resource "aws_lb_target_group" "es_target_group" { name = "es-target-group" port = 9200 protocol = "TCP" vpc_id = var.elasticsearch_vpc_id target_type = "instance" } resource "aws_lb_target_group_attachment" "es_attachment" { target_group_arn = aws_lb_target_group.es_target_group.arn target_id = var.elastic_ec2_instance_id port = 9200 } # 创建内部NLB resource "aws_lb" "es_nlb" { name = "es-nlb" internal = true load_balancer_type = "network" vpc_id = var.elasticsearch_vpc_id subnet_ids = var.elastic_dev_subnet_ids } # NLB监听9200端口 resource "aws_lb_listener" "es_listener" { load_balancer_arn = aws_lb.es_nlb.arn port = "9200" protocol = "TCP" default_action { type = "forward" target_group_arn = aws_lb_target_group.es_target_group.arn } } # 创建VPC端点服务,关联NLB并允许Atlantis VPC访问 resource "aws_vpc_endpoint_service" "es_service" { acceptance_required = false # 无需手动接受客户端连接请求 network_load_balancer_arns = [aws_lb.es_nlb.arn] allowed_principals { principal_type = "VPC" principal = var.atlantis_vpc_id } } # 给ES EC2安全组添加允许NLB访问的规则(替换为你的ES安全组ID) resource "aws_security_group_rule" "es_allow_nlb" { type = "ingress" from_port = 9200 to_port = 9200 protocol = "tcp" source_security_group_id = aws_lb.es_nlb.security_groups[0] security_group_id = "sg-你的ES安全组ID" }
客户端(Atlantis所在VPC)代码
# 变量定义 variable "atlantis_vpc_id" { type = string } variable "atlantis_subnet_ids" { type = list(string) } variable "es_vpce_service_name" { type = string # 取值为服务端aws_vpc_endpoint_service.es_service.service_name } # 创建客户端VPC端点 resource "aws_vpc_endpoint" "atlantis_es_endpoint" { vpc_id = var.atlantis_vpc_id service_name = var.es_vpce_service_name vpc_endpoint_type = "Interface" subnet_ids = var.atlantis_subnet_ids private_dns_enabled = true # 启用私有DNS,支持自定义域名访问 security_group_ids = ["sg-你的Atlantis ECS安全组ID"] } # 配置Atlantis安全组允许访问端点的9200端口 resource "aws_security_group_rule" "atlantis_allow_es_endpoint" { type = "egress" from_port = 9200 to_port = 9200 protocol = "tcp" destination_security_group_id = aws_vpc_endpoint.atlantis_es_endpoint.security_groups[0] security_group_id = "sg-你的Atlantis ECS安全组ID" }
关键说明
- 原代码无效原因:你创建的是访问AWS EC2官方API的端点,与你的ES服务无任何关联,因此能ping通
ec2.us-east-2.api.aws但无法访问ES - 必须使用NLB:Privatelink端点服务仅支持四层的Network Load Balancer,适配私有链路的流量转发需求
- 安全组链路:确保流量路径
Atlantis → 客户端端点 → 服务端NLB → ES EC2中,每一步的安全组都允许对应端口的流量通行
内容的提问来源于stack exchange,提问作者goat potato
相关产品推荐
相关产品推荐

