在EC2上建立一个处理大容量数据的Elasticsearch集群
背景 – 人们所处环境或过去经历的情况和条件。
当需要在每天超过一亿条记录、涉及超过两千个变量的(半)无模式数据上进行近实时的投入和聚合时,该如何在EC2上构建?
由于想使用X-Pack,不能使用Elasticsearch Service。由于安全组、调优潜力、成本等各种原因,也不选择Elastic公司的托管服务。另外,希望尽量减少X-Pack的许可费用,因此也希望节点的数量尽量少。
大纲
-
- Elasticsearch 6.4以降を想定(5.x でもほぼ共通だがノード間通信の暗号化が必須か否か、G1GCが使えるか否か、が違う)
-
- EC2インスタンスはメモリーが多いもの、256GB以上を選ぶ
-
- EBSではなく、SSD(所謂エフェメラルストレージ/揮発性のNVMe)が付いてくるインスタンス、ストレージが2台以上、できれば4台くらいあるものを選択し、RAIDでストライピングする
-
- ノード間の通信を暗号化するのに証明書を入れるが、手間を少なくするために一度Dockerイメージを作ってECRに入れる
-
- ノードあたりのヒープサイズは128GBとか、「JVMの32GB制限」を気にせず、G1GCを有効化することで大容量メモリーと性能をバランスする
- データノードの他に、独立したコーディネーターノードを建てる
建立程序
前提 tí)
-
- インスタンスタイプはi3.8xlarge を想定
m5d、c5d、r5d等のNitro世代のディスク付きでも同じだが、ルートのEBSがNVMe扱いなのでデバイスの番号がずれるのでRAID構成時に注意する
OSは初期状態のAmazon Linux
ElasticsearchそのものはDocker上で動かすのであまり拘らなくて良いかもしれない
主机的调优
基本步骤与官方文件相同,但需要进行RAID配置。
请更新并安装Docker。
应用系统等的更新并安装Docker。
yum -y update
yum -y install docker
在limits.conf文件中添加设置。
放宽文件描述符的上限,无限制地锁定内存。如果在Shell中以以下方式执行,将会附加写入(千万不要将其复制到limits.conf文件中)。
bash -c 'echo root soft nofile 1048576 >> /etc/security/limits.conf'
bash -c 'echo root hard nofile 1048576 >> /etc/security/limits.conf'
bash -c 'echo * soft nofile 1048576 >> /etc/security/limits.conf'
bash -c 'echo * hard nofile 1048576 >> /etc/security/limits.conf'
bash -c 'echo * soft memlock unlimited >> /etc/security/limits.conf'
bash -c 'echo * hard memlock unlimited >> /etc/security/limits.conf'
在sysctl.conf中添加设置
进行网络和交换的设置。您也可以将其粘贴到shell中进行追加。
bash -c 'echo net.ipv4.tcp_tw_reuse = 1 >> /etc/sysctl.conf'
bash -c 'echo net.ipv4.tcp_fin_timeout = 30 >> /etc/sysctl.conf'
bash -c 'echo net.ipv4.ip_local_port_range = 16384 65535 >> /etc/sysctl.conf'
bash -c 'echo vm.max_map_count = 262144 >> /etc/sysctl.conf'
bash -c 'echo vm.swappiness = 1 >> /etc/sysctl.conf'
请在 /etc/rc.local 文件中加入以下内容。
请打开 /etc/rc.local 文件并添加以下内容。
使用未被广泛了解的 AWS 169.254.169.254 地址来获取实例ID,以设置主机名。
将RAID的配置写在这里,因为如果使用临时存储,数据将在关机后消失并且RAID的配置也会丢失,因此如果没有配置RAID,需要重新配置。
在此示例中,假设使用 i3.8xlarge 实例,因此将构建RAID的目标设备从 /dev/nvme0 到 /dev/nvme3 的4台进行配置。对于Nitro世代,从 /dev/nvme1 开始。
将/data 目录设置为 Elasticsearch 的数据目录,因此可以这样做,但还需要考虑权限。
# Set Hostname
hostname "$(curl -s http://169.254.169.254/latest/meta-data/instance-id |sed 's/\./-/g')"
# Init RAID
if [ ! -d /data ]
then
mkdir /data
fi
if [ ! -d /dev/md0 ]
then
# Initialize the RAID with four NVMe drives
mdadm --create --verbose --level=0 /dev/md0 --name=DATA --raid-devices=4 /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1
mkfs.ext4 /dev/md0
mdadm --detail --scan | tee -a /etc/mdadm.conf
# Just in case, Update the kernel option
dracut -H -f /boot/initramfs-$(uname -r).img $(uname -r)
# Mount the RAID
mount -a
fi
chmod 777 /data
将fstab文件进行追加操作。
请在Shell中执行以下命令,将配置的RAID在启动时挂载到/data。
bash -c 'echo /dev/md0 /data ext4 defaults,nofail,noatime,discard 0 2 >> /etc/fstab'
重启主机
reboot
启动Elasticsearch容器
创建Dockerfile。
基本上我們以 Elastic 官方映像為基礎,然後安裝必要的插件。最近,X-Pack 通常已經預先安裝,所以可能不太需要再添加插件。
由於節點間的通信必須加密,我們生成了 p12 憑證文件並將其嵌入到映像中。(切勿將其放入公開的存儲庫)
FROM docker.elastic.co/elasticsearch/elasticsearch:6.6.2
#### 形態素解析のプラグイン等インストールする場合はここに列挙する
RUN \
elasticsearch-plugin install --batch analysis-icu && \
elasticsearch-plugin install --batch analysis-kuromoji
#### ノード間の通信の暗号化に使うp12ファイルを作っておいて、よしなに入れてやる
RUN mkdir /usr/share/elasticsearch/config/certs
ADD elastic-certificates.p12 /usr/share/elasticsearch/config/certs/elastic-certificates.p12
ADD elastic-stack-ca.p12 /usr/share/elasticsearch/config/certs/elastic-stack-ca.p12
RUN chown -R elasticsearch /usr/share/elasticsearch/config/certs
RUN chgrp -R root /usr/share/elasticsearch/config/certs
RUN chmod o-rx /usr/share/elasticsearch/config/certs
RUN chmod 640 /usr/share/elasticsearch/config/certs/elastic-stack-ca.p12
RUN chmod 640 /usr/share/elasticsearch/config/certs/elastic-certificates.p12
建筑
构建。可以生成包含插件和证书的镜像。
将它附上易于放入ECR的标签。
docker build -t 0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2 .
将其放入ECR中
登录到ECR上,然后进行推送。
aws ecr get-login --no-include-email --profile hoge | sudo /bin/bash
docker push 0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2
启动Elasticsearch
在每个节点上启动Elasticsearch容器的方式如下:
– 将Xms和Xmx设置为主机内存的大约50%。不用担心JVM的32GB(地址空间是32位还是64位)的问题。在EC2上,我记得大约是31GB并且变成了64位,但是由于机器性能高并且使用了G1GC,所以更加不用担心。
– 在discovery.zen.ping.unicast.hosts中列举构建集群的机器的IP地址。
– 存储数据的目录在容器内无法更改。
– 使用ELASTIC_PASSWORD环境变量指定默认用户的密码。
数据节点(负责存储和聚合处理数据)
- データノードは node.master 、 node.data=true 、 node.ingest が全て true
docker pull 0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2
docker run -d --net=host -v /data:/usr/share/elasticsearch/data \
-e "node.master=true" \
-e "node.data=true" \
-e "node.ingest=true" \
-e "ELASTIC_PASSWORD=P4ssW0rd" \
-e "node.name=$(curl -s http://169.254.169.254/latest/meta-data/instance-id |sed 's/\./-/g')" \
-e "ES_JAVA_OPTS=-Xms128G -Xmx128G -XX:-UseConcMarkSweepGC -XX:-UseCMSInitiatingOccupancyOnly -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=75" \
-e "network.host=0.0.0.0" \
-e "bootstrap.memory_lock=true" \
-e "discovery.zen.ping.unicast.hosts=3.0.0.1,3.0.0.2,3.0.0.3" \
-e "discovery.zen.minimum_master_nodes=1" \
-e "xpack.security.transport.ssl.enabled=true" \
-e "xpack.security.transport.ssl.verification_mode=certificate" \
-e "xpack.security.transport.ssl.keystore.path=/usr/share/elasticsearch/config/certs/elastic-stack-ca.p12" \
-e "xpack.security.transport.ssl.truststore.path=/usr/share/elasticsearch/config/certs/elastic-certificates.p12" \
-e "thread_pool.bulk.queue_size=1000" \
-e "cluster.name=high-performance-es" \
--ulimit nofile=524288:524288 --ulimit memlock=-1:-1 \
--privileged \
--name elasticsearch \
0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2
协调节点(仅负责输入输出门户)
-
- コーディネーターはクラスターのエンドポイントの役割を担い、入出力をデータノードに割り振る役割
node.master 、 node.data=true 、 node.ingest が全て false
インスタンスサイズは小さくて大丈夫だが、EC2で小さいインスタンスを使う場合、ネットワーク帯域が制限されるか、クレジットの枯渇でパフォーマンスが落ちることがあるので、そこそこ大きめのインスタンスがオススメ
コーディネーターノードはゆとりがあるので、ここでKibanaを動かすといい
docker pull 0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2
docker run -d --net=host -v /data:/usr/share/elasticsearch/data \
-e "node.master=false" \
-e "node.data=false" \
-e "node.ingest=false" \
-e "node.name=Coordinator" \
-e "ELASTIC_PASSWORD=P4ssW0rd" \
-e "ES_JAVA_OPTS=-Xms30G -Xmx30G -XX:-UseConcMarkSweepGC -XX:-UseCMSInitiatingOccupancyOnly -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=75" \
-e "network.host=0.0.0.0" \
-e "bootstrap.memory_lock=true" \
-e "discovery.zen.ping.unicast.hosts=3.0.0.1,3.0.0.2,3.0.0.3" \
-e "discovery.zen.minimum_master_nodes=1" \
-e "xpack.security.transport.ssl.enabled=true" \
-e "xpack.security.transport.ssl.verification_mode=certificate" \
-e "xpack.security.transport.ssl.keystore.path=/usr/share/elasticsearch/config/certs/elastic-stack-ca.p12" \
-e "xpack.security.transport.ssl.truststore.path=/usr/share/elasticsearch/config/certs/elastic-certificates.p12" \
-e "thread_pool.bulk.queue_size=1000" \
-e "cluster.name=high-performance-es" \
--ulimit nofile=524288:524288 --ulimit memlock=-1:-1 \
--privileged \
--name elasticsearch \
0000000000.dkr.ecr.ap-northeast-1.amazonaws.com/es/high-performance-es:6.6.2
调整索引设置
在设置索引时,需要考虑文档的大小、输入输出频率、性能要求和可用性等因素。特别是在使用临时存储来提高性能的情况下,如果发生硬件故障,数据可能会丢失。因此,需要考虑是否需要具有副本或在EBS上备份数据,以及将永久数据存储在其他数据库中承载,或者Elasticsearch是否注重灵活性和速度等方面,这需要进行选择和集中考虑。
我认为以下设置对性能影响重大。
-
- refresh_interval
投入したデータが反映されるまでの時間に影響する。長くすれば書き込み処理が粗くなるので軽くなるが、投入から集計までの時差=Latencyが延びる
number_of_shards
インデックスをクラスター内でいくつに分割するかの値。多すぎでも少なすぎでもよくないので難しいが、ノード数の4倍にした。インデックスあたりのドキュメント数や容量でも考える必要があるし、インデックスをどういう単位で分割するかにもよる。
codec
圧縮設定。 best_compression でいいと思う。圧縮と伸張はCPUを使うが、ディスクIOの方が問題になるので、書き込みと読み出しの時点でのサイズを最小にする方が早い印象。
number_of_replicas
レプリカを作ればデータの保全はしやすいが、データを複製・同期するので遅くなる。最速を目指すならレプリカは作らない。
ドキュメントに対する制約をいじって使わないデータを扱わないようにする
max_docvalue_fields_search
total_fields
depth
nested_fields
analyzer
変数ごとに有効・無効を切り替えられるが、形態素解析をしないような変数では基本的に無効にしておく。
结束
-
- Dockerにしておくとアップデートの時に作業しやすい
-
- Kibanaの設定は人間の工数がかかっているデータなので、S3にバックアップする方が良い。Kibanaの設定も当然クラスター内にあるので、誤ったシャットダウンや障害、作業ミスで消えると困る。
-
- なにか色々はしょってる気がする
-
- 誤りや更新が必要なところはコメントください
- すでに7.0が出ている… プラグイン周りが変わったと思うけど他は使えるはず