Amazon Web Services ブログ

Amazon Elasticsearch Service で PostgreSQL ログを分析する

バージョン 9.6.6 以降の Amazon RDS は、Amazon CloudWatch への PostgreSQL ログの発行をサポートしています。 Aurora PostgreSQL は、バージョン 9.6.12 以降、およびバージョン 10.7 以降の CloudWatch Logs へのログの発行をサポートしています。このデータを CloudWatch から Amazon Elasticsearch Service (Amazon ES) にライブストリーミングすることにより、RDS PostgreSQL DB ログの継続的な可視性を維持します。Kibana と簡単な検索構文を使用して、データをリアルタイムで視覚化、分析、検出できます。また、PostgreSQL ログのモニタリングを設定し、Kibana でアラームを設定して、ログに記録されたエラーまたは長時間実行されているクエリをタイムリーに検出できるようにすることもできます。

CloudWatch を使用すると、ログをクエリして視覚化を実行できますが、複数の AWS アカウントに複数のデータベースがある場合、これは困難な場合があります。この記事で使用するソリューションは理想的です。それはログを一元的にストリーミングし、各アカウントの複数のコンソールにログインせずに複数のデータベースのダッシュボードを視覚化するためです。

Amazon ES は完全マネージド型のサービスで、容易に、ダウンタイムなしで Elasticsearch を大規模にデプロイ、セキュリティ保護、運用することができます。ウェブサイト、モバイルデバイス、サーバー、センサーが生成した非構造化ログおよび半構造化ログを分析できます。これにより、運用インテリジェンス、アプリケーションモニタリング、根本原因の分析などが保証されます。このサービスは、オープンソース API、マネージド型のKibana を提供し、Logstash や他の AWS のサービスと統合して、任意のソースからデータを安全に取り込みます。Amazon ES を使用すると、リアルタイムで検索、分析、視覚化できます。

この記事では、RDS PostgreSQL データベースのログを CloudWatch に発行し、データを Amazon ES にライブストリーミングする方法を示します。また、データ保持しきい値を超えるコールドデータを削除する方法についても学びます。

大まかな手順は次のとおりです。

  1. Amazon ES ドメインを作成します。
  2. RDS PostgreSQL インスタンスを設定します。
  3. Amazon ES へのデータストリーミングを設定します。
  4. ストレージとパフォーマンスを向上させるために、コールドデータをアーカイブおよび消去します。

前提条件

  • 適切な AWS のサービスにアクセスできる有効な AWS アカウント。
  • Aurora/RDS PostgreSQL データベース。詳細については、「Amazon RDS」を参照してください。

Amazon ES ドメインの作成

Amazon ES ドメインは、設定、インスタンスタイプ、インスタンス数、指定したストレージリソースを持つクラスターです。新しいドメインを作成するには、「Amazon ES ドメインを作成する」を参照してください。

ドメインを作成したら、下のスクリーンショットのプレビューに示すように、Amazon ES ドメインの概要ページでエンドポイント、ARN、Kibana URL を見つけます。

エンドポイント、ARN、Kibana URL の場所を示す Amazon ES ドメインの概要ページのスクリーンショット。

RDS PostgreSQL インスタンスの設定

CloudWatch にログを発行するように RDS PostgreSQL データベースのログファイルを設定するには、次の手順を実行します。

  1. AWS マネジメントコンソールにログインし、Database カテゴリーで、[RDS] を選択します。
  2. 目的のデータベースインスタンスを選択します。
  3. [Modify] をクリックします。
  4. ログをエクスポートするには、以下のスクリーンショットのプレビューに示すように、[PostgreSQL log] と [Upgrade log] を選択します。
    選択した PostgreSQL ログと Upgrade ログボックスを表示するログエクスポートページのスクリーンショット。
  5. [Continue] をクリックします。
  6. [Apply Immediately] をクリックします。

新しいロググループが作成されたことを確認するには、CloudWatch コンソールに移動します。Management and Governance で、[Logs] を選択します。新しいロググループは次のように表示されます。/aws/rds/instance/<dbname>/postgresql

Amazon ES へのデータストリーミングの設定

