1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AWS日記20 (Amazon Elasticsearch Service)

Last updated at Posted at 2020-10-31

はじめに

今回は Amazon Elasticsearch Service を試します。
DynamoDBからデータをロードする方式を試します。
[Lambda関数・SAMテンプレート]
(https://github.com/tanaka-takurou/serverless-elastic-search-page-go)

システム構成図

20201031.jpg

準備

AWS SAM の準備をします

[Amazon Elasticsearch Serviceの資料]
Amazon Elasticsearch Service

AWS SAM テンプレート作成

AWS SAM テンプレートで API-Gateway , Lambda, DynamoDB, Amazon Elasticsearch Serviceの設定をします。

[参考資料]
AWS SAM テンプレートを作成する

template.yml
template.yml

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Serverless Elastic Search Service Page

Parameters:
  ApplicationName:
    Type: String
    Default: 'ServerlessElasticSearchServicePage'
  FrontPageApiStageName:
    Type: String
    Default: 'ProdStage'
  DataTableName:
    Type: String
    Default: 'search_target'
  ESDomainName:
    Type: String
    Default: 'es-sample'
    AllowedPattern: "[a-z][a-z0-9\\-]+"
  ESIndexName:
    Type: String
    Default: 'messages'
  ESTypeName:
    Type: String
    Default: 'message'

Resources:
  FrontPageApi:
    Type: AWS::Serverless::Api
    Properties:
      Name: ServerlessElasticSearchServicePageApi
      EndpointConfiguration: REGIONAL
      StageName: !Ref FrontPageApiStageName
  FrontPageFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: ServerlessElasticSearchServicePageFrontFunction
      CodeUri: bin/
      Handler: main
      MemorySize: 256
      Runtime: go1.x
      Description: 'Test Front Function'
      Policies:
      Environment:
        Variables:
          REGION: !Ref 'AWS::Region'
          API_PATH: !Join [ '', [ '/', !Ref FrontPageApiStageName, '/api'] ]
      Events:
        FrontPageApi:
          Type: Api
          Properties:
            Path: '/'
            Method: get
            RestApiId: !Ref FrontPageApi
  ElasticSearchServiceLoadFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: ElasticSearchServiceLoadFunction
      CodeUri: api/load/bin/
      Handler: main
      MemorySize: 256
      Runtime: go1.x
      Description: 'ElasticSearchService Service Load Function'
      Policies:
      Environment:
        Variables:
          REGION: !Ref 'AWS::Region'
          DOMAIN: !GetAtt ElasticSearchServiceDomain.DomainEndpoint
          ES_INDEX_NAME: !Ref ESIndexName
          ES_TYPE_NAME: !Ref ESTypeName
      Events:
        FrontPageApi:
          Type: Api
          Properties:
            Path: '/api'
            Method: post
            RestApiId: !Ref FrontPageApi
  ElasticSearchServiceSaveFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: ElasticSearchServiceSaveFunction
      CodeUri: api/save/bin/
      Handler: main
      MemorySize: 256
      Runtime: go1.x
      Description: 'ElasticSearchService Service Save Function'
      Policies:
      Environment:
        Variables:
          REGION: !Ref 'AWS::Region'
          DOMAIN: !GetAtt ElasticSearchServiceDomain.DomainEndpoint
          ES_INDEX_NAME: !Ref ESIndexName
          ES_TYPE_NAME: !Ref ESTypeName
      Events:
        Stream:
          Type: DynamoDB
          Properties:
            Stream: !GetAtt DataTable.StreamArn
            BatchSize: 100
            StartingPosition: LATEST
  DataTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
      - AttributeName: "id"
        AttributeType: "N"
      KeySchema:
      - AttributeName: "id"
        KeyType: "HASH"
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
      SSESpecification:
        SSEEnabled: True
      TableName: !Ref DataTableName
      StreamSpecification:
        StreamViewType: "NEW_IMAGE"
  ElasticsearchDomain:
    Type: AWS::Elasticsearch::Domain
    Properties:
      DomainName: !Ref ESDomainName
      ElasticsearchClusterConfig:
        DedicatedMasterEnabled: "false"
        InstanceCount: "1"
        ZoneAwarenessEnabled: "false"
        InstanceType: "t2.micro.elasticsearch"
      EBSOptions:
        EBSEnabled: true
        VolumeSize: 10
        VolumeType: "gp2"
      SnapshotOptions:
        AutomatedSnapshotStartHour: "0"
      AccessPolicies:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              AWS: "*"
            Action: "es:ESHttp*"
            Resource: "*"
      AdvancedOptions:
        rest.action.multi.allow_explicit_index: "true"

Outputs:
  APIURI:
    Description: "URI"
    Value: !Join [ '', [ 'https://', !Ref FrontPageApi, '.execute-api.',!Ref 'AWS::Region','.amazonaws.com/',!Ref FrontPageApiStageName,'/'] ]

Amazon Elasticsearch Serviceの設定は以下の部分

  ElasticsearchDomain:
    Type: AWS::Elasticsearch::Domain
    Properties:
      DomainName: !Ref ESDomainName
      ElasticsearchClusterConfig:
        DedicatedMasterEnabled: "false"
        InstanceCount: "1"
        ZoneAwarenessEnabled: "false"
        InstanceType: "t2.micro.elasticsearch"
      EBSOptions:
        EBSEnabled: true
        VolumeSize: 10
        VolumeType: "gp2"
      SnapshotOptions:
        AutomatedSnapshotStartHour: "0"
      AccessPolicies:
        Version: "2012-10-17"
        Statement:
          - Effect: "Allow"
            Principal:
              AWS: "*"
            Action: "es:ESHttp*"
            Resource: "*"
      AdvancedOptions:
        rest.action.multi.allow_explicit_index: "true"

Lambda関数作成

※ Lambda関数は aws-lambda-go を利用しました。

Elasticsearchのインデックスを追加・更新するには POSTリクエスト を使う

	jsonStr := `{"` + name + `":"` + value + `"}`
	req, err := http.NewRequest(
		"POST",
		os.Getenv("DOMAIN") + "/" + os.Getenv("ES_INDEX_NAME") + "/" + os.Getenv("ES_TYPE_NAME") + "/",
		bytes.NewBuffer([]byte(jsonStr)),
	)
	if err != nil {
		return err
	}
    req.Header.Set("Content-Type", "application/json")
	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		return err
	}
	defer res.Body.Close()

