ハンズオン(簡易版): CFnテンプレート入門(EC2::VolumeAttachment)

事前作業2.8. CFnリソースファイルの更新 (EC2::Instance IamInstanceProfile Instance0)

手順の目的 [why]

リソース(Instance0)のCloudFormationリソースファイルを更新します。

設定値の指定

設定値の指定

手順に必要な設定値を変数に格納をします。

1. CloudFormationリソース名

CloudFormationリソース名を指定します。

変数の設定:

TEMPLATE_CFN_RESOURCE_NAME='Instance0'

2. リソースファイル名

リソースファイル用ディレクトリを指定します。

変数の設定:

DIR_TEMPLATE_CFN_RESOURCE="${HOME}/environment/conf-handson-cli-cfn-ec2-VolumeAttachment/resources"

リソースファイル名を指定します。

変数の設定:

FILE_TEMPLATE_CFN_RESOURCE="${DIR_TEMPLATE_CFN_RESOURCE}/${TEMPLATE_CFN_RESOURCE_NAME}.txt" \
  && echo ${FILE_TEMPLATE_CFN_RESOURCE}

結果(例):

${HOME}/environment/conf-handson-cli-cfn-ec2-VolumeAttachment/resources/Instance0.txt

3. インスタンスプロファイルのリソース名

インスタンスプロファイルのリソース名の指定します。

変数の設定:

TEMPLATE_CFN_RESOURCE_NAME_IAM_INSTANCE_PROFILE="InstanceProfile0"

設定値の確認

各変数に正しい設定値が格納されていることを確認しながら保存します。

変数の確認:

cat << END

  # 1. TEMPLATE_CFN_RESOURCE_NAME:"Instance0"
       TEMPLATE_CFN_RESOURCE_NAME="${TEMPLATE_CFN_RESOURCE_NAME}"
  # 2. FILE_TEMPLATE_CFN_RESOURCE:"${HOME}/environment/conf-handson-cli-cfn-ec2-VolumeAttachment/resources/Instance0.txt"
       FILE_TEMPLATE_CFN_RESOURCE="${FILE_TEMPLATE_CFN_RESOURCE}"
  # 3. TEMPLATE_CFN_RESOURCE_NAME_IAM_INSTANCE_PROFILE:"InstanceProfile0"
       TEMPLATE_CFN_RESOURCE_NAME_IAM_INSTANCE_PROFILE="${TEMPLATE_CFN_RESOURCE_NAME_IAM_INSTANCE_PROFILE}"

END

下段の変数が入っていない、もしくは上段と同等の値が入っていない場合は、それぞれの手順番号に戻って変数の設定を行います。

処理の実行

CFnリソースファイルを更新します。

変数の確認:

cat << END

  # FILE_TEMPLATE_CFN_RESOURCE:"${HOME}/environment/conf-handson-cli-cfn-ec2-VolumeAttachment/resources/Instance0.txt"
    FILE_TEMPLATE_CFN_RESOURCE="${FILE_TEMPLATE_CFN_RESOURCE}"
  # TEMPLATE_CFN_RESOURCE_NAME_IAM_INSTANCE_PROFILE:"InstanceProfile0"
    TEMPLATE_CFN_RESOURCE_NAME_IAM_INSTANCE_PROFILE="${TEMPLATE_CFN_RESOURCE_NAME_IAM_INSTANCE_PROFILE}"

END

コマンド:

if [ ! $( grep 'IamInstanceProfile:' ${FILE_TEMPLATE_CFN_RESOURCE}) ];then
cat << EOF >> ${FILE_TEMPLATE_CFN_RESOURCE}
      IamInstanceProfile: !Ref ${TEMPLATE_CFN_RESOURCE_NAME_IAM_INSTANCE_PROFILE}
EOF
fi

cat ${FILE_TEMPLATE_CFN_RESOURCE}

結果(例):