CloudWatch から Amazon ES へのストリーミングを設定するには、「Amazon Elasticsearch Service への CloudWatch Logs データのストリーミング」を参照してください。ログ形式とフィルターを設定するには、次の手順を実行します。

  1. Configure Log Format and Filters ページの Log Format で、下のスクリーンショットプレビューに示すように [Common Log Format] を選択します。
    Configure Log Format and Filters 画面のスクリーンショットのプレビューと、Common Log Format の選択
  2. Subscription Filter Pattern には、日付、時刻、その他、メッセージを入力します。
  3. [Test Pattern] を選択します。以下のスクリーンショットは、これらの 3 つの手順を示す Configure Log Format and Filters ページのプレビューです。
    Configure Log Format and Filters ページのスクリーンショット。選択した Common Log Format が示され、Subscription Filter Pattern で [date、time、misc、message] が入力されています。このステップでは、パターンをテストして、データを整理する方法を示します。フィルターパターンを使用して、データを整理し、ログの構造に基づいて各ログステートメントを分離できます。この分離は、Kibana で視覚化データを作成するときに役立ちます。
    次のコードは、ログステートメントの例です。

    2019-08-08 02:47:24 UTC:72.21.217.47(7556):uadmin_TyOXrDmzkyCdRXcKdMHCnqqVCgZpDBHDLThdSNunLrzHNqFHNxjqxdwj@<dbname>:[11381]:LOG: connection authorized: user=uadmin_TyOXrDmzkyCdRXcKdMHCnqqVCgZpDBHDLThdSNunLrzHNqFHNxjqxdwj database=<dbname> SSL enabled (protocol=TLSv1.2, cipher=ECDHE-RSA-AES256-GCM-SHA384, compression=off)

    フィルターを適用すると、前述の文は次のように保存されます。

    date=August 7th 2019,
    time=02:47:24,
    misc=UTC:72.21.217.47(7556):uadmin_TyOXrDmzkyCdRXcKdMHCnqqVCgZpDBHDLThdSNunLrzHNqFHNxjqxdwj@<dbname>:[11381]:LOG:,
    message=connection authorized: user=uadmin_TyOXrDmzkyCdRXcKdMHCnqqVCgZpDBHDLThdSNunLrzHNqFHNxjqxdwj database=<dbname> SSL enabled (protocol=TLSv1.2, cipher=ECDHE-RSA-AES256-GCM-SHA384, compression=off)
  4. [Next] を選択します。
  5. [Review] をクリックします。
  6. [ストリーミングの開始] を選択します。

AWS Lambda でインデックス名パターンを変更する

AWS Lambda のインデックス名パターンを変更するには、次の手順を実行します。

  1. Lambda コンソールを開きます。
  2. 前の手順で自動的に作成された新しい関数を選択します (たとえば、LogsToElasticsearchEx_my-elk-stack_<account-number>)。
  3. Lambda 関数のインデックスプレフィックスを置き換えます (index.js)。次のコードを参照してください。
            // index name format: cwl-<databaseName>-YYYY.MM.DD
            var idxName = payload.logGroup.toLowerCase().split('/');
            var indexName = [
                'cwl-' + idxName[4] + '-' + timestamp.getUTCFullYear(), // log group + year
                ('0' + (timestamp.getUTCMonth() + 1)).slice(-2), // month
                ('0' + timestamp.getUTCDate()).slice(-2) // day
            ].join('.');

ベストプラクティスは、データベースごとに 1 つのインデックスを持つことです。これは、パフォーマンスとスケーリングに役立ちます。

この時点で、Lambda 関数はログを JSON 形式に変換し、ログを Amazon ES にエクスポートします。ただし、Lambda がログをエクスポートできるようにアクセス許可を設定しなかったため、HTTP ステータス 403 でエラーになります。

Lambda ログを表示するには、CloudWatch に移動し、/aws/Lambda/LogsToElasticsearchEx_my-elk-stack_<accountid> の下のログを表示します。次のコードは、エラーメッセージの例を示しています。

{ “errorMessage”: “{\”statusCode\”:403,\”responseBody\”:{\”Message\”:\”User: arn:aws:sts::<account_number>:assumed-role/my-elk-stack/LogsToElasticsearchEx_my-elk-stack_<account_number> is not authorized to perform: es:ESHttpPost\”}}” }

このエラーメッセージから、ARN をコピーして Amazon ES アクセスポリシーに含めることができます。

Amazon ES ドメインのアクセスポリシーを変更する

アクセスポリシーを変更するには、次の手順を実行します。

  1. Amazon ES コンソールを開きます。
  2. 前の手順で作成された ES ドメインを選択します。
  3. 次の要件を満たす [Modify access policy] を選択します。
    • CloudWatch からのデータの流入を許可し、ユーザーが Kibana ダッシュボードを表示するためのアクセス許可も含んでいる。
    • 各アカウントの Amazon ES アクセスポリシーに対応する ARN エントリがある。これは、複数のアカウントにデータベースインスタンスがあり、ログのエクスポートを構成している場合に行います。
    • Amazon ES および Kibana エンドポイントへの匿名アクセス用のポリシーがある。
    • CIDR ビットを使用して、単一のユーザーまたは複数のユーザーにアクセスを許可している。

次のスクリーンショットは、ES ドメインページのプレビューと、選択する [Modify access policy] ボタンを示しています。

ES ドメインページと選択する [Modify access policy] ボタンのスクリーンショットプレビュー。

