3
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Amazon Elasticsearch Service とlambda(Python3) を一瞬で疎通するメモ

Amazon Elasticsearch Serviceと Lambda(Python3)を一瞬で疎通するメモ

要件

  • AWS Lambdaと AWS Elasticsearch Serviceの連携ができること
  • ローカルPCで下記が出来ること
    • curlで Elasticsearch Serviceに接続可能
    • kibanaを利用可能
    • python-lambda-localで Lambdaを実行し、Elasticsearch Serviceに接続可能

Elasticsearch Serviceアクセスポリシー設定

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:ap-northeast-1:[アカウントID]:domain/[ESドメイン]/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "[アクセス元IPアドレス]"
          ]
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::[アカウントID]:user/[ユーザ]"
      },
      "Action": "es:ESHttpGet",
      "Resource": "arn:aws:es:ap-northeast-1:[アカウントID]:domain/[ESドメイン]/*"
    }
  ]
}
  • Elasticsearch Serviceのドメインを最小構成で起動しておく
  • 下記ポリシーを持った IAMユーザを作成
    • AWSLambdaFullAccess
    • AmazonESFullAccess

Elasticsearch Service動作確認

  • ローカルPCから curlでの接続
$ curl -XGET https://xxxx.ap-northeast-1.es.amazonaws.com/_aliases
# {".kibana":{"aliases":{}}}
  • kibanaはブラウザでいい感じに動くことを確認する

Lambda実装サンプル

※botocoreを使用したサンプルは、EC2バージョンアップなどにより動かなくなる(なった)ため修正

pip3 install requests -t./

requestパッケージを AmazonLinuxの EC2でダウンロード

pip3 install requests-aws4auth -t./
# 依存関係で python-request 他もダウンロードされる

※requests_aws4auth, requests, bin, certifi, chardet, idna, requests, urllib3 を scpなどで手元に持ってくるか、任意の S3バケットにアップロードする

import boto3
import json
import requests
from requests_aws4auth import AWS4Auth

def handler(event, context):
    url = "https://****-****.ap-northeast-1.es.amazonaws.com/_search"
    credentials = boto3.Session().get_credentials()
    awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, 'ap-northeast-1', 'es', session_token=credentials.token)

    query = {"size": 1}
    response = requests.get(url, auth=awsauth, headers={"Content-Type": "application/json"}, data=json.dumps(query))

    return json.loads(response.text)

※初回は「アクション->関数のエクスポート->デプロイパッケージのダウンロード」で lambda_function.pyファイルをダウンロードし、先程ダウンロードした requestsパッケージにコピーしてzipファイルに圧縮、「コード エントリ タイプ->.zipファイルをアップロード」で展開すると楽

  • 下記ポリシーを持った IAMロールを作成
    • AmazonESFullAccess
  • Lambda環境変数に設定
    • ES_ENDPOINT_URL
    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY
    • AWS_SESSION_TOKEN
  • Python以外だと署名バージョン4 の実装が若干面倒かも

Lambda動作確認

  • AWSデベロッパーコンソールに Lambdaソースを貼り付けてテスト
{
  ".kibana": {
    "aliases": {}
  }
}
  • ローカルPCから python-lambda-localで実行
$ export ES_ENDPOINT_URL=https://xxxx.ap-northeast-1.es.amazonaws.com
$ echo "{}" > event.json
$ python-lambda-local -f handler index.py event.json
# [root - INFO - 2017-11-xx xx:xx:xx,xxx] Event: {}
# [root - INFO - 2017-11-xx xx:xx:xx,xxx] START RequestId: xxxx
# [botocore.vendored.requests.packages.urllib3.connectionpool - INFO - 2017-11-xx xx:xx:xx,xxx] Starting new HTTPS connection (1): xxxx.ap-northeast-1.es.amazonaws.com
# [root - INFO - 2017-11-xx xx:xx:xx,xxx] END RequestId: xxxx
# [root - INFO - 2017-11-xx xx:xx:xx,xxx] RESULT:
# {'.kibana': {'aliases': {}}}
# [root - INFO - 2017-11-xx xx:xx:xx,xxx] REPORT RequestId: xxxx    Duration: 383.92 ms
  • ここまでやったら Lambda関数をエクスポートして 以後は CloudFormationでデプロイするとあとあとよい
  • ElasticSearchは忘れず止めておく😇

参考リンク

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
3
Help us understand the problem. What are the problem?