Как зарегистрировать службу ECS в целевой группе, определенной в другом стеке

#amazon-web-services #amazon-cloudformation #amazon-ecs #aws-cdk

#amazon-веб-сервисы #aws-cloudformation #amazon-ecs #aws-cdk

Вопрос:

У меня есть 2 стека, первый определяет мое приложение LB, а другой определяет мою службу ECS.

В первом стеке я определил несколько целевых групп для своих нескольких служб ECS и хотел бы зарегистрировать соответствующую службу.

Для справки, я последовал этому примеру здесь, чтобы разделить свое приложение

Как я могу зарегистрировать свою службу ECS в целевой группе, определенной в другом стеке?

Моя служба ECS…

     const service = new ecs.Ec2Service(this, 'jenkinsService', {
      cluster: props.cluster,
      taskDefinition,
      serviceName: 'Jenkins-Master',
      minHealthyPercent: 0,
      maxHealthyPercent: 100
    });

    props.targetGroup.addTarget(service) // I want to register against a specific Target Group

  

Моя пользовательская целевая группа

 
        const jenkinsMastertargetGroup = this.targetGroup = new elbv2.ApplicationTargetGroup(this, 'Jenkins-Master', {
          vpc: props.vpc,
          port: 80,
          targetType: elbv2.TargetType.INSTANCE,
          targetGroupName: 'WDD-Jenkins-Master',
          deregistrationDelay: cdk.Duration.seconds(250),
          healthCheck:{
            port: '8080',
            path:'/log/all',
            interval: cdk.Duration.minutes(3)
          }

        });

  

Действие на моем слушателе для пересылки в TG

         elbHTTPlistener.addAction('JenkinsMasterResponse', {
          priority: 5,
          conditions: [
            //ListenerCondition.hostHeaders(['sub1.test.com.au/jenkins']),
            ListenerCondition.pathPatterns(['/jenkins']),
          ],
          action: ListenerAction.forward([jenkinsMastertargetGroup]),
        });
  

Комментарии:

1. если вы следуете примеру, предоставленному aws, вы уже должны быть в состоянии передать свой объект TargetGroup из одного «стека» в другой «стек». Если только каждый ваш «стек» не находится в разных развертываниях, например, вам нужно запустить «развертывание cdk» в каждом стеке. Я сделал аналогичную вещь в 2 разных развертываниях cdk.

2. Не могли бы вы поделиться примером? @Chun

Ответ №1:

Я нашел относительно простое решение этой проблемы, используя импорт / экспорт в cloudformation.

В 1-м стеке, где я определил ELB моего приложения, я определяю пустую целевую группу, а затем экспортирую ARN для целевой группы.

Обязательно добавьте правило для вашего TG.

 
const emptytg = new elbv2.ApplicationTargetGroup(this, 'tg1', {
        vpc,
        port: 80,
        targetGroupName: 'name',
        targetType: elbv2.TargetType.INSTANCE,
});

Listener.addAction('tg1', {
        priority: 2,
        conditions:[
          ListenerCondition.pathPatterns(['/tg1']),
        ],
        action: ListenerAction.forward([tg1])
      });

new cdk.CfnOutput(this,'tg1Export', {
      value: emptytg.targetGroupArn,
      exportName: 'emptytgARN'
    });

  

Ниже приведен другой стек, содержащий службу ECS, вы можете импортировать TG, а затем использовать целевой метод .addTarget.

 
const importedGroup = elbv2.ApplicationTargetGroup.fromTargetGroupAttributes(this, 'imported-tg',{
targetGroupArn: cdk.Fn.importValue('wddSharedResourcesjenkinsMastertargetGrouptargetGroupArn'),
});

importedGroup.addTarget(service);  

  

Это работает довольно хорошо для меня, и я надеюсь, что это поможет другим в будущем.

Ответ №2:

В моем варианте использования используется 1 балансировщик нагрузки приложений (и 1 прослушиватель HTTPS), и у него разные пути, которые указывают на разные развертывания ECS

например

И способ, которым я настраиваю, отличается от вашего. Вместо того, чтобы указывать всю целевую группу в стеке слушателей, я определяю эти целевые группы в стеке ECS.

StackLoadBalancer

     const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', {
      vpc,
      internetFacing: true
    });

    // make sure allow Application Load Balancer can accessing out to reach private service
    lb.connections.securityGroups[0].addEgressRule(
      ec2.Peer.ipv4(vpc.vpcCidrBlock),
      ec2.Port.allTcp(),
      "Allow Local Balancer to access service");

    lb.logAccessLogs(logBucket)

    const defaultTargetGroup = new elbv2.ApplicationTargetGroup(this, 'TargetGroup', {
      vpc: vpc,
      port: 80
    });

    const listener = lb.addListener('Listener', {
      port: 443,
      certificates: [certification],
      defaultTargetGroups: [defaultTargetGroup],
      open: true
    });

    new cdk.CfnOutput(this, 'listenerarn', { value: listener.listenerArn, exportName: this.stackName   "-listenerarn" })
  

stackA

    const ecsService = new ecs.Ec2Service(this, 'Service', {
      cluster,
      taskDefinition
    });

    ecsService.connections.securityGroups[0].addIngressRule(
      ec2.Peer.ipv4(vpc.vpcCidrBlock),
      ec2.Port.allTcp(),
      "Allow CloudFormation ECS Service Update Properly"
    );

    const targetGroup = new elbv2.ApplicationTargetGroup(this, 'application-a-tg', {
      vpc,
      port: portNumber,
      protocol: elbv2.ApplicationProtocol.HTTP,
      healthCheck: {
        interval: cdk.Duration.seconds(60),
        path: "/",
        timeout: cdk.Duration.seconds(5),
        healthyHttpCodes: "200-499"
      },
      stickinessCookieDuration: cdk.Duration.hours(1),
      deregistrationDelay: cdk.Duration.seconds(30),
      targets: [
        ecsService.loadBalancerTarget({
          containerName: 'web'
        })]
    });


    const rule1 = new elbv2.CfnListenerRule(this, "rule1", {
      listenerArn: cdk.Fn.importValue("StackLoadBalancerStack-listenerarn"),
      actions: [{
        type: "forward",
        targetGroupArn: targetGroup.targetGroupArn
      }],
      conditions: [{
        field: "path-pattern",
        pathPatternConfig: {
          values: ["/application-a/*"]
        },

      }],
      priority: 10
    });
  

Наиболее важной частью в stackA является CfnListenerRule, я не смог настроить «собственный» код CDK для этого во время разработки.

Комментарии:

1. Привет @Chun спасибо за помощь, которую я обновил с помощью решения, которое сработало для меня. Мое решение может помочь, поскольку оно более «родное» и использует меньше кода. Еще раз спасибо!