elasticdumpでelasticsearch のデータをコピーする

elasticdumpは豊富なオプションを備え、手軽にElasticsearch間のデータ転送が行える実用的なツールです。
2020.11.20

はじめに

ご家庭のElasticsearchクラスタのデータをコピーやダンプをしたい時ってよくありますよね。そのためにスクリプトを書いたりするのはおおげさだし、多くの手順からなるツールのセットアップは面倒なものです。そんな時にちょうどいいツールelasticdumpを試して実際にデータの転送を試してみました。

elasticdumpとは

elasticdumpはnodejs上で動作するCLIツールです。npmやyarnでインストールする他に/docker も提供されています。任意のElasticsearchをコピー元、コピー先としてデータやメタデータ(エイリアスやマッピング)の転送を行えます。

データソース・コピー先としてElasticsearch以外に以下のストレージをサポートしています。

  • Amazon S3(とS3互換のオブジェクトストレージ)
  • ローカルファイルシステム

データのフォーマットとしてJSONおよびCSVをサポートしています

簡単な使い方

最も簡単な使い方は2つのクラスタ間でのデータのコピーです。

以下の例ではステージング環境とプロダクション環境間でデータのコピーを行います。

elasticdump \
  --input=http://production.es.com:9200/my_index \
  --output=http://staging.es.com:9200/my_index

Dockerの場合は以下のようになります。

docker run --rm -ti elasticdump/elasticsearch-dump \
 --input=http://production.es.com:9200/my_index \
  --output=http://staging.es.com:9200/my_index

(便利な)オプション

多くのオプションがあるのですが、使ってみて便利だったオプションを紹介します。すべてのオプションはnpmページで紹介されています。

  • --limit elasticdumpはデータソースから複数回に分けてデータの取得とコピー先への送信を行います。—limitではこのバッチサイズを指定できます。似たようなオプションに —size がありますが、こちらは転送するデータ数の上限なので注意が必要です
  • --inputSocksProxy, --outputSocksProxy 転送先、転送元への接続にSOCK PROXYを使うことができます
  • --searchBody 転送するデータに対してクエリによる絞り込みができます
  • --awsAccessKeyId, --awsSecretAccessKey elasticdumpはAmazon Elasticsearch ServiceのIAMによるアクセス制御に対応しています
  • --awsIniFileProfile アクセスキーの代わりにAWS CLIのプロファイルを使用することもできます

使ってみる

実際にデータの転送を試してみました。 今回は手元のマシンからVPN接続したネットワーク上のSOCK PROXYを経由して2万件ほどのデータを転送しました。docker pullを除くと6分ほどかかりました。SOCK PROXY経由であることを考慮しても多少時間がかかっているように思えます。データ量がこれより多い場合にはバッチサイズや並行度の調整、あるいはネットワーク的に近い場所から実行する必要があると思います。

docker run --rm -ti elasticdump/elasticsearch-dump \
                                               --input=https://source-es.ap-northeast-1.es.amazonaws.com/source_index \
                                               --output=https://dest-es.ap-northeast-1.es.amazonaws.com/dest_index \
                                               --type=data \
                                               --inputSocksProxy=proxy.example.com \
                                               --outputSocksProxy=proxy.example.com \
                                               --inputSocksPort=1080 \
                                               --outputSocksPort=1080 \
                                               --limit 1000 \
                                               ----concurrency 5

