[JAWS-UG CLI] Elasticsearch Service:#1 ドメインの作成と更新

AWS CLIを利用して、Elasticsearch Serviceドメインを作成してみます。


前提条件
========


Elasticsearch Serviceへの権限
-----------------------------

Elasticsearch Serviceに対してフル権限があること。


AWS CLIのバージョン
-------------------

以下のバージョンで動作確認済

* AWS CLI 1.10.19

```:bash:コマンド:
aws --version
```

```text:結果(例):
aws-cli/1.10.19 Python/2.7.10 Darwin/15.4.0 botocore/1.4.10
```


0. 準備
=======


0.1. リージョンの決定
---------------------

利用するリージョンを決めます。 (カレントユーザが利用するカレントリージョンも切り変わります。)

```bash:変数の設定(東京リージョンの場合):
export AWS_DEFAULT_REGION='ap-northeast-1'
```


0.2. プロファイルの確認
-----------------------

プロファイルが想定のものになっていることを確認します。

```:bash:コマンド:
aws configure list
```

```text:結果(例):

            Name                    Value             Type    Location
            ----                    -----             ----    --------
         profile         es-prjz-mbp13        env    AWS_DEFAULT_PROFILE
      access_key     ****************XXXX shared-credentials-file
      secret_key     ****************XXXX shared-credentials-file
          region                         ap-northeast-1  env    AWS_DEFAULT_REGION
```

AssumeRoleを利用している場合はprofileが '<not set>'と表示されます。 それ以外のときにprofileが '<not set>' と表示される場合は、以下を実行してください。

```bash:変数の設定:
export AWS_DEFAULT_PROFILE=<IAMユーザ名>
```


0.3. AWS IDの取得
-----------------

```bash:変数の設定:
AWS_ID=$( \
  aws sts get-caller-identity \
     --query 'Account' \
     --output text \
  ) \
    && echo ${AWS_ID}
```

```text:結果(例):
XXXXXXXXXXXX
```

(aws cli1.10.18以降が必要です。)


1. 事前作業
===========


1.1. ドメイン名の決定
---------------------

作成するドメインの名前を決めます。

```bash:変数の設定:
ES_DOMAIN_NAME="handson-esdomain-$(date +%Y%m%d)" \
  && echo ${ES_DOMAIN_NAME}
```

```text:結果(例):
handson-esdomain-20160411
```

そのリージョンでユニークである必要があります。

すでに同じ名前のドメインが存在しないことを確認します。

```:bash:コマンド:
aws es list-domain-names \
  --query "DomainNames[?DomainName == \`${ES_DOMAIN_NAME}\`]"
```

```json:結果(例):
[]
```


2. ドメインの作成
=================


2.1. EBSの設定
--------------

```bash:変数の設定:
EBS_STORAGE_CLASS="gp2"
EBS_SIZE="10"
EBS_IOPS="0"
```

```bash:変数の設定:
FILE_EBS_OPTIONS="${ES_DOMAIN_NAME}-ebs-options.json"
```


2.2. Elasticsearchインスタンスの設定
------------------------------------

```bash:変数の設定:
ES_INSTANCE_TYPE="t2.micro.elasticsearch"
ES_INSTANCE_COUNT="1"
ES_DEDICATED_MASTER="false"
ES_ZONE_AWARENESS="false"
```

```bash:変数の設定:
FILE_ES_CLUSTER_CONFIG="${ES_DOMAIN_NAME}-cluster-config.json"
```


2.3. ドメインの作成
-------------------

ドメインを作成します。

```bash:変数の確認:
cat << ETX

  EBS_STORAGE_CLASS:      ${EBS_STORAGE_CLASS}
  EBS_SIZE:               ${EBS_SIZE}
  EBS_IOPS:               ${EBS_IOPS}

  ES_DOMAIN_NAME:         ${ES_DOMAIN_NAME}
  ES_INSTANCE_TYPE:       ${ES_INSTANCE_TYPE}
  ES_INSTANCE_COUNT:      ${ES_INSTANCE_COUNT}
  ES_DEDICATED_MASTER:    ${ES_DEDICATED_MASTER}
  ES_ZONE_AWARENESS:      ${ES_ZONE_AWARENESS}

  FILE_ES_CLUSTER_CONFIG: ${FILE_ES_CLUSTER_CONFIG}
  FILE_EBS_OPTIONS:       ${FILE_EBS_OPTIONS}

ETX
```

