CloudFormationを使用して、NLBにセキュリティグループを設定する

2023/08/10、NLBがセキュリティグループをサポートすることが発表されました。

https://aws.amazon.com/jp/about-aws/whats-new/2023/08/network-load-balancer-supports-security-groups/

今回はCloudFormationを使用して、NLBにセキュリティグループを適用した構成を作成します。

構築する環境

Diagram of using CloudFormation to set up Security Groups in NLB.

基本的には以下のページの構成と同様です。

あわせて読みたい
EC2 Auto Scaling入門 – スケーリングポリシーなし 【EC2 Auto Scaling入門 - スケーリングポリシーなし】 EC2 Auto Scalingを利用することによって、任意の数のEC2インスタンスを起動し、アプリケーションの可用性を高め...

上記のページの構成からの変更点は、ALBではなくNLBを使用する点です。

このNLBにセキュリティグループを適用します。

構築する環境

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

https://github.com/awstut-an-r/awstut-saa/tree/main/01/006

テンプレートファイルのポイント解説

本ページは、NLBにセキュリティグループを適用する方法を中心に取り上げます。

プライベートサブネットにAuto Scalingグループを構築し、ELBに関連づける方法等については、以下のページをご確認ください。

あわせて読みたい
EC2 Auto Scaling入門 – スケーリングポリシーなし 【EC2 Auto Scaling入門 - スケーリングポリシーなし】 EC2 Auto Scalingを利用することによって、任意の数のEC2インスタンスを起動し、アプリケーションの可用性を高め...

セキュリティグループ

Resources:
  NLBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${Prefix}-NLBSecurityGroup"
      GroupDescription: Allow HTTP Only.
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: !Ref HTTPPort
          ToPort: !Ref HTTPPort
          CidrIp: 0.0.0.0/0

  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupName: !Sub "${Prefix}-InstanceSecurityGroup"
      GroupDescription: Allow HTTP from NLBSecurityGroup.
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: !Ref HTTPPort
          ToPort: !Ref HTTPPort
          SourceSecurityGroupId: !Ref NLBSecurityGroup
Code language: YAML (yaml)

2つのセキュリティグループを作成します。

1つ目はNLB用です。
全IPアドレスからのHTTP通信(80/TCP)を許可します。

2つ目はEC2インスタンス用です。
送信元にNLB用セキュリティグループを指定することで、同リソースを経由したインバウンドトラフィックを許可します。

NLB

Resources:
  NLB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Sub "${Prefix}-ALB"
      Scheme: internet-facing
      SecurityGroups:
        - !Ref NLBSecurityGroup
      Subnets:
        - !Ref PublicSubnet1
        - !Ref PublicSubnet2
      Type: network

  NLBTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      VpcId: !Ref VPC
      Name: !Sub "${Prefix}-NLBTargetGroup"
      Protocol: TCP
      Port: !Ref HTTPPort
      HealthCheckProtocol: TCP
      HealthyThresholdCount: !Ref HealthyThresholdCount
      HealthCheckIntervalSeconds: !Ref HealthCheckIntervalSeconds
      UnhealthyThresholdCount: !Ref UnhealthyThresholdCount

  NLBListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      DefaultActions:
        - TargetGroupArn: !Ref NLBTargetGroup
          Type: forward
      LoadBalancerArn: !Ref NLB
      Port: !Ref HTTPPort
      Protocol: TCP
Code language: YAML (yaml)

NLBを構築するために、3つのリソース(NLB本体、ターゲットグループ、リソース)を作成します。

今回、特にポイントの設定はNLB本体のSecurityGroupsプロパティです。
先ほどご説明したNLB用セキュリティグループを指定します。

(参考) 起動テンプレート

Resources:
  LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateData:
        IamInstanceProfile:
          Arn: !GetAtt InstanceProfile.Arn
        ImageId: !Ref ImageId
        InstanceType: !Ref InstanceType
        SecurityGroupIds:
          - !Ref InstanceSecurityGroup
        UserData: !Base64 |
          #!/bin/bash -xe
          yum update -y
          yum install -y httpd
          systemctl start httpd
          systemctl enable httpd
          ec2-metadata -i > /var/www/html/index.html
      LaunchTemplateName: !Sub "${Prefix}-LaunchTemplate"
Code language: YAML (yaml)

Auto Scalingグループ用の起動テンプレートです。
SecurityGroupIdsプロパティで、先述のEC2用セキュリティグループを指定します。

ユーザデータを使用して、インスタンスの初期化処理を定義します。
今回はApacheをインストール・起動後、インスタンスIDを書き込んだHTML(index.html)をルートディレクトリに配置します。

ユーザデータに関する詳細は以下のページをご確認ください。

あわせて読みたい
Linuxインスタンスの初期化方法4選 【Linuxインスタンスを初期化する4つの方法】 EC2インスタンスの起動時に初期化処理を実行する方法を考えます。 EC2インスタンスを構築時に初期化する以下の4つの手法を...

NLBがセキュリティグループに対応したことによって、大きなメリットがあります。
それはNLB配下のインスタンスのトラフィック制御が容易になったことです。

NLBがセキュリティグループの対応以前は、今回と同様の挙動を実現するためには手間のかかる作業が必要でした。
それはNLBでクライアントIPの保存を無効化した上で、NLBに割り当てられたプライベートアドレスを指定するという方法です。

こちらの詳細については、以下のページをご確認ください。

あわせて読みたい
CFNカスタムリソースを使用してNLBのプライベートアドレスを取得し、セキュリティグループの送信元に指... 【CloudFormationカスタムリソースを使用してNLBのプライベートアドレスを取得し、セキュリティグループの送信元に指定する】 ALBとは異なり、NLBにはセキュリティグル...

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

あわせて読みたい
CloudFormationのネストされたスタックで環境を構築する 【CloudFormationのネストされたスタックで環境を構築する方法】 CloudFormationにおけるネストされたスタックを検証します。 CloudFormationでは、スタックをネストす...

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • NLB:saa-01-006-ALB
  • NLBのDNS名:saa-01-006-ALB-e1094ac0c1da946d.elb.ap-northeast-1.amazonaws.com
  • NLBのターゲットグループ:saa-01-006-AutoScalingGroup
  • NLB用のセキュリティグループ:sg-03d85dadbf8cc1ad7
  • EC2インスタンス用のセキュリティグループ:sg-0a0aca4eeda6a6291

AWS Management Consoleから作成された各リソースを確認します。

セキュリティグループを確認します。

Detail of VPC 1.
Detail of VPC 2.

前者はNLB用です。
全アドレスからのHTTP通信(80/tcp)を許可する内容です。

後者はEC2インスタンス用です。
NLB用セキュリティグループからのHTTP通信(80/tcp)を許可する内容です。

NLBを確認します。

Detail of NLB 1.

正常にNLBが作成されています。
確かにNLBにセキュリティグループがアタッチされています。

Auto Scalingグループを確認します。

Detail of NLB 2.

グループ内に2つのインスタンスが配置されていることがわかります。

動作確認

準備が整いましたので、NLBにアクセスします。

$ curl http://saa-01-006-ALB-e1094ac0c1da946d.elb.ap-northeast-1.amazonaws.com
instance-id: i-0ee1c4b8d8eac321e

$ curl http://saa-01-006-ALB-e1094ac0c1da946d.elb.ap-northeast-1.amazonaws.com
instance-id: i-04a6075a54e5cb5f5
Code language: Bash (bash)

NLBを通じて2つのEC2インスタンスにアクセスすることができました。
つまりNLB用・EC2インスタンス用のセキュリティグループが正常に動作したということです。

まとめ

NLBにセキュリティグループを適用した構成を作成しました。