elasticsearch-rubyでAWSのElasticsearch Serviceで構築したElasticsearchに接続したときにはまった

https://dev-nabewata07.hatenablog.com/entry/2019/08/11/183106

上記記事の「アクセスポリシーで権限を設定する」までの手順でドメインの作成、アクセスポリシーの設定を行ったあとにRubyelasticsearchfaraday_middleware/aws_sigv4というgemを使ってAWSのElasticsearch Serviceで構築したElasticsearchに接続したときにハマったので対応を記録する。

該当のGem

https://rubygems.org/gems/elasticsearch

https://rubygems.org/gems/faraday_middleware-aws-sigv4

環境

Rubyのバージョン

$ ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin18]

各Gemのバージョン

aws-sigv4 (1.1.0)
elasticsearch (7.3.0)
elasticsearch-api (7.3.0)
elasticsearch-transport (7.3.0)

結論から

接続先のポート番号が9200以外のときはElasticsearch::Client.newでクライアントを作るときは引数でportも指定する必要がある。

具体的な理由は今回のelasticsearch-rubyGemではデフォルトのポート番号が9200で設定されるがAWSのElasticsearch Serviceで作成したドメインにアクセスするときは80または443番ポートでアクセスする必要があるため。

スクリプトは下記のように記述した。

host = ENV['ES_HOST']
port = 443
client = Elasticsearch::Client.new(host: host, port: port) do |f|
  f.request :aws_sigv4,
    service: service,
    region: region,
    access_key_id: ENV['AWS_ACCESS_KEY_ID'],
    secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
  f.adapter Faraday.default_adapter
end

最初に記述したスクリプト

require 'elasticsearch'
require 'faraday_middleware/aws_sigv4'

require 'dotenv'
Dotenv.load

# e.g. https://my-domain.region.es.com
host = ENV['ES_HOST']

region = 'ap-northeast-1'
service = 'es'

client = Elasticsearch::Client.new(host: host) do |f|
  f.request :aws_sigv4,
    service: service,
    region: region,
    access_key_id: ENV['AWS_ACCESS_KEY_ID'],
    secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
  f.adapter Faraday.default_adapter
end

puts client.cat.indices

実行すると

$ bundle exec ruby sample.rb
...
/path/to/ruby/2.6.0/net/http.rb:947:in `initialize': execution expired (Net::OpenTimeout)
...
/path/to/ruby/2.6.0/net/http.rb:947:in `initialize': execution expired (Faraday::ConnectionFailed)

上記のように例外が発生して失敗した。

対応

調査したところelasticsearch-transportのドキュメントにDefult Portの項目があり、別のポート番号の場合は指定するように書いてあった。

https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-transport#default-port

The default port is 9200. Please specify a port for your host(s) if they differ from this default. Please see below for an exception to this when connecting using an Elastic Cloud ID.

もとにしているGemであるelasticsearch-rubyのドキュメントにも

https://github.com/elastic/elasticsearch-ruby

Usageの項目に

https://github.com/elastic/elasticsearch-ruby#usage

このGemはelasticsearch-transportelasticsearch-apiの2つのライブラリのラッパーである旨と

Both of these libraries are extensively documented. Please read the elasticsearch-transport and the elasticsearch-api documentation carefully.

のようにそちらのドキュメントを読むように記述してあった。

具体的には結論からで書いたようにportを明示的に指定した。

まとめ

当たり前だけどライブラリを使うときはドキュメントを注意深く読む。

心がけていたつもりだったけど時間がないときなどはおろそかにしがちなのでいい反省になった。