Elasticsearchのインデックスを検索するには GETリクエスト を使う

	var d interface{}
	res, err := http.Get(os.Getenv("DOMAIN") + "/" + os.Getenv("ES_INDEX_NAME") + "/" + os.Getenv("ES_TYPE_NAME") + "/_search?q=" + word)
	if err != nil {
		return d, err
	}
	defer res.Body.Close()

	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return d, err
	}

	err = json.Unmarshal(body, &d)
	if err != nil {
		return d, err
	}
	return d, nil

終わりに

Amazon Elasticsearch Serviceは、完全マネージド型サービスであり Elasticsearchを手軽に利用できます。
今回はDynamoDBからデータをロードしましたが、Amazon Kinesis Data StreamsやAmazon CloudWatchからもロードできるため今後試していこうと思います。

参考資料
[AWSエキスパート養成読本](https://www.amazon.co.jp/dp/4774179922) [はじめての Elasticsearch](https://qiita.com/nskydiving/items/1c2dc4e0b9c98d164329) [Amazon Elasticsearch Serviceを触ってみた](https://qiita.com/takayuki-miura0203/items/c2ad9527d818fd20ca93) [Amazon Elasticsearch Serviceについてまとめてみる](https://qiita.com/corn0214/items/ed777d7bfa3d5353fd5a) [[AWS]Amazon Elasticsearch Serviceでよく使うコマンド集(Amazon ES/Elasticsearch)](https://qiita.com/kenboo/items/0146b081f165b9e18736) [CloudFormationでDynamoDB streamを設定する](https://qiita.com/hir00/items/b3011d1e80fb1e94a711)
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?