share facebook facebook2 twitter menu hatena pocket slack

2017.05.15 MON

Amazon Elasticsearch Service ドメインを安全(当社比)に操作出来て、且つドメインの設定を toml フォーマットで管理するコマンドラインツールを作った

川原 洋平

WRITTEN BY 川原 洋平

作ったもの

inokappa/eryastic
Contribute to eryastic development by creating an account on GitHub.

github.com

eryastic と書いて、「えりゃすてぃっく」と呼んでいる。

なんで作ったの?

  • マネジメントコンソールでの Amazon Elasticsearch Service ドメインの操作をそろそろ卒業したかった
  • 手順書作成を簡素化したかった
  • TOML フォーマットを使ってみたかった

何が出来る?

  • Amazon Elasticsearch Service ドメインの一覧を取得
  • Amazon Elasticsearch Service ドメインを作成
  • Amazon Elasticsearch Service ドメインを削除
  • Amazon Elasticsearch Service ドメインの設定を export
  • Amazon Elasticsearch Service ドメイン構成を更新

将来的には、スナップショット作成、レストア機能も取り込む予定。

何が安全なん?

当社比(自分比)だけど、ドメイン作成、削除、更新時には、必ず設定内容を確認するステップを設けた。
例えば、ドメインを削除したい場合。

bash-3.2$ AWS_PROFILE=xxxxx AWS_REGION=ap-northeast-1 bundle exec eryastic domain --delete --domain-name=oreno-es1
I, [2017-04-16T13:05:20.957089 #19624]  INFO -- : 以下の Amazon Elasticsearch Service ドメインを削除します.
+----------------------------------------+------------------------------------------------------------------------------+
| key                                    | value                                                                        |
+----------------------------------------+------------------------------------------------------------------------------+
| domain_id                              | 123456789012/oreno-es1                                                       |
| domain_name                            | oreno-es1                                                                    |
| arn                                    | arn:aws:es:ap-northeast-1:123456789012:domain/oreno-es1                      |
| created                                | true                                                                         |
| deleted                                | false                                                                        |
| endpoint                               | search-oreno-es1-xxxxxxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com  |
| processing                             | false                                                                        |
| elasticsearch_version                  | 2.3                                                                          |
| access_policies                        | {                                                                            |
|                                        |   "Version": "2012-10-17",                                                   |
|                                        |   "Statement": [                                                             |
...
|                                        | }                                                                            |
| instance_type                          | t2.micro.elasticsearch                                                       |
| instance_count                         | 1                                                                            |
| dedicated_master_enabled               | false                                                                        |
| zone_awareness_enabled                 | false                                                                        |
| ebs_enabled                            | true                                                                         |
| volume_type                            | gp2                                                                          |
| volume_size                            | 10                                                                           |
| automated_snapshot_start_hour          | 1                                                                            |
| rest.action.multi.allow_explicit_index | true                                                                         |
+----------------------------------------+------------------------------------------------------------------------------+
処理を続行しますか ? [y|n]:

おっと、削除するのは oreno-es01 ではなく、oreno-es02 だった…場合には、n を入力することで処理を中断させることが出来る。

n
W, [2017-04-16T13:09:13.896709 #19624]  WARN -- : 処理を中止します.

デモ

事前に

Eryastic を実行する環境には Amazon Elasticsearch Service を操作出来る権限が必要になります。
今回は以下のように Amazon Elasticsearch Service のアクセスポリシーに Eryastic を実行する環境の IP アドレスを登録しています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:ap-northeast-1:123456789012:domain/demo-es1/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "xxx.xxx.xxx.111",
            "xxx.xxx.xxx.222"
          ]
        }
      }
    }
  ]
}

help

$ bundle exec eryastic --help domain
Usage:
  eryastic domain

