AWS上でansibleを用いてPresto環境を構築

#目的
ansibleを用いて簡単にAmazonEC2上にPresto環境を構築すること。

#環境条件
- ansibleサーバ
    - EC2：t2.micro
    - OS：Red Hat Enterprise Linux 7.4 (HVM), SSD Volume Type
    - Disk：汎用SSD（GP2） 30GB
- Presto Coordinatorサーバ、Presto Workerサーバ
    - EC2：t2.large
    - OS：Red Hat Enterprise Linux 7.4 (HVM), SSD Volume Type
    - Disk：汎用SSD（GP2） 30GB
    - その他：IP固定

ちなみに[Presto](https://prestodb.io/)とは、オープンソースの分散SQLエンジンであり、AmazonEMRでも使えるらしい。※[参考](https://aws.amazon.com/jp/emr/details/presto/)
今回は、2018/02/20時点で最新である、[Presto 0.195](https://prestodb.io/docs/current/)を利用する。

##ansibleのディレクトリ構成
```
├── presto
│   ├── all.yml
│   ├── group_vars
│   │   └── all
│   ├── inv.ini
│   ├── README.md
│   ├── roles
│   │   ├── client
│   │   │   └── tasks
│   │   │       └── main.yml
│   │   ├── common
│   │   │   ├── files
│   │   │   │   └── jmx.properties
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   └── templates
│   │   │       ├── jvm.config.j2
│   │   │       ├── log.properties.j2
│   │   │       └── node.properties.j2
│   │   ├── coordinator
│   │   │   ├── tasks
│   │   │   │   └── main.yml
│   │   │   └── templates
│   │   │       └── config.properties.j2
│   │   ├── start
│   │   │   └── tasks
│   │   │       └── main.yml
│   │   ├── stop
│   │   │   └── tasks
│   │   │       └── main.yml
│   │   └── worker
│   │       ├── tasks
│   │       │   └── main.yml
│   │       └── templates
│   │           └── config.properties.j2
│   └── site.yml
```

##それぞれのファイルの中身と役割や実施していること

###presto/all.yml
各ホストに対してどのロールを実行するかを定義しているファイル。ansible-playbookの実行時にsite.ymlから読み込まれる。

```presto/all.yml
- hosts: presto_coordinator
  roles: 
     - common
     - coordinator
     - client

- hosts: presto_worker
  roles: 
     - common
     - worker

- hosts: all
  roles:
     - start
#     - stop
```
###presto/group_vars/all
変数として利用する、各種設定事項を記載するファイル。main.ymlやxxx.j2の変数を置換する元となる情報。

```
---

config:
       presto_server_tarball_url: https://repo1.maven.org/maven2/com/facebook/presto/presto-server/0.195/presto-server-0.195.tar.gz
node_properties:
       node_environment: test
jvm_config:
       heap_xmx: 4G
       G1HeapRegionSize: 32M
coordinator_config_properties:
       http_port: 8080
       query_max_memory: 4GB
       query_max_memory_per_node: 1GB
       address: 192.168.56.101
worker_config_properties:
       http_port: 8080
       query_max_memory: 4GB
       query_max_memory_per_node: 1GB
log_properties:
       log_level: INFO
client:
       presto_client_jar_url: https://repo1.maven.org/maven2/com/facebook/presto/presto-cli/0.195/presto-cli-0.195-executable.jar
```

###presto/inv.ini
インベントリーファイル。各グループとホストを紐付けるためのもの。ansible-palybookの実行対象。

```presto/inv.ini
[presto_coordinator]
192.168.56.101
[presto_worker]
192.168.56.102
```

###presto/README.md
このansibleコードの説明と、実行コマンドを記載した説明用ファイル。

```presto/README.md
# What is this?

ansible-playbook for setting up presto

# What is this tool able to?

setup presto server
setup presto client
presto server start/stop

# How to use

files which are needed to edit

    inv.ini: it is inventory file.
    group_vars/all: it is configuration file.

execute command

    ansible-playbook ./site.yml -i inv.ini -vvv -k
```

###presto/roles/client/tasks/main.yml
prestoクライアントをインストールするための、タスク実行定義ファイル。clientのjarファイルをダウンロードしてきて、/usr/local/bin/prestoとしてOS上に設置する。

```presto/roles/client/tasks/main.yml
- name: get jar
  get_url:
    url: "{{ client.presto_client_jar_url }}"
    dest: /usr/local/bin/presto
    mode: 0755
```

###roles/common/tasks/main.yml
prestoサーバを構築する上で、coordinator、worker問わず、共通的に必要なインストレーションや設定を実施するための、タスク実行定義ファイル。jdkのインストール、prestoサーバのバイナリーファイルのインストールや、必要なディレクトリの作成、各種設定ファイルの作成と配置を実施する。

```roles/common/tasks/main.yml
- name: install jdk
  yum:
    name: java
    state: latest

- name: get tarball
  get_url: 
    url: "{{ config.presto_server_tarball_url }}"
    dest: /opt/presto-server.tar.gz

- name: create presto-server directory
  file: 
    path: /opt/presto-server
    state: directory

- name: unarchive tarball
  command: tar zxvf /opt/presto-server.tar.gz -C /opt/presto-server --strip-components 1

- name: create etc directory
  file:
    path: /opt/presto-server/etc
    state: directory

- name: deliver node.properties file
  template:
    src: node.properties.j2
    dest: /opt/presto-server/etc/node.properties
    owner: root
    group: root
    mode: 0644

- name: deliver jvm.config file
  template:
    src: jvm.config.j2
    dest: /opt/presto-server/etc/jvm.config
    owner: root
    group: root
    mode: 0644

- name: deliver log.properties file
  template:
    src: log.properties.j2
    dest: /opt/presto-server/etc/log.properties
    owner: root
    group: root
    mode: 0644

- name: create catalog directory
  file:
    path: /opt/presto-server/etc/catalog
    state: directory

- name: deliver jmx.properties file
  copy:
    src: jmx.properties
    dest: /opt/presto-server/etc/catalog/jmx.properties
    owner: root
    group: root
    mode: 0644
```

###presto/roles/common/files/jmx.properties
prestoサーバの設定ファイル。各サーバに配布する。

```presto/roles/common/files/jmx.properties
connector.name=jmx
```
###presto/roles/common/templates/jvm.config.j2
prestoサーバの設定ファイル。変数変換をしつつ各サーバに配布する。

```presto/roles/common/templates/jvm.config.j2
-server
-Xmx{{ jvm_config.heap_xmx }}
-XX:+UseG1GC
-XX:G1HeapRegionSize={{ jvm_config.G1HeapRegionSize }}
-XX:+UseGCOverheadLimit
-XX:+ExplicitGCInvokesConcurrent
-XX:+HeapDumpOnOutOfMemoryError
-XX:+ExitOnOutOfMemoryError 
```

###presto/roles/common/templates/log.properties.j2
prestoサーバの設定ファイル。変数変換をしつつ各サーバに配布する。

```presto/roles/common/templates/log.properties.j2
com.facebook.presto={{ log_properties.log_level }}
```

###presto/roles/common/templates/node.properties.j2
prestoサーバの設定ファイル。変数変換をしつつ各サーバに配布する。

```presto/roles/common/templates/node.properties.j2
node.environment={{ node_properties.node_environment }}
node.id={{ ansible_hostname }}
node.data-dir=/var/presto/data
```

###presto/roles/coordinator/tasks/main.yml
prestoサーバを構築する上で、coordinatorに必要な設定を実施するための、タスク実行定義ファイル。設定ファイルの作成と配置を実施する。

```presto/roles/coordinator/tasks/main.yml
- name: deliver config.properties file
  template:
    src: config.properties.j2
    dest: /opt/presto-server/etc/config.properties
    owner: root
    group: root
    mode: 0644
```

###presto/roles/coordinator/templates/config.properties.j2
prestoサーバのcoordinator用の設定ファイル。変数変換をしつつ各サーバに配布する。

```presto/roles/coordinator/templates/config.properties.j2
coordinator=true
node-scheduler.include-coordinator=false
http-server.http.port={{ coordinator_config_properties.http_port }}
query.max-memory={{ coordinator_config_properties.query_max_memory }}
query.max-memory-per-node={{ coordinator_config_properties.query_max_memory_per_node }}
discovery-server.enabled=true
discovery.uri=http://{{ coordinator_config_properties.address }}:{{ coordinator_config_properties.http_port }}
```
###presto/roles/worker/tasks/main.yml 
prestoサーバを構築する上で、coordinatorに必要な設定を実施するための、タスク実行定義ファイル。設定ファイルの作成と配置を実施する。

```presto/roles/worker/tasks/main.yml 
- name: deliver config.properties file
  template:
    src: config.properties.j2
    dest: /opt/presto-server/etc/config.properties
    owner: root
    group: root
    mode: 0644
```

###presto/roles/worker/templates/config.properties.j2
prestoサーバのworker用の設定ファイル。変数変換をしつつ各サーバに配布する。

```presto/roles/worker/templates/config.properties.j2 
coordinator=false
http-server.http.port={{ worker_config_properties.http_port }}
query.max-memory={{ worker_config_properties.query_max_memory }}
query.max-memory-per-node={{ worker_config_properties.query_max_memory_per_node }}
discovery.uri=http://{{ coordinator_config_properties.address }}:{{ coordinator_config_properties.http_port }}
```

###presto/roles/start/tasks/main.yml
prestoサーバを起動するための、タスク実行定義ファイル。

```presto/roles/start/tasks/main.yml 
- name: start presto server
  command: /opt/presto-server/bin/launcher start
```

###presto/roles/stop/tasks/main.yml
prestoサーバを停止するための、タスク実行定義ファイル。

```presto/roles/stop/tasks/main.yml 
- name: stop presto server
  command: /opt/presto-server/bin/launcher stop
```

###presto/site.yml
ansible-playbookの実行時に利用するファイル。

```presto/site.yml
- include: all.yml
```

##起動後の確認
上記ansibleコードを実行し、192.168.56.101をpresto coordinatorとして構築し、192.168.56.102をworkerとして構築したあと、clientロールを実行した192.168.56.101上で、prestoクライアントを利用する。

```
[root@ip-192-168-56-101 ~]# presto
presto> 
presto> SELECT * FROM system.runtime.nodes;
     node_id      |         http_uri          | node_version | coordinator | state  
------------------+---------------------------+--------------+-------------+--------
ip-192-168-56-102 | http://192.168.56.102:8080| 0.195        | false       | active 
ip-192-168-56-101 | http://192.168.56.101:8080| 0.195        | true        | active 
(2 rows)

Query 20180222_025304_00001_gxwuk, FINISHED, 2 nodes
Splits: 17 total, 17 done (100.00%)
0:00 [2 rows, 104B] [46 rows/s, 2.34KB/s]
```