如何将端口80和443从ELB映射到同一个ECS容器?

时间:2016-10-29 02:01:59

标签: amazon-web-services amazon-cloudformation elastic-load-balancer amazon-ecs

我正在构建一个CloudFormation堆栈。我有

  • ECS容器中的一个Web应用,PortMappingsContainerPort的9000和9002,映射到HostPort的80和443,
  • 应用程序负载均衡器(AWS::ElasticLoadBalancingV2::LoadBalancer),端口80上的HTTP为ListenerTargetGroup,端口443上为HTTPS

当我定义Service时,我只能指定一个负载均衡器元素;虽然LoadBalancers是复数,但文档说只允许一个负载均衡器,并且指定两个负载均衡器元素不起作用。那么,如何映射两个端口?

这是我的CloudFormation JSON的服务部分,只有HTTPS部分可用。可以扩展为将HTTP路由到同一个容器吗?如果没有,最好的解决方案是什么?

"Service": {
  "Type": "AWS::ECS::Service",
  "DependsOn": ["AutoScalingGroup", "HTTPSListener"],
  "Properties": {
    "Cluster": { "Ref": "Cluster" },
    "DesiredCount": { "Ref": "InstanceCount" },
    "LoadBalancers": [
      {
        "TargetGroupArn": { "Ref": "HTTPSTargetGroup" },
        "ContainerName": "nginx",
        "ContainerPort": "9002"
      }
    ],
    "Role": { "Ref": "ServiceRole" },
    "TaskDefinition": { "Ref": "TaskDefinition" }
  }
}

CloudFormation解决方案非常理想,但API解决方案也很有用。

我可以为HTTP创建第二个Service,使用单独的负载均衡器和容器实例,但这既不简单也不经济。

2 个答案:

答案 0 :(得分:1)

我会建议其中一个选项:

a)将任务(容器)注册到同一负载均衡器的两个不同任务定义,作为容器引导过程的一部分,而不是使用ECS服务的内置功能。<​​/ p>

b)定义另一个ECS服务,每个服务都与它自己的目标组相关联。两个目标组都与相同的ALB链接。

答案 1 :(得分:0)

部分解决方案是在创建堆栈后通过API手动注册实例与HTTP目标组:

autoscaling = boto3.client('autoscaling')
auto_scaling_groups = autoscaling.describe_auto_scaling_groups(AutoScalingGroupNames=[auto_scaling_group_name])
instances = auto_scaling_groups['AutoScalingGroups'][0]['Instances']

elbv2 = boto3.client('elbv2')
for instance in instances:
    elbv2.register_targets(
        TargetGroupArn=http_target_group_arn,
        Targets=[{'Id': instance['InstanceId'], 'Port': instance}]
    )

这不是一个完全可以接受的答案,因为将来由自动调节组创建的实例不会自动注册到HTTP目标组。应该可以对实例进行装配以进行自我注册;我会调查一下。