Thu, 19 Nov 2020 08:39:27 GMT | starting dump
Thu, 19 Nov 2020 08:39:43 GMT | got 1000 objects from source elasticsearch (offset: 0)
Thu, 19 Nov 2020 08:39:54 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:40:10 GMT | got 1000 objects from source elasticsearch (offset: 1000)
Thu, 19 Nov 2020 08:40:16 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:40:28 GMT | got 1000 objects from source elasticsearch (offset: 2000)
Thu, 19 Nov 2020 08:40:36 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:40:47 GMT | got 1000 objects from source elasticsearch (offset: 3000)
Thu, 19 Nov 2020 08:40:51 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:40:57 GMT | got 1000 objects from source elasticsearch (offset: 4000)
Thu, 19 Nov 2020 08:41:02 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:41:09 GMT | got 1000 objects from source elasticsearch (offset: 5000)
Thu, 19 Nov 2020 08:41:14 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:41:23 GMT | got 1000 objects from source elasticsearch (offset: 6000)
Thu, 19 Nov 2020 08:41:27 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:41:35 GMT | got 1000 objects from source elasticsearch (offset: 7000)
Thu, 19 Nov 2020 08:41:40 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:41:49 GMT | got 1000 objects from source elasticsearch (offset: 8000)
Thu, 19 Nov 2020 08:41:54 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:42:03 GMT | got 1000 objects from source elasticsearch (offset: 9000)
Thu, 19 Nov 2020 08:42:07 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:42:13 GMT | got 1000 objects from source elasticsearch (offset: 10000)
Thu, 19 Nov 2020 08:42:17 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:42:25 GMT | got 1000 objects from source elasticsearch (offset: 11000)
Thu, 19 Nov 2020 08:42:29 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:42:37 GMT | got 1000 objects from source elasticsearch (offset: 12000)
Thu, 19 Nov 2020 08:42:42 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:42:49 GMT | got 1000 objects from source elasticsearch (offset: 13000)
Thu, 19 Nov 2020 08:42:54 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:43:01 GMT | got 1000 objects from source elasticsearch (offset: 14000)
Thu, 19 Nov 2020 08:43:05 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:43:11 GMT | got 1000 objects from source elasticsearch (offset: 15000)
Thu, 19 Nov 2020 08:43:15 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:43:20 GMT | got 1000 objects from source elasticsearch (offset: 16000)
Thu, 19 Nov 2020 08:43:25 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:43:31 GMT | got 1000 objects from source elasticsearch (offset: 17000)
Thu, 19 Nov 2020 08:43:38 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:43:45 GMT | got 1000 objects from source elasticsearch (offset: 18000)
Thu, 19 Nov 2020 08:43:49 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:43:55 GMT | got 1000 objects from source elasticsearch (offset: 19000)
Thu, 19 Nov 2020 08:44:00 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:44:10 GMT | got 1000 objects from source elasticsearch (offset: 20000)
Thu, 19 Nov 2020 08:44:15 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:44:23 GMT | got 1000 objects from source elasticsearch (offset: 21000)
Thu, 19 Nov 2020 08:44:29 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:44:37 GMT | got 1000 objects from source elasticsearch (offset: 22000)
Thu, 19 Nov 2020 08:44:42 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:44:49 GMT | got 1000 objects from source elasticsearch (offset: 23000)
Thu, 19 Nov 2020 08:44:52 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:44:59 GMT | got 1000 objects from source elasticsearch (offset: 24000)
Thu, 19 Nov 2020 08:45:05 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:45:11 GMT | got 1000 objects from source elasticsearch (offset: 25000)
Thu, 19 Nov 2020 08:45:16 GMT | sent 1000 objects to destination elasticsearch, wrote 1000
Thu, 19 Nov 2020 08:45:21 GMT | got 961 objects from source elasticsearch (offset: 26000)
Thu, 19 Nov 2020 08:45:25 GMT | sent 961 objects to destination elasticsearch, wrote 961
Thu, 19 Nov 2020 08:45:25 GMT | got 0 objects from source elasticsearch (offset: 26961)
Thu, 19 Nov 2020 08:45:25 GMT | Total Writes: 26961
Thu, 19 Nov 2020 08:45:25 GMT | dump complete

まとめ

elasticdumpは手軽にElasticsearch間のデータ転送が行えるだけでなく豊富なオプションを備えていて実用的なツールだと思いました。