BeeX Technical BlogSSM マネージドインスタンスに出てきていない EC2 インスタンスはどれだ!?

アイキャッチ画像が Systems Manager になってますが実際はほぼ AWS CLI の記事です。那須です。

とある作業で、Systems Manager(以下SSM)でたくさんある EC2 インスタンスを管理しようと思って準備していたら、どうも EC2 インスタンスの数と SSM のマネージドインスタンスの数が合わないことに気がつきました。 インスタンス数が少なければどれが正しく設定できていないかすぐに分かるんですが、100 台近くの EC2 インスタンスがあって 98 台は SSM のマネージドインスタンスとして見えてるけど残りの 2 台はどれ?ってなりましたので、どうやって設定がうまくいっていない EC2 インスタンスを特定したのかをご紹介します。

Excel をうまく使えば特定できるんですが、どうせ EC2 インスタンスの一覧を AWS CLI で取得するなら欲しい情報もそのまま bash でやろうと思ったので、今回は bash メインです。mac や Windows PC で WSL2 を使っている方が対象の記事になっていますが、PowerShell でも似たようなことができるはずですよ。(私は Windows 10 に WSL2 を入れて bash を使ってます。zsh では試してませんが、たぶんできるんじゃないでしょうか…)

 

まずは EC2 インスタンスの一覧を作ろう

SSM マネージドインスタンスの一覧と比較するための情報を取得します。 何も考えずに describe-instances を実行すると停止中の EC2 インスタンスまで表示されるので、running 状態の EC2 インスタンスの ID 一覧を取ってきましょう。 出力を text にしている理由は、あとで簡単に bash の array に入れるためです。 人が見るだけなら json で出力するのがいいと思います。

$ aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" --query "sort(Reservations[].Instances[].InstanceId)" --output text
i-11111111111111111     i-22222222222222222     i-33333333333333333     i-44444444444444444     i-55555555555555555 ....

 

次に今の SSM マネージドインスタンスの一覧を調べよう

今の SSM マネージドインスタンスの一覧を取得します。 先ほど running 状態の EC2 インスタンスの一覧を取得したので、ここでも条件を揃えるために PingStatus が Online の SSM マネージドインスタンスの一覧を出します。

$ aws ssm describe-instance-information --filters "Key=PingStatus,Values=Online" --query 'sort(InstanceInformationList[*].InstanceId[])' --output text
i-11111111111111111     i-22222222222222222     i-33333333333333333     i-44444444444444444     i-55555555555555555 ....

さあこれで比較する 2 つの一覧が作れましたね。

 

さっそく差分を出してみる

