0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【AWS CF】「The target group does not have an associated load balancer」エラーの原因と解決方法

Posted at

概要

AWS CloudFormationで以下のエラーに遭遇しました。
本記事ではその原因と解決方法を記載します。

Resource handler returned message: "Invalid request provided: CreateService error: The target group with targetGroupArn arn:aws:elasticloadbalancing:ap-northeast-1:1234567890:targetgroup/Sample-Web-Blue/00b3e54db86b7e99 does not have an associated load balancer.

原因は依存関係にあった

このエラーは、「LBに紐づいているターゲットグループが存在せずに、サービスが作成されているよ」ということになります。

しかし、実際のテンプレートでは、LBのリスナーもターゲットグループも作成していました。

  #*******************************************************************************
  # TargetGroup
  # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-taskdefinition.html
  #*******************************************************************************
  TargetGroupWebBlue:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      HealthCheckIntervalSeconds: 5
      HealthCheckPath: "/"
      HealthCheckPort: "traffic-port"
      HealthCheckProtocol: "HTTP"
      HealthCheckTimeoutSeconds: 2
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 2
      Matcher:
        HttpCode: "200"
      Name: !Sub ${SysTag}-Web-Blue
      Port: 80
      Protocol: "HTTP"
      VpcId: !Sub ${rVpcId}
      TargetGroupAttributes:
        -
          Key: deregistration_delay.timeout_seconds
          Value: 0
  TargetGroupWebGreen:
    Type: "AWS::ElasticLoadBalancingV2::TargetGroup"
    Properties:
      HealthCheckIntervalSeconds: 5
      HealthCheckPath: "/"
      HealthCheckPort: "traffic-port"
      HealthCheckProtocol: "HTTP"
      HealthCheckTimeoutSeconds: 2
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 2
      Matcher:
        HttpCode: "200"
      Name: !Sub ${SysTag}-Web-Green
      Port: 80
      Protocol: "HTTP"
      VpcId: !Sub ${rVpcId}
      TargetGroupAttributes:
        -
          Key: deregistration_delay.timeout_seconds
          Value: 0

  #*******************************************************************************
  # Listener
  # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-elasticloadbalancingv2-listener.html
  #*******************************************************************************

  HttpListenerRuleWebBlue:
    Type: 'AWS::ElasticLoadBalancingV2::ListenerRule'
    Properties:
      Actions:
        - Type: forward
          ForwardConfig:
            TargetGroups:
              - TargetGroupArn: !Ref TargetGroupWebBlue
                Weight: 1
      Conditions:
        - Field: host-header
          Values:
            - xxx.sample.com
      ListenerArn: !ImportValue HttpDefaultListener-XXX
      Priority: 2
  HttpListenerRuleWebGreen:
    Type: 'AWS::ElasticLoadBalancingV2::ListenerRule'
    Properties:
      Actions:
        - Type: forward
          ForwardConfig:
            TargetGroups:
              - TargetGroupArn: !Ref TargetGroupWebGreen
                Weight: 1
      Conditions:
        - Field: host-header
          Values:
            - xxx.sample.com
      ListenerArn: !ImportValue HttpDefaultListenerTest-XXX
      Priority: 2

  #*******************************************************************************
  # Service
  # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html
  #*******************************************************************************
  ServiceXXX:
    Type: AWS::ECS::Service
    DependsOn: HttpListenerRuleWebBlue
    Properties: 
      Cluster: !Sub ${rEcsName}
      DesiredCount: !Ref TaskDeployNumWeb
      ServiceName: !Sub ${SysTag}
      LaunchType: "EC2"
      PlacementStrategies:
        - Field: "attribute:ecs.availability-zone"
          Type: spread
        - Field: "instanceId"
          Type: spread
      DeploymentController:
        Type: CODE_DEPLOY
      LoadBalancers:
        - TargetGroupArn: !Ref TargetGroupWebBlue
          ContainerPort: 80
          ContainerName: Web
      TaskDefinition: !Ref TaskWeb

あれ、やっぱりちゃんと記載しているよなぁ...
おかしいなぁ...と詰まりました。

ということで、以下の記事を見つけました。

The target group does not have an associated load balancer

上記の記事では、CloudFormationがリソースを作成する際の依存関係のところで、問題が発生していると指摘しています。

つまり、今回で言えば、ServiceXXXリソースが依存するHttpListenerRuleWebBlueリソースが正しく作成される前に、ServiceXXXリソースが作成されようとしていたため、このエラーが発生したと言えます。

ServiceXXXLoadBalancersプロパティがTargetGroupWebBlueを指定しているので、そのターゲットグループはロードバランサーに関連している必要があります。したがって、TargetGroupWebBlueがロードバランサーに関連付けられていること必要があります。

エラーメッセージにあったdoes not have an associated load balancerの意味がこれでわかりました。

CloudFormationは、リソースの作成順序を決定する際に、リソース間の依存関係を自動的に解決しようとしてくれますが、リソース間で相互に依存し合う場合や、外部リソースに依存する場合などに、依存関係の解決が難しくなることがあるようです。

まず、今回は以下のような関係でした。

HttpListenerRuleWebBlueTargetGroupWebBlueを必要としている
HttpListenerRuleWebBlueは、HttpDefaultListener-XXX(外部スタックのテンプレートからインポート)を必要としている
HttpDefaultListener-XXXLoadBalancerを必要としている
ServiceXXXTargetGroupWebBlueを必要としている

ここで、おそらくCloudFormationは以下の順序で作成を試みたのでしょう(推測)。

①ふむふむ、HttpListenerRuleWebBlueTargetGroupWebBlueを必要としているのか、それでは先にTargetGroupWebBlueを作らないと。
TargetGroupWebBlueを作ったぞ。
③お、TargetGroupWebBlueを必要としているリソースが他にもある。ServiceXXX!Refされているからこっち先に作っておこう。
④あれ、ServiceXXXHttpListenerRuleWebBlueが必要だって。そんなリソースないぞ?

結果:ServiceXXXのターゲットグループにELBが紐づいていない、というエラーになる

解決策はDependsOn

上記記事のように、DependsOn: Listenerを追加してあげます。
これだけでOKです!

  ServiceXXX:
    Type: AWS::ECS::Service
    DependsOn: HttpListenerRuleWebBlue # これを追加!
    Properties: 

DependsOnプロパティは、CloudFormationスタック内のリソース間の依存関係を定義するために使用されます。特定のリソースが他のリソースに依存している場合、DependsOnを使用して、依存関係を明示的に設定できるとのこと。

もう少し丁寧にすると、CloudFormationに対してServiceXXXリソースはHttpListenerRuleWebBlueリソースに依存しているよ、ということを明示的に伝えます。
すると、HttpListenerRuleWebBlueリソースが正常に作成されてから ServiceXXXリソースが作成されるように制御されます。
そして、HttpListenerRuleWebBlueリソースの作成にはTargetGroupWebBlueリソースが正しく関連付けられているため、エラーが解消された、というわけです。

これにより、CloudFormationはリソースを適切な順序で作成または更新することができました。
CloudFormationプロフェッショナルへの道は遠い...

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?