LoginSignup
0

More than 1 year has passed since last update.

Organization

Ubuntu 20.04 LTSにCloudWatch エージェントをインストールして設定ファイルを作成するCFnを作った話

はじめに

CloudFormationのヘルパースクリプト、とっても便利ですよね。テンプレートにスクリプトを定義しておくだけでEC2を作成するときにソフトウェアをインストールしたりサービスを開始したりできちゃいます。

今回は、そのヘルパースクリプトを使ってCloudwatch agentのインストールと設定ファイルの作成を行う機会があったので忘れないように書いていきたいと思います。

構築する環境

  • Ubuntu Server 20.04 LTS (HVM), SSD Volume Type(ami-0f2dd5fc989207c82)

CFnをつくる

ヘルパースクリプトの準備

さっそく、ヘルパースクリプトを使ってcloudwatch agentをインストール!
といきたいところですが、残念ながらUbuntuにはデフォルトでインストールされていません。なので、まずはaws-cfn-bootstrapパッケージをダウンロードしていきます。EC2が起動するときに実行されるUserDateにヘルパースクリプトに下記のスクリプトを追加します。


apt-get update
apt-get install -y python-setuptools
mkdir -p /opt/aws/bin
apt-get install -y wget
wget https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz
python3 -m easy_install --script-dir /opt/aws/bin aws-cfn-bootstrap-py3-latest.tar.gz

▶ ヘルパースクリプトリファレンス

CloudWatchエージェントのインストール

次に、cloudwatchエージェントをインストールします。これも同様にUserDateに追加します。


wget https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb -O /tmp/amazon-cloudwatch-agent.deb
dpkg -i /tmp/amazon-cloudwatch-agent.deb
/opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource EC2 --region ${AWS::Region} --configsets default
/opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackId} --resource EC2 --region ${AWS::Region}

amazon-cloudwatch-agent.jsonの作成

ヘルパースクリプトとcloudwatchエージェントのインストールまでできたので、次は設定ファイルのamazon-cloudwatch-agent.jsonを作成していきましょう。設定ファイルの書き方は公式ドキュメント を参考にしました。

ヘルパースクリプトの作成

次はようやくヘルパースクリプトです。
AWS::CloudFormation::Initタイプを使うことでcfn-init ヘルパースクリプト用のメタデータを EC2に取り込むことができます。

  • cfn-hup
    リソースのメタデータの変更を検出して変更された時にユーザーが指定した操作を実行してくれるデーモンさんです。今回はトリガーとしてスタックの更新イベントを検知していて、検知するとhooks.d配下の設定ファイルにあるアクションが実行されます。

  • hooks.conf 設定ファイル
    cfn-hupデーモンが定期的に呼び出すユーザーアクションが定義されてます。

  • cfn-hup.conf 設定ファイル
    cfn-hupデーモンのターゲットとなるスタックの名前とAWS認証情報が格納されてます。

今回は、スタックを新規で作成するときはdefaultに、スタックの更新でメタデータを更新するときにはUpdateEnvironmentの方に行くようにしています。

  EC2:
    Type: AWS::EC2::Instance
    Metadata:
      AWS::CloudFormation::Init:
        configSets:
          default:
            - "01_setupCfnHup"
            - "02_config_amazon-cloudwatch-agent"
            - "03_restart_amazon-cloudwatch-agent"
          UpdateEnvironment:
            - "02_config_amazon-cloudwatch-agent"
            - "03_restart_amazon-cloudwatch-agent"

        01_setupCfnHup:
          files:
            /etc/cfn/cfn-hup.conf:
              content: !Sub |
                [main]
                stack=${AWS::StackName}
                region=${AWS::Region}
                interval=1
              mode: '000400'
              owner: root
              group: root
            /etc/cfn/hooks.d/cfn-auto-reloader.conf:
              content: !Sub |
                [cfn-auto-reloader-hook]
                triggers=post.update
                path=Resources.EC2.Metadata.AWS::CloudFormation::Init
                action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource EC2 --configsets UpdateEnvironment --region ${AWS::Region}
                runas=root
              mode: '000400'
              owner: root
              group: root
            /lib/systemd/system/cfn-hup.service:
              content: !Sub |
                [Unit]
                Description=cfn-hup daemon
                [Service]
                Type=simple
                ExecStart=/opt/aws/bin/cfn-hup
                Restart=always
                [Install]
                WantedBy=multi-user.target
          commands:
            01enable_cfn_hup:
              command: "systemctl enable cfn-hup.service"
            02start_cfn_hup:
              command: "systemctl start cfn-hup.service"
        02_config_amazon-cloudwatch-agent:
          files:
            /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json:
              content: !Sub |
                {
                  // ここに amazon-cloudwatch-agent.json を書く//
                }
              mode: '000644'
              owner: root
              group: root

        03_restart_amazon-cloudwatch-agent:
          commands:
            01_stop_service:
              command: "/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a stop"
            02_start_service:
              command: "/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json"


ちょっとつまったところなのですが、「03_restart_amazon-cloudwatch-agent」のコマンド

/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -s -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json

ではjsonファイルをtoml形式の設定ファイルamazon-cloudwatch-agent.tomlに変換して、エージェントを開始させているようです。なのでこのCFnで作成したEC2には、amazon-cloudwatch-agent.jsonというファイルは存在しません。

CloudWatchエージェントのためのロールの作成

AWS リソースにアクセスするにはアクセス権限が必要です。EC2に必要な権限を与えたIAMロールを作成していきましょう。
以下のポリシーをアタッチしたロールCloudwatchRoleを作成しました。

  • AWSマネージドポリシー
    • CloudWatchAgentServerPolicy
    • CloudWatchAgentAdminPolicy
    • AmazonSSMManagedInstanceCore
  • カスタムポリシー
    • 今回はS3とlogsにアクセス許可をするポリシーをつけました。状況に合わせてよきように。
  CloudwatchRole:
    Type: AWS::IAM::Role
    Properties: 
      RoleName: "CloudwatchRole"
      Path: /
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - ec2.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: CloudwatchRolePolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement: 
                  - Effect: Allow
                    Action:
                      // 省略 //
                    Resource: '*'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
        - arn:aws:iam::aws:policy/CloudWatchAgentAdminPolicy
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

インスタンスプロファイルの作成

最後に、先ほど作成したロールをEC2に渡すためにインスタンスプロファイルを作成します。

  CWAgentInstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Path: "/"
      Roles:
      - !Ref CloudwatchRole

おわりに

CloudFormationを作成するのにいろいろとはまりましたが、CFnでぱぱっとできるとウィザードでポチポチ設定していくよりも簡単ですね!

まだまだ分からないことだらけのCloudFormation。奥が深い。

(他にもっといい方法があるよ、ここ間違えてるよ、というところがありましたら教えていただけると嬉しいです!)

参考サイト

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
What you can do with signing up
0