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は忘れず止めておく😇