将 AWS ECS 服务与 CDK 连接
Connecting AWS ECS Services with the CDK
我想将两个容器部署到一个 ECS 集群中,一个从外部通过 HTTP 调用,然后它又通过 HTTP 调用另一个容器。
const cluster = new ecs.Cluster(this, "mycluster", {});
cluster.addDefaultCloudMapNamespace({ name: "local" });
new ecsPatterns.ApplicationLoadBalancedFargateService(this, "abc", {
cluster,
taskImageOptions: {
containerPort: 8000,
image: ecs.ContainerImage.fromRegistry("my/abc-image:latest"),
},
});
const xyztask = new ecs.FargateTaskDefinition(this, "xyztask");
const xyz = xyztask.addContainer("xyzcontainer", {
image: ecs.ContainerImage.fromRegistry("my/xyz-image:latest"),
});
xyz.addPortMappings({ containerPort: 8000 });
new ecs.FargateService(this, "xyz", {
cluster,
taskDefinition: xyztask,
cloudMapOptions: { name: "xyz" },
});
abc 服务如下所示:
const axios = require("axios");
const bodyParser = require("body-parser");
const express = require("express");
const app = express();
app.use(bodyParser.json());
app.post("/", async ({ body: { x } }, response) => {
response.end(JSON.stringify({ x }));
await axios.post(
`http://xyz.local:8000/`,
{ x },
{ timeout: 3000 }
);
});
app.listen(8000);
xyz 服务如下所示:
const axios = require("axios");
const bodyParser = require("body-parser");
const express = require("express");
const app = express();
app.use(bodyParser.json());
app.post("/", async ({ body: { x } }, response) => {
response.end();
});
app.listen(8000);
abc 服务可以从外部访问,但不知何故向 xyz 的请求总是失败。
我试着做出有根据的猜测,因为我在这里看到两个起点:
a) 该问题与 DNS 解析有关。
您可以通过在与 abc 服务和 运行: nslookup xyz.local
相同的子网内启动一个 EC2 实例来检查是否属于这种情况。如果 dns 解析产生 xyz 服务容器的 IP,则 DNS 解析不是问题。
b) xyz 服务的安全组阻止来自 abc 服务的传入调用。默认情况下允许传出连接,但通常不允许传入连接(ApplicationLoadBalancedFargateService 构造除外,它默认为来自任何地方的连接打开 ALB 的安全组 [1])。我想 FargateService 构造相反默认不打开任何传入容器端口,因此您必须手动连接这两个服务:
// initialize both services as before
const abc = new ecsPatterns.ApplicationLoadBalancedFargateService(...)
const xyz = new ecs.FargateService(...);
// add the ingress rule to xyz service for abc service's traffic via TCP port 8000
xyz.connections.allowFrom(abc, Port.tcp(8000));
我还没有尝试过这个,但我想到的是导致您的问题的两个可能原因。
参考资料
我想将两个容器部署到一个 ECS 集群中,一个从外部通过 HTTP 调用,然后它又通过 HTTP 调用另一个容器。
const cluster = new ecs.Cluster(this, "mycluster", {});
cluster.addDefaultCloudMapNamespace({ name: "local" });
new ecsPatterns.ApplicationLoadBalancedFargateService(this, "abc", {
cluster,
taskImageOptions: {
containerPort: 8000,
image: ecs.ContainerImage.fromRegistry("my/abc-image:latest"),
},
});
const xyztask = new ecs.FargateTaskDefinition(this, "xyztask");
const xyz = xyztask.addContainer("xyzcontainer", {
image: ecs.ContainerImage.fromRegistry("my/xyz-image:latest"),
});
xyz.addPortMappings({ containerPort: 8000 });
new ecs.FargateService(this, "xyz", {
cluster,
taskDefinition: xyztask,
cloudMapOptions: { name: "xyz" },
});
abc 服务如下所示:
const axios = require("axios");
const bodyParser = require("body-parser");
const express = require("express");
const app = express();
app.use(bodyParser.json());
app.post("/", async ({ body: { x } }, response) => {
response.end(JSON.stringify({ x }));
await axios.post(
`http://xyz.local:8000/`,
{ x },
{ timeout: 3000 }
);
});
app.listen(8000);
xyz 服务如下所示:
const axios = require("axios");
const bodyParser = require("body-parser");
const express = require("express");
const app = express();
app.use(bodyParser.json());
app.post("/", async ({ body: { x } }, response) => {
response.end();
});
app.listen(8000);
abc 服务可以从外部访问,但不知何故向 xyz 的请求总是失败。
我试着做出有根据的猜测,因为我在这里看到两个起点:
a) 该问题与 DNS 解析有关。
您可以通过在与 abc 服务和 运行: nslookup xyz.local
相同的子网内启动一个 EC2 实例来检查是否属于这种情况。如果 dns 解析产生 xyz 服务容器的 IP,则 DNS 解析不是问题。
b) xyz 服务的安全组阻止来自 abc 服务的传入调用。默认情况下允许传出连接,但通常不允许传入连接(ApplicationLoadBalancedFargateService 构造除外,它默认为来自任何地方的连接打开 ALB 的安全组 [1])。我想 FargateService 构造相反默认不打开任何传入容器端口,因此您必须手动连接这两个服务:
// initialize both services as before
const abc = new ecsPatterns.ApplicationLoadBalancedFargateService(...)
const xyz = new ecs.FargateService(...);
// add the ingress rule to xyz service for abc service's traffic via TCP port 8000
xyz.connections.allowFrom(abc, Port.tcp(8000));
我还没有尝试过这个,但我想到的是导致您的问题的两个可能原因。