You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:17:57