Amazon Web Services ブログ

Amazon Athena ワークグループを使用したクエリの分離とコストの管理

Amazon Athena は、Amazon S3 のデータに対するサーバーレスのクエリエンジンです。多くのお客様が、Athena を使用してアプリケーションおよびサービスのログを照会し、自動化されたレポートをスケジュールし、それらのアプリケーションと統合し、新しい分析ベースの機能を可能にしています。

ビジネスアナリスト、データサイエンティスト、セキュリティ、オペレーションエンジニアなど、さまざまな種類のユーザーが Athena を活用しています。しかし、コストを最小限に抑えながらユーザーが最高の体験を得られるには、こうしたワークロードをどのように分離および管理すればよいでしょうか?

この記事では、ワークグループを使用して以下を行う方法を説明します。

  • ワークロードを分離する。
  • ユーザーのアクセスをコントロールする。
  • クエリの使用状況およびコストを管理する。

ワークロードを分離する

デフォルトでは、すべての Athena クエリはプライマリワークグループで実行されます。  管理者は、新しいワークグループを作成して、さまざまな種類のワークロードを分離することができます。  管理者は通常、ワークグループを使用して、アドホッククエリを実行しているアナリストを自動レポートから分離します。  その分離を行う方法は次のとおりです。

最初に、2 つのワークグループを作成します。1 つはアドホックユーザー用 (ad-hoc-users) 、もう 1 つは自動レポート用 (reporting) です。

次に、特定の出力場所を選択します。このワークグループ内で実行されたすべてのクエリは、その結果をこの出力場所に保存します。結果を単一の安全な場所にルーティングすることで、ユーザーは表示が許可されているデータにだけアクセスできるようになります。また、適切な暗号化設定を選択して、S3 でクエリ結果の暗号化を強制することもできます。

ワークグループは、Athena への新規ユーザーの登録を簡単にするのにも役立ちます。[override client-side settings] を選択すると、ワークグループ内のすべてのクエリに対して定義済みの設定が強制されます。ユーザーは、クエリ結果の出力場所や S3 暗号化キーを設定する必要がなくなりました。これらの設定は、クエリが実行されるワークグループに対して定義されたパラメータにデフォルト設定されます。さらに、それぞれのワークグループは固有のクエリ履歴と保存されたクエリインベントリを保持しているため、クエリを簡単に追跡できます。

最後に、ワークグループを作成するときに、最大 50 のキーと値のペアのタグを追加して、ワークグループのリソースを識別しやすくすることができます。タグは、Athena のコストをユーザーグループ間で割り当てるときにも役立ちます。ad-hoc-users および reporting ワークグループに対して、その名前と部門の関係で「Name」および「Dept」タグを作成します。

ワークグループへのユーザーのアクセスをコントロールする

これで、ad-hoc-usersreporting の 2 つのワークグループが定義されたので、次はそれらを使用および更新できるユーザーをコントロールする必要があります。  ワークグループは IAM リソースであるため、ARN があることに留意してください。 ユーザーと関連付ける IAM ポリシーでこの ARN を使用できます。  この例では、アドホックユーザーのチームを表す単一の IAM ユーザーを作成し、その個人を IAM グループに追加します。このグループには、これらのユーザーが実行できる操作を強制するポリシーが含まれています。

ワークグループにアクセスするための IAM ポリシーワークグループのサンプルポリシーを確認することから始めて、ポリシーオプションに慣れてください。 以下の IAM ポリシーを使用して、analyst ユーザーに権限を設定します。このユーザーに、ad-hoc-users ワークグループでの作業に必要な権限だけを付与します。正確に必要性に適合するようにこのポリシーを微調整してください。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "athena:ListWorkGroups"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "athena:StartQueryExecution",
                "athena:GetQueryResults",
                "athena:DeleteNamedQuery",
                "athena:GetNamedQuery",
                "athena:ListQueryExecutions",
                "athena:StopQueryExecution",
                "athena:GetQueryResultsStream",
                "athena:GetQueryExecutions",
                "athena:ListNamedQueries",
                "athena:CreateNamedQuery",
                "athena:GetQueryExecution",
                "athena:BatchGetNamedQuery",
                "athena:BatchGetQueryExecution",
                "athena:GetWorkGroup",
                "athena:ListTagsForResource"
            ],
            "Resource": "arn:aws:athena:us-east-1:112233445566:workgroup/ad-hoc-users"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObjectAcl",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:ListMultipartUploadParts"
            ],
            "Resource": "arn:aws:s3:::demo/workgroups/adhocusers/*"
        },
{
            "Effect": "Allow",
            "Action": [
                "glue:Get*"
            ],
            "Resource": [
                "arn:aws:glue:us-east-1:112233445566:catalog",
                "arn:aws:glue:us-east-1:112233445566:database/amazon",
                "arn:aws:glue:us-east-1:112233445566:table/amazon/*"
            ]
        }
    ]
}