複数のアカウントについては、次のポリシー例を参照してください。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:sts::<db_account_number1>:assumed-role/my_elk_stack/LogsToElasticsearchEx_my-elk-stack_<es_account_number>",
          "arn:aws:sts::<db_account_number2>:assumed-role/my_elk_stack/LogsToElasticsearchEx_my-elk-stack_<es_account_number>",
          "arn:aws:sts::<db_account_number3>:assumed-role/my_elk_stack/LogsToElasticsearchEx_my-elk-stack_<es_account_number>",
          "arn:aws:sts::<db_account_number4>:assumed-role/my_elk_stack/LogsToElasticsearchEx_my-elk-stack_<es_account_number>",
          "arn:aws:sts::<db_account_number5>:assumed-role/my_elk_stack/LogsToElasticsearchEx_my-elk-stack_<es_account_number>"
        ]
      },
      "Action": [
        "es:ESHttpGet",
        "es:ESHttpHead",
        "es:ESHttpPost",
        "es:ESHttpPut"
      ],
      "Resource": "arn:aws:es:us-east-1:<es_account_number>:domain/my-elk-stack/*"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:ESHttpGet",
      "Resource": "arn:aws:es:us-east-1:<es_account_number>:domain/my-elk-stack/*",
      "Condition": {
        "IpAddress": {
           "aws:SourceIp": [ "<first two blocks of your ip for multiple users>.0.0/24", "<full ip address for single user>/32" ]
        }
      }
    }
  ]
}

コールドデータのアーカイブと消去

Lambda 関数は、データベースごとに 1 日に 1 つのインデックスを作成します。クラスタ内のストレージと過密インデックスを管理するには、古いインデックスを日付ごとに徐々に削除することがベストプラクティスです。そうすることで、Amazon ES の不要な負荷を減らし、クエリのパフォーマンスを改善します。

これを実現するには、インデックスを反復処理し、設定したアーカイブ期間に基づいてインデックスを削除する Lambda 関数 (サンプル – Node.js Lambda function を参照) を作成する必要があります。必要なだけのデータをアーカイブできます。

複数のデータベースインデックスと 15 日間のデータアーカイブ用に Node.js Lambda 削除関数を作成します。必要に応じて日数を変更します。

Lambda 関数を作成したら、定期的なスケジュールで Lambda インデックス削除関数を呼び出すのに役立つ CloudWatch ルールを作成します。ルールを設定するには、次の手順を実行します。

  1. Amazon ES ドメインを含む AWS マネジメントコンソールアカウントにログインします。
  2. CloudWatch コンソールの Events で、[Rules] を選択します。
  3. [Create rule] を選択します。
  4. Events Source では、[Schedule] を選択します。
  5. Cron expression には、0 0/2 * * ? * と入力します。
    この式は、2 時間ごとに関数を呼び出します。これらのインデックスの自動スナップショットが進行中の場合、インデックスが残っている可能性があります。
  6. [Add target] を選択します。
  7. ドロップダウンメニューから、[Lambda function] を選択し、[Configure details] をクリックします。
  8. 次の画面の Function で、下のスクリーンショットのプレビューに示すように、CloudWatch ルールの名前と説明を入力します。

上記の手順 1〜8 を示すスクリーンショットプレビュー。

Lambda 関数が古いインデックスを削除できるようにする権限も追加します。

  1. Amazon ES コンソールを開きます。
  2. 前の手順で作成された ES ドメインを選択します。
  3. [Modify access policy] を選択します。
  4. 既存のポリシーに次のコードを追加します。
    {
    "Effect": "Allow",
    "Principal": {
    "AWS": "arn:aws:iam::<accountNumber>:role/service-role/<curatorFunctionName>"
    },
    "Action": "es:ESHttpDelete",
    "Resource": "arn:aws:es:us-east-1:<accountNumber>:domain/my-elk-stack/*"
    }

まとめ

この記事では、PostgreSQL ログを Amazon ES にストリーミングし、ストレージとパフォーマンスの管理に役立つライフサイクルポリシーを設定する方法を示しました。これで、強力で簡単なクエリ分析エンジンを使用して、ログをインテリジェントに視覚化して分析できます。

このブログ記事はシリーズの一部です。Amazon ES に保存されたデータの視覚化と分析のために Kibana を設定する方法については、「Kibana ダッシュボードの設定と作成」を参照してください。

 


著者について

 

Marcel George はアマゾン ウェブ サービスのコンサルタントです。 お客様と協力し、AWS クラウドでスケーラブルかつ可用性と安全性に優れたソリューションの構築に取り組んでいます。彼の専門分野は、同種および異種のオンプレミスデータベースをAmazon RDS や Aurora PostgreSQL へ移行する技術です。