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

解决AWS Lambda同时连接RDS与OTEL Collector的网络问题

问题:Lambda关联VPC后可连接RDS但无法连接OTEL Collector

我正在AWS Lambda上搭建OpenTelemetry + OpenSearch + Tracetest的示例,遇到了如下网络问题:

  • 未接入RDS时,Lambda运行正常,遥测数据可在OTEL Collector与Tracetest中正常显示;
  • 接入RDS后,Lambda返回500错误;
  • 进一步排查发现:Lambda未关联VPC时,遥测功能正常;关联VPC后,能够成功连接RDS,但无法连接OTEL Collector。

我使用Terraform搭建基础设施,Serverless Framework部署Lambda,相关配置代码如下:

Terraform配置

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }

  required_version = ">= 1.2"
}

variable "domain" {
  default = "terraform-open-search"
}

variable "region" {
  default = "us-east-2"
}

provider "aws" {
  region = var.region
}

resource "aws_default_vpc" "default" { }

resource "aws_default_security_group" "default" {
  vpc_id = aws_default_vpc.default.id
  ingress {
    protocol  = -1
    self      = true
    from_port = 0
    to_port   = 0
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

}
resource "aws_security_group" "app_server_security_group" {
  egress = [
    {
      cidr_blocks      = ["0.0.0.0/0",]
      description      = ""
      from_port        = 22
      ipv6_cidr_blocks = []
      prefix_list_ids  = []
      protocol         = "-1"
      security_groups  = []
      self             = false
      to_port          = 60000
    }
  ]
  ingress = [
    {
      cidr_blocks      = ["0.0.0.0/0",]
      description      = ""
      from_port        = 22
      ipv6_cidr_blocks = []
      prefix_list_ids  = []
      protocol         = "tcp"
      security_groups  = []
      self             = false
      to_port          = 60000
    }
  ]
}

resource "aws_default_subnet" "default" {
  availability_zone = "${var.region}a"
}

resource "aws_iam_policy" "policy" {
  name        = "test_policy"
  path        = "/"
  description = "My test policy"
  policy = jsonencode({
    Version   = "2012-10-17"
    Statement = [
      {
        Action = [
          "ec2:Describe*",
        ]
        Effect   = "Allow"
        Resource = "*"
      },
    ]
  })
}

resource "aws_iam_role" "aws_ec2_iam_role" {
  name               = "aws_ec2_iam_role"
  assume_role_policy = jsonencode({
    Version   = "2012-10-17"
    Statement = [
      {
        "Action" : "sts:AssumeRole",
        "Principal" : {
          "Service" : "ec2.amazonaws.com"
        },
        "Effect" : "Allow",
        "Sid" : ""
      }
    ]
  })
}
resource "aws_iam_policy_attachment" "test-attach" {
  name       = "test-attachment"
  roles      = [aws_iam_role.aws_ec2_iam_role.name]
  policy_arn = aws_iam_policy.policy.arn
}

resource "aws_iam_instance_profile" "test_profile" {
  name  = "test_profile"
  role = aws_iam_role.aws_ec2_iam_role.name
}



data "aws_region" "current" {}

data "aws_caller_identity" "current" {}

resource "aws_opensearch_domain" "open_search" {
  domain_name    = var.domain
  engine_version = "Elasticsearch_7.10"

  ebs_options {
    ebs_enabled = true
    volume_size = 10
  }

  cluster_config {
    instance_type = "m4.large.search"

  }

  tags = {
    Domain = "TestDomain"
  }

  domain_endpoint_options {
    enforce_https = true
    tls_security_policy = "Policy-Min-TLS-1-2-2019-07"
  }

  advanced_security_options {
    enabled                        = true
    internal_user_database_enabled = true
    master_user_options {
      master_user_name     = "example"
      master_user_password = "Example1#"
    }
  }

  encrypt_at_rest {
    enabled = true
  }


  node_to_node_encryption {
    enabled = true
  }


  access_policies = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:domain/${var.domain}/*"
    }
  ]
}
POLICY
}




resource "aws_ssm_parameter" "vpcId" {
  name        = "/default/vpc_id"
  description = "VPC IP"
  type        = "String"
  value       = aws_default_vpc.default.id
}
output "VPC_ID" {
  value = aws_default_vpc.default.id
}

resource "aws_ssm_parameter" "subnetId" {
  name        = "/default/subnet_id"
  description = "SUBNET ID"
  type        = "String"
  value       = aws_default_subnet.default.id
}
output "SUBNET_ID" {
  value = aws_default_subnet.default.id
}

resource "aws_ssm_parameter" "securityGroupId" {
  name        = "/default/security_group"
  description = "Security Group ID"
  type        = "String"
  value       = aws_default_security_group.default.id
}
output "SECURITY_GROUP_ID" {
  value = aws_default_security_group.default.id
}

resource "aws_ssm_parameter" "ec2SecurityGroupId" {
  name        = "/ec2/security_group"
  description = "EC2 Security Group ID"
  type        = "String"
  value       = aws_security_group.app_server_security_group.id
}

output "EC2_SECURITY_GROUP_ID" {
  value = aws_security_group.app_server_security_group.id
}


# Ec2
resource "aws_instance" "shared_infra" {
  ami                    = "ami-089a545a9ed9893b6"
  instance_type          = "t2.large"
  key_name               = "pokemon-infra"
  vpc_security_group_ids = [aws_default_security_group.default.id, aws_security_group.app_server_security_group.id]
  user_data              = file("./file.sh")
  iam_instance_profile = aws_iam_instance_profile.test_profile.name
  tags                   = {
    Name       = "PokemonInfraStructure"
    OpenSearch = aws_opensearch_domain.open_search.endpoint
  }
  root_block_device {
    volume_size = 20
  }
  depends_on = [aws_opensearch_domain.open_search]
}

## parameters.tf
resource "aws_ssm_parameter" "endpoint" {
  name        = "/ec2/public_ip"
  description = "Ec2 instance public IP"
  type        = "String"
  value       = aws_instance.shared_infra.public_ip
}

output "EC2_PUBLIC_IP" {
  value = aws_instance.shared_infra.public_ip
}

Serverless配置

service: lambda-otel

plugins:
  - serverless-webpack

custom:
  webpack:
    webpackConfig: 'webpack.config.js'
    includeModules: true
  databaseName: "pokeshop"
  databaseUsername: "ashketchum"
  databasePassword: "squirtle123"
  databaseEndpoint:
    Fn::GetAtt: [PokeDatabase, "Endpoint.Address"]

provider:
  name: aws
  runtime: nodejs16.x
  region: us-east-2
#  vpc:
#    securityGroupIds:
#      - ${ssm:/default/security_group}
#      - ${ssm:/ec2/security_group}
#    subnetIds:
#      - ${ssm:/default/subnet_id}
  environment:
    NODE_OPTIONS: --require lambda-wrapper
    COLLECTOR_ENDPOINT: http://${ssm:/ec2/public_ip}:4317
    DATABASE_URL:
      Fn::Join:
        - ""
        - - "postgres://"
          - ${self:custom.databaseUsername}
          - ":"
          - ${self:custom.databasePassword}
          - "@"
          - ${self:custom.databaseEndpoint}
          - "/"
          - ${self:custom.databaseName}
          - "?schema=public"


functions:
  minimal:
    handler: handler.hello
#    vpc:
#      securityGroupIds:
#        - ${ssm:/default/security_group}
#        - ${ssm:/ec2/security_group}
#      subnetIds:
#        - ${ssm:/default/subnet_id}
    events:
      - httpApi:
          path: /
          method: get


resources:
  Resources:
    PokeDatabase:
      Type: "AWS::RDS::DBInstance"
      Properties:
        DBName: ${self:custom.databaseName}
        AllocatedStorage: "5"
        PubliclyAccessible: true
        DBInstanceClass: "db.t3.micro"
        Engine: "Postgres"
        MasterUsername: ${self:custom.databaseUsername}
        MasterUserPassword: ${self:custom.databasePassword}

注:目前已注释了将Lambda关联到默认VPC的代码,该VPC配置了开放的安全组。


内容的提问来源于stack exchange,提问作者CESCO

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 19:55:22