Fargate 上多个容器(django、nginx)的最佳实践
Best practice for multiple Container(django,nginx) on Fargate
我有多个containers/images
比如admin(django)
,nginx(httpserver)
我的系统在下面。
port80-> nginx -> port8011 -> admin
我想在 fargate
上部署这些。
然而我还是一头雾水
两个镜像,两个容器,两个任务定义,两个负载均衡器就可以了。
但是一个publicIP只能给nginx?
容器之间如何连接?
目前我的源码是这样的
我熟悉 docker-compose,但不熟悉 aws fargate。
感谢任何帮助。
const VPCID='vpc-0867d6797e62XXXXX';
const vpc = ec2.Vpc.fromLookup(this, "VPC", {
vpcId:VPCID
//isDefault: true,
});
const cluster = new ecs.Cluster(this, "SampleCluster", {
vpc:vpc,
clusterName: "StAdminNginxCluster"
});
const adminRepo = ecr.Repository.fromRepositoryArn(this, 'AdminRepository', 'arn:aws:ecr:ap-northeast-1:678100XXXXXX:repository/st_admin_site');
const nginxRepo = ecr.Repository.fromRepositoryArn(this, 'NginxRepository', 'arn:aws:ecr:ap-northeast-1:678100XXXXXX:repository/st_nginx');
const adminImage = ecs.ContainerImage.fromEcrRepository(adminRepo,"latest");
const nginxImage = ecs.ContainerImage.fromEcrRepository(nginxRepo,"latest");
//make task definition
const taskDefinitionAdmin = new ecs.FargateTaskDefinition(this, "TaskDefAdmin",{
memoryLimitMiB: 512,
cpu: 256,
});
const taskDefinitionNginx = new ecs.FargateTaskDefinition(this, "TaskDefNginx",{
memoryLimitMiB: 512,
cpu: 256,
});
const adminContainer = taskDefinitionAdmin.addContainer("AdminContainer", {
image: adminImage,
});
const nginxContainer = taskDefinitionNginx.addContainer("NginxContainer", {
image: nginxImage,
});
adminContainer.addPortMappings({
containerPort: 8011
});
nginxContainer.addPortMappings({
containerPort: 80
})
const ecsServiceAdmin = new ecs.FargateService(this, "ServiceAdmin", {
cluster,
taskDefinition:taskDefinitionAdmin,
desiredCount: 2
});
const ecsServiceNginx = new ecs.FargateService(this, "ServiceNginx", {
cluster,
taskDefinition:taskDefinitionNginx,
desiredCount: 2
});
const lbAdmin = new elb.ApplicationLoadBalancer(this, "LBAdmin", {
vpc: cluster.vpc,
internetFacing: true
});
const listenerAdmin = lbAdmin.addListener("Listener", { port: 8011 });
const targetGroupAdmin = listenerAdmin.addTargets("ECSAdmin", {
protocol: elb.ApplicationProtocol.HTTP,
port: 8011,
targets: [ecsServiceAdmin]
});
const lbNginx = new elb.ApplicationLoadBalancer(this, "LBNginx", {
vpc: cluster.vpc,
internetFacing: true
});
const listenerNginx = lbNginx.addListener("Listener", { port: 80 });
const targetGroupNginx = listenerNginx.addTargets("ECS", {
protocol: elb.ApplicationProtocol.HTTP,
port: 80,
targets: [ecsServiceNginx]
});
这个 docker-compose 有效。
version: "3.9"
services:
admindjango:
image: 678100XXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/st_admin_site:latest
ports:
- "8011:8011"
restart: always
nginx:
image: 678100XXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/st_nginx:latest
ports:
- '80:80'
depends_on:
- admindjango
更新
我用两个容器定义一个任务。
我刚从一个 taskDifinition
.addContainer
中调用了两次 addContainer
。
(暂时忽略loadbalancer
)
您也可以通过 127.0.0.1:XXX 访问每个容器。
它很适合我的目的。感谢 @Mark B
const taskDefinitionAdmin = new ecs.FargateTaskDefinition(this, "TaskDefAdmin",{
memoryLimitMiB: 512,
cpu: 256,
});
const adminContainer = taskDefinitionAdmin.addContainer("AdminContainer", {
image: adminImage,
});
adminContainer.addPortMappings({
containerPort: 8011,
hostPort: 8011
});
const nginxContainer = taskDefinitionAdmin.addContainer("NginxContainer", {
image: nginxImage,
});
nginxContainer.addPortMappings({
containerPort: 80,
hostPort: 80
})
const adminSG = new ec2.SecurityGroup(this, 'admin-server-sg', {
vpc,
allowAllOutbound: true,
description: 'security group for a web server',
});
adminSG.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(80),
'allow SSH access from anywhere',
);
const ecsAdminService = new ecs.FargateService(this, "AdminService", {
cluster,
taskDefinition:taskDefinitionAdmin,
desiredCount: 2,
vpcSubnets: {subnetType: ec2.SubnetType.PUBLIC },
assignPublicIp: true,
securityGroups:[adminSG]
});
How can I connect between container?
在您当前的配置中,您无法在容器之间直接连接。您必须让 Nginx 连接到连接到 Django 任务的内部负载平衡器。
Web 浏览器 -> Public Nginx 负载均衡器 -> Nginx 容器 -> 私有 Django 负载均衡器 -> Django 容器。
我建议查看 运行 同一 ECS 任务中的两个容器。如果只拥有一个负载均衡器和一半数量的 Fargate 实例,您可能会节省一大笔钱。流量看起来像这样:
Web 浏览器 -> Public 负载均衡器 -> 端口 80 上的 Nginx 容器 -> 端口 8011 上的 Django 容器。
在那种情况下,您可以将 Nginx 配置为将请求代理到 127.0.0.1:8011
。同一任务中的所有容器都可以在 Fargate 实例内通过 127.0.0.1
相互连接。请参阅 Fargate 网络文档 here。
更高级的设置是将每个容器 运行 作为一个单独的任务,并使用 AWS App Mesh 进行内部容器通信,而不是内部负载平衡器。对于您的情况,这可能有点矫枉过正,并且更适合具有许多独立部署的微服务的大型环境。
我有多个containers/images
比如admin(django)
,nginx(httpserver)
我的系统在下面。
port80-> nginx -> port8011 -> admin
我想在 fargate
上部署这些。
然而我还是一头雾水
两个镜像,两个容器,两个任务定义,两个负载均衡器就可以了。
但是一个publicIP只能给nginx?
容器之间如何连接?
目前我的源码是这样的
我熟悉 docker-compose,但不熟悉 aws fargate。
感谢任何帮助。
const VPCID='vpc-0867d6797e62XXXXX';
const vpc = ec2.Vpc.fromLookup(this, "VPC", {
vpcId:VPCID
//isDefault: true,
});
const cluster = new ecs.Cluster(this, "SampleCluster", {
vpc:vpc,
clusterName: "StAdminNginxCluster"
});
const adminRepo = ecr.Repository.fromRepositoryArn(this, 'AdminRepository', 'arn:aws:ecr:ap-northeast-1:678100XXXXXX:repository/st_admin_site');
const nginxRepo = ecr.Repository.fromRepositoryArn(this, 'NginxRepository', 'arn:aws:ecr:ap-northeast-1:678100XXXXXX:repository/st_nginx');
const adminImage = ecs.ContainerImage.fromEcrRepository(adminRepo,"latest");
const nginxImage = ecs.ContainerImage.fromEcrRepository(nginxRepo,"latest");
//make task definition
const taskDefinitionAdmin = new ecs.FargateTaskDefinition(this, "TaskDefAdmin",{
memoryLimitMiB: 512,
cpu: 256,
});
const taskDefinitionNginx = new ecs.FargateTaskDefinition(this, "TaskDefNginx",{
memoryLimitMiB: 512,
cpu: 256,
});
const adminContainer = taskDefinitionAdmin.addContainer("AdminContainer", {
image: adminImage,
});
const nginxContainer = taskDefinitionNginx.addContainer("NginxContainer", {
image: nginxImage,
});
adminContainer.addPortMappings({
containerPort: 8011
});
nginxContainer.addPortMappings({
containerPort: 80
})
const ecsServiceAdmin = new ecs.FargateService(this, "ServiceAdmin", {
cluster,
taskDefinition:taskDefinitionAdmin,
desiredCount: 2
});
const ecsServiceNginx = new ecs.FargateService(this, "ServiceNginx", {
cluster,
taskDefinition:taskDefinitionNginx,
desiredCount: 2
});
const lbAdmin = new elb.ApplicationLoadBalancer(this, "LBAdmin", {
vpc: cluster.vpc,
internetFacing: true
});
const listenerAdmin = lbAdmin.addListener("Listener", { port: 8011 });
const targetGroupAdmin = listenerAdmin.addTargets("ECSAdmin", {
protocol: elb.ApplicationProtocol.HTTP,
port: 8011,
targets: [ecsServiceAdmin]
});
const lbNginx = new elb.ApplicationLoadBalancer(this, "LBNginx", {
vpc: cluster.vpc,
internetFacing: true
});
const listenerNginx = lbNginx.addListener("Listener", { port: 80 });
const targetGroupNginx = listenerNginx.addTargets("ECS", {
protocol: elb.ApplicationProtocol.HTTP,
port: 80,
targets: [ecsServiceNginx]
});
这个 docker-compose 有效。
version: "3.9"
services:
admindjango:
image: 678100XXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/st_admin_site:latest
ports:
- "8011:8011"
restart: always
nginx:
image: 678100XXXXXX.dkr.ecr.ap-northeast-1.amazonaws.com/st_nginx:latest
ports:
- '80:80'
depends_on:
- admindjango
更新
我用两个容器定义一个任务。
我刚从一个 taskDifinition
.addContainer
中调用了两次 addContainer
。
(暂时忽略loadbalancer
)
您也可以通过 127.0.0.1:XXX 访问每个容器。
它很适合我的目的。感谢 @Mark B
const taskDefinitionAdmin = new ecs.FargateTaskDefinition(this, "TaskDefAdmin",{
memoryLimitMiB: 512,
cpu: 256,
});
const adminContainer = taskDefinitionAdmin.addContainer("AdminContainer", {
image: adminImage,
});
adminContainer.addPortMappings({
containerPort: 8011,
hostPort: 8011
});
const nginxContainer = taskDefinitionAdmin.addContainer("NginxContainer", {
image: nginxImage,
});
nginxContainer.addPortMappings({
containerPort: 80,
hostPort: 80
})
const adminSG = new ec2.SecurityGroup(this, 'admin-server-sg', {
vpc,
allowAllOutbound: true,
description: 'security group for a web server',
});
adminSG.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(80),
'allow SSH access from anywhere',
);
const ecsAdminService = new ecs.FargateService(this, "AdminService", {
cluster,
taskDefinition:taskDefinitionAdmin,
desiredCount: 2,
vpcSubnets: {subnetType: ec2.SubnetType.PUBLIC },
assignPublicIp: true,
securityGroups:[adminSG]
});
How can I connect between container?
在您当前的配置中,您无法在容器之间直接连接。您必须让 Nginx 连接到连接到 Django 任务的内部负载平衡器。
Web 浏览器 -> Public Nginx 负载均衡器 -> Nginx 容器 -> 私有 Django 负载均衡器 -> Django 容器。
我建议查看 运行 同一 ECS 任务中的两个容器。如果只拥有一个负载均衡器和一半数量的 Fargate 实例,您可能会节省一大笔钱。流量看起来像这样:
Web 浏览器 -> Public 负载均衡器 -> 端口 80 上的 Nginx 容器 -> 端口 8011 上的 Django 容器。
在那种情况下,您可以将 Nginx 配置为将请求代理到 127.0.0.1:8011
。同一任务中的所有容器都可以在 Fargate 实例内通过 127.0.0.1
相互连接。请参阅 Fargate 网络文档 here。
更高级的设置是将每个容器 运行 作为一个单独的任务,并使用 AWS App Mesh 进行内部容器通信,而不是内部负载平衡器。对于您的情况,这可能有点矫枉过正,并且更适合具有许多独立部署的微服务的大型环境。