Options:
  -c, [--create], [--no-create]    # Amazon Elasticsearch Service ドメインを作成する.
  -d, [--delete], [--no-delete]    # Amazon Elasticsearch Service ドメインを削除する.
  -e, [--export], [--no-export]    # Amazon Elasticsearch Service ドメインの設定を export する.
  -l, [--list], [--no-list]        # Amazon Elasticsearch Service ドメインの一覧を取得する.
  -u, [--update], [--no-update]    # Amazon Elasticsearch Service ドメイン構成を更新する.
  -n, [--domain-name=DOMAIN_NAME]  # Amazon Elasticsearch Service ドメイン名を指定する.
  -f, [--config-file=CONFIG_FILE]  # Amazon Elasticsearch Service 設定ファイルを指定する.

Amazon Elasticsearch Service ドメインを操作する.

設定ファイル例

toml フォーマットで以下のように記載する.

[main]
domain_name = "oreno-es2"
elasticsearch_version = "2.3"
access_policies = '''
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:ap-northeast-1:xxxxxxxxxxx:domain/oreno-es/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": "xxx.xxx.xxx.xxx"
        }
      }
    }
  ]
}
'''

[elasticsearch_cluster_config]
instance_type = "t2.micro.elasticsearch"
instance_count = 1
dedicated_master_enabled = false
zone_awareness_enabled = false

[ebs_options]
ebs_enabled = true
volume_type = "gp2"
volume_size = 10

[snapshot_options]
automated_snapshot_start_hour = 1

Amazon Elasticsearch Service ドメインの一覧を取得する

  • run
$ AWS_PROFILE=xxxxx AWS_REGION=ap-northeast-1 bundle exec eryastic domain --list
  • output