Instance0:
  Type: AWS::EC2::Instance
  Properties:
    ImageId: ami-09ebacdc178ae23b7
    InstanceType: t3.micro
    Tags:
      - Key: Name
        Value: !Ref AWS::StackName
    NetworkInterfaces:
      - DeviceIndex: "0"
        SubnetId: !Ref Subnet0
        GroupSet:
        - !Ref SecurityGroup0
        AssociatePublicIpAddress: "true"
    UserData: !Base64 |
      #!/bin/bash
      # configure sshd
      cat << EOF >> /etc/ssh/sshd_config
      Port 22022
      EOF
      systemctl restart sshd.service
      # yum
      yum update -y
      #
      # logs agent
      #
      readonly EC2_METADATA_SECOND='900'
      readonly EC2_METADATA_TOKEN=$( \
        curl -s \
          -X PUT "http://169.254.169.254/latest/api/token" \
          -H "X-aws-ec2-metadata-token-ttl-seconds: ${EC2_METADATA_SECOND}" \
      )
      readonly EC2_METADATA_HEADER="X-aws-ec2-metadata-token: ${EC2_METADATA_TOKEN}"
      readonly EC2_REGION_NAME=$( \
        curl -s -H "${EC2_METADATA_HEADER}" \
          http://169.254.169.254/latest/meta-data/placement/availability-zone \
        | sed -e 's/[a-z]*$//' \
      )
      # install cloudwatch agent
      readonly URL_DOWNLOAD_LINK="https://s3.${EC2_REGION_NAME}.amazonaws.com/amazoncloudwatch-agent-${EC2_REGION_NAME}/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm"
      cd /tmp/
      wget ${URL_DOWNLOAD_LINK}
      rpm -U ./amazon-cloudwatch-agent.rpm
      # setup cloudwatch agent
      readonly LOGS_CONF='/opt/aws/amazon-cloudwatch-agent/etc/logs.conf'
      # logs.conf
      cat << EOF > ${LOGS_CONF}
      {
        "agent": {
          "logfile": "/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log"
        },
        "logs": {
          "logs_collected": {
            "files": {
              "collect_list": [
                {
                  "file_path": "/var/log/secure",
                  "log_group_name": "/var/log/secure",
                  "timezone": "UTC"
                }
              ]
            }
          },
          "log_stream_name": "{instance_id}",
          "force_flush_interval" : 15
        }
      }
      EOF
      # start cloudwatch agent
      /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
        -a fetch-config \
        -m ec2 \
        -c file:${LOGS_CONF} \
        -s
      #
      # disk format (sdh)
      #
      DEVICE_FILE_NAME="sdh"
      MOUNT_POINT_NAME="/mnt-handson-cli-ebs"
      DISK_TYPE='xfs'
      DISK_TARGET="/dev/${DEVICE_FILE_NAME}"
      # format disk
      mkfs \
         -t ${DISK_TYPE} \
         ${DISK_TARGET}
      # make mount point
      mkdir ${MOUNT_POINT_NAME}
      # update fstab
      cp /etc/fstab /etc/fstab.$(date +%s)
      DEVICE_LINK_NAME=$( \
        file -s ${DISK_TARGET} \
        | sed "s/^.*\`//" \
        | sed "s/'$//" \
      )
      DISK_UUID=$( \
        sudo blkid \
          | grep /dev/${DEVICE_LINK_NAME} \
          | sed "s/^.*UUID=\"//" \
          | sed "s/\".*$//" \
      )
      DISK_TYPE_TARGET=$( \
        sudo blkid \
          | grep /dev/${DEVICE_LINK_NAME} \
          | sed "s/^.*TYPE=\"//" \
          | sed "s/\".*$//" \
      )
      if [ ! $( grep ${DISK_UUID} /etc/fstab ) ]; then
        sh -c "echo \"UUID=${DISK_UUID}     ${MOUNT_POINT_NAME} ${DISK_TYPE_TARGET} defaults,nofail  0  2\" >> /etc/fstab"
      fi
      # mount disk
      mount ${MOUNT_POINT_NAME}
      chown ec2-user:ec2-user ${MOUNT_POINT_NAME}
    KeyName: handson-cli-cfn-ec2-VolumeAttachment-keypair
    IamInstanceProfile: !Ref InstanceProfile0

完了確認

「リソースファイル"${HOME}/environment/conf-handson-cli-cfn-ec2-VolumeAttachment/resources/Instance0.txt"に'IamInstanceProfile'プロパティが存在する。」ことを確認します。

コマンド:

cat ${FILE_TEMPLATE_CFN_RESOURCE} \
  | grep 'IamInstanceProfile:'

結果(例):

IamInstanceProfile: !Ref InstanceProfile0

手順の完了