SYSTEMS MANAGER SERVICESのAutomationsを使用してみる

Last-modified: Mon, 13 Nov 2017 12:53:14 JST (65d)

Amazon Linuxの2017.09より、SystemManagerServicesのエージェントがインストール済みになったのを契機に、
試してみたかったAutomationsを試してみます。
ここでは、サンプルとしてあるAWS-UpdateLinuxAmiを動かすことで、動きを見てみます。

デフォルトVPCの作成

Automationを使用するには、デフォルトVPCが必須です。以前はデフォルトVPCを削除したらサポート行きでしたが、
現在は作成することができます。
自分は当然削除してしまっているので(汗 この際に作成しておきます。
削除せず使っている場合はスキップします。

  1. VPCより、アクションクリック。デフォルトVPCの作成をクリックします。
    vpc01.png
  2. 確認画面が出るので作成ボタンをクリックして、デフォルトVPCを作成します。
    vpc02.jpg

IAMの作成

Automationsで使用するIAMを作成します。最近IAMの仕様が変更され、やり方が変わっているので、ここでは簡単に済ませるため、
ここを参考に、CloudFormationを使用して作成します。

  1. Launch Stackボタンをクリックします。
    iam01.png
  2. 実行するCloudFormationのリージョンを東京に変更しておきます。これは必須ではないのですが、東京リージョンにまとめておいたほうが管理しやすいので。
    iam02.png
  3. スタックの名前を適当に付けます。
    iam03.png
  4. オプションの項目は設定するところはないので、次へ進みます。
    iam04.png
  5. 確認画面が出ます。一番下にある、AWS CloudFromationによって~にチェックを入れ、作成ボタンをクリックします。
    iam05.png
  6. ロールが二つ作成されます。
    iam06.png

Automationの実行

ここでは、サンプルとしてAWS-UpdateLinuxAmiを動かしてみます。

  1. EC2管理画面から、自動化をクリックし、自動化ドキュメントの実行をクリックします。
    Automationでは、実行するタスクスクリプトをドキュメントと言います。
    auto01.jpg
  2. ドキュメント名に「AWS-UpdateLinuxAmi」と入力し、でてきたものにチェックをします。
    バージョンは1を選択します。
    このバージョンは、ドキュメントのバージョンになります。(現時点で最新が1の為)
    auto02.jpg
  3. パラメタ入力欄では、SourceAmildに「ami-2a69be4c」(現時点で最新のAmazonLinuxAMIです。ここを自分の作成したAmazonLinuxAMIのIDに置き換えれば、パッチ適用を自動化できます)をセットします。
    それ以外のパラメタはとりあえずデフォルトでいいです。
    (見ればわかると思いますが、InstanceIamRoleとAutomationAssumeRoleは先ほど作成したIAMが初期値で入っています。
    TargetAmiNameはパッチ適用後に作成するAMIの命名規則。InstanceTypeはパッチ適用の為一時起動するEC2インスタンスのインスタンスタイプになります。)
    auto03.png
  4. 自動化を実行をクリックすると、タスクが実行されます。
    auto04.png
  5. ドキュメントの内容に従い、指定したAMIでEC2が起動され、パッチ適用されます。
    auto05.png
  6. タスクの進捗具合はこんな感じで見れます。
    auto06.png
  7. 各タスクの出力内容はここをクリックします。
    auto07.png
  8. こんな感じで表示されます。
    auto08.png
  9. 全タスクが終了したら、AMIが作成されます。
    auto09.png
  10. 一時作成されたEC2インスタンスは自動的にターミネートされます。
    (というかターミネートするようにタスクが組まれています)
    auto10.png
  • なお、注意点として、CloudFormationと違い、タスクがコケても、展開されたリソースはロールバックされませんので注意しましょう。
    auto11.jpg

コマンドの実行

Systems Manager Servicesエージェントが導入されているEC2インスタンスに、SSHで接続することなくコマンドを実行することができます。(このあたりも参照)
これは先ほどのAWS-UpdateLinuxAmiでも内部で使用されています。
ここでは、単独でコマンドを実行してみます。

  1. EC2管理画面からコマンドの実行をクリックします。
    command01.jpg
  2. コマンドのドキュメントで、「AWS-RunShellScript」を選択します。
    command02.jpg
  3. ターゲットの選択では、SMSエージェント導入済みでかつ起動中のインスタンスIDを選択します。
    このインスタンスには先ほど作成した「ManagedInstanceProfile」ロールが適用されている必要があります。
    Commandsではそこで実行したいコマンドを記述します。
    ommand03.jpg
  4. 実行すると、Automationの時と同様出力の表示で結果を表示できます。
    command04.jpg
  5. こんな感じです。
    このようにSSHキーを使用せずコマンドを実行することにより、キーを扱わなくてもインスタンスに対しコマンドを実行することが可能です。
    ommand05.jpg

Amazon EC2 Systems Manager ドキュメントについて

  • Amazon EC2 Systems Manager ドキュメントとは?
    説明はここにあります。
    ドキュメントの種類には、「Command」「Policy」「Automation」の3種類があり、それぞれ使用できるバージョンが異なるようです。

ここでは、先ほど実行した「AWS-UpdateLinuxAmi」のドキュメントを見ながら、「Automation」を例に、その中身を探っていきます。

  • ドキュメントはどこにある?
    EC2管理画面のドキュメントから、名前で検索すると出てきます。
    document01.jpg
    では、実際にドキュメントの中身を見てみましょう。
    下にあるコンテンツタブをクリックすると、ドキュメントの中身が見えます。
    document02.jpg
    このドキュメントは以下の構造になっております。以下公式ドキュメントより引用します。
    • schemaVersion: 使用するスキーマバージョン。
    • Description: ドキュメントの目的を説明するために提供する情報。
    • assumeRole: The ARN of the role that allows Automation to perform the actions on your behalf.
    • Parameters: ドキュメントで受け入れるパラメータ。
    • mainSteps: 複数のステップ (プラグイン) を含めることができるオブジェクト。ステップには、1 つまたは複数のアクション、任意の前提条件、アクションの一意の名前、これらのアクションの入力 (パラメータ) が含まれます。
      では見ていきます。
      "schemaVersion":"0.3",
      とあり、これがスキーマバージョン0.3のドキュメントであることを定義しています。
      Automation タイプのドキュメントは、スキーマバージョン 0.3 を使用する必要があります。 
      とありますので、現時点では0.3固定でよいでしょう。
      次に
      "description":"Updates AMI with Linux distribution packages and Amazon software. For details,see https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sysman-ami-walkthrough.html",
      と、このドキュメントの説明が記述されています。
      次にこのドキュメントがとるパラメタが定義されています。
      一つ抜き出します。
         "SourceAmiId":{
           "type":"String",
           "description":"(Required) The source Amazon Machine Image ID."
         },
      どうやら、構文的には
      "変数名":{
        "type":"型",
        #description":パラメタの説明
       }
      というようです。型にはStringもしくはStringlistがあるようです。
      次にメインステップです。この中にいくつかのアクションが入ります。
      いかに一つ抜き出します。
         {
           "name":"launchInstance",
           "action":"aws:runInstances",
           "maxAttempts":3,
           "timeoutSeconds":1200,
           "onFailure":"Abort",
           "inputs":{
             "ImageId":"{{SourceAmiId}}",
             "InstanceType":"{{InstanceType}}",
             "UserData":"IyEvYmluL2Jhc2gNCg0KZnVuY3Rpb24gZ2V0X2NvbnRlbnRzKCkgew0KICAgIGlmIFsgLXggIiQod2hpY2ggY3VybCkiIF07IHRoZW4NCiAgICAgICAgY3VybCAtcyAtZiAiJDEiDQogICAgZWxpZiBbIC14ICIkKHdoaWNoIHdnZXQpIiBdOyB0aGVuDQogICAgICAgIHdnZXQgIiQxIiAtTyAtDQogICAgZWxzZQ0KICAgICAgICBkaWUgIk5vIGRvd25sb2FkIHV0aWxpdHkgKGN1cmwsIHdnZXQpIg0KICAgIGZpDQp9DQoNCnJlYWRvbmx5IElERU5USVRZX1VSTD0iaHR0cDovLzE2OS4yNTQuMTY5LjI1NC8yMDE2LTA2LTMwL2R5bmFtaWMvaW5zdGFuY2UtaWRlbnRpdHkvZG9jdW1lbnQvIg0KcmVhZG9ubHkgVFJVRV9SRUdJT049JChnZXRfY29udGVudHMgIiRJREVOVElUWV9VUkwiIHwgYXdrIC1GXCIgJy9yZWdpb24vIHsgcHJpbnQgJDQgfScpDQpyZWFkb25seSBERUZBVUxUX1JFR0lPTj0idXMtZWFzdC0xIg0KcmVhZG9ubHkgUkVHSU9OPSIke1RSVUVfUkVHSU9OOi0kREVGQVVMVF9SRUdJT059Ig0KDQpyZWFkb25seSBTQ1JJUFRfTkFNRT0iYXdzLWluc3RhbGwtc3NtLWFnZW50Ig0KIFNDUklQVF9VUkw9Imh0dHBzOi8vYXdzLXNzbS1kb3dubG9hZHMtJFJFR0lPTi5zMy5hbWF6b25hd3MuY29tL3NjcmlwdHMvJFNDUklQVF9OQU1FIg0KDQppZiBbICIkUkVHSU9OIiA9ICJjbi1ub3J0aC0xIiBdOyB0aGVuDQogIFNDUklQVF9VUkw9Imh0dHBzOi8vYXdzLXNzbS1kb3dubG9hZHMtJFJFR0lPTi5zMy5jbi1ub3J0aC0xLmFtYXpvbmF3cy5jb20uY24vc2NyaXB0cy8kU0NSSVBUX05BTUUiDQpmaQ0KDQppZiBbICIkUkVHSU9OIiA9ICJ1cy1nb3Ytd2VzdC0xIiBdOyB0aGVuDQogIFNDUklQVF9VUkw9Imh0dHBzOi8vYXdzLXNzbS1kb3dubG9hZHMtJFJFR0lPTi5zMy11cy1nb3Ytd2VzdC0xLmFtYXpvbmF3cy5jb20vc2NyaXB0cy8kU0NSSVBUX05BTUUiDQpmaQ0KDQpjZCAvdG1wDQpGSUxFX1NJWkU9MA0KTUFYX1JFVFJZX0NPVU5UPTMNClJFVFJZX0NPVU5UPTANCg0Kd2hpbGUgWyAkUkVUUllfQ09VTlQgLWx0ICRNQVhfUkVUUllfQ09VTlQgXSA7IGRvDQogIGVjaG8gQVdTLVVwZGF0ZUxpbnV4QW1pOiBEb3dubG9hZGluZyBzY3JpcHQgZnJvbSAkU0NSSVBUX1VSTA0KICBnZXRfY29udGVudHMgIiRTQ1JJUFRfVVJMIiA+ICIkU0NSSVBUX05BTUUiDQogIEZJTEVfU0laRT0kKGR1IC1rIC90bXAvJFNDUklQVF9OQU1FIHwgY3V0IC1mMSkNCiAgZWNobyBBV1MtVXBkYXRlTGludXhBbWk6IEZpbmlzaGVkIGRvd25sb2FkaW5nIHNjcmlwdCwgc2l6ZTogJEZJTEVfU0laRQ0KICBpZiBbICRGSUxFX1NJWkUgLWd0IDAgXTsgdGhlbg0KICAgIGJyZWFrDQogIGVsc2UNCiAgICBpZiBbWyAkUkVUUllfQ09VTlQgLWx0IE1BWF9SRVRSWV9DT1VOVCBdXTsgdGhlbg0KICAgICAgUkVUUllfQ09VTlQ9JCgoUkVUUllfQ09VTlQrMSkpOw0KICAgICAgZWNobyBBV1MtVXBkYXRlTGludXhBbWk6IEZpbGVTaXplIGlzIDAsIHJldHJ5Q291bnQ6ICRSRVRSWV9DT1VOVA0KICAgIGZpDQogIGZpIA0KZG9uZQ0KDQppZiBbICRGSUxFX1NJWkUgLWd0IDAgXTsgdGhlbg0KICBjaG1vZCAreCAiJFNDUklQVF9OQU1FIg0KICBlY2hvIEFXUy1VcGRhdGVMaW51eEFtaTogUnVubmluZyBVcGRhdGVTU01BZ2VudCBzY3JpcHQgbm93IC4uLi4NCiAgLi8iJFNDUklQVF9OQU1FIiAtLXJlZ2lvbiAiJFJFR0lPTiINCmVsc2UNCiAgZWNobyBBV1MtVXBkYXRlTGludXhBbWk6IFVuYWJsZSB0byBkb3dubG9hZCBzY3JpcHQsIHF1aXR0aW5nIC4uLi4NCmZp",
             "MinInstanceCount":1,
             "MaxInstanceCount":1,
             "IamInstanceProfileName":"{{InstanceIamRole}}"
           }
         },
      アクションについては、"ここ"に説明があります。
      ここでは、「runInstances」アクションを定義しています。
      この中で、パラメタは{{変数名}}で使えることがわかります。
      基本的にAWSのサービスはすべてAPIで動いていますので、これも最終的にはAPIを呼び出しています。
      したがって、パラメタにセットする値はAPIに準じています。
      なお、UserDataにある文字列はBASE64でエンコードされており、展開すると以下の内容になります。
      #!/bin/bash
      
      function get_contents() {
          if [ -x "$(which curl)" ]; then
              curl -s -f "$1"
          elif [ -x "$(which wget)" ]; then
              wget "$1" -O -
          else
              die "No download utility (curl, wget)"
          fi
      }
      
      readonly IDENTITY_URL="http://169.254.169.254/2016-06-30/dynamic/instance-identity/document/"
      readonly TRUE_REGION=$(get_contents "$IDENTITY_URL" | awk -F\" '/region/ { print $4 }')
      readonly DEFAULT_REGION="us-east-1"
      readonly REGION="${TRUE_REGION:-$DEFAULT_REGION}"
      
      readonly SCRIPT_NAME="aws-install-ssm-agent"
       SCRIPT_URL="https://aws-ssm-downloads-$REGION.s3.amazonaws.com/scripts/$SCRIPT_NAME"
      
      if [ "$REGION" = "cn-north-1" ]; then
        SCRIPT_URL="https://aws-ssm-downloads-$REGION.s3.cn-north-1.amazonaws.com.cn/scripts/$SCRIPT_NAME"
      fi
      
      if [ "$REGION" = "us-gov-west-1" ]; then
        SCRIPT_URL="https://aws-ssm-downloads-$REGION.s3-us-gov-west-1.amazonaws.com/scripts/$SCRIPT_NAME"
      fi
      
      cd /tmp
      FILE_SIZE=0
      MAX_RETRY_COUNT=3
      RETRY_COUNT=0
      
      while [ $RETRY_COUNT -lt $MAX_RETRY_COUNT ] ; do
        echo AWS-UpdateLinuxAmi: Downloading script from $SCRIPT_URL
        get_contents "$SCRIPT_URL" > "$SCRIPT_NAME"
        FILE_SIZE=$(du -k /tmp/$SCRIPT_NAME | cut -f1)
        echo AWS-UpdateLinuxAmi: Finished downloading script, size: $FILE_SIZE
        if [ $FILE_SIZE -gt 0 ]; then
          break
        else
          if [[ $RETRY_COUNT -lt MAX_RETRY_COUNT ]]; then
            RETRY_COUNT=$( (RETRY_COUNT +1) );
            echo AWS-UpdateLinuxAmi: FileSize is 0, retryCount: $RETRY_COUNT
          fi
        fi 
      done
      
      if [ $FILE_SIZE -gt 0 ]; then
        chmod +x "$SCRIPT_NAME"
        echo AWS-UpdateLinuxAmi: Running UpdateSSMAgent script now ....
        ./"$SCRIPT_NAME" --region "$REGION"
      else
        echo AWS-UpdateLinuxAmi: Unable to download script, quitting ....
      fi
      また、runCommandを使用することで、「Command」のドキュメント(要するにコマンド実行用のドキュメント)を呼び出し、起動したEC2インスタンス内でコマンドを実行しています。

Counter: 55, today: 1, yesterday: 0

このページの参照回数は、55です。