【问题标题】:Lambda in VPC has Connection Error against AWS APIVPC 中的 Lambda 对 AWS API 有连接错误
【发布时间】:2020-02-13 18:41:25
【问题描述】:

我有一个需要访问 AWS API 的 Python lambda。如果它不与 VPC 子网关联,则它可以工作。但是,当它与 VPC 子网关联时,它会收到异常 botocore.exceptions.EndpointConnectionError 和消息 Could not connect to the endpoint URL: "https://ec2.us-east-1.amazonaws.com/"。我见过herehere 描述的这种问题,通常是由于缺少 NAT 网关路由引起的。但是,我有all the correct "pieces",它仍然不起作用。

我拥有的是:

  • 具有创建两个逻辑 ENI 的关联的 Lambda:
    • 两个私有子网,每个 AZ 一个。
    • 一个完全允许的安全组(允许所有入站/出站流量)
  • 私有子网具有自定义路由表,其中路由将 0.0.0.0/0 发送到 NAT 网关
  • 每个 NAT 网关都位于一个公共子网中(每个 AZ 一个),该子网有一个自定义路由表,其中路由将 0.0.0.0/0 发送到 VPC 的 IGW。
  • 所有子网都与允许所有入站和出站流量的 NACL 相关联。

当我检查流日志时,我看到 lambda ENI 成功地发起了 DNS 请求(端口 53),如下所示:

2 405857719141 eni-03bb24a034d226e5c 10.136.95.104 10.136.7.233 38109 53 17 1 73 1571250675 1571250733 接受确定

除此之外没有其他 VPC 流日志记录...没有任何指示“REJECTED”。我的实际 Python 代码在 lambda 未与 VPC 关联时工作,如下所示:

def lambda_handler(event, context):
    from botocore.client import Config
    from botocore.session import Session

    logger.info(f'Create Session')
    s = Session()
    logger.info(f'Session Created')
    logger.info(f'fetching client')
    ec2_res = boto3.resource('ec2')
    logger.info(f'got vpc resource')

    #I've tried different approaches to creating a client
    ec2_client = s.create_client('ec2',config=Config(connect_timeout=45, read_timeout=45, retries={'max_attempts': 0}))
    #ec2_client = boto3.client('ec2', config=config)
    #ec2_client = boto3.client('ec2', endpoint_url="https://aws.amazon.com/ec2",config=config)
    #ec2_client = boto3.client('ec2',endpoint_url=endpoint)
    logger.info(f'fetched_client')

    route_table_id = os.environ['fromTGWRouteTableId']
    logger.info(f'got route table id from environment')

    try: 
        logger.info(f'route table(s):{route_table_id}')
        #this request will throw an exception in 40 seconds.
        route_table = ec2_client.describe_route_tables(RouteTableIds=[route_table_id])
        logger.info(f'got client response for route_tables')
        rt = route_table['RouteTables'][0]
        logger.info(f'The RT ID is: {rt.id}')
    except Exception as e:
        logger.info(f'{type(e)}')
        logger.info(f'{e}')

    return

我必须调整 lambda 和 boto3 客户端超时恰到好处才能真正捕获错误。 其他任何事情都会导致超时。以下是 lambda 的 CloudWatch 日志条目:

START RequestId: a3ce5c07-f5ec-4b91-b6d8-c94e05fbecc9 Version: $LATEST
[INFO] 2019-10-16T20:22:38.914Z a3ce5c07-f5ec-4b91-b6d8-c94e05fbecc9 Create Session
[INFO] 2019-10-16T20:22:39.36Z a3ce5c07-f5ec-4b91-b6d8-c94e05fbecc9 Session Created
[INFO] 2019-10-16T20:22:39.92Z a3ce5c07-f5ec-4b91-b6d8-c94e05fbecc9 fetching client
[INFO] 2019-10-16T20:22:39.94Z a3ce5c07-f5ec-4b91-b6d8-c94e05fbecc9 Found credentials in environment variables.
[INFO] 2019-10-16T20:22:40.33Z a3ce5c07-f5ec-4b91-b6d8-c94e05fbecc9 got vpc resource
[INFO] 2019-10-16T20:22:40.33Z a3ce5c07-f5ec-4b91-b6d8-c94e05fbecc9 fetched_client
[INFO] 2019-10-16T20:22:40.33Z a3ce5c07-f5ec-4b91-b6d8-c94e05fbecc9 got route table id from environment
[INFO] 2019-10-16T20:22:40.33Z a3ce5c07-f5ec-4b91-b6d8-c94e05fbecc9 route table(s):rtb-0d92f4db98072d6fc
[INFO] 2019-10-16T20:22:49.493Z bd2bf6b7-2fa6-46ea-8115-cb830cb07f32 <class 'botocore.exceptions.EndpointConnectionError'>
[INFO] 2019-10-16T20:22:49.493Z bd2bf6b7-2fa6-46ea-8115-cb830cb07f32 Could not connect to the endpoint URL: "https://ec2.us-east-1.amazonaws.com/"
END RequestId: bd2bf6b7-2fa6-46ea-8115-cb830cb07f32
REPORT RequestId: bd2bf6b7-2fa6-46ea-8115-cb830cb07f32 Duration: 40960.97 ms Billed Duration: 41000 ms Memory Size: 128 MB Max Memory Used: 83 MB
2 unknown eni-07003b087845964ff - - - - - - - 1571257388 1571257400 - NODATA

