🐙

【初心者向け】AWS LambdaからEC2 Run Commandを実行する方法

2022/05/16に公開

はじめに

先日業務で初めてAWS Lambdaを触りました。
今回はLambdaとEC2 RunCommandで、任意のタイミングでEC2上でコマンドを実行できるようにする設定をしたのですが、少し苦戦したのでやり方を残しておきます。
この記事が誰かのお役に立てれば幸いです。

そもそもLambdaって何だ?という方は以下の記事がおすすめです!簡潔にまとまっています!
https://blog.apar.jp/web/10804/

IAMでEC2に割り当てるロールの作成

そもそも何でロール作る必要あるの?って思いました? 大丈夫です、私も当初そう思いました。

その理由は、EC2でRunCommandするにはAWS Systems Manager(旧称 SSM)という権限を付与する必要があるからなんです。ということで、AWS Systems Managerが使えるIAMロールを作っていきます。

まずはAWSのコンソールからIAMのページに移動します。
ロールを作成をクリックします。


次にEC2を選択して次へをクリックします。

「AmazonEC2RoleforSSM」で検索→チェックボックスにチェック→次へボタンをクリックします。

次のページでロール名(任意の名称)をつけてロールを作成ボタンをクリックします。

以上でEC2にアタッチするロールの作成は完了です!

EC2の作成

次はEC2を作成して、先ほどのロールをアタッチしていきます。
EC2の起動方法は省略しますので、分からない方が以下の記事などを参考にしながら作成を行ってください。
https://dev.classmethod.jp/articles/creation_vpc_ec2_for_beginner_2/

まずはコンソールでEC2と検索し、EC2のダッシュボード画面に移動します。
次にインスタンスを起動をクリックします。
私の場合、
OSイメージ: Ubuntu
インスタンスタイプ: t2.micro
を選択し、

高度な詳細から先ほど作成したロールを選択して、

作成ボタンをクリックしたら完了です!

Lambdaに割り当てるロールの作成

先ほどと同じ要領でIAMロールを作成します。

その際Lambdaを選択し、次へをクリックします。

次に「AmazonEC2ReadOnlyAccess」と「AmazonSSMFullAccess」を検索してチェックをつけて次へをクリックします。


最後にロール名を入力し、ポリシー名に「AmazonEC2ReadOnlyAccess」と「AmazonSSMFullAccess」の2つが入っていることを選択したらロールを作成をクリックします。

これでLambdaの関数に割り当てるロールの作成は完了です!

Lambda関数の作成

最後にLambdaの関数を作成していきます。

まずはコンソールからLambdaと検索してLambdaのページに移動します。
続いて関数の作成ボタンをクリックします。

1から作成、関数名、ランタイムはNode.js 16.xを選択します。
ランタイムの部分は自分の得意な言語でOK。

選択したら関数を作成ボタンをクリックします。
※関数 URL を有効化にチェック入れておくとURLをクリックしたときに関数が実行されるようになります。後からAPIGatewayを使ってURLを発行することも可能です。

次に作成した関数の詳細ページで、
設定>アクセス権限から実行ロールを選択します。
実行ロールは先ほど作成したLambdaの関数に割り当てるロールを選択します。

続いて、コードからindex.jsのコードを編集していきます。

最終的に以下のコードになりました。

'use strict';

const AWS = require('aws-sdk')
const ssm = new (require('aws-sdk/clients/ssm'))();

module.exports.handler = async event => {

  try {
    let params = {
      DocumentName: 'AWS-RunShellScript',
      InstanceIds: ['<EC2のインスタンスID>'],
      Parameters: {
        commands: ['touch hoge.txt', 'touch foo.txt'], // EC2で実行したいコマンドを書いていきます(複数可)。
        workingDirectory:'/home/ubuntu' // コマンドを実行する場所。Ubuntuを選択したのでこうなります。
      },
      // SSMの実行結果をCloudWatchにロギング
      CloudWatchOutputConfig: {
        CloudWatchLogGroupName: 'SSMLogs',
        CloudWatchOutputEnabled: true
      },
      // タイムアウト設定
      TimeoutSeconds: 3600 // 1 hour
    }
    const sendCommandResult = await ssm.sendCommand(params).promise();  

  } catch(e){
    console.log(e);
  }

};

今回は、['touch hoge.txt', 'touch foo.txt']の2つのコマンドを実行するように設定しました。

Lambdaを実行したら、EC2にログインしてhoge.txtとfoo.txtができていることを確認したら完了です!

上手くいかない場合は、
関数の詳細画面で、モニタリング>ログからエラーログを確認できるはずなので、エラーを見てデバッグしてみてください。

Discussion