【问题标题】:Unable to access AWS CloudWatch from containers on EC2 instance on private subnet无法从私有子网上 EC2 实例上的容器访问 AWS CloudWatch
【发布时间】:2021-08-18 22:03:44
【问题描述】:

我有一个带有三个 EC2 实例的 AWS VPC 设置,其中一个可以访问公共互联网,而另外两个不能。应用程序服务(在 node.js 中开发)是 docker 容器化的,并在所有三个实例中运行。我正在将他们的日志从文件移动到 AWS CloudWatch。该应用程序使用 Winston 记录器,我添加了 winston-cloudwatch 来为 CloudWatch 提供传输。

export const logger = new winston.createLogger({
  transports: [],
  handleExceptions: false,
  exitOnError: false
});
if (process.env.NODE_ENV === 'production') {
  const cloudWatchConfig = {
    logGroupName: process.env.CLOUDWATCH_GROUP_NAME,
    logStreamName: process.env.SERVICE,
    awsRegion: process.env.CLOUDWATCH_REGION,
    messageFormatter: ({ level, message }) => `[${process.env.SERVICE}:${level}] : ${message}`
  }
  logger.add(new WinstonCloudWatch(cloudWatchConfig))
}

在具有公共互联网访问权限的 EC2 实例上运行的容器正在将日志发送到 CloudWatch;那里没有问题。但是,在私有子网上的实例上运行的那些不能。第一个问题是从该 EC2 实例访问 CloudWatch 服务器,为此我在私有子网上为服务 com.amazonaws.ca-central-1.logs 设置了一个 VPC 接口端点。之后,我可以从实例访问 CloudWatch,即,我可以使用命令行指令访问 CloudWatch,例如:

$ aws logs describe-log-groups --log-group-name my-app-logs

等等。我还可以使用“put-log-events”子命令创建日志。

但是,在此实例的容器中,我仍然无法连接到 CloudWatch。这是我得到的错误:

UnknownEndpoint:无法访问主机:logs.ca-central-1.amazonaws.com'. This service may not be available in the ca-central-1' 区域。 在 Request.ENOTFOUND_ERROR (/users-svc/node_modules/aws-sdk/lib/event_listeners.js:530:46) 在 Request.callListeners (/users-svc/node_modules/aws-sdk/lib/sequential_executor.js:106:20) 在 Request.emit (/users-svc/node_modules/aws-sdk/lib/sequential_executor.js:78:10) 在 Request.emit (/users-svc/node_modules/aws-sdk/lib/request.js:688:14) 出错时(/users-svc/node_modules/aws-sdk/lib/event_listeners.js:362:22) 在客户端请求。 (/users-svc/node_modules/aws-sdk/lib/http/node.js:99:9) 在 ClientRequest.emit (events.js:400:28) 在 ClientRequest.emit (domain.js:470:12) 在 TLSSocket.socketErrorListener (_http_client.js:475:9) 在 TLSSocket.emit (events.js:400:28) { 代码:'UnknownEndpoint',区域:'ca-central-1',主机名:'logs.ca-central-1.amazonaws.com', 可重试:true,originalError:错误:getaddrinfo EAI_AGAIN logs.ca-central-1.amazonaws.com 在 GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:69:26) { 错误号:-3001, 代码:“网络错误”, 系统调用:'getaddrinfo', 主机名:'logs.ca-central-1.amazonaws.com', 区域:'ca-central-1', 可重试:真, 时间:2021-08-17T16:30:35.796Z },时间:2021-08-17T16:30:35.796Z }

因此,容器中的应用程序服务无法访问 CloudWatch 主机。

我是 AWS 的新手,所以这可能是由于一个微不足道的遗漏。但是,我怀疑问题在于容器无法在私有子网上找到此 CloudWatch 接口端点,这又可能是因为它无法将主机名解析为 IP 地址。当容器通过覆盖网络相互连接时,它们应该如何连接到这个 EndPoint? Interface EndPoint 获得在私有子网上分配的 IP 地址,它允许实例通过 AWS 的 PrivateLink 连接到 AWS 服务(在本例中为 CloudWatch)。由于我可以从私有子网上的该实例连接到 CloudWatch,因此该实例可以将主机名解析为 IP 地址。我如何让这个实例上的容器做同样的事情?实例上可访问公共 Internet 的容器使用 Google 的 DNS 服务器 8.8.8.8 和 9.9.9.9,因此它们能够解析 CloudWatch 主机名的公共 IP 地址。私有子网上实例上的容器必须需要某种方式来解析私有子网上 CloudWatch 主机名的 IP 地址。

顺便说一句,我在启用容器日志记录时看到了对 awslogs 驱动程序和 CloudWatch 代理的引用,但我认为它们提供了将日志从容器获取到 CloudWatch 的替代方法;没有他们我应该可以这样做。

【问题讨论】:

    标签: node.js amazon-web-services docker amazon-ec2 amazon-cloudwatch


    【解决方案1】:

    事实证明,这个问题是由于分配给我的 VPC 中的私有子网的子网地址空间与 docker swarm 默认创建其子网空间的方式发生冲突造成的。这是回答我的inquiry[1] 的stackoverflow 源,特别是用户cueedee 发布的第一个答案,而不是他的第二个。我先尝试了第二种方法,就是在docker-compose-yml中加入以下内容:

    networks:
        default:
            ipam:
                config:
                    - subnet: '192.168.0.0/24'
                driver: 'default'
    

    这不起作用:docker stack deploy 没有更新该指令所表达的地址空间。在此之后,我尝试像这样强制更新:

    $ docker swarm init --default-addr-pool 192.168.0.0/16 --force-new-cluster

    不过,docker swarm 并没有更新其子网地址空间。最后,我按照 cueedee 在他的第一个答案中的建议做了,即重新创建 swarm:

    $ docker swarm init --default-addr-pool 192.168.0.0/16

    这给了我想要的结果,我可以通过以下方式验证:

    $ 码头工人信息

     Swarm: active
      NodeID: 
      Is Manager: true
      ClusterID: 
      Managers: 3
      Nodes: 3
      Default Address Pool: 192.168.0.0/16  
      SubnetSize: 24
    

    使用原始 docker-compose.yml 重新部署应用程序消除了我面临的问题:私有子网上的容器现在能够将日志发送到 CloudWatch。

    【讨论】:

      猜你喜欢
      • 2019-09-04
      • 2019-05-26
      • 2022-01-22
      • 1970-01-01
      • 2016-10-02
      • 2012-03-10
      • 2020-10-27
      • 2022-06-10
      • 1970-01-01
      相关资源
      最近更新 更多