【发布时间】: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 theca-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