Posted at

CloudWatch Agentをインストールしてゲスト内メトリクスとログファイルデータを収集する (2台目以降)

CloudWatch Agentを起動済みのEC2インスタンス(Amazon Linux 2)にインストールしてゲスト内メトリクスとログファイル内データを収集します。本メモは2台目以降の設定方法です。

最初の1台目の手順はこちら


前提条件


  • AWS CLIがインストールされており、クレデンシャル/リージョンが設定されている。

  • JSONファイル検証用にjsonlintがインストールされている。

  • ログインできるEC2インスタンス(Linux) が起動されていること。今回はAmazon Linux 2。

  • EC2インスタンスがインターネットまたはVPCエンドポイント経由でCloudWatch、CloudWatch Logs、SSMエンドポイントにアクセスできる。

  • CloudWatch Agnentの1台目の構築時に、設定をSSMパラメータストアに保存している。


EC2実行用ロールの作成およびEC2インスタンスへの紐付け

RunCommandでCloudWatch Agentをインストール/構成するための"AmazonEC2RoleforSSM"ポリシーおよびCloudWatchAgentのための"CloudWatchAgentServerPolicy"ポリシーを持つロールを作成します。さらにEC2インスタンスにロールを紐付けるためにインスタンスプロファイルを作成してロールを付与し、インスタンスに紐付けます。

*"CloudWatchAgentAdminPolicy"はCloudWatch Agentのコンフィグを再利用するためSSMパラメータストアに書き込むための権限が含まれるため2台目以降は使用しない。


Assume Role Documentの作成


作業フォルダの作成


コマンド

ls -d ${HOME}/tmp/

# 存在しない場合
mkdir -p ${HOME}/tmp/



変数の設定


コマンド

# Assume Role Document ディレクトリ

DIR_IAM_ROLE_DOC="${HOME}/tmp"
# Role名
IAM_ROLE_NAME='CloudWatchAgentInstanceServerRole'
# Principle名
IAM_PRINCIPAL='ec2.amazonaws.com'


ファイル名の設定


コマンド

FILE_IAM_ROLE_DOC="${DIR_IAM_ROLE_DOC}/${IAM_ROLE_NAME}.json" \

&& echo ${FILE_IAM_ROLE_DOC}


Output例

/Users/xxxxx/tmp/CloudWatchAgentInstanceServerRole.json



Assume Role Documentの作成


コマンド

cat << EOF > ${FILE_IAM_ROLE_DOC}

{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "
${IAM_PRINCIPAL}"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF

cat ${FILE_IAM_ROLE_DOC}



Output例

{

"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}

jsonlintでjsonファイルが壊れていないかチェックします。問題なければ何も出力されません。


コマンド

jsonlint -q ${FILE_IAM_ROLE_DOC}



IAMロールの作成


コマンド

aws iam create-role \

--role-name ${IAM_ROLE_NAME} \
--assume-role-policy-document file://${FILE_IAM_ROLE_DOC}


Output例

{

"Role": {
"Path": "/",
"RoleName": "CloudWatchAgentInstanceServerRole",
"RoleId": "AROAJBP27QT6327XBN3VQ",
"Arn": "arn:aws:iam::xxxxxxxxxxxx:role/CloudWatchAgentInstanceServerRole",
"CreateDate": "2019-02-09T08:53:09Z",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
}
}


IAMポリシーのアタッチ


AmazonEC2RoleforSSM

変数の設定


コマンド

IAM_POLICY_NAME="AmazonEC2RoleforSSM"

IAM_POLICY_ARN=$( \
aws iam list-policies \
--scope AWS \
--max-items 1000 \
--query "Policies[?PolicyName==\`${IAM_POLICY_NAME}\`].Arn" \
--output text \
) \
&& echo "${IAM_POLICY_ARN}"


Output例

arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM


ポリシーをロールへアタッチ


コマンド

aws iam attach-role-policy \

--role-name ${IAM_ROLE_NAME} \
--policy-arn ${IAM_POLICY_ARN}


Output例

出力なし



CloudWatchAgentAdminPolicy

変数の設定


コマンド

IAM_POLICY_NAME="CloudWatchAgentServerPolicy"

IAM_POLICY_ARN=$( \
aws iam list-policies \
--scope AWS \
--max-items 1000 \
--query "Policies[?PolicyName==\`${IAM_POLICY_NAME}\`].Arn" \
--output text \
) \
&& echo "${IAM_POLICY_ARN}"


Output例

arn:aws:iam::aws:policy/CloudWatchAgentAdminPolicy


ポリシーをロールへアタッチ


コマンド

aws iam attach-role-policy \

--role-name ${IAM_ROLE_NAME} \
--policy-arn ${IAM_POLICY_ARN}


Output例

出力なし



アタッチされたポリシーの確認


コマンド

aws iam list-attached-role-policies \

--role-name ${IAM_ROLE_NAME} \
--query "AttachedPolicies[].PolicyName"


Output例

[

"AmazonEC2RoleforSSM",
"CloudWatchAgentServerPolicy"
]


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

変数の設定


コマンド

IAM_INSTANCE_PROFILE_NAME='CloudWatchAgentInstanceServerProfile'


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


コマンド

aws iam create-instance-profile \

--instance-profile-name ${IAM_INSTANCE_PROFILE_NAME}


Output例

{

"InstanceProfile": {
"Path": "/",
"InstanceProfileName": "CloudWatchAgentInstanceServerProfile",
"InstanceProfileId": "AIPAJJIV2ATCBNDDRTQXS",
"Arn": "arn:aws:iam::xxxxxxxxxxxx:instance-profile/CloudWatchAgentInstanceServerProfile",
"CreateDate": "2019-02-09T08:55:37Z",
"Roles": []
}


インスタンスプロファイルへのロールのアタッチ


コマンド

aws iam add-role-to-instance-profile \

--instance-profile-name ${IAM_INSTANCE_PROFILE_NAME} \
--role-name ${IAM_ROLE_NAME}


Output例

出力なし



EC2インスタンスへのインスタンスプロファイルのアタッチ


変数の設定

INSTANCE_ID="インスタンスプロファイルを紐付けるインスタンスID"


インスタンスへのアタッチ


コマンド

aws ec2 associate-iam-instance-profile \

--iam-instance-profile "Name=${IAM_INSTANCE_PROFILE_NAME}" \
--instance-id ${INSTANCE_ID}


Output例

{

"IamInstanceProfileAssociation": {
"AssociationId": "iip-assoc-086fefee2bcb2a5ac",
"InstanceId": "i-0ae3a2e7317e5e8d0",
"IamInstanceProfile": {
"Arn": "arn:aws:iam::xxxxxxxxxxxx:instance-profile/CloudWatchAgentInstanceServerProfile",
"Id": "AIPAJJIV2ATCBNDDRTQXS"
},
"State": "associating"
}
}


確認


コマンド

aws ec2 describe-iam-instance-profile-associations \

--query "IamInstanceProfileAssociations[?InstanceId==\`${INSTANCE_ID}\`].State"


Output例

[

"associated"
]


Systems Manager(SSM)からCloudWatch Agentをインストールする


マネージドインスタンスの登録確認

マネージドインスタンスとして登録されているかを確認します。今回はAmazon Linux 2を使用しているため初めからSSMエージェントがインストールされており、マネージドインスタンスとして認識されます。インストールされないOSの場合やバージョンが古い場合は別途インストール/アップデートが必要です。


コマンド

aws ssm describe-instance-information \

--query "InstanceInformationList[?InstanceId==\`${INSTANCE_ID}\`]"


Output例

 [

{
"InstanceId": "i-0ae3a2e7317e5e8d0",
"PingStatus": "Online",
"LastPingDateTime": 1549703111.672,
"AgentVersion": "2.3.372.0",
"IsLatestVersion": false,
"PlatformType": "Linux",
"PlatformName": "Amazon Linux",
"PlatformVersion": "2",
"ResourceType": "EC2Instance",
"IPAddress": "172.31.30.106",
"ComputerName": "ip-172-31-30-106.ap-northeast-1.compute.internal"
}
]


CloudWatch Agentのインストール


変数の設定


コマンド

INSTANCE_ID="インストール先のインスタンスID"

SSM_COMMAND_DOCUMENT_NAME="AWS-ConfigureAWSPackage"
SSM_COMMAND_TARGETS="Key=instanceids,Values=${INSTANCE_ID}"
SSM_COMMAND_PARAMETERS="action=Install, name=AmazonCloudWatchAgent, version=latest"


Run CommandでCloudWatch Agentをインストール


コマンド

aws ssm send-command \

--document-name ${SSM_COMMAND_DOCUMENT_NAME} \
--targets ${SSM_COMMAND_TARGETS} \
--parameters "${SSM_COMMAND_PARAMETERS}"


Output例

{

"Command": {
"CommandId": "3c303421-1328-4613-9602-d041533b24b1",
"DocumentName": "AWS-ConfigureAWSPackage",
        (...省略...)
"RequestedDateTime": 1549185898.031,
"Status": "Pending",
"StatusDetails": "Pending",
        (...省略...)
}



確認


コマンド

SSM_COMMAND_ID="3c303421-1328-4613-9602-d041533b24b1" #上記の結果からコピー

aws ssm list-command-invocations \
--command-id ${SSM_COMMAND_ID} \
--instance-id ${INSTANCE_ID} \
--query "CommandInvocations[].Status" \
--output text


Output例

Success



CloudWatch Agentの設定


collectdのインストール

このままCloudWatch Agentを起動するとcollectdがないと怒られるので、collectdをSSM RunCommandの"AWS-RunShellScript"ドキュメントを使用していインストールします。


変数の設定


コマンド

INSTANCE_ID="インストール先のインスタンスID"

SSM_COMMAND_DOCUMENT_NAME="AWS-RunShellScript"
SSM_COMMAND_TARGETS="Key=instanceids,Values=${INSTANCE_ID}"
SSM_COMMAND_PARAMETERS="commands=sudo amazon-linux-extras install -y epel && sudo yum -y install collectd"


RunCommandでcollectdをインストール


コマンド

aws ssm send-command \

--document-name ${SSM_COMMAND_DOCUMENT_NAME} \
--targets ${SSM_COMMAND_TARGETS} \
--parameters "${SSM_COMMAND_PARAMETERS}"


Output例

{

"Command": {
"CommandId": "da0bb8b3-9c9a-466f-a7e2-f4543ef11c49",
"DocumentName": "AWS-RunShellScript",
        (...省略...)
"RequestedDateTime": 1549185898.031,
"Status": "Pending",
"StatusDetails": "Pending",
        (...省略...)
}



確認


コマンド

SSM_COMMAND_ID="da0bb8b3-9c9a-466f-a7e2-f4543ef11c49" #上記の結果からコピー

aws ssm list-command-invocations \
--command-id ${SSM_COMMAND_ID} \
--instance-id ${INSTANCE_ID} \
--query "CommandInvocations[].Status" \
--output text


Output例

Success



CloudWatch Agentの構成、起動

SSM経由でCloudWatch Agentを構成、起動します。1台目を構築した際に設定がSSMパラメータストアに"AmazonCloudWatch-linux"というキーで保存されているためそちらを利用できます。


変数の設定


コマンド

INSTANCE_ID="インストール先のインスタンスID"

SSM_CONFIG_PARAMETER_NAME="AmazonCloudWatch-linux"
SSM_COMMAND_DOCUMENT_NAME="AmazonCloudWatch-ManageAgent"
SSM_COMMAND_TARGETS="Key=instanceids,Values=${INSTANCE_ID}"
SSM_COMMAND_PARAMETERS="action=configure, mode=ec2, optionalConfigurationSource=ssm, optionalConfigurationLocation=${SSM_CONFIG_PARAMETER_NAME}, optionalRestart=yes"


Run CommandでCloudWatch Agentを起動


コマンド

aws ssm send-command \

--document-name ${SSM_COMMAND_DOCUMENT_NAME} \
--targets ${SSM_COMMAND_TARGETS} \
--parameters "${SSM_COMMAND_PARAMETERS}"


Output例

{

"Command": {
"CommandId": "813175eb-8e52-4ffb-a833-d258eb3e7064",
"DocumentName": "AmazonCloudWatch-ManageAgent",
        (...省略...)
"RequestedDateTime": 1549190668.591,
"Status": "Pending",
"StatusDetails": "Pending",
        (...省略...)
}


確認


コマンド

SSM_COMMAND_ID="813175eb-8e52-4ffb-a833-d258eb3e7064" #上記の結果からコピー

aws ssm list-command-invocations \
--command-id ${SSM_COMMAND_ID} \
--instance-id ${INSTANCE_ID} \
--query "CommandInvocations[].Status" \
--output text


Output例

Success



取得されたメトリクス/ログの確認


メトリクス

CloudWatchにカスタムメトリクスのmem_used_percentが取得されています。image.png


ログ

CloudWatch Logsに/var/log/messagesのログが取得されています。

image.png


まとめ

今回はすでに起動済みのEC2インスタンスに対してCloudWatch Agentをインストールしましたが、EC2インスタンス起動時にインストールするにはUserDataを利用するのが良いでしょう。

参考: 新しいCloudWatch Agentを有効化したEC2オートスケール環境をCloudFormationで設定してみた

AMIに仕込む場合はログストリーム名がAMIを作成したインスタンスIDとなってしまうため起動時に再構成が必要後なるようです。

参考:CloudWatch Agent 仕込み済み AMI からEC2インスタンスを作成するときの注意


参考

AWS CLIの書き方はJAWS-UG CLI専門支部の過去資料が大変参考になります。

https://jawsug-cli.doorkeeper.jp/