工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

ElasticsearchをLambdaから読み書きする

概要

Elasticsearchを、Lambdaから読み書きする方法をメモした。



背景と目的

都合により、Elasticsearchを使用する必要が出た。Lambdaから読み書きしたいので、作業内容をメモしておく。



詳細

1. Elasticsearch

1.1 Elasticsearch ドメインの作成

まず、Elasticsearch ドメインを作成した。

デプロイタイプの選択

  • デプロイタイプ: 開発およびテスト用
  • バージョン: 7.10

ドメインの設定

  • ドメイン名: es-test1
  • カスタムエンドポイント: 無効
  • 自動調整: 無効
  • データノード
  • データノードストレージ
    • ストレージタイプ: EBS
    • ボリュームタイプ: 汎用SSD
    • ストレージサイズ: 10GB
  • 専用マスターノード: 無効

アクセスとセキュリティの設定

  • ネットワーク構成: パブリックアクセス
  • 細かいアクセスコントロール
    • マスターユーザー: 作成
  • Kibana の SAML 認証: 無効
  • Amazon Cognito 認証: 有効
    • IAMロール: 自動作成
      • ロールポリシー: AmazonESCognitoAccess
  • アクセスポリシー
    • ドメインアクセスポリシー: オープンアクセスを許可
  • 暗号化
    • 暗号化: すべて有効
    • 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から読み書きすることができた。