```bash:変数の設定:
cat << EOF > ${FILE_ES_CLUSTER_CONFIG}
{
  "InstanceType":           "${ES_INSTANCE_TYPE}",
  "InstanceCount":          ${ES_INSTANCE_COUNT},
  "DedicatedMasterEnabled": ${ES_DEDICATED_MASTER},
  "ZoneAwarenessEnabled":   ${ES_ZONE_AWARENESS}
}
EOF

cat ${FILE_ES_CLUSTER_CONFIG}
```

```json:結果(例):
{
  "InstanceType":           "t2.micro.elasticsearch",
  "InstanceCount":          1,
  "DedicatedMasterEnabled": false,
  "ZoneAwarenessEnabled":   false
}
```


```:bash:コマンド:
cat << EOF > ${FILE_EBS_OPTIONS}
{
  "EBSEnabled": true,
  "VolumeType": "${EBS_STORAGE_CLASS}",
  "VolumeSize": ${EBS_SIZE},
  "Iops":       ${EBS_IOPS}
}
EOF

cat ${FILE_EBS_OPTIONS}
```

```json:結果(例):
{
  "EBSEnabled": true,
  "VolumeType": "gp2",
  "VolumeSize": 10,
  "Iops":       0
}
```

```:bash:コマンド:
aws es create-elasticsearch-domain \
  --domain-name ${ES_DOMAIN_NAME} \
  --elasticsearch-cluster-config file://"${FILE_ES_CLUSTER_CONFIG}" \
  --ebs-options file://"${FILE_EBS_OPTIONS}"
```


```json:結果(例):
{
  "DomainStatus": {
    "ElasticsearchClusterConfig": {
        "DedicatedMasterEnabled": false,
        "InstanceCount": 1,
        "ZoneAwarenessEnabled": false,
        "InstanceType": "t2.micro.elasticsearch"
    },
    "DomainId": "XXXXXXXXXXXX/handson-esdomain-20160411",
    "Created": true,
    "Deleted": false,
    "EBSOptions": {
        "Iops": 0,
        "VolumeSize": 10 ,
        "VolumeType": "gp2",
        "EBSEnabled": true
    },
    "Processing": true,
    "DomainName": "handson-esdomain-20160411",
    "SnapshotOptions": {
        "AutomatedSnapshotStartHour": 0
    },
    "AccessPolicies": "",
    "AdvancedOptions": {
        "rest.action.multi.allow_explicit_index": "true"
    },
    "ARN": "arn:aws:es:ap-northeast-1:XXXXXXXXXXXX:domain/handson-esdomain-20160411"
  }
}
```


2.2. ドメインの確認
-------------------

ドメインの一覧を表示してみましょう。

```:bash:コマンド:
aws es list-domain-names \
  --query "DomainNames[?DomainName == \`${ES_DOMAIN_NAME}\`]"
```

```json:結果(例):
[
  {
    "DomainName": "handson-esdomain-20160411"
  }
]
```


2.3. ドメインの内容確認
-----------------------

作成したドメインを確認してみましょう。

```:bash:コマンド:
aws es describe-elasticsearch-domain \
  --domain-name ${ES_DOMAIN_NAME}
```

```json:結果(例):
{
  "DomainStatus": {
    "ElasticsearchClusterConfig": {
        "DedicatedMasterEnabled": false,
        "InstanceCount": 1,
        "ZoneAwarenessEnabled": false,
        "InstanceType": "t2.micro.elasticsearch"
    },
    "DomainId": "XXXXXXXXXXXX/handson-esdomain-20160411",
    "Created": true,
    "Deleted": false,
    "EBSOptions": {
        "Iops": 0,
        "VolumeSize": 10,
        "VolumeType": "gp2",
        "EBSEnabled": true
    },
    "Processing": true,
    "DomainName": "handson-esdomain-20160411",
    "SnapshotOptions": {
        "AutomatedSnapshotStartHour": 0
    },
    "AccessPolicies": "",
    "AdvancedOptions": {
        "rest.action.multi.allow_explicit_index": "true"
    },
    "ARN": "arn:aws:es:ap-northeast-1:XXXXXXXXXXXX:domain/handson-esdomain-20160411"
  }
}
```