I, [2017-04-15T22:23:40.059602 #25839]  INFO -- : Amazon Elasticsearch Service ドメインの一覧を取得します.
+-------------+-----------------------------------------------------------------------------+-----------------------+---------+---------+------------+
| domain_name | endpoint                                                                    | elasticsearch_version | created | deleted | processing |
+-------------+-----------------------------------------------------------------------------+-----------------------+---------+---------+------------+
| oreno-es1   | search-oreno-es1-xxxxxxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com | 2.3                   | true    | false   | false      |
+-------------+-----------------------------------------------------------------------------+-----------------------+---------+---------+------------+

Amazon Elasticsearch Service ドメインを作成する

  • run
$ AWS_PROFILE=xxxxx AWS_REGION=ap-northeast-1 bundle exec eryastic domain --create --config-file=setting.toml
  • output
I, [2017-04-15T22:25:44.451627 #26254]  INFO -- : 以下の構成で Elasticsearch ドメインを作成します.
+-------------------------------+-------------------------------------------------------------------------------+
| key                           | value                                                                         |
+-------------------------------+-------------------------------------------------------------------------------+
| domain_name                   | oreno-es2                                                                     |
| elasticsearch_version         | 2.3                                                                           |
| access_policies               | {                                                                             |
|                               |   "Version": "2012-10-17",                                                    |
|                               |   "Statement": [                                                              |
...
|                               |   ]                                                                           |
|                               | }                                                                             |
| instance_type                 | t2.micro.elasticsearch                                                        |
| instance_count                | 1                                                                             |
| dedicated_master_enabled      | false                                                                         |
| zone_awareness_enabled        | false                                                                         |
| ebs_enabled                   | true                                                                          |
| volume_type                   | gp2                                                                           |
| volume_size                   | 10                                                                            |
| automated_snapshot_start_hour | 1                                                                             |
+-------------------------------+-------------------------------------------------------------------------------+
処理を続行しますか ? [y|n]:
y
I, [2017-04-15T22:27:30.283862 #26254]  INFO -- : 処理を続行します.
I, [2017-04-15T22:27:31.292834 #26254]  INFO -- : 処理が成功しました.

Amazon Elasticsearch Service ドメインを削除する

  • run
$ AWS_PROFILE=xxxxx AWS_REGION=ap-northeast-1 bundle exec eryastic domain --delete --domain-name=oreno-es1
  • output
I, [2017-04-15T22:29:44.633351 #27057]  INFO -- : 以下の Amazon Elasticsearch Service ドメインを削除します.
+-------------------------------+-------------------------------------------------------------------------------+
| key                           | value                                                                         |
+-------------------------------+-------------------------------------------------------------------------------+
| domain_name                   | oreno-es1                                                                     |
| elasticsearch_version         | 2.3                                                                           |
| access_policies               | {                                                                             |
|                               |   "Version": "2012-10-17",                                                    |
|                               |   "Statement": [                                                              |
...
|                               |   ]                                                                           |
|                               | }                                                                             |
| instance_type                 | t2.micro.elasticsearch                                                        |
| instance_count                | 1                                                                             |
| dedicated_master_enabled      | false                                                                         |
| zone_awareness_enabled        | false                                                                         |
| ebs_enabled                   | true                                                                          |
| volume_type                   | gp2                                                                           |
| volume_size                   | 10                                                                            |
| automated_snapshot_start_hour | 1                                                                             |
+-------------------------------+-------------------------------------------------------------------------------+
処理を続行しますか ? [y|n]:
y
I, [2017-04-15T22:27:30.283862 #26254]  INFO -- : 処理を続行します.
I, [2017-04-15T22:27:31.292834 #26254]  INFO -- : 処理が成功しました.

Amazon Elasticsearch Service ドメインの設定を export する

  • run
$ AWS_PROFILE=xxxxx AWS_REGION=ap-northeast-1 bundle exec eryastic --export --domain-name=oreno-es2 --config-file=oreno-es2.toml
  • output
I, [2017-04-15T22:32:25.935996 #27636]  INFO -- : Amazon Elasticsearch Service ドメイン oreno-es2 設定を export します.
[main]
domain_id = "xxxxxxxxxxxxxxxx/oreno-es2"
arn = "arn:aws:es:ap-northeast-1:xxxxxxxxxxxxxxxx:domain/oreno-es2"
domain_name = "oreno-es2"
endpoint = ""
elasticsearch_version = "2.3"
access_policies = '''
{
  "Version": "2012-10-17",
  "Statement": [
...
  ]
}
'''

[elasticsearch_cluster_config]
instance_type = "t2.micro.elasticsearch"
instance_count = 1
dedicated_master_enabled = false
zone_awareness_enabled = false



[ebs_options]
ebs_enabled = true
volume_type = "gp2"
volume_size = 10


[snapshot_options]
automated_snapshot_start_hour = 1

--config-file で指定したファイルに toml フォーマットにて設定が出力されている.

Amazon Elasticsearch Service ドメイン構成を更新する

  • run
$ AWS_PROFILE=xxxxx AWS_REGION=ap-northeast-1 bundle exec eryastic domain --update --domain-name=oreno-es2 --config-file=oreno-es2.toml
  • output

辛かったこと

TOML フォーマットの制約

  • 設定キーに .(ピリオド)は使えない(Amazon Elasticsearch Service の advanced_optionrest.action.multi.allow_explicit_index というキーがあって泣いた)
  • 厳密に言うと、キーを "(ダブルクォーテーション)で括れば良いが、文字列扱いとなってしまい解析した後の処理がめんどくさい(一旦、諦めた)

自分の Ruby 力の無さ…

  • オブジェクト ID を意識ぜず、Hash が入った変数をガンガン使いまわしていたら、Hash#delete しているメソッドを通った後の変数の中身が変わってて焦った…
  • 結局はMarshalクラスを使って以下のようにディープコピーして回避した… Ruby 面白いけど難しい
 config_tmp = config_parse(config_file)
      %w(domain_id arn endpoint).each do |key|
        config_tmp.delete(key.to_sym) if key.to_sym
      end

      log.info('以下の構成で Elasticsearch ドメインを作成します.')
      config = Marshal.load(Marshal.dump(config_tmp))
      puts display_domain_resources(config_tmp)

元記事はこちら

Amazon Elasticsearch Service ドメインを安全(当社比)に操作出来て、且つドメインの設定を toml フォーマットで管理するコマンドラインツールを作った