概要

CloudFormationでハマったことを淡々と書いていく

ハマったこと

InternetGatewayをアタッチする

ダメな例

    IGWRoute:
      Type: AWS::EC2::Route
      DependsOn: IGW
      Properties:
        RouteTableId: !Ref PublicRouteTable
        DestinationCidrBlock: 0.0.0.0/0
        GatewayId: !Ref IGW

エラー

route table rtb-xxxxxx and network gateway igw-xxxxxx belong to different networks

解決策

先に AWS::EC2::VPCGatewayAttachment でIGWをVPCに紐付けてあげないとです。

  AttachGatewayToVPC:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties: 
      InternetGatewayId: !Ref IGW
      VpcId: !Ref VPC

  IGWRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGatewayToVPC
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref IGW

サブネットを作成する

ダメな例

  SubnetPublic1a:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref SubnetPublic1aCidr
      AvailabilityZone: !Ref AWS::Region
      Tags:
        - Key: Name
          Value: !Join ['-', ['sb', !Ref Prefix, 'public1a']]

エラー

Value (ap-northeast-1) for parameter availabilityZone is invalid. Subnets can currently only be created in the following availability zones: ap-northeast-1a, ap-northeast-1c.

解決策

!Ref AWS::Region だと ap-northeast-1 までしか取れないからですね。

他のリージョンに ac が必ずあるわけではないですが、あるところを狙っていきましょうという対応。オレゴンとか使えば間違いないんじゃないでしょうか。
// あと、 AWS::XXX の関数が入ったJoinの良い感じの書き方を知りたいです。

  SubnetPublic1a:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: !Ref SubnetPublic1aCidr
      AvailabilityZone: !Join
        - ''
        - - !Ref AWS::Region
          - 'a'
      Tags:
        - Key: Name
          Value: !Join ['-', ['sb', !Ref Prefix, 'public1a']]

ALBを作る

まず前提として、 AWS::ElasticLoadBalancing::LoadBalancer はCLB用。
AWS::ElasticLoadBalancingV2::XXX がALB用。2017/10/22時点ではNLBもV2で作れることを確認。

作成順

  1. AWS::ElasticLoadBalancingV2::LoadBalancer
    • Webコンソールでいうロードバランサーの項目をまず作成を行う
  2. AWS::ElasticLoadBalancingV2::TargetGroup
    • Webコンソールでいうターゲットグループの項目の作成を行う
    • ここはWebコンソールと違い、ALBと同時作成が行えるわけではない。
      • CloudFormationではALBとTGは別れているため、それぞれ作成する
  3. AWS::ElasticLoadBalancingV2::Listener
    • 最後にリスナーの設定を行う
    • ここはHTTPもしくはHTTPSで受けたリクエストをどのターゲットグループへ配るかの設定
  4. AWS::ElasticLoadBalancingV2::ListenerRule

コード

AWSTemplateFormatVersion: '2010-09-09'
Description: ALB Template

Parameters:
  Prefix:
    Type: String
  VPCId:
    Type: String
  SubnetPublic1a:
    Type: String
  SubnetPublic1c:
    Type: String
  ALBSg:
    Type: String

Resources:
  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Join ['-', ['tg', !Ref Prefix]]
      VpcId: !Ref VPCId
      # HealthCheck
      HealthCheckIntervalSeconds: 30
      HealthCheckPath: '/'
      HealthCheckPort: '80'
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 5
      UnhealthyThresholdCount: 2
      Matcher:
        HttpCode: '200'
      # Routing
      # MEMO: トラフィックポートの場合は 'traffic-port'
      Port: '80'
      Protocol: HTTP
      TargetType: 'instance'
      TargetGroupAttributes:
        # ターゲットの登録解除までの待機時間
        - Key: 'deregistration_delay.timeout_seconds'
          Value: 300

  ALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Type: 'application'
      Name: !Join ['-', ['alb', !Ref Prefix]]
      SecurityGroups: [!Ref ALBSg]
      IpAddressType: 'ipv4'
      Scheme: 'internet-facing'
      Subnets:
        - !Ref SubnetPublic1a
        - !Ref SubnetPublic1c
      # MEMO:
      #   LoadBalancerAttributesはLBのログの保存・削除保護・アイドルタイムアウトの設定を行う事が可能
      # 参考:
      #   ドキュメント
      #     http://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/APIReference/API_LoadBalancerAttribute.html
      #     http://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/application-load-balancers.html#load-balancer-attributes
      #   アイドルタイムアウトについて(CLB)
      #     http://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/classic/config-idle-timeout.html
      LoadBalancerAttributes:
        - Key: idle_timeout.timeout_seconds
          Value: 140

  HTTPListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      # Certificates: !Ref ACMArn
      DefaultActions:
        - Type: 'forward'
          TargetGroupArn: !Ref TargetGroup
      LoadBalancerArn: !Ref ALB
      Port: '80'
      Protocol: 'HTTP'
      # http://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/create-https-listener.html
      # SslPolicy: 'ELBSecurityPolicy-2016-08'

  ListenerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    Properties:
      Actions:
        - Type: 'forward'
          TargetGroupArn: !Ref TargetGroup
      # MEMO:
      #   リスナーの条件
      # 参考:
      #   http://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/APIReference/API_RuleCondition.html
      Conditions:
        - Field: 'path-pattern'
          Values: ['/img/*']
      ListenerArn: !Ref HTTPListener
      Priority: 10

TODO

  • ドレイニングの設定周りがよくわからないので調べる
    • 接続中のHTTPリクエストの処理後、ターゲットグループの idle_timeout.timeout_seconds だけ待つのか
    • 切断リクエストが来てから idle_timeout.timeout_seconds だけ待つのか