【NestedStack】Web3層のオートスケーリング構成をCloudFormationで爆速構築したい

AWS

はじめに

今回は、AWSの入門でよくみかけるWeb3層構成にオートスケーリングの要素を追加しCloudFormationで、20分程度(爆速?)で構築したいと思います。

スタックの作成手順を簡素化するためにネストされたスタックを使用します。以下を参考にご覧いただければと思います。

テンプレートの更新箇所は以下を参考に作成していきます。

AWS CloudFormation で Auto Scaling グループを作成する - Amazon EC2 Auto Scaling
AWS CloudFormation を使用して Auto Scaling グループを作成する方法について説明します。

構成図

事前準備

CloudFormationテンプレートのダウンロード

CloudFormationテンプレートは以下にございます。

ダウンロードしてデスクトップなど任意のフォルダに保存します。

aws-improvement-tips/nestedstack-basic-struct-autoscaling at main · kosments/aws-improvement-tips
Contribute to kosments/aws-improvement-tips development by creating an account on GitHub.

※その他のファイルも後述の手順で使用するためダウンロードしておきます

CloudFormation:YAMLテンプレートのポイント

以前から追加されたYAMLテンプレートのポイントを記述します。

  1. LaunchTemplate:
    • AWS::EC2::LaunchTemplateリソースを使用して、EC2インスタンスの起動テンプレートを定義しています。
    • KeyName、ImageId、InstanceType、IamInstanceProfile、NetworkInterfacesなどのプロパティを指定しています。
    • UserDataセクションでは、EC2インスタンス起動時に実行されるスクリプトを定義しています。このスクリプトは、WordPressの設定、EFSのマウント、DBパラメータの取得などを行っています。
      • EFSについては、WordPressのコンテンツデータが配置されていることを想定してマウントしています。
  2. AutoScalingGroup:
    • AWS::AutoScaling::AutoScalingGroupリソースを使用して、AutoScalingグループを定義しています。
    • VPCZoneIdentifierプロパティでは、!Split関数と!ImportValue関数を使用して、パブリックサブネットIDのリストを取得しています。
    • LaunchTemplateプロパティでは、先ほど定義したLaunchTemplateを参照しています。
    • TargetGroupARNsプロパティでは、!ImportValue関数を使用して、HTTP用のターゲットグループをインポートしています。
    • DesiredCapacity、MaxSize、MinSizeプロパティを使用して、AutoScalingグループの desired/max/min のインスタンス数を設定しています。
    • Tagsプロパティでは、AutoScalingグループとそのインスタンスにタグを割り当てています。PropagateAtLaunch: trueを指定することで、これらのタグが起動されたインスタンスに伝播されます。
