PHP から Elasticsearch を操作するために Elastica というライブラリを使っている.今まで EC2 で運用していた Elasticsearch を Amazon ES に移行する話があり,Elastica から Amazon ES を操作するときに悩むことが多かったため,まとめておこうと思う.
github.com
ちなみに,僕は使ったことはないけれど,Elastic 社から公式に提供されている elasticsearch-php というライブラリもある.ただ,Elastic 社の公式ライブラリだと,積極的に Amazon ES 対応をすることはないだろうし,Amazon ES を使う場合は,サードパーティライブラリの Elastica の方が良い気がする.
github.com
Amazon ES に接続する方法
Amazon ES に接続する方法を復習しておくと,大きく3種類ある.
- リソースベース
- IP ベース
- IAM ユーザーとロールベース
docs.aws.amazon.com
今回のように,アプリケーションから Amazon ES に接続する場合は IAM を使う.IAM Role を使うのがベスト.必要に応じて IP 設定を変更して運用することも考えられるが,Amazon ES で IP 設定を変更すると,ノードが全台作り直されてしまうため,クラスタのデータ規模によっては1時間程度待たされることもあるので,実質不可能だと思うし,そもそも,アーキテクチャ的に微妙すぎる.
また,IP ベースの場合は未署名の匿名リクエストも受け付けることができるが,IAM を使う場合,署名付きリクエスト(AWS 署名バージョン 4)を送る必要がある.よって,ライブラリが署名付きリクエストに対応している必要がある.
docs.aws.amazon.com
docs.aws.amazon.com
Elastica から Amazon ES に接続する
github.com
Issue を見ると,Elastica は既に署名付きリクエストの対応がされているが,実装例などのドキュメントが全くなくて,よくわからなかった.困ったので Gitter で聞いてみたら,すぐ教えてもらうことができて助かった.簡単過ぎるけど,今回の構成をまとめた.
ライブラリをインストールする
署名付きリクエストを送るためには,Elastica 3.1.1 以上が必要になる.ただし,このままで実行すると,以下のエラーが出る.
Class 'GuzzleHttp\Psr7\Uri' not found
Elastica の composer.json
を見ると,suggest
プロパティに以下の設定がある.suggest
とは,基本的には必要ないけど,入れておくと便利な依存パッケージのことを意味している.Ruby の Gemfile にはそういう概念がないため,今まで知らなかった.
{
(中略)
"require-dev": {
"aws/aws-sdk-php": "~3.0",
"guzzlehttp/guzzle": "~6.0"
},
"suggest": {
"aws/aws-sdk-php": "Allow using IAM authentication with Amazon ElasticSearch Service",
"egeloen/http-adapter": "Allow using httpadapter transport",
"guzzlehttp/guzzle": "Allow using guzzle 6 as the http transport",
"monolog/monolog": "Logging request"
},
(中略)
}
よって,Amazon ES に IAM で接続する場合は,以下のような composer.json
になる(バージョン設定はご自由に).
{
(中略)
"require": {
"ruflin/Elastica": "~3.2",
"aws/aws-sdk-php": "~3.25",
"guzzlehttp/guzzle": "~6.2"
},
(中略)
}
まだ aws/aws-sdk-php
v2 を使っていると動かないため,合わせて aws/aws-sdk-php
をバージョンアップする必要がある.
Elastica のクライアント実装
以下のように transport
に AwsAuthV4
を設定して,aws_region
を設定すると,Amazon ES に IAM で接続できるようになる.
$client = new Elastica\Client(
array(
'host' => 'xxx.ap-northeast-1.es.amazonaws.com',
'port' => 80,
'transport' => ['type' => 'AwsAuthV4', 'postWithRequestBody' => true],
'aws_region' => 'ap-northeast-1'
)
);
もし IAM Role ではなく,クレデンシャルを埋め込む場合(非推奨な実装)は,以下のようになる.
$client = new Elastica\Client(
array(
'host' => 'xxx.ap-northeast-1.es.amazonaws.com',
'port' => 80,
'transport' => ['type' => 'AwsAuthV4', 'postWithRequestBody' => true],
'aws_access_key_id' => 'yyy',
'aws_secret_access_key' => 'xxx',
'aws_region' => 'ap-northeast-1'
)
);
まとめ
- Elastica は Amazon ES の接続をサポートしている
- ドキュメントが詳しくないため,困ったら Gitter で聞いてみると良い
- 必ず IAM Role を使おう
参考情報 : Amazon ES を運用するときに知っておくと便利なこと
kakakakakku.hatenablog.com