これで、analyst ユーザーは、ad-hoc-users ワークグループでのみクエリを実行できます。analyst ユーザーは他のワークグループに切り替えることはできますが、何らかの操作を実行しようとするとアクセス権がなくなります。さらに、Amazon データベースに属するテーブルだけを一覧表示および照会するように制限されています。データベースやテーブルなどの AWS Glue リソースへのアクセスのコントロールの詳細については、アクセスコントロールのための AWS Glue リソースポリシーを参照してください。

次のスクリーンショットは、Athena コンソールで analyst に表示される内容を示しています。

特定のディレクトリにファイルとして保存された SQL クエリを実行する単純な Node.js ツールを作成しました。私の Athena テストランナーコードは athena_test_runner GitHub リポジトリにあります。ワークグループを使用するように設定した後、このコードを使用してレポーティングツールをシミュレートできます。これを行うには、analyst ユーザーに対して以前に定義されたような権限を持つ IAM ロールを作成します。今回は、reporting ワークグループへのアクセスに制限します。

次の JavaScript コードの例は、クエリを実行するときにプログラムでワークグループを選択する方法を示しています。

function executeQueries(files) {
    params = 
    {
      "QueryString": "",
      "ResultConfiguration": { 
        "OutputLocation": ""
      },
      "QueryExecutionContext": {
        "Database": "default"
      },
      "WorkGroup":"reporting"
    }
 
    params.QueryString = "SELECT * FROM amazon.final_parquet LIMIT 10"
    return new Promise((resolve, reject) => {
        athena.startQueryExecution(params, (err, results) => {
            if (err) {
                reject(err.message)
            } else {
                resolve(results)
            }
        })
    })
}

次のコマンドを使用して、reporting ワークグループでサンプル自動化レポートを実行します。

node index.js testsuite/

クエリ履歴はワークグループ間で分離されたままです。ad-hoc-users ワークグループを使用して analyst として Athena コンソールにログインしているユーザーには、reporting ワークグループで実行した自動レポートは表示されません。

クエリの使用状況およびコストの管理

アドホックユーザ用と自動レポート用の 2 つのワークグループが設定されています。ここで、不良なクエリに対して保護する必要があります。このユースケースでは、クエリの使用に関する 2 つの潜在的な状況を監視およびコントロールする必要があります。

  • 予算内で許可されている以上のデータをスキャンするクエリをユーザーが実行しないようにします。
  • 不明確なクエリの廃棄を引き起こす可能性がある自動化されたスクリプトのバグに対して保護します。

まず、ad-hoc-users ワークグループのデータ使用制御を設定します。データ使用制御には、クエリ単位とワークグループ単位の 2 種類があります。

アナリストのクエリ単位の制御を 1 GB に設定します。この制御は、1 GB を超えるスキャンを試みる、ad-hoc-users ワークグループで実行されたクエリをキャンセルします。

操作でこの制限を守るには、[Update] を選択してクエリエディタに戻り、1 GB を超えるスキャンを行うクエリを実行します。このクエリは、エラーメッセージ「Query cancelled! : Bytes scanned limit was exceeded」を発生させます。キャンセル時点までにクエリがスキャンしたデータには料金が発生することに留意してください。この場合なら、1 GB のデータに対して料金が発生します。

それでは、reporting ワークグループに切り替えます。このワークロードでは、個々のクエリが大量のデータをスキャンすることを心配する必要はありません。ただし、このワークグループ内のすべてのクエリについてスキャンされたデータの総量を制御する必要はあります。

