How to Set Up an Elasticsearch Cluster on Ubuntu 18.04
This article serves as a guide on how to install an Elasticsearch cluster on three Ubuntu 18.04 machines. There are ways to automatically deploy an Elasticsearch cluster using Kubernetes or Docker Cluster, but this guide will serve as a guide on how to manually set up a cluster.
But first a few terminologies:
- Cluster - a collection of machines/servers that all have Elasticsearch installed, delegate responsibilities amongst themselves, and that all communicate with each other through a collective API.
- Nodes - a machine/server in the cluster
First, SSH into all ES nodes in the cluster:
ssh <ubuntu username>@<ES node ip>
Elasticsearch can’t be run as a root user. Elasticsearch itself restricts this. We need to create a new user named elasticsearch
.
sudo adduser elasticsearch
sudo adduser elasticsearch sudo
sudo -su elasticsearch
After you log in, let’s install some prerequisites:
sudo apt-get install unzip
sudo apt install openjdk-11-jre-headless
sudo apt-get install apt-transport-https
echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list
Now let’s install Elasticsearch. In this article, we’ll install version 7.13.3, but you can install any other versions that you want.
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
sudo apt-get update && sudo apt-get install elasticsearch=7.13.3
Add custom settings to elasticsearch.yml
Now let’s add custom settings to elasticsearch.yml
. This YAML file is used to configure Elasticsearch.
Let’s have one of our machines be a “master node”, which is responsible for lightweight cluster-wide actions such as creating or deleting an index, tracking which nodes are part of the cluster, and deciding which shards to allocate to which nodes. It is important for cluster health to have a stable master node.
Do this command only on the master node in the cluster:
sudo bash -c 'cat > /etc/elasticsearch/elasticsearch.yml << EOF
cluster.name: cool-cluster
node.name: ${HOSTNAME} # This will default to the host name of our machine
node.master: true
node.data: true
path.logs: /var/log/elasticsearch
path.data: /usr/share/elasticsearch/data
bootstrap.memory_lock: true
network.host: <NODE IP ADDRESS>
discovery.seed_hosts: ["<NODE IP ADDRESS MASTER NODE>", "<NODE IP ADDRESS DATA NODE 1>", "<NODE IP ADDRESS DATA NODE 2>"]
cluster.initial_master_nodes: ["<NODE IP ADDRESS MASTER NODE>"]
xpack.security.enabled: true
# This turns on TLS/SSL for inter-node communication
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.client_authentication: required
xpack.security.transport.ssl.keystore.path: /etc/elasticsearch/certs/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: /etc/elasticsearch/certs/elastic-certificates.p12
# This turns on TLS/SSL for the HTTP (Rest) interface
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: /etc/elasticsearch/certs/elasticsearch-ssl-http/elasticsearch/${HOSTNAME}/http.p12
# These settings need to be entered in elasticsearch-keystore
# xpack.security.transport.ssl.keystore.secure_password
# xpack.security.transport.ssl.truststore.secure_password
# xpack.security.http.ssl.keystore.secure_password
EOF'
Now configure elasticsearch.yml
for each data node in the cluster. Repeat for all data nodes:
sudo bash -c 'cat > /etc/elasticsearch/elasticsearch.yml << EOF
cluster.name: cool-cluster
node.name: ${HOSTNAME}
node.master: false
node.data: true
path.logs: /var/log/elasticsearch
path.data: /usr/share/elasticsearch/data
path.home: /usr/share/elasticsearch
bootstrap.memory_lock: true
network.host: <PRIVATE IP ADDRESS>
discovery.seed_hosts: ["<PRIVATE IP ADDRESS MASTER NODE>", "<PRIVATE IP ADDRESS DATA NODE 1>", "<PRIVATE IP ADDRESS DATA NODE 2>"]
cluster.initial_master_nodes: ["<PRIVATE IP ADDRESS MASTER NODE>"]
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
# This turns on TLS/SSL for inter-node communication
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.client_authentication: required
xpack.security.transport.ssl.keystore.path: /etc/elasticsearch/certs/elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: /etc/elasticsearch/certs/elastic-certificates.p12
# This turns on SSL for the HTTP (Rest) interface
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: /etc/elasticsearch/certs/elasticsearch-ssl-http/elasticsearch/${HOSTNAME}/http.p12
# These settings need to be entered in elasticsearch-keystore
# xpack.security.transport.ssl.keystore.secure_password
# xpack.security.transport.ssl.truststore.secure_password
# xpack.security.http.ssl.keystore.secure_password
EOF'
Open ports 9200-9300
Now that you’ve configured elasticsearch.yml
for each node in the cluster, we need to open ports 9200-9300 so that clients can interact with Elasticsearch and nodes can interact with each other.
Repeat this for every node in the cluster:
sudo ufw allow 9200:9300/tcp
sudo ufw allow ssh
sudo ufw enable
Increase file descriptors
Now let’s increase file descriptors on each node. Elasticsearch recommends doing this because it uses a lot of file descriptors or file handles. Running out of file descriptors can be disastrous and will most probably lead to data loss. Make sure to increase the limit on the number of open files descriptors for the user running Elasticsearch to 65536
or higher.
sudo bash -c 'cat > /etc/default/elasticsearch << EOF
ES_STARTUP_SLEEP_TIME=5
MAX_OPEN_FILES=65536
MAX_LOCKED_MEMORY=unlimited
EOF'
Disable Swapping
Next, let’s disable swapping. Swapping is very bad for performance, for node stability, and should be avoided at all costs. It can cause garbage collections to last for minutes instead of milliseconds and can cause nodes to respond slowly or even to disconnect from the cluster. In a resilient distributed system, it’s more effective to let the operating system kill the node.
First, add LimitMEMLOCK=infinity
to /usr/lib/systemd/system/elasticsearch.service
sudo vim /usr/lib/systemd/system/elasticsearch.service
You’ll have to manually add LimitMEMLOCK=infinity
under the [Service] section:
sudo bash -c 'cat > /etc/security/limits.conf << EOF
elasticsearch soft memlock unlimited
elasticsearch hard memlock unlimited
EOF'
Increase vm.max_map_count
Elasticsearch uses a mmapfs
directory by default to store its indices. The default operating system limits on mmap counts is likely to be too low, which may result in out of memory exceptions. To set this value permanently, update the vm.max_map_count
setting in /etc/sysctl.conf
. To verify after rebooting, run sysctl vm.max_map_count
.
sudo vim /etc/sysctl.conf
Add vm.max_map_count=262144
manually to the bottom of the file. Verify your change with:
sudo sysctl -p
Change the permission of the ES folder
sudo chown -R elasticsearch:elasticsearch /usr/share/elasticsearch
If you don’t do this, then the elasticsearch
user will not be able to access this folder when running.
Enable TLS/SSL Inter-node communications
Before you enable TLS/SSL, make sure that you stop Elasticsearch and Kibana on all nodes in the cluster:
sudo service elasticsearch stop
sudo service kibana stop
Do for master node only:
sudo ES_PATH_CONF=/etc/elasticsearch /usr/share/elasticsearch/bin/elasticsearch-certutil ca
sudo ES_PATH_CONF=/etc/elasticsearch /usr/share/elasticsearch/bin/elasticsearch-certutil cert --ca /usr/share/elasticsearch/elastic-stack-ca.p12
sudo ES_PATH_CONF=/etc/elasticsearch /usr/share/elasticsearch/bin/elasticsearch-certutil http
Do for each node:
sudo mkdir /etc/elasticsearch/certs
sudo mkdir /etc/elasticsearch/certs/elasticsearch-ssl-http
sudo chown -R elasticsearch:elasticsearch /etc/elasticsearch /etc/elasticsearch/certs
Do on master node:
sudo cp /usr/share/elasticsearch/elastic-certificates.p12 /etc/elasticsearch/certs
sudo cp /usr/share/elasticsearch/elastic-stack-ca.p12 /etc/elasticsearch/certs
sudo cp /usr/share/elasticsearch/elasticsearch-ssl-http.zip /etc/elasticsearch/certs
Copy cert from master node to other nodes in the cluster
sudo scp /etc/elasticsearch/certs/elastic-certificates.p12 elasticsearch@<REMOTE PRIVATE IP>:/etc/elasticsearch/certs/
sudo scp /etc/elasticsearch/certs/elastic-stack-ca.p12 elasticsearch@<REMOTE PRIVATE IP>:/etc/elasticsearch/certs/
sudo scp /etc/elasticsearch/certs/elasticsearch-ssl-http.zip elasticsearch@<REMOTE PRIVATE IP>:/etc/elasticsearch/certs/
Do for each node:
sudo chmod -R elasticsearch:elasticsearch /etc/elasticsearch/certs/*
sudo unzip /etc/elasticsearch/certs/elasticsearch-ssl-http.zip -d /etc/elasticsearch/certs/elasticsearch-ssl-http
For each environment, you’ll have to add
xpack.security.transport.ssl.keystore.secure_password
xpack.security.transport.ssl.truststore.secure_password
xpack.security.http.ssl.keystore.secure_password
if you decide to generate a TLS/SSL certificate with a password.
ES_PATH_CONF=/etc/elasticsearch /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
It will prompt you for the value of the setting you want to insert. Enter the password to your TLS/SSL certificates.
ES_PATH_CONF=/etc/elasticsearch /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
It will prompt you for the value of the setting you want to insert. Enter the password to your TLS/SSL Central Authority (CA).
ES_PATH_CONF=/etc/elasticsearch /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password
Repeat this for each node.
Do this from a terminal on your local computer:
This downloads the Certificate Authority (CA) and certificate from the remote server so that we can back it up in case things go bad.
scp elasticsearch@<REMOTE PRIVATE IP>:/etc/elasticsearch/certs/elastic-stack-ca.p12 .
scp elasticsearch@<REMOTE PRIVATE IP>:/etc/elasticsearch/certs/elastic-certificates.p12 .
scp elasticsearch@<REMOTE PRIVATE IP>:/etc/elasticsearch/certs/elasticsearch-ssl-http.zip .
Tip: remember the period (.) at the end!
Check certificate expiry date
Note that we’ll have to renew the certificate and Certificate Authority every 3 years.
openssl pkcs12 -in elastic-certificates.p12 -nodes | openssl x509 -noout -enddate
Generate user credentials
This is a one-time operation that will generate all credentials needed to access Elasticsearch API, Kibana, etc… Be careful when you’re running this command. ES will not let you run it a second time! If you mess it up, you’ll have to reinstall ES, and delete the etc/elasticsearch, /usr/share/elasticsearch folders!
sudo ES_PATH_CONF=/etc/elasticsearch /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto
Start Elasticsearch
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch
Test things out
curl -XGET <http://<master node ip>/
curl -XGET <http://<master node ip>:9200/_cluster/health?pretty
Check logs
sudo tail /var/log/elasticsearch/<cluster name>.log