关于我忽略了什么的任何想法?

更新

在我的 Python 代码中,我添加了以下测试:

contents = urllib.request.urlopen("https://google.com").readline()
logger.info(f'http response: {contents}')

上面会抛出一个带有消息urlopen error [Errno -3] Temporary failure in name resolution 的URLError。

然后,我在我的 VPC 的公共子网中创建了一个 Ubuntu EC2 实例。对 google.com 的 ping 测试因“未知主机”而失败。 如果我明确提供一个公共互联网 IP 地址来 ping,那么它就可以工作。

同样hostdig失败,如图:

ubuntu@ip-10-136-80-220:/etc$ host google.com
;; connection timed out; no servers could be reached
ubuntu@ip-10-136-80-220:/etc$ dig google.com

; <<>> DiG 9.10.3-P4-Ubuntu <<>> google.com
;; global options: +cmd
;; connection timed out; no servers could be reached

如果我明确地将 dig 指向公共 DNS 服务器,我可以使它成功。这有效:dig @8.8.8.8 google.com

以下是我的 resolv.conf 的内容,真实的公司名称以“mycompany.com”为掩码:

# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 10.136.7.233
nameserver 10.136.7.249
search preprod.awse1.mycompany.com

以上对应于以下 DHCP 选项集。

domain-name = preprod.awse1.mycompany.com; domain-name-servers = 10.136.7.233, 10.136.7.249;

我认为上述两个 DNS 服务器都在不同的 AWS 账户中提供。尽管如此,ping 测试在这两个 DNS 服务器地址上都失败了。我不确定这是否意味着这些服务器不存在,或者它们根本不响应 ICMP。

刚才我创建了自己的 DHCP 选项集,和上面一样,但是我将 DNS 服务器更改为 8.8.8.8 和 8.8.4.4 并将其关联到 VPC。然后我修改了我的 lambda 以输出 /etc/resolv.conf 的内容,以验证它“占用”了新的 8.8.8.8/8.8.4.4 DNS 服务器 - 并且 lambda 仍然出现相同的 DNS 错误!很奇怪,来自 EC2 实例的显式 dig @8.8.8.8 google.com 有效,但与同一子网关联的 lambda 会出现 DNS 错误。我想知道与 Lambda 关联的临时 ENI 是否有自己的 DNS 服务器记录 - 它们更新速度不够快,无法反映我对 lambda 所做的更改?

顺便说一句,VPC 有“DNS 解析”和“DNS 主机名”,enabled

为什么 DNS 无法正常工作?如图所示,我使用的是自己的 DNS 服务器还是 google 提供的服务器都没有关系。

【问题讨论】:

  • 您能否通过来自同一个 Lambda 的 HTTP 请求访问非 AWS 端点?如果您只有一个子网/安全组组合(因此只有一个 ENI),它是否有效?同一子网中具有相同 SG 的 EC2 实例能否访问公共端点?
  • @jarmod 我在我的问题中添加了Update 部分。会喜欢你的想法。
  • @jarmod 我又更新了。我的网络代理问题干扰了我的测试。现在我的问题包含有关 VPC 中 DNS 问题的更新。
  • 您使用的是自定义 DHCP 选项集还是 VPC 默认选项?您可能需要进一步调试。检查 dig,检查 /etc/resolv.conf 设置等。
  • @jarmod 根据您的提示,我已经提供了更多信息。

标签: amazon-web-services aws-lambda amazon-vpc


【解决方案1】:

我现在已经解决了这个问题。问题的核心是我的 VPC 的 DHCP 选项集要求位于不同 VPC 中的 DNS 服务器。我的启用 VPC 的 lambda 与一个子网相关联,该子网没有专门针对 DNS 的路由表条目。我需要的是路由表中的一条路由,它将通过中转网关指向这些 DNS 服务器地址以到达另一个 VPC。相反,我的子网有一条将 DNS 请求定向到公共互联网的路由(不出所料,它没有找到通往其他 VPC 的路径)。

我的 VPC 中有另一个子网,它确实有一个指向中转网关的路由表和路由。这个其他子网也有资格获得关联的 lambda。因此,仅更改我的 lambda 使用的子网就足以使整个工作正常。

发现此问题的根源受到其他因素的阻碍,例如 AWS 流日志显示 DNS 请求的“接受 / 确定” - 实际上它们不起作用。我需要更好地掌握解释流日志(并在适当的时候忽略它们)。

【讨论】:

    猜你喜欢
    • 2019-07-27
    • 1970-01-01
    • 2021-01-07
    • 2020-03-02
    • 2019-11-14
    • 2017-10-12
    • 2018-07-10
    • 2018-05-04
    相关资源
    最近更新 更多