2.4. ドメインの設定確認
-----------------------

```:bash:コマンド:
aws es describe-elasticsearch-domain-config \
  --domain-name ${ES_DOMAIN_NAME}
```

```json:結果(例):
{
  "DomainConfig": {
    "ElasticsearchClusterConfig": {
        "Status": {
            "PendingDeletion": false,
            "State": "Active",
            "CreationDate": 1457742577.891,
            "UpdateVersion": 1,
            "UpdateDate": 1457742577.891
        },
        "Options": {
            "DedicatedMasterEnabled": false,
            "InstanceCount": 1,
            "ZoneAwarenessEnabled": false,
            "InstanceType": "t2.micro.elasticsearch"
        }
    },
    "AdvancedOptions": {
        "Status": {
            "PendingDeletion": false,
            "State": "Active",
            "CreationDate": 1457742577.891,
            "UpdateVersion": 1,
            "UpdateDate": 1457742577.891
        },
        "Options": {
            "rest.action.multi.allow_explicit_index": "true"
        }
    },
    "EBSOptions": {
        "Status": {
            "PendingDeletion": false,
            "State": "Active",
            "CreationDate": 1457742577.891,
            "UpdateVersion": 2,
            "UpdateDate": 1457742577.891
        },
        "Options": {
            "Iops": 0,
            "VolumeSize": 10,
            "VolumeType": "gp2",
            "EBSEnabled": true
        }
    },
    "AccessPolicies": {
        "Status": {
            "PendingDeletion": false,
            "State": "Active",
            "CreationDate": 1457742577.891,
            "UpdateVersion": 1,
            "UpdateDate": 1457742577.891
        },
        "Options": ""
    },
    "SnapshotOptions": {
        "Status": {
            "PendingDeletion": false,
            "State": "Active",
            "CreationDate": 1457742577.891,
            "UpdateVersion": 1,
            "UpdateDate": 1457742577.891
        },
        "Options": {
            "AutomatedSnapshotStartHour": 0
        }
    }
  }
}
```

ドメインの起動状況を確認します。


```bash:変数の設定:
ES_CONFIG_STAT=$( \
  aws es describe-elasticsearch-domain-config \
    --domain-name ${ES_DOMAIN_NAME} \
    --query 'DomainConfig.ElasticsearchClusterConfig.Status.State' \
    --output text \
) \
  && echo ${ES_CONFIG_STAT}
```

```text:結果(例):
Processing
```

ProcessingがActiveに変われば利用可能です。(10分程度かかります。)

```bash:変数の設定:
ES_CONFIG_STAT=$( \
  aws es describe-elasticsearch-domain-config \
    --domain-name ${ES_DOMAIN_NAME} \
    --query 'DomainConfig.ElasticsearchClusterConfig.Status.State' \
    --output text \
) \
  && echo ${ES_CONFIG_STAT}
```

```text:結果(例):
Active
```


2.5. ドメインの設定確認
-----------------------

```:bash:コマンド:
aws es describe-elasticsearch-domains \
  --domain-name ${ES_DOMAIN_NAME}
```

```json:結果(例):
{
  "DomainStatusList": [
    {
        "ElasticsearchClusterConfig": {
            "DedicatedMasterEnabled": false,
            "InstanceCount": 1,
            "ZoneAwarenessEnabled": false,
            "InstanceType": "t2.micro.elasticsearch"
        },
        "Endpoint": "search-handson-esdomain-20160411-xxxxxxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com",
        "Created": true,
        "Deleted": false,
        "DomainName": "handson-esdomain-20160411",
        "EBSOptions": {
            "Iops": 0,
            "VolumeSize": 10,
            "VolumeType": "gp2",
            "EBSEnabled": true
        },
        "SnapshotOptions": {
            "AutomatedSnapshotStartHour": 0
        },
        "DomainId": "XXXXXXXXXXXX/handson-esdomain-20160411",
        "AccessPolicies": "",
        "Processing": false,
        "AdvancedOptions": {
            "rest.action.multi.allow_explicit_index": "true",
        },
        "ARN": "arn:aws:es:ap-northeast-1:XXXXXXXXXXXX:domain/handson-esdomain-20160411"
    }
  ]
}
```


2.6. ドメインのARN取得
----------------------

Elasticsearch Serviceでドメインを操作するときは、対象ドメインのARNを特定する必要があります。

```bash:変数の設定:
ES_DOMAIN_ARN=$( \
  aws es describe-elasticsearch-domain \
    --domain-name ${ES_DOMAIN_NAME} \
    --query 'DomainStatus.ARN' \
    --output text \
) \
  && echo ${ES_DOMAIN_ARN}
```

```text:結果(例):
arn:aws:es:ap-northeast-1:XXXXXXXXXXXX:domain/handson-esdomain-20160411
```


3. ドメインのエンドポイントへのアクセス
=======================================

Elasticsearch Serviceにブラウザでアクセスしてみましょう。

まず、ドメインのエンドポイント(URL)を取得します。

```bash:変数の設定:
ES_DOMAIN_ENDPOINT=$( \
  aws es describe-elasticsearch-domains \
  --domain-name ${ES_DOMAIN_NAME} \
  --query "DomainStatusList[?ARN == \`${ES_DOMAIN_ARN}\`].Endpoint" \
  --output text \
) \
  && echo ${ES_DOMAIN_ENDPOINT}
```

```text:結果(例):
search-handson-esdomain-20160411-xxxxxxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com
```

次にKibanaのURLを取得します。

```bash:変数の設定:
ES_KIBANA_ENDPOINT=$( \
  echo "${ES_DOMAIN_ENDPOINT}/_plugin/kibana/" \
) \
  && echo ${ES_KIBANA_ENDPOINT}
```

```text:結果(例):
search-handson-esdomain-20160411-xxxxxxxxxxxxxxxxxxxxxxxxxx.ap-northeast-1.es.amazonaws.com/_plugin/kibana/
```

Kibanaにブラウザでアクセスしてみましょう。

以下のようにエラーが出るはずです。

```text:ブラウザ:
{"Message":"User: anonymous is not authorized to perform: es:ESHttpGet on resource: arn:aws:es:ap-northeast-1:XXXXXXXXXXXX:domain/handson-esdomain-20160411/_plugin/kibana/"}
```

この時点では、アクセス許可がされていないため、誰もアクセスできません。


4. ドメインの更新
=================

ドメインのアクセスポリシーを変更してみます。


4.1. ポリシーの作成
-------------------

```bash:変数の設定:
FILE_INPUT="${ES_DOMAIN_NAME}-AccessPolicy".json
```

```bash:変数の確認:
cat << ETX

  AWS_DEFAULT_REGION: ${AWS_DEFAULT_REGION}
  AWS_ID:             ${AWS_ID}
  ES_DOMAIN_NAME:     ${ES_DOMAIN_NAME}
  FILE_INPUT:         ${FILE_INPUT}

ETX
```

```:bash:コマンド:
cat << EOF >> ${FILE_INPUT}
{
  "Version": "2012-10-17",
  "Statement": [
    {
"Action": "es:*",
"Principal":"*",
"Effect": "Allow",
"Resource":"arn:aws:es:${AWS_DEFAULT_REGION}:${AWS_ID}:domain/${ES_DOMAIN_NAME}/*"
    }
  ]
}

EOF

cat ${FILE_INPUT}
```

JSONファイルを作成したら、フォーマットが壊れてないか必ず確認します。

```:bash:コマンド:
jsonlint -q ${FILE_INPUT}
```

エラーが出力されなければOKです。


4.2. ポリシーの設定
-------------------

```bash:変数の確認:
cat << ETX

  ES_DOMAIN_NAME:     ${ES_DOMAIN_NAME}
  FILE_INPUT:         ${FILE_INPUT}

ETX
```

```:bash:コマンド:
aws es update-elasticsearch-domain-config \
  --domain-name ${ES_DOMAIN_NAME} \
  --access-policies file://${FILE_INPUT}
```

```json:結果(例):
{
  "DomainConfig": {
    "ElasticsearchClusterConfig": {
        "Status": {
            "PendingDeletion": false,
            "State": "Active",
            "CreationDate": 1459853258.411,
            "UpdateVersion": 6,
            "UpdateDate": 1459853734.055
        },
        "Options": {
            "DedicatedMasterEnabled": false,
            "InstanceCount": 1,
            "ZoneAwarenessEnabled": false,
            "InstanceType": "t2.micro.elasticsearch"
        }
    },
    "AdvancedOptions": {
        "Status": {
            "PendingDeletion": false,
            "State": "Active",
            "CreationDate": 1459861451.767,
            "UpdateVersion": 9,
            "UpdateDate": 1459861451.767
        },
        "Options": {
            "rest.action.multi.allow_explicit_index": "true"
        }
    },
    "EBSOptions": {
        "Status": {
            "PendingDeletion": false,
            "State": "Active",
            "CreationDate": 1459853258.411,
            "UpdateVersion": 6,
            "UpdateDate": 1459853734.055
        },
        "Options": {
            "VolumeSize": 10,
            "VolumeType": "gp2",
            "EBSEnabled": true
        }
    },
    "AccessPolicies": {
        "Status": {
            "PendingDeletion": false,
            "State": "Processing",
            "CreationDate": 1459861451.633,
            "UpdateVersion": 9,
            "UpdateDate": 1459861451.633
        },
        "Options": "{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":"*","Action":"es:ESHttp*","Resource":"arn:aws:es:us-west-2:961382088619:domain/example-esdomain-20160401/>>*<<"}]}"
    },
    "SnapshotOptions": {
        "Status": {
            "PendingDeletion": false,
            "State": "Active",
            "CreationDate": 1459853258.411,
            "UpdateVersion": 6,
            "UpdateDate": 1459853734.055
        },
        "Options": {
            "AutomatedSnapshotStartHour": 0
        }
    }
  }
}
```


```:bash:コマンド:
aws es describe-elasticsearch-domain \
  --domain-name ${ES_DOMAIN_NAME}
```

```json:結果(例):
{
  "DomainStatus": {
    "ElasticsearchClusterConfig": {
        "DedicatedMasterEnabled": false,
        "InstanceCount": 1,
        "ZoneAwarenessEnabled": false,
        "InstanceType": "t2.micro.elasticsearch"
    },
    "DomainId": "XXXXXXXXXXXX/handson-esdomain-20160411",
    "Created": true,
    "Deleted": false,
    "EBSOptions": {
        "Iops": 0,
        "VolumeSize": ||EBS_SIZE|,
        "VolumeType": "gp2",
        "EBSEnabled": true
    },
    "Processing": true,
    "DomainName": "handson-esdomain-20160411",
    "SnapshotOptions": {
        "AutomatedSnapshotStartHour": 0
    },
    "AccessPolicies": "{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"*"},"Action":"es:*","Resource":"arn:aws:es:ap-northeast-1:XXXXXXXXXXXX:domain/handson-esdomain-20160411/*"}]}",
    "AdvancedOptions": {
        "rest.action.multi.allow_explicit_index": "true",
        "indices.fielddata.cache.size": ""
    },
    "ARN": "arn:aws:es:ap-northeast-1:XXXXXXXXXXXX:domain/handson-esdomain-20160411"
  }
}
```

AccessPoliciesのStateがActiveになるまで待ちましょう。(10分ほどかかります)

```bash:変数の設定:
ES_ACCESS_POLICIES_STATUS=$( \
  aws es describe-elasticsearch-domain-config \
    --domain-name ${ES_DOMAIN_NAME} \
    --query 'DomainConfig.AccessPolicies.Status.State' \
    --output text \
) \
  && echo ${ES_ACCESS_POLICIES_STATUS}
```

```text:結果(例):
Active
```


5. Kibanaへのアクセス確認
=========================

再度、以下のURLにブラウザでアクセスします。

```:bash:コマンド:
echo ${ES_KIBANA_ENDPOINT}
```

"Kibana is loading."という画面が表示されればOKです。

設定作業はインデックス作成後に行うので、今はそのままにしておいてください。


完了
====

以上で、Elasticsearch Serviceドメインの作成と設定確認、アクセスポリシーの変更をしてみました。