reporting ワークグループについてワークロードごとのデータ使用量制御を作成します。特定の期間にワークグループ内のすべてのクエリによってスキャンされるデータの最大量を設定することができます。

自動化されたレポート作成ワークロードの場合、おそらく、プロセスにかかる時間と、この間にクエリがスキャンするデータの総量を把握しておく必要があります。実行するレポートはわずかしかないため、数分以内に実行され、数メガバイトのデータしかスキャンされないことが予想されます。5 分以内に予想よりも多くのデータがクエリでスキャンされたときに通知するように、最低水準アラームを設定することから始めます。次の例は、デモ目的専用です。ほとんどの場合、この期間はもっと長くなります。作成した Amazon SNS トピックに通知を送信するようにアラームを設定しました。

アラームを検証するために、テストクエリをマイナーチェンジし、より多くのデータをスキャンさせました。この変更により、次の Amazon CloudWatch ダッシュボードに示すように SNS アラームが発生しました。

次に、reporting ワークグループ内のクエリが 15分間で 1 GB のデータを超えたときにトリガーされる最高水準アラームを作成します。この場合、このアラームはワークグループを無効にする AWS Lambda 関数をトリガーし、追加のクエリが実行されないようにします。このアラームは、誤った自動化コードや暴走したクエリによる費用を防ぐためのものです。

データ使用制御を作成する前に、ワークグループを無効にするための Node.js Lambda 関数を作成してください。以下のコードを貼り付けます。

exports.handler = async (event) => {
    const AWS = require('aws-sdk')
    let athena = new AWS.Athena({region: 'us-east-1'})
 
    let msg = JSON.parse(event.Records[0].Sns.Message)
    let wgname = msg.Trigger.Dimensions.filter((i)=>i.name=='WorkGroup')[0].value
    
    athena.updateWorkGroup({WorkGroup: wgname, State: 'DISABLED'})
 
    const response = {
        statusCode: 200,
        body: JSON.stringify(`Workgroup ${wgname} has been disabled`),
    };
    return response;
}

このコードは、SNS メッセージ本文からワークグループ名を取得し、その名前と状態を「DISABLED」として UpdateWorkGroup API アクションを呼び出します。Athena API には、最新バージョンの AWS SDK が必要です。Lambda バンドルを作成するときは、そのバンドルに最新バージョンの AWS SDK を含めてください。

次に、新しい SNS トピックとサブスクリプションを作成します。[Protocol] では、[AWS Lambda] を選択します。次に、前の手順で作成した Lambda 関数を選択します。

Athena コンソールで、2 番目のアラーム (15 分間で 1 GB) を作成し、先ほど作成した SNS トピックを指すようにします。トリガーされると、この SNS トピックは、reporting ワークグループを無効にする Lambda 関数を呼び出します。このワークグループでは、これ以上クエリを実行することはできません。ワークグループが無効になると、コンソールに次のエラーメッセージが表示されます。

Athena は、CloudWatch の AWS/Athena ネームスペースで、ワークグループごとに他の集約されたメトリクス (クエリステータスやクエリタイプ (DDL または DML)) を公開します。詳細については、CloudWatch メトリクスを使用した Athena クエリの監視を参照してください。

コストアロケーションタグ

ad-hoc-usersreporting ワークグループを作成したときに、Name タグと Dept タグを追加しました。これらのタグを Billing and Cost Management コンソールで使用して、ワークグループごとの使用量を判断することができます。

まとめ

この記事では、Athena のワークグループを使用してさまざまな照会ワークロードを分離し、アクセスを管理し、データ使用制御を定義して暴走したクエリから保護する方法を学びました。CloudWatch に公開されるメトリクスは、クエリのパフォーマンスを監視し、ユーザーが可能な限り最高の体験を得ていることを確認するのに役立ちます。詳細については、ワークグループを使用してクエリアクセスを制御するを参照してください。

著者について

Roy Hasson は、AWS Analytics のグローバルビジネス開発マネージャーです。彼は世界中の顧客と協力して、データ処理、分析、ビジネスインテリジェンスのニーズを満たすソリューションを設計しています。Roy は、マンチェスターユナイテッドの大ファンであり、家族とともにチームを応援しています。