【未経験向け】CCNA(200-301)とは? NW未経験が1ヶ月で合格した際に使用した魔法の学習教材、サイトを紹介!!!

CloudWatch LogsのログをS3にエクスポートするLambdaを作った

AWS

タイトル通りです。

管理人は当サイトだけでなく他にもWebサイトや自宅にサーバを持っています。
それらのサーバのログをCloudWatch Logsで収集しているのですが、ずっとCW Logsに入れておくわけにもいかないのでS3へ退避させるLambdaを作成しました。

スポンサーリンク

本記事の概要

目的

  • CloudWatch Logsに格納してるログをS3へエクスポートするLambdaを作成する

前提条件

  • CloudWatch Logsにロググループとログストリームが存在していること
  • Lambdaのランタイムには「Node.js 14.x」を利用する
  • 当記事の内容は、ある程度のAWSの基礎的知識を身に着けている前提とする

CW Logs To S3退避用Lambdaを作成する手順

1. Lambda関数を作成する

  1. Lambdaコンソールを開き、新しい関数を作成します。
  2. 「一から作成」にチェックがついてることを確認します。
  3. 以下のパラメータを指定します。
    「関数名」「タイム」
    ※アーキテクチャ は「x86_64」を指定します
  4. 実行ロールは「基本的な Lambda アクセス権限で新しいロールを作成」を選択しておきます。
    ※後でポリシーを追加します
  5. 詳細設定はデフォルトのまま、画面右下の「関数の作成」をクリックします。
  6. 関数作成後、初期ファイル (index.js)に後述の「Lambdaコード」を張り付け、デプロイします。
  7. 環境変数の設定を行います。Lambda関数画面の設定タブから環境変数項目を選択し、以下の変数を設定します。
    • Key=BucketName
      Valueには退避先S3バケット名を入力してください
    • Key=DestinationPrefix
      Valueには退避元のCloudWatch Logsのロググループ名を入力してください
    • Key=LogGroupName
      Valueには退避元のCloudWatch Logsのロググループ名を入力してください
    • Key=TaskName
      ValueにはLambda関数名を入力してください

2. CWLogsとS3操作用のIAMポリシーを作成する

  1. IAMコンソールへ遷移し、左ペインから「IAMポリシー」を選択します。
  2. 以下の権限を持つIAMポリシーを作成します。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "logs:CreateExportTask",
                "s3:GetBucketAcl",
                "s3:PutObject"
            ],
            "Resource": "*"
        }
    ]
}
  1. Lambda関数作成時に生成されたIAMロールに上記IAMポリシーを付与します。

3. テスト実行

  1. 作成したLambda関数を実行してみます。
  2. S3へログが退避されてること、及びLambda関数の実行ログ(CloudWatch Logs)を確認します。

4. EventBridgeで処理を自動化する

  1. Lambda関数画面の設定タブからトリガー項目を選択し、新しいトリガーから「EventBridge (CloudWatch Events)」を選択します。
  2. 各項目に応じた適切なパラメータを指定し、画面右下「追加」をクリックします。
    • ルール:新規ルールを作成
    • ルール名:<任意のルール名を入力>
    • ルールの説明:<任意の説明を入力>
    • ルールタイプ:スケジュール式 「cron(5 16 * * ? *)」
      ※日次で01:05 JSTでスケジュール実行するcron式になります
  3. EventBradgeが追加されたことを確認します。

Lambdaコード

'use strict';

const aws = require('aws-sdk');
aws.config.update({region: 'ap-northeast-1'}); // 対象リージョンを指定

/**
 * メイン処理
 * @param event : 呼び出し元サービスから渡される値
 * @param context : AWS側の各種情報
 * @param callback : 呼び出し元サービスへ返す値
 * 
 */
exports.handler = (event, context, callback) => {
  const cloudwatchlogs = new aws.CloudWatchLogs();
  let params;
  let getToTime = [];
  getToTime = getTimeData();


  /* 
  "destination"で設定したS3バケットに、"destinationPrefix"で設定したフォルダを作り、
  "logGroupName"で設定したCludWatchのロググループのlogをexportする。
  exportするlogの範囲は、"from"から"to"で設定した範囲。
  */
  params = {
    'destination': process.env.BucketName,
    'from': getToTime[0],
    'to': getToTime[1],
    'logGroupName': process.env.LogGroupName,
    'destinationPrefix': `${process.env.DestinationPrefix}/${getToTime[2]}`,
    'taskName': `${process.env.TaskName}/${getToTime[2]}`
  };

  console.log(JSON.stringify(params));

  /* logのexport処理 */
  cloudwatchlogs.createExportTask(params, (err, data) => {
    let response;
    if (err) {
      console.log(err, err.stack);
      response = err.stack;
    } else {
      console.log(data);
      response = data;
    }
    callback(null, response);
  });
};


/**
 * ログ取得の開始日時、終了日時、日付フォーマットを返す。
 * ログデータは、エクスポートできるようになるまで最大 12時間かかる場合があるので、
 * 1日前のログを取得するように日時を調整。
 * @return arr : [from, to, format]
 * 
 */
function getTimeData() {
  let arr=[];
  let now = new Date();
  now.setTime(now.getTime() + 1000*60*60*9);// JSTに変換
  let yyyy,mm,dd;
  console.log(now);

  /* 開始日:fromをarrにセット */
  now.setDate(now.getDate()-2);
  now.setHours(0);
  now.setMinutes(0);
  now.setSeconds(0);
  now.setMilliseconds(0);
  arr.push(now.getTime());
  console.log(`ログ取得from:${now.getFullYear()}/${now.getMonth() + 1}/${now.getDate()}`);

  /* 終了日:toをarrにセット */
  now.setDate(now.getDate()+1);
  arr.push(now.getTime());
  console.log(`ログ取得to:${now.getFullYear()}/${now.getMonth() + 1}/${now.getDate()}`);

  yyyy = now.getFullYear();
  mm = ('0' + (now.getMonth() + 1)).slice(-2);
  dd = ('0' + now.getDate()).slice(-2);
  arr.push(`${yyyy}-${mm}-${dd}`);

  return arr;
}

参考記事

コメント

タイトルとURLをコピーしました