Resources:
  # ------------------------------ #
  # LaunchTemplate
  # ------------------------------ #
  LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateName: !Join ["-", [!Ref TagEnv, !Ref TagApplication, launchtemplate]]
      LaunchTemplateData:
        KeyName: !Ref Keypair
        ImageId: !Ref AmiId
        InstanceType: t2.micro
        IamInstanceProfile:
          Arn: !GetAtt Ec2InstanceProfile.Arn
        NetworkInterfaces: 
        - AssociatePublicIpAddress: true
          DeviceIndex: 0
          SubnetId: !ImportValue testPublicSubnet1a
          Groups:
            - !ImportValue testEC2SecurityGroup
        TagSpecifications:
        - ResourceType: instance
          Tags:
          - Key: Name
            Value: !Join ["-", [!Ref TagEnv, !Ref TagApplication, ec2-webap-server]]
        UserData: 
          Fn::Base64: |
            #!/bin/bash
            # Set variables
            aws configure set region ap-northeast-1
            DB_NAME_PARAM="/wordpress/DB_NAME"
            DB_USER_PARAM="/wordpress/DB_USER"
            DB_PASSWORD_PARAM="/wordpress/DB_PASSWORD"
            DB_HOST_PARAM="/wordpress/DB_HOST"
            EFS_ID_PARAM="/wordpress/EFS_ID"
            EFS_ID=$(aws ssm get-parameter --with-decryption --name $EFS_ID_PARAM --query "Parameter.Value" --output text)
            WEB_ROOT="/var/www/html/"
            WP_CONFIG_SAMPLE="$WEB_ROOTwp-config-sample.php"
            WP_CONFIG="$WEB_ROOTwp-config.php"

            yum -y update
            amazon-linux-extras install php7.2 -y
            yum -y install mysql httpd php-mbstring php-xml gd php-gd
            systemctl enable httpd.service
            systemctl start httpd.service
            systemctl status httpd.service
            wget <http://ja.wordpress.org/latest-ja.tar.gz> ~/
            tar zxvf /latest-ja.tar.gz
            yum -y install amazon-efs-utils

            # Add EFS mount to /etc/fstab
            echo "$EFS_ID:/ /var/www/html efs _netdev,noresvport,tls,iam 0 0" >> /etc/fstab
            sudo mount -fav
            mount -t efs $EFS_ID $WEB_ROOT
            chown apache:apache -R /var/www/html
            cd /var/www/html

            # Get parameter values from SSM Parameter Store
            DB_NAME=$(aws ssm get-parameter --name $DB_NAME_PARAM --query "Parameter.Value" --output text)
            DB_USER=$(aws ssm get-parameter --with-decryption --name $DB_USER_PARAM --query "Parameter.Value" --output text)
            DB_PASSWORD=$(aws ssm get-parameter --with-decryption --name $DB_PASSWORD_PARAM --query "Parameter.Value" --output text)
            DB_HOST=$(aws ssm get-parameter --with-decryption --name $DB_HOST_PARAM --query "Parameter.Value" --output text)

            # Copy wp-config-sample.php to wp-config.php
            cp $WP_CONFIG_SAMPLE $WP_CONFIG

            # Update wp-config.php file
            sed -i -e "s/define( 'DB_NAME', '.*' );/define('DB_NAME', '$DB_NAME');/" $WP_CONFIG
            sed -i -e "s/define( 'DB_USER', '.*' );/define('DB_USER', '$DB_USER');/" $WP_CONFIG
            sed -i -e "s/define( 'DB_PASSWORD', '.*' );/define('DB_PASSWORD', '$DB_PASSWORD');/" $WP_CONFIG
            sed -i -e "s/define( 'DB_HOST', '.*' );/define('DB_HOST', '$DB_HOST');/" $WP_CONFIG
            #memory config fix
            sed -i -e "s/pm = dynamic/pm = static/" /etc/php-fpm.d/www.conf
            sed -i -e "s/pm.max_children = 50/pm.max_children = 3/" /etc/php-fpm.d/www.conf
            systemctl restart  php-fpm
  # ------------------------------------------------------------#
  # AutoScaling Group
  # ------------------------------------------------------------#
  AutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      AutoScalingGroupName: !Join ["-", [!Ref TagOwner, !Ref TagApplication, !Ref TagEnv, !Ref TagUser, asg]]
      VPCZoneIdentifier: !Split [",", !ImportValue testPublicSubnetIds]
      LaunchTemplate:
        LaunchTemplateId: !Ref LaunchTemplate
        Version: !GetAtt LaunchTemplate.LatestVersionNumber
      TargetGroupARNs: 
        - !ImportValue testHttpTargetGroup
      DesiredCapacity: 2
      MaxSize: 2
      MinSize: 2
      Tags:
        - Key: Name
          Value: !Join ["-", [!Ref TagOwner, !Ref TagApplication, !Ref TagEnv, !Ref TagUser, asg]]
          PropagateAtLaunch: true

構築手順

1.S3バケットの作成

任意のターミナルを開きをカレントディレクトリに以下のファイルを配置して、コマンドを実行します。

test-cfn-template-bucket.yml

aws cloudformation create-stack --region ap-northeast-1 --stack-name test-cfn-template-bucket --template-body file://test-cfn-template-bucket.yml

2.テンプレートをS3にアップロード

作成したバケットに子テンプレートとなる以下のファイルをアップロードしておきます。

  • test-nw.yml
  • test-rds.yml
  • test-alb.yml
  • test-asg.yml

3.親スタックの作成

  • 任意のターミナルソフトを開き、保存しておいた以下のYAMLテンプレートをカレントディレクトリに配置します。
$ ls
root-stack.yml
  • リソースの作成:以下のコマンドを実行します。
aws cloudformation create-stack --region ap-northeast-1 --stack-name test-root-stack --template-body file://test-root-stack.yml

各リソースが作成されました。

補足:スタックの作成_GUI

マネジメントコンソールからスタックの作成を行う手順も記載していますので、GUIの方がわかりやすいという方はこちらをお試しください。

手順は、以下の通りで、リンクにも詳細がございます。

  1. CloudFormation画面を開きスタックの作成>新しいソースを使用(標準)を選択
  2. テンプレートの準備完了>テンプレートファイルのアップロードを選択して、保存したymlを選択
  3. スタックに任意の名称を入力して、パラメータは環境に合わせて変更>次へを選択。
  4. スタックオプションは特に変更せず、次へを選択
  5. レビュー画面を確認して送信を選択

まとめ

今回は、NestedStackを用いて、AutoScaling構成を作成しました。

NestedStackはS3に子テンプレートを配置する必要があるため、こちらを自動化も含めたPipelineの作成なども検証してみたいと思います。

最後までご覧いただきありがとうございました。

コメント

タイトルとURLをコピーしました