GCPの環境でGCE discovery pluginを使ってみた!


はじめに

ElasticsearchのクラスタをGCPで構築する際に使った方が良いプラグインを紹介したいと思います。
それは、GCE discovery pluginです。
このプラグインを使用することで、Unicastでホスト名やIPアドレスを指定することなく、よしなにクラスタを組んでくれます。

以前にEC2 discovery pluginの紹介をしましたが、インスタンスがダウンした際にノードIDの重複問題を抱えてました。
そこの改善も含めて今回記載させて頂きます。

それでは早速ですが、構築していきます( ゚Д゚)ゞビシッ

Setup Firewall Rules

ファイアウォールルールを作成します。
ノード間で通信するために9200-9300でポートを解放します。
また、9200でHTTP通信を受け付けるため解放します。

$ gcloud compute firewall-rules create elasticsearch --direction=INGRESS \
 --priority=1000 --network=default --action=ALLOW \
 --rules=tcp:9200,tcp:9300-9400 --source-ranges=0.0.0.0/0

Create an instance using gcloud SDK

インスタンスを構築する準備ができましたので、インスタンスを構築します。
gcloudが実行できる環境を前提に進めます。
もし、gcloudの実行環境がない場合は、Cloud SDKインストールのサイトを参考にしてください。

$ gcloud compute instances create es-gce-discovery \
  --machine-type=n1-standard-2 --subnet=default \
  --min-cpu-platform=Automatic \
  --tags=elasticsearch,http-server,https-server \
  --image=ubuntu-1604-xenial-v20180306 \
  --image-project=ubuntu-os-cloud \
  --boot-disk-size=10GB --boot-disk-type=pd-standard \
  --boot-disk-device-name=sgce-discovery --scopes=compute-ro

インスタンスが立ち上がったのでSSHで接続します。

gcloud compute ssh es-gce-discovery

Install Java

インスタンスにJDK 8をインストールします。

$ sudo apt-get update
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer
$ sudo apt-get install oracle-java8-set-default
$ java -version
java version "1.8.0_171"
Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)

Install Elasticsearch and GCE discovery plugin

Elasticsearchをインストールするため、PGP-keyをインストールします。
Install Elasticsearch with Dibian Packages

$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

次に"apt-transport-https"をインストールします。

$ sudo apt-get install apt-transport-https

リポジトリを追加します。

$ echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-6.x.list

Elasticsearchをインストールします。

$ sudo apt-get update && sudo apt-get install elasticsearch
$ sudo /usr/share/elasticsearch/bin/elasticsearch -version
Version: 6.2.4, Build: ccec39f/2018-04-12T20:37:28.497551Z, JVM: 1.8.0_171

次に"GCE discovery plugin"をインストールします。

$ sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install discovery-gce

インストールが完了したので、Elasticsearchの設定ファイルに設定を追加します。

$ sudo vim /etc/elasticsearch/elasticsearch.yml
### クラスタ名はデフォルト"elasticsearch"
cluster.name: lannister
### ノード名を動的に設定するため、${HOSTNAME} を使用する
node.name: ${HOSTNAME}
### GCEのホスト名をネットワークサービスにバインド
network.host: _gce:hostname_
### スプリットブレインを避けるため、適正なノード数にする
discovery.zen.minimum_master_nodes: 2
### "GCE discovery plugin"の設定をする
cloud.gce.project_id: "your Project-Name"
cloud.gce.zone: us-east1-b
discovery.zen.hosts_provider: gce

Elasticsearchを起動します。

$ sudo /etc/init.d/elasticsearch start

curlコマンドでサービス起動の確認をします。

$ curl ${HOSTNAME}:9200

起動確認できたので、インスタンスからログオフします。

ちなみにですが、Elasticsearch起動後にログを確認すると永遠と"WARN"が出力されますが、無視してください。
1台しかないから当たり前ですが、ノード数が足りないために発生しています。

$ sudo tail -f /var/log/elasticsearch/lannister.log
[2018-05-13T07:45:11,358][WARN ][o.e.d.z.ZenDiscovery     ] [es-gce-discovery] not enough master nodes discovered during pinging (found [[Candidate{node={es-gce-discovery}{SAFhkm66S7eGgURWMHS3Ww}{EHnLunWFQTuYHgVJ-WXDkA}{es-gce-discovery.c.winter-jet-194500.internal}{10.142.0.2:9300}, clusterStateVersion=-1}]], but needed [2]), pinging again

Create a GCE custom image

ローカル環境からディスクイメージを保管するバケットを作成します。

$ gsutil mb -p "your Project-Name" -c regional -l us-east1 gs://es-test-bucket/

Elasticsearchをインストールしたインスタンスを停止します。

$ gcloud compute instances stop es-gce-discovery

停止したインスタンスのスナップショットを取得します。

$ gcloud compute disks snapshot es-gce-discovery \
  --snapshot-names=es-gce-discovery-snapshot

取得したスナップショットで、GCEディスクを作成します。

$ gcloud compute disks create es-gce-discovery-disk \
  --source-snapshot es-gce-discovery-snapshot

元のイメージディスクより50%より大きい一時ディスクを作成します。
今回は、元のディスクが10GBなため、一時ディスクは15GBで作成します。

$ gcloud compute disks create es-gce-discovery-temp-disk --size 15GB

スコープのstorage-rwを使用し、二つのディスクをマウントした一時的なインスタンスを作成します。

$ gcloud compute instances create es-temp-instance --scopes storage-rw \
  --disk name=es-gce-discovery-disk,device-name=es-gce-discovery-disk \
  --disk name=es-gce-discovery-temp-disk,device-name=es-gce-discovery-temp-disk

作成できたら一時インスタンスにアクセスします。

$ gcloud compute ssh sherry-temp-instance

ディスクを確認します。

$ ls /dev/disk/by-id/
google-es-gce-discovery-disk        google-persistent-disk-0                           scsi-0Google_PersistentDisk_es-gce-discovery-disk-part1  scsi-0Google_PersistentDisk_persistent-disk-0-part1
google-es-gce-discovery-disk-part1  google-persistent-disk-0-part1                     scsi-0Google_PersistentDisk_es-gce-discovery-temp-disk
google-es-gce-discovery-temp-disk   scsi-0Google_PersistentDisk_es-gce-discovery-disk  scsi-0Google_PersistentDisk_persistent-disk-0

次にディスクフォーマットし、マウントします。

$ sudo mkdir /mnt/tmp
$ sudo mkfs.ext4 -F /dev/disk/by-id/google-es-gce-discovery-temp-disk 
$ sudo mount -o discard,defaults /dev/disk/by-id/google-es-gce-discovery-temp-disk /mnt/tmp

イメージをマウントします。

$ sudo mkdir /mnt/image-disk
$ sudo mount /dev/disk/by-id/google-es-gce-discovery-disk-part1 /mnt/image-disk

Elasticsearchのデータディレクトリを削除します。
Elasticsearchが初めて開始すると新しいインスタンス毎にElasticsearchのデータディレクトリが作成されます。

$ sudo rm -fR /mnt/image-disk/var/lib/elasticsearch/nodes

SSHキーを削除します。

$ sudo rm -f /mnt/image-disk/home/micci184/.ssh/authorized_keys

イメージをアンマウントします。

$ sudo umount /mnt/image-disk/

一時ディスク上のイメージディスクからdisk.rawを作成します。
disk.rawという名前である必要があります。

$ sudo dd if=/dev/disk/by-id/google-es-gce-discovery-disk of=/mnt/tmp/disk.raw bs=4096

disk.rawファイルのtarファイルを作成します。

$ cd /mnt/tmp
$ sudo tar czvf es-gce-discovery-disk.tar.gz disk.raw

バケットにtarファイルをコピーします。

$ gsutil cp /mnt/tmp/es-gce-discovery-disk.tar.gz gs://es-test-bucket/

ファイル転送が完了したら、一時インスタンスをログオフします。
最後に新しいインスタンスを作成するためのカスタムイメージを作成します。

$ gcloud compute images create es-gce-discovery-image \
  --source-uri=https://storage.googleapis.com/es-test-bucket/es-gce-discovery-disk.tar.gz

Create instances based on our custom image

3つの新しいインスタンスを作成します。

$ gcloud compute instances create es-instance-1 \
  --machine-type=n1-standard-2 --subnet=default \
  --min-cpu-platform=Automatic --tags=elasticsearch,http-server,https-server \
  --image=es-gce-discovery-image --image-project=winter-jet-194500 \
  --boot-disk-size=20GB --boot-disk-type=pd-standard \
  --boot-disk-device-name=es-instance-1 --scopes=compute-ro

$ gcloud compute instances create es-instance-2 \
  --machine-type=n1-standard-2 --subnet=default \
  --min-cpu-platform=Automatic --tags=elasticsearch,http-server,https-server \
  --image=es-gce-discovery-image --image-project=winter-jet-194500 \
  --boot-disk-size=20GB --boot-disk-type=pd-standard \
  --boot-disk-device-name=es-instance-2 --scopes=compute-ro

$ gcloud compute instances create es-instance-3 \
  --machine-type=n1-standard-2 --subnet=default \
  --min-cpu-platform=Automatic --tags=elasticsearch,http-server,https-server \
  --image=es-gce-discovery-image --image-project=winter-jet-194500 \
  --boot-disk-size=20GB --boot-disk-type=pd-standard \
  --boot-disk-device-name=es-instance-3 --scopes=compute-ro

3台のインスタンスが作成できたら、Elasticsearchのサービスを起動します。
自動起動させたい場合は、Elasticsearchの公式サイトを参考にして設定してください。

$ gcloud compute ssh es-instance-1
$ sudo /etc/init.d/elasticsearch start
$ exit
$ gcloud compute ssh es-instance-2
$ sudo /etc/init.d/elasticsearch start
$ exit
$ gcloud compute ssh es-instance-3
$ sudo /etc/init.d/elasticsearch start
$ exit

es-instance-1インスタンスから、curlコマンドでクラスタの確認をします。
クラスタ内の3つのノードが表示されれば完了です。

$ curl es-instance-1:9200/_cat/nodes
10.142.0.4 12 30 4 0.09 0.14 0.08 mdi - es-instance-1
10.142.0.5 14 30 8 0.31 0.28 0.13 mdi * es-instance-2
10.142.0.6 15 30 8 0.34 0.29 0.13 mdi - es-instance-3

いかがでしたか?
GCP環境でもElasticsearchクラスタの環境を柔軟に構築できることがわかったかと思います。
ありがとうございました!

参考

Getting Started with the GCE Discovery Plugin on Google Cloud
Install Elasticsearch with Debian Package
Cloud SDKのインストール