概要
Elasticsearchを、Lambdaから読み書きする方法をメモした。
背景と目的
都合により、Elasticsearchを使用する必要が出た。Lambdaから読み書きしたいので、作業内容をメモしておく。
詳細
1. Elasticsearch
1.1 Elasticsearch ドメインの作成
まず、Elasticsearch ドメインを作成した。
デプロイタイプの選択
- デプロイタイプ: 開発およびテスト用
- バージョン: 7.10
ドメインの設定
- ドメイン名: es-test1
- カスタムエンドポイント: 無効
- 自動調整: 無効
- データノード
- インスタンスタイプ: t3.small.elasticsearch
- ノードの数: 1
- データノードストレージ
- ストレージタイプ: EBS
- ボリュームタイプ: 汎用SSD
- ストレージサイズ: 10GB
- 専用マスターノード: 無効
アクセスとセキュリティの設定
- ネットワーク構成: パブリックアクセス
- 細かいアクセスコントロール
- マスターユーザー: 作成
- Kibana の SAML 認証: 無効
- Amazon Cognito 認証: 有効
- IAMロール: 自動作成
- ロールポリシー: AmazonESCognitoAccess
- IAMロール: 自動作成
- アクセスポリシー
- ドメインアクセスポリシー: オープンアクセスを許可
- 暗号化
- 暗号化: すべて有効
- KMSマスターキー: aws/es
- 任意のElasticsearch クラスターの設定: デフォルト
15分以上待ってようやく利用可能(ステータス=アクティブ)になる。
1.2 内部ユーザーの追加
- Kibana(Opendistro for Elasticsearch)に上記で作成したマスターユーザーでログインし、Securityメニューに移動。
- Internal usersで、create internal userをクリック
- ユーザー名、パスワードを入力。
- Backend roles、Attributesは空
1.3 内部ユーザーのアクセス制御
ロールを作成
最低限、データの追加、取得ができるようにする。
- ロール名: test
- Cluster permissions
- indices:data/write/bulk
- Index permissions
- Index: *
- Permissions: data_access
- Tenant permissions
- Name: *
ロールにユーザーをマッピング
上記で作成した内部ユーザーをマッピングした。
2. Lambdaから入出力
2.1 関数の作成
- 関数名: es-test1
- 実行ロール: Lambda自動作成ロールに対してIAMで以下を追加
- AmazonESFullAccess
2.2 ドメイン名の取得
# client作成 client = boto3.client('es') # ドメインのリスト取得 response = client.list_domain_names() print(json.dumps(response, indent=4))
{ "ResponseMetadata": { "RequestId": "...", "HTTPStatusCode": 200, "HTTPHeaders": { "x-amzn-requestid": "...", "content-type": "application/json", "content-length": "43", "date": "Sun, 08 Aug 2021 13:11:36 GMT" }, "RetryAttempts": 0 }, "DomainNames": [ { "DomainName": "es-test1" } ] }
2.3 データの保存
上記で作成した内部ユーザーの認証情報を使って実行。 es.indexで、データを保存(または更新) es.indexを実行するには、indices:data/write/bulk permissionをCluster permissionsに付与したroleが必要。(参考)
from elasticsearch import Elasticsearch, RequestsHttpConnection from requests_aws4auth import AWS4Auth import boto3 host = '' # For example, my-test-domain.us-east-1.es.amazonaws.com region = '' # e.g. us-west-1 es = Elasticsearch( hosts = [{'host': host, 'port': 443}], #http_auth = awsauth, http_auth = ("ユーザー名", "パスワード"), use_ssl = True, verify_certs = True, connection_class = RequestsHttpConnection ) document = { "title": "Moneyball", "director": "Bennett Miller", "year": "2011" } es.index(index="movies", doc_type="_doc", id="56", body=document)
2.4 データの取得
es.getでindexとidを指定して取り出す。
es.get(index="movies", doc_type="_doc", id="56")
まとめと今後の課題
Elasticsearchのドメインを作成し、Lambdaから読み書きすることができた。