さきほどの一覧を配列に入れて、それぞれの差分を表示しています。uniq -u がめちゃくちゃ便利ですね(今日知りました

$ declare -a ssm=(`aws ssm describe-instance-information --filters "Key=PingStatus,Values=Online" --query 'sort(InstanceInformationList[*].InstanceId[])' --output text`)
$ declare -a ec2=(`aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" --query "sort(Reservations[].Instances[].InstanceId)" --output text`)
$ echo ${ssm[@]} ${ec2[@]} | tr ' ' '\n' | sort | uniq -u
i-00000000000000000
i-99999999999999999

この例では 2 つのインスタンスが起動しているけど SSM マネージドインスタンスとして登録されていないことがわかりました。 EC2 インスタンス ID だけで十分特定できているのですが、人が見た時に「ID だけじゃわからん…」って気持ちになりますよね?(私はなりました

そこで、出てきた EC2 インスタンス ID の名前を一緒に出力することにしました。Name タグを取ってくるようにしていますが、もし他にわかりやすいタグがあればそれを指定しましょう。

$ declare -a diff_ec2_ssm=(`echo ${ssm[@]} ${ec2[@]} | tr ' ' '\n' | sort | uniq -u`)
$ for diff_instance_id in "${diff_ec2_ssm[@]}" ; do
>     name_tag=`aws ec2 describe-instances --instance-ids ${diff_instance_id} --query "Reservations[].Instances[].Tags[?Key=='Name'].Value[]" --output text`
>     echo "$name_tag $diff_instance_id" 
> done
nasutest0 i-00000000000000000
nasutest9 i-99999999999999999

 

スクリプト化するとこうなります

スクリプト名は ssm_unmanaged_instances.sh にしました。 各 AWS CLI 実行時に –profile がついていますが、それぞれの環境にあわせて実行できるようにプロファイル名を指定できるようにしています。

#!/bin/bash

declare -a ssm=(`aws ssm describe-instance-information --filters "Key=PingStatus,Values=Online" --query 'sort(InstanceInformationList[*].InstanceId[])' --output text --profile $1`)
declare -a ec2=(`aws ec2 describe-instances --filters "Name=instance-state-name,Values=running" --query "sort(Reservations[].Instances[].InstanceId)" --output text --profile $1`)
declare -a diff_ec2_ssm=(`echo ${ssm[@]} ${ec2[@]} | tr ' ' '\n' | sort | uniq -u`)

for diff_instance_id in "${diff_ec2_ssm[@]}" ; do
    name_tag=`aws ec2 describe-instances --instance-ids ${diff_instance_id} --query "Reservations[].Instances[].Tags[?Key=='Name'].Value[]" --output text --profile $1`
    echo "$name_tag $diff_instance_id" 
done

実行するには、以下のように第 1 引数にプロファイル名を指定しましょう。 本当は引数のチェックとかを入れるべきですが、さすがにこれくらいの量のソースならすぐわかるだろうと思うので usage 表示まで作ってません。

$ ./ssm_unmanaged_instances.sh nasu_admin
nasutest0 i-00000000000000000
nasutest9 i-99999999999999999

実際に実行してもらうとわかるのですが、結果が出るまで結構時間がかかります。 差分があればあるほど時間がかかるのでもう少し違ったやり方で Name タグを取ってくるのがよさそうですが、時間があまりなかったのでひとまず最低限結果がわかるスクリプトになっています。

 

2020/09/29追記:PowerShell でもできます!

社内にいる PowerShell マスターが作ってくれました! 以下の内容を PowerShell で実行しても同じ結果が得られます!

#!/usr/bin/env pwsh

<#
.SYNOPSIS
    ssm_unmanaged_instances.ps1
.DESCRIPTION
    SSMが無効になっているインスタンス一覧
.EXAMPLE
    PS >./ssm_unmanaged_instances.ps1 -Profile aws-cli-profile-name
    PS >./ssm_unmanaged_instances.ps1 -Profile aws-cli-profile-name --region ap-northeast-1
.PARAMETER Profile
    AWSプロファイル名を設定
.PARAMETER Region
    AWS-リージョンを指定
.INPUTS
    None
        You cannot pipe objects
.OUTPUTS
    none
.NOTES
    none
#>

PARAM(
    [Parameter(Mandatory = $True)]
    [String]$Profile,
    [Parameter(Mandatory = $False)]
    [String]$Region = "ap-northeast-1"
)

PROCESS {

    # SticMode設定
    Set-StrictMode -Version Latest
    # エラー時に処理をstop
    $ErrorActionPreference = "stop"

    # ssm一覧 取得
    [array]$ssm = aws ssm describe-instance-information --filters 'Key=PingStatus,Values=Online' --query 'InstanceInformationList[].{InstanceId:InstanceId} | sort_by(@,&InstanceId)' --output json --profile $Profile --region $Region | ConvertFrom-Json
    # ec2一覧 取得
    [array]$runningEC2 = aws ec2 describe-instances --filters 'Name=instance-state-name,Values=running' --query 'Reservations[].Instances[].{InstanceId:InstanceId,Name:Tags[?Key==`Name`]|[0].Value} | sort_by(@,&InstanceId)' --output json --profile $Profile --region $Region | ConvertFrom-Json

    # 一覧が取得出来た場合のみ結果比較
    if ( [boolean]$ssm -and [boolean]$runningEC2 ) {
        # PingStatusNG リスト取得
        [array]$pingStatusNG = Compare-Object -ReferenceObject $runningEC2.InstanceId -DifferenceObject $ssm.InstanceId -PassThru
        # 対象表示
        $runningEC2 | Where-Object InstanceId -In $pingStatusNG

    }
    else {
        Write-Host "SSM-PingStatus/RunningEC2Instance is not found"
    }

}

実際に実行した場合の出力例です。

> .\ssm_unmanaged_instances.ps1 -Profile nasu_admin

InstanceId          Name
----------          ----
i-00000000000000000 nasutest0
i-99999999999999999 nasutest9

 

さいごに

マネジメントコンソールでこの情報を確認できればいいのですが、どこで見れるかわからなかったので簡単ではありますがスクリプトを作ってみました。 AWS CLI を使えばマネジメントコンソールでは確認できない情報もすぐに確認できるので本当に重宝します。 運用作業では GUI での手作業だけでは辛い場面も多々ありますので、日々の運用の中で AWS CLI を積極的に使っていきましょう!

関連サービス:基幹クラウド/SAP BASIS運用保守

基幹クラウド/SAP BASIS運用保守

日々進化し続けるクラウドサービスを最大限に活用し、信頼性・柔軟性を兼ね備えた運用保守サービスを提供します。

詳細を見る

カテゴリ

タグ

BeeX Technical Blogについてのお問い合わせ

BeeX Technical Blogのエントリにご質問が御座いましたらお気軽にお問合せください。

お電話でのお問い合わせ

☎ 03-6260-6240

受付時間 平日9:30〜18:00

フォームでのお問い合わせ

お問い合わせフォーム