Closed8

amazon linux 2022(プレビュー版)でSSM Agentの検証

ピン留めされたアイテム
jimatomojimatomo

正式にサポートされてはいないので参考程度です。

GitHub上ではIssueが上がっているようですね。
https://github.com/amazonlinux/amazon-linux-2022/issues/13

次回のリリースではパッケージが用意されるっぽいです(そろそろGAに向けたリリース候補が提供予定なので、最後の一歩感ありますね。)

Q: Amazon Linux 2022 (AL2022) の一般提供 (GA) はいつになりますか?
テスト用の AL2022 のリリース候補は、2022 年 7 月末に利用できる予定です。AL2022 GA バージョンは、その数か月後に提供されます。

https://aws.amazon.com/jp/linux/amazon-linux-2022/faqs/

jimatomojimatomo

Amazon Linux 2022のクセのあるところ

SSHのキーとしてRSAキーを使ってはいけないところがハマりどころです。

これはOpen SSHのバージョンが新しいものを利用しているからだそうです。
バージョンを確認してみましょう

$ ssh -V
OpenSSH_8.6p1, OpenSSL 3.0.3 3 May 2022

※今回利用しているAMIは「al2022-ami-2022.0.20220628.8-kernel-5.15-x86_64」です

どうやら今後はRSAキーを利用せずにED25519を利用する形がよさそうですね。
https://news.mynavi.jp/techplus/article/20200529-1044828/

jimatomojimatomo

インスタンスプロファイルでSSMへのアクセスを許可

S3やCloudWatchなどへのアクセスはオプションなので、最小限マネージドインスタンスに必要な権限を付与します。
IAMロールを作りましょう。
このときにアタッチするポリシーは「AmazonSSMManagedInstanceCore」です。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/setup-instance-profile.html

IAMロールをEC2に割り当てたらちゃんと反映されているか確認してみましょう。(AWS CLIはプリインストールされているのでそのままawsコマンドが打てます)

$ aws --version
aws-cli/2.7.8 Python/3.9.13 Linux/5.15.43-20.123.amzn2022.x86_64 source/x86_64.amzn.2022 prompt/off
$
$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                <not set>             None    None
access_key     ****************DQPY         iam-role
secret_key     ****************Awfl         iam-role
    region           ap-northeast-1             imds
jimatomojimatomo

手動でSSM Agentをインストール

今回利用しているAMIは「al2022-ami-2022.0.20220628.8-kernel-5.15-x86_64」ですが、デフォルトでSSM Agentはインストールされていません。正式サポートではないですが、無理やりAmazon Linux 2のrpmからインストールしてみます。

では、インストールしてみましょう。

$ mkdir /tmp/ssm
$ curl https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm -o /tmp/ssm/amazon-ssm-agent.rpm
$ sudo yum install -y /tmp/ssm/amazon-ssm-agent.rpm
Last metadata expiration check: 0:35:03 ago on Sat 16 Jul 2022 01:40:25 PM UTC.
Dependencies resolved.
================================================================================================================
 Package                       Architecture        Version                      Repository                 Size
================================================================================================================
Installing:
 amazon-ssm-agent              x86_64              3.1.1575.0-1                 @commandline               25 M

Transaction Summary
================================================================================================================
Install  1 Package

Total size: 25 M
Installed size: 94 M
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Running scriptlet: amazon-ssm-agent-3.1.1575.0-1.x86_64                                                   1/1
  Preparing        :                                                                                        1/1
  Running scriptlet: amazon-ssm-agent-3.1.1575.0-1.x86_64                                                   1/1
  Installing       : amazon-ssm-agent-3.1.1575.0-1.x86_64                                                   1/1
  Running scriptlet: amazon-ssm-agent-3.1.1575.0-1.x86_64                                                   1/1
Created symlink /etc/systemd/system/multi-user.target.wants/amazon-ssm-agent.service → /etc/systemd/system/amazon-ssm-agent.service.

  Verifying        : amazon-ssm-agent-3.1.1575.0-1.x86_64                                                   1/1

Installed:
  amazon-ssm-agent-3.1.1575.0-1.x86_64

Complete!

おまけでステータスを確認してみましょう

$ 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 Sat 2022-07-16 14:15:32 UTC; 28min ago
   Main PID: 2383 (amazon-ssm-agen)
      Tasks: 17 (limit: 1128)
     Memory: 17.2M
        CPU: 1.010s
     CGroup: /system.slice/amazon-ssm-agent.service
             tq 2383 /usr/bin/amazon-ssm-agent
             mq 2450 /usr/bin/ssm-agent-worker

(以下略)

この状態で利用可能になっています。
コンソールからFleet Managerを見てみるとちゃんと登録されています
Fleet Managerの画面

jimatomojimatomo

【検証内容#1】Systems Manager Inventory

SSM Inventoryはマネージドインスタンスからメタデータを収集して可視化するサービスです。
さっそく有効化してみましょう!

有効化手順

マネジメントコンソールにログインしてSystems Managerのページを表示します。
左ペインから「インベントリ」をクリックします。
「すべてのインスタンスでインベントリを有効にするには、ここをクリックします。」をクリック
SSM Inventoryの有効化

裏側では以下のAWSが所有しているSystems Manager Automationのドキュメントが有効化されています。※状況はステートマネージャーから確認できます。
ドキュメント名:AWS-GatherSoftwareInventory

Fleet Managerの画面から確認

各インスタンスのインベントリの情報はFleet Managerから確認可能です。
インベントリの確認

jimatomojimatomo

【検証内容#2】Systems Manager Automation(下準備)

今回はSSM Automationを使ってインスタンスの自動起動のジョブを組んでみようと思います。
シンプルにPostgreSQLをインストールしてDBを起動するところまでをやってみようと思います。
※例によってAmazon Linux 2022自体はちゃんと動作保証がされていないので動かなかったどんまいということで…

yumで探してみると13系が利用できそうなので、それでもいいかなと思いつつ、そしたらsystemctlで自動起動すればいいんじゃないかなとなりそうなので、あえてソースコードからインストールして最新の14.4を動かしてみようかなと思います。
以下のコマンドを実行してインストールしていきます。

# 必要なパッケージをインストール
sudo yum install -y readline-devel
sudo yum install -y zlib-devel
sudo yum install -y openssl-devel

# インストールユーザの作成(postgres)
sudo useradd postgres
sudo passwd postgres

# インストール先(ドキュメントのデフォルトのもの)
sudo mkdir /usr/local/pgsql
sudo chown postgres. /usr/local/pgsql

# ソールコードの配置
cd /usr/local/src; pwd
sudo curl https://ftp.postgresql.org/pub/source/v14.4/postgresql-14.4.tar.gz --output postgresql-14.4.tar.gz

# 解凍
sudo gunzip postgresql-14.4.tar.gz
sudo tar xf postgresql-14.4.tar
sudo chown -R postgres. postgresql-14.4

# インストール
sudo su - postgres

cd /usr/local/src/postgresql-14.4/;pwd
./configure --with-openssl
make world
make check
make install-world
make install-docs
make clean

# 環境変数の設定
cp -pv ~/.bash_profile ~/.bash_profile_bk
cat << 'EOF' >> ~/.bash_profile

export PGHOME=/usr/local/pgsql
export PATH=$PGHOME/bin:$PATH
export MANPATH=/usr/local/pgsql/share/man:$MANPATH
export PGDATA=/usr/local/pgsql/data
EOF

exit

sudo su - postgres

# データ用のディレクトリ作成
mkdir /usr/local
initdb --encoding=UTF8 --no-local

pg_ctl -l logfile start

psql -l

pg_ctl stop

インストールが完了したら、EC2インスタンスを停止しておきます。

そしたらAutomationのドキュメントを作っていきましょう。

jimatomojimatomo

【検証内容#2】Systems Manager Automation

Systems ManagerのAutomationで以下のフローを書いてみます。

  1. 「EC2インスタンスの起動」はAWS側のAPIをコール⇒pythonの関数※
  2. 「PostgreSQLサーバのプロセスを起動」はEC2内のコマンドをコール⇒Bash
    ※よくやる操作はアクションタイプからテンプレートが提供されていたりします。EC2を起動する操作もテンプレートが提供されています。ただし、インスタンスIDを入力する必要があり柔軟性がないので、今回はTagの中のNameで対象のインスタンスを抽出するロジックを書きたいのでPythonのコードを利用します。

マネジメントコンソールからSSMドキュメントの画面を表示します。
「Create document」から「Automation」を選択します。
ドキュメントの作成画面

ここからはビルダー画面でそれぞれの設定を整理していきます。

ドキュメント詳細

名前を入れるだけです。

ドキュメント属性

IAMロールを事前に作っておいて、SSM AutomationがそれをAssumeRoleするようにします。これはexecuteScriptやRunCommandを実施するための権限を付与しておきます。
今回はざっくり以下のマネージドポリシーをアタッチしたロールで動作確認しています。

  • AmazonEC2FullAccess
  • AmazonSSMAutomationRole

ステップ1 EC2インスタンスの起動

設定項目1 設定項目2 設定値
ステップ名 - StartEC2Instance
アクションタイプ - aws:executeScript
入力 Runtime python3.6
Handler script_handler
Script 表の下に記載
出力 名前 TargetInstanceIds
セレクター $.Payload
タイプ StringMap
script
def script_handler(events, context):
  import boto3
  tagKey   = 'Name'
  tagValue = 'ssm-test-003'
  
  #Initialize client
  ec2 = boto3.client('ec2')

  instanceQuery = ec2.describe_instances(
  Filters=[
    {
      "Name": "tag:" + tagKey,
      "Values": [tagValue]
    }]
  )
  if not instanceQuery['Reservations']:
    noInstancesForTagString = "No instances found for specified tag."
    return({ 'noInstancesFound' : noInstancesForTagString })
  else:
    queryResponse = instanceQuery['Reservations']
    for results in queryResponse:
      instanceSet = results['Instances']
      instanceIds = []
      for instance in instanceSet:
        if instance['State']['Name'] == 'stopped':
          instanceIds.append(instance['InstanceId'])
      if not instanceIds:
        message_body = "no instance is stopped"
      else:
        ec2.start_instances(InstanceIds = instanceIds)
        message_body = "start instaces"
    return ({"instance_ids": instanceIds})

ステップ2 EC2のステータスがOKになるまで待機する

設定項目1 設定項目2 設定値
ステップ名 - WaitEC2StatusOK
アクションタイプ - aws:executeScript
入力 Runtime python3.6
Handler poll_instance
Script 表の下に記載
追加の入力 入力名 InputPayload
入力値 {{ StartEC2Instance.TargetInstanceIds }}
script
def poll_instance(events, context):
  import boto3
  import time

  ec2 = boto3.client('ec2')

  instance_ids = events['instance_ids']

  instance_status = "null"

  for instance_id in instance_ids:
    while True:
      res = ec2.describe_instance_status(InstanceIds=[instance_id])
  
      if len(res['InstanceStatuses']) == 0:
        print("Instance status information is not available yet")
        time.sleep(5)
        continue
  
      instance_status = res['InstanceStatuses'][0]['InstanceStatus']['Status']
  
      print('[INFO] Polling to get status of the instance', instance_status)
  
      if instance_status == 'ok':
        break
  
      time.sleep(10)
  
  time.sleep(60)
  
  return {'Status': instance_status, 'InstanceId': instance_ids}

ステップ2 マネージドインスタンス上で起動コマンドを実行

設定項目1 設定項目2 設定値
ステップ名 - StartPostgreSQL
アクションタイプ - aws:runCommand
入力 Document name AWS-RunShellScript
Targets [{"Key":"tag:Name","Values": ["ssm-test-003"]}]
追加の入力 入力名 Parameters
入力値 {"commands":["#!/bin/bash", "sudo su - postgres -c 'pg_ctl -l logfile start'"]}

実行してみる

ドキュメントの詳細ページから「オートメーションを実行」をクリック
シンプルな実行のまま何もいじらず、実行をクリック
正常に実行完了したら、Fleet Managerからターミナルセッションを起動してちゃんと実行されているか確認する

jimatomojimatomo

【おまけ】SSM AgentつながりでInspectorを見てみた

マネージドインスタンスとして認識されていても、Inspectorのコンソールから見てみたらサポートされていないOSとしてスキャンの対象外になっていました。
そりゃそうか…

このスクラップは2022/07/17にクローズされました