AWS EC2インスタンスで、OSのテンプレートに入れておくと便利なもの


AWSでEC2インスタンスのOSといえば、いつもAmazon Linux2を使っていた。昔はAmazon Linuxの時代もあったけれど、いつの間にかサポート期限が切れて、AL2切替対応とかを騒ぎながらやってた時期もあったな。。。

Amazon Linux2も気が付けばサポート期限が近い。2025年まで期限はあるが、5年以上使う場合、ライフサイクルが短い。
このためRed Hat Enterprise Linux を選定したが、使ってるディストリビューションが同じFedoraだから、さほど困ることはなかった。ただ、ハマりポイントはあるので、そこをご紹介。

AWSで複数のEC2インスタンスを構築するとき、1台マスター的なOSテンプレートを作って、それをAMIコピーするとデプロイの時短となる。VMware時代もやっていた手法。

備忘兼メモ。以下はLinux（RHEL8）での手順だが、手順は異なれど、Windowsも同様に設定しておくといいと思います。

# 前提
・EC2インスタンスがインターネットに接続できること。
※またはSSMのエンドポイントが接続できるインスタンスであること。
・RedHatEnterpriseLinuxであること。
※AmazonLinux2ではSSMAgentは初回から導入済みのため実施不要、CloudwatchAgentのみ。

# SSM Agent
俗に言うセッションマネージャーというやつ。AWSマネジメントコンソールからサーバを操作したいとき、SSMエージェントを入れておくとセッションマネージャから操作が可能。セッションマネージャとは、VMwareでいうvCenter。ちなみにAmazonLinux2ではインストール済のため不要。

### SSM Agent導入方法
[Red Hat Enterprise Linux インスタンスに SSM Agent を手動でインストールする](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/agent-install-rhel.html)

```shell-session:インストール
$ sudo dnf install -y https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazoon-ssm-agent.rpm
・・・（以下インストールが続く）
Updating Subscription Management repositories.
・・・
```
「ap-northeast-1」はインスタンスのリージョンを記載。


```shell-session:状態確認
$ sudo systemctl status amazon-ssm-agent
　 amazon-ssm-agent.service - amazon-ssm-agent
   Loaded: loaded (/etc/systemd/system/amazon-ssm-agent.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2022-07-13 02:53:27 UTC; 31s ago
 Main PID: 4937 (amazon-ssm-agen)
    Tasks: 13 (limit: 4700)
   Memory: 25.0M
   CGroup: /system.slice/amazon-ssm-agent.service
           tq4937 /usr/bin/amazon-ssm-agent
           mq4993 /usr/bin/ssm-agent-worker
```

インストールはできた。起動して次回以降、自動で起動するように設定

```shell-session:自動起動
$ sudo systemctl enable amazon-ssm-agent
```

念為リスタート。
```shell-session:再起動
$ sudo systemctl restart amazon-ssm-agent
```

起動確認
```shell-session:起動確認
$ sudo systemctl status amazon-ssm-agent
 amazon-ssm-agent.service - amazon-ssm-agent
    Loaded: loaded (/etc/systemd/system/amazon-ssm-agent.service; enabled; vendor preset: disabled)
    Active: active (running) since Wed 2022-07-13 02:55:14 UTC; 11s ago
  Main PID: 5042 (amazon-ssm-agen)
     Tasks: 12 (limit: 4700)
    Memory: 19.1M
    CGroup: /system.slice/amazon-ssm-agent.service
            tq5042 /usr/bin/amazon-ssm-agent
            mq5048 /usr/bin/ssm-agent-worker
```


# CloudWatch Agent
意外に忘れがちなこのエージェント。これがないと、Cloudwatchでメモリ使用率が見れないのと、CloudwatchLogsにログを送信できないので、必ず入れておく。
[コマンドラインを使用して CloudWatch エージェントをダウンロードおよび設定する](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/download-cloudwatch-agent-commandline.html)

### CloudWatch Agent導入方法

CWAはPythonが必要なので、事前に導入する。
```shell-session:Python3インストール
$ sudo yum -y install python3
・・・（以下インストールが続く）
Updating Subscription Management repositories.
・・・
```

```shell-session:Python3導入確認
$ python3 --version
Python 3.6.8
```

公式にwgetで入れろと書いてあるので、wgetを入れておく。他でもいいと思うけど一応。
```shell-session:wgetインストール
$ sudo dnf install wget
・・・（以下インストールが続く）
Updating Subscription Management repositories.
・・・
```
wgetがgetできたので、ここでようやくCWAをgetしに行く。
```shell-session:CloudwatchAgentダウンロード
$ sudo wget https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
```

カレントにrpmがあることを確認。

```shell-session
$ ll
 -rw-r--r--. 1 root root 49257016 Jul 10 02:53 amazon-cloudwatch-agent.rpm
```

CloudwatchAgentをインストール。
```shell-session:CWAインストール
$ sudo rpm -U ./amazon-cloudwatch-agent.rpm
create group cwagent, result: 0
create user cwagent, result: 0
create group aoc, result: 0
create user aoc, result: 0
```


ここで設定終わって起動できるか、と思いきや、CWAの起動にこける。
なにやらいくつかの前提パッケージ（Collectdとか）を入れてないとダメとのこと。なので、案内に従って以下を入れる。
[CentOS、RHEL、または Amazon Linux を実行している Amazon EC2 インスタンスの EPEL リポジトリを有効にするにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-enable-epel/)

```shell-session:RHEL 8 用の EPEL リリースパッケージをインストール。
$ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -y
・・・（以下インストールが続く）
Updating Subscription Management repositories.
```
なんでこれ↓やってたのかもはや忘れてしまったが、必要でやってた記憶。開発者向けリポジトリなので、怪しいリポジトリではない。
```shell-session:
$ sudo dnf config-manager --set-enabled codeready-builder-for-rhel-8-rhui-rpms
```

> EPELは、EnterpriseLinux用のExtraPackagesの略で、Fedoraチームが提供する無料のオープンソースリポジトリです。 EPELは、CentOS、RedHat、Oracle Linux、ScientificLinuxディストリビューション用の追加または補足のソフトウェアパッケージを提供します。
[RHEL8にEPELリポジトリをインストールする方法](https://ja.linux-console.net/?p=769#gsc.tab=0)

dnf使ったりyum使ったりで恐縮ですが、以下リンクのとおり、とりあえずyumでepel-releaseインストール。
[collectdをインストールしてサーバの監視をしよう！](https://genchan.net/it/server/8088/)

```shell-session:epel-releaseをインストール。
$ sudo yum -y install epel-release
・・・（以下インストールが続く）
Updating Subscription Management repositories.
```

ついにここでcollectdをインストール。
```shell-session:collectdをインストール。
$ sudo yum -y install collectd
・・・（以下インストールが続く）
Updating Subscription Management repositories.
```

ここでやっとCloudwatchエージェントを起動してみる。
```shell-session:Cloudwatchエージェントを起動
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws//amazon-cloudwatch-agent/bin/config.json -s
（以下は起動ログ）
 ****** processing amazon-cloudwatch-agent ******
 /opt/aws/amazon-cloudwatch-agent/bin/config-downloader --output-dir /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d --download-source file:/opt/aws/amazon-cloudwatch-agent/bin/config.json --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml --multi-config default
 I! Trying to detect region from ec2
 2022/07/13 04:14:22 D! [EC2] Found active network interface
 Successfully fetched the config and saved in /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/file_config.json.tmp
 Start configuration validation...
 /opt/aws/amazon-cloudwatch-agent/bin/config-translator --input /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --input-dir /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d --output /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml --multi-config default
 2022/07/13 04:14:22 Reading json config file path: /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/file_config.json.tmp ...
 2022/07/13 04:14:22 I! Valid Json input schema.
 I! Detecting run_as_user...
 I! Trying to detect region from ec2
 2022/07/13 04:14:22 D! [EC2] Found active network interface
 No csm configuration found.
 No log configuration found.
 Configuration validation first phase succeeded
 /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -schematest -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml
 Configuration validation second phase succeeded
 Configuration validation succeeded
 amazon-cloudwatch-agent has already been stopped
 Created symlink /etc/systemd/system/multi-user.target.wants/amazon-cloudwatch-agent.service ・・ /etc/systemd/system/amazon-cloudwatch-agent.service.
 Redirecting to /bin/systemctl restart amazon-cloudwatch-agent.service

```

起動できた！というわけで、CWAの初期設定ウィザードを立ち上げる。
よしなに初期設定する。
```shell-session:よしなにCloudwatch初期設定
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard
 ================================================================
 = Welcome to the Amazon CloudWatch Agent Configuration Manager =
 =                                                              =
 = CloudWatch Agent allows you to collect metrics and logs from =
 = your host and send them to CloudWatch. Additional CloudWatch =
 = charges may apply.                                           =
 ================================================================
 On which OS are you planning to use the agent?
 1. linux
 2. windows
 3. darwin
 default choice: [1]:
 1
 Trying to fetch the default region based on ec2 metadata...
 Are you using EC2 or On-Premises hosts?
 1. EC2
 2. On-Premises
 default choice: [1]:
 1
 Which user are you planning to run the agent?
 1. root
 2. cwagent
 3. others
 default choice: [1]:
 1
 Do you want to turn on StatsD daemon?
 1. yes
 2. no
 default choice: [1]:
 1
 Which port do you want StatsD daemon to listen to?
 default choice: [8125]
 8125
 What is the collect interval for StatsD daemon?
 1. 10s
 2. 30s
 3. 60s
 default choice: [1]:
 1
 What is the aggregation interval for metrics collected by StatsD daemon?
 1. Do not aggregate
 2. 10s
 3. 30s
 4. 60s
 default choice: [4]:
 1
 Do you want to monitor metrics from CollectD? WARNING: CollectD must be installed or the Agent will fail to start
 1. yes
 2. no
 default choice: [1]:
 1
 Do you want to monitor any host metrics? e.g. CPU, memory, etc.
 1. yes
 2. no
 default choice: [1]:
 1
 Do you want to monitor cpu metrics per core?
 1. yes
 2. no
 default choice: [1]:
 1
 Do you want to add ec2 dimensions (ImageId, InstanceId, InstanceType, AutoScalingGroupName) into all of your metrics if the info is available?
 1. yes
 2. no
 default choice: [1]:
 1
 Do you want to aggregate ec2 dimensions (InstanceId)?
 1. yes
 2. no
 default choice: [1]:
 1
 Would you like to collect your metrics at high resolution (sub-minute resolution)? This enables sub-minute resolution for all metrics, but you can customize for specific metrics in the output json file.
 1. 1s
 2. 10s
 3. 30s
 4. 60s
 default choice: [4]:
 4
 Which default metrics config do you want?
 1. Basic
 2. Standard
 3. Advanced
 4. None
 default choice: [1]:
 1
 Current config as follows:
 {
 	"agent": {
 		"metrics_collection_interval": 60,
 		"run_as_user": "root"
 	},
 	"metrics": {
 		"aggregation_dimensions": [
 			[
 				"InstanceId"
 			]
 		],
 		"append_dimensions": {
 			"AutoScalingGroupName": "${aws:AutoScalingGroupName}",
 			"ImageId": "${aws:ImageId}",
 			"InstanceId": "${aws:InstanceId}",
 			"InstanceType": "${aws:InstanceType}"
 		},
 		"metrics_collected": {
 			"collectd": {
 				"metrics_aggregation_interval": 0
 			},
 			"disk": {
 				"measurement": [
 					"used_percent"
 				],
 				"metrics_collection_interval": 60,
 				"resources": [
 					"*"
 				]
 			},
 			"mem": {
 				"measurement": [
 					"mem_used_percent"
 				],
 				"metrics_collection_interval": 60
 			},
 			"statsd": {
 				"metrics_aggregation_interval": 0,
 				"metrics_collection_interval": 10,
 				"service_address": ":8125"
 			}
 		}
 	}
 }
 Are you satisfied with the above config? Note: it can be manually customized after the wizard completes to add additional items.
 1. yes
 2. no
 default choice: [1]:
 1
 Do you have any existing CloudWatch Log Agent (http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html) configuration file to import for migration?
 1. yes
 2. no
 default choice: [2]:
 2
 Do you want to monitor any log files?
 1. yes
 2. no
 default choice: [1]:
 2
 Saved config file to /opt/aws/amazon-cloudwatch-agent/bin/config.json successfully.
 Current config as follows:
 {
 	"agent": {
 		"metrics_collection_interval": 60,
 		"run_as_user": "root"
 	},
 	"metrics": {
 		"aggregation_dimensions": [
 			[
 				"InstanceId"
 			]
 		],
 		"append_dimensions": {
 			"AutoScalingGroupName": "${aws:AutoScalingGroupName}",
 			"ImageId": "${aws:ImageId}",
 			"InstanceId": "${aws:InstanceId}",
 			"InstanceType": "${aws:InstanceType}"
 		},
 		"metrics_collected": {
 			"collectd": {
 				"metrics_aggregation_interval": 0
 			},
 			"disk": {
 				"measurement": [
 					"used_percent"
 				],
 				"metrics_collection_interval": 60,
 				"resources": [
 					"*"
 				]
 			},
 			"mem": {
 				"measurement": [
 					"mem_used_percent"
 				],
 				"metrics_collection_interval": 60
 			},
 			"statsd": {
 				"metrics_aggregation_interval": 0,
 				"metrics_collection_interval": 10,
 				"service_address": ":8125"
 			}
 		}
 	}
 }
 Please check the above content of the config.
 The config file is also located at /opt/aws/amazon-cloudwatch-agent/bin/config.json.
 Edit it manually if needed.
 Do you want to store the config in the SSM parameter store?
 1. yes
 2. no
 default choice: [1]:
 1
 What parameter store name do you want to use to store your config? (Use 'AmazonCloudWatch-' prefix if you use our managed AWS policy)
 default choice: [AmazonCloudWatch-linux]
 
 Trying to fetch the default region based on ec2 metadata...
 Which region do you want to store the config in the parameter store?
 default choice: [ap-northeast-1]
 
 Which AWS credential should be used to send json config to parameter store?
 1. XSSSSSSSSSSSSSSSS(From SDK)
 2. Other
 default choice: [1]:
 1
 Please make sure the creds you used have the right permissions configured for SSM access.
 Which AWS credential should be used to send json config to parameter store?
 1. XSSSSSSSSSSSSSSSS(From SDK)
 2. Other
 default choice: [1]:
 1
 Please make sure the creds you used have the right permissions configured for SSM access.
 Error in putting config to parameter store AmazonCloudWatch-linux: AccessDeniedException: User: arn:aws:sts::XXXXXXXXXXXX:assumed-role/tsc-iamrole-ssmcore/i-ZZZZZ is not authorized to perform: ssm:PutParameter on resource: arn:aws:ssm:ap-northeast-1:XXXXXXX:parameter/AmazonCloudWatch-linux because no identity-based policy allows the ssm:PutParameter action
 	status code: 400, request id: ZZZZZZZZZZZZZZZZZZZZZZZ
 Program exits now.
```

最後にAccessDeniedExceptionエラーが出ているが、これはEC2インスタンスにssm動作許可のIAMロールを指定していないから。あとで必ずEC2インスタンスにロールを割り当てる。
エージェントを再起動。

```shell:Cloudwatchエージェントを起動
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws//amazon-cloudwatch-agent/bin/config.json -s
（以下は起動ログ）
****** processing amazon-cloudwatch-agent ******
/opt/aws/amazon-cloudwatch-agent/bin/config-downloader --output-dir /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d --download-source file:/opt/aws/amazon-cloudwatch-agent/bin/config.json --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml --multi-config default
I! Trying to detect region from ec2
2022/07/13 04:19:06 D! [EC2] Found active network interface
Successfully fetched the config and saved in /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/file_config.json.tmp
Start configuration validation...
/opt/aws/amazon-cloudwatch-agent/bin/config-translator --input /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json --input-dir /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d --output /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml --mode ec2 --config /opt/aws/amazon-cloudwatch-agent/etc/common-config.toml --multi-config default
2022/07/13 04:19:06 Reading json config file path: /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.d/file_config.json.tmp ...
2022/07/13 04:19:06 I! Valid Json input schema.
I! Detecting run_as_user...
I! Trying to detect region from ec2
2022/07/13 04:19:06 D! [EC2] Found active network interface
No csm configuration found.
No log configuration found.
Configuration validation first phase succeeded
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -schematest -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml
Configuration validation second phase succeeded
Configuration validation succeeded
Redirecting to /bin/systemctl stop amazon-cloudwatch-agent.service
Redirecting to /bin/systemctl restart amazon-cloudwatch-agent.service
```
ちゃんと起動できたか確認。
```shell-session:Cloudwatch起動状態確認
$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -m ec2 -a status
{
  "status": "running",
  "starttime": "2022-07-13T04:19:06+00:00",
  "configstatus": "configured",
  "cwoc_status": "stopped",
  "cwoc_starttime": "",
  "cwoc_configstatus": "not configured",
  "version": "1.247353.0b251941"
}
```

Systemctlでも確認しておく。
```shell-session:起動確認
$ sudo systemctl status amazon-cloudwatch-agent.service
・・ amazon-cloudwatch-agent.service - Amazon CloudWatch Agent
   Loaded: loaded (/etc/systemd/system/amazon-cloudwatch-agent.service; enabled; vendor preset: disabled)
   Active: active (running) since Wed 2022-07-13 04:19:06 UTC; 1min 3s ago
 Main PID: 15197 (amazon-cloudwat)
    Tasks: 6 (limit: 4700)
   Memory: 17.9M
   CGroup: /system.slice/amazon-cloudwatch-agent.service
           mq15197 /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudw>

Jul 13 04:19:06 ip-10-240-99-11.ap-northeast-1.compute.internal systemd[1]: Started Amazon CloudWatch Agent.
Jul 13 04:19:06 ip-10-240-99-11.ap-northeast-1.compute.internal start-amazon-cloudwatch-agent[15197]: /opt/aws/amazon-cloudwatch-agent/etc>
Jul 13 04:19:06 ip-10-240-99-11.ap-northeast-1.compute.internal start-amazon-cloudwatch-agent[15197]: I! Detecting run_as_user...
```

# 時刻関連設定
公式手順に従って、時刻設定だけはやっておく。ログの時刻にかかわるため。
[Linux インスタンスの時刻の設定](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/set-time.html)
```shell-session:
$ sudo systemctl status chronyd
$ chronyc sources -v
あとは上記の手順で気になるやつを実行。
```

# 続きの記事
[つづきの記事をかきました](https://qiita.com/If_it_bleeds-we_can_kill_it/items/37b9aa7d46c487e3ae01)

# 余談
去年2022年のなにが一番楽しかったって、ブルーノマーズのライブに行けたこと。素晴らしかったですわ。マイケルジャクソン＋ジェームズブラウンという感じで、とてもファンキー。YouTubeやCDで聞くあの歌声、そのまま。歌唱力、ダンスともに尋常じゃなかった。
~~俺も本当はシステムエンジニアなんかより、ブルーノマーズになりたい。どこで道を誤ったのか・・・。~~
これもまた彼らしい歌で、チャラかっこいい感じ。Chunky＝ぽっちゃり、という意味らしく、そういう人がタイプだと高々に歌う。そこに関しては気が合うかもしれない。
[Bruno Mars - Chunky (from the Victoria’s Secret 2016 Fashion Show) (Official Live Performance)](https://www.youtube.com/watch?v=5kEfq8jPsu4)