blog
How to setup and install Elasticsearch: From a single node to a cluster of nodes
Elasticsearch is a complex software incomparable to other mainstream database software, whether it’s RDBMS or NoSQL. It functions primarily as your search engine and works as your document database to store valuable data for analytics.
Elasticsearch works as part of the ELK stack (Elastic, Logstash, Beats, and Kibana). It can also be used with other external visualization tools such as Grafana or Knowi, for example. However, we’ll not cover these tools in this blog.
Instead, we will focus on setting up a single node and then transitioning to a 3-node cluster, with default security using SSL/TLS socket for communication.
Elasticsearch has various ways to achieve this installation and setup. But it can be tedious and difficult to install if you stumble into problems. Especially with the recent version releases, as there have been several vital changes and some settings may not work in your current configuration setup.
Here, we will guide you to install Elasticsearch version 8.2.0 on an Ubuntu 20.04.3 LTS (Focal Fossa) environment.
For installation under a Debian environment, you can reference the official documentation.
I have the following server nodes for this example, which shall be ready to be set up and installed with Elasticsearch.
Server nodes:
1st node: pupnode170 (192.168.40.170)
2nd node: pupnode171 (192.168.40.171)
3rd node: pupnode172 (192.168.40.172)
Linux OS Version:
root@pupnode170:~# cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.3 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.3 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
The steps will be laid out in order, so it’s easier to follow. At times, you will need to revisit and repeat previous steps.
Let’s get started.
Setting up your single node installation
In this section, we need to set up the server nodes that must be installed with Elasticsearch.
Let’s begin setting up the first node with host IP 192.168.40.170. Just follow the steps accordingly by running the commands as stated in the steps.
1. Setup the GPG required for repository
Open up your shell and ensure that your OS system user has the sudo privilege or as a super admin or root user.
$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
2. Install necessary dependency tools
$ sudo apt update && sudo apt-get install apt-transport-https
3. Setup the repository
$ echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-8.x.list
4. Install Elasticsearch
$ sudo apt-get update && sudo apt-get install elasticsearch
This will install the Elasticsearch package and the result will look like this:
root@pupnode170:~# sudo apt-get update && sudo apt-get install elasticsearch
Get:1 https://artifacts.elastic.co/packages/8.x/apt stable InRelease [10.4 kB]
Get:2 https://artifacts.elastic.co/packages/8.x/apt stable/main amd64 Packages [66.2 kB]
Hit:3 http://security.ubuntu.com/ubuntu focal-security InRelease
Hit:4 http://archive.ubuntu.com/ubuntu focal InRelease
Hit:5 http://archive.ubuntu.com/ubuntu focal-updates InRelease
Hit:6 http://archive.ubuntu.com/ubuntu focal-backports InRelease
Fetched 76.6 kB in 1s (70.8 kB/s)
Reading package lists... Done
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
elasticsearch
0 upgraded, 1 newly installed, 0 to remove and 247 not upgraded.
Need to get 607 MB of archives.
After this operation, 1247 MB of additional disk space will be used.
Get:1 https://artifacts.elastic.co/packages/8.x/apt stable/main amd64 elasticsearch amd64 8.10.2 [607 MB]
Fetched 607 MB in 12s (49.7 MB/s)
Selecting previously unselected package elasticsearch.
(Reading database ... 72714 files and directories currently installed.)
Preparing to unpack .../elasticsearch_8.10.2_amd64.deb ...
Creating elasticsearch group... OK
Creating elasticsearch user... OK
Unpacking elasticsearch (8.10.2) ...
Setting up elasticsearch (8.10.2) ...
--------------------------- Security autoconfiguration information ------------------------------
Authentication and authorization are enabled.
TLS for the transport and HTTP layers is enabled and configured.
The generated password for the elastic built-in superuser is : lfmBlynaPj4UbJ9v1FFU
If this node should join an existing cluster, you can reconfigure this with
'/usr/share/elasticsearch/bin/elasticsearch-reconfigure-node --enrollment-token <token-here>'
after creating an enrollment token on your existing cluster.
You can complete the following actions at any time:
Reset the password of the elastic built-in superuser with
'/usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic'.
Generate an enrollment token for Kibana instances with
'/usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s kibana'.
Generate an enrollment token for Elasticsearch nodes with
'/usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s node'.
-------------------------------------------------------------------------------------------------
### NOT starting on installation, please execute the following statements to configure elasticsearch service to start automatically using systemd
sudo systemctl daemon-reload
sudo systemctl enable elasticsearch.service
### You can start elasticsearch service by executing
sudo systemctl start elasticsearch.service
If you look closely, Elasticsearch has generated the password from the output from the installation log.
…
The generated password for the elastic built-in superuser is : lfmBlynaPj4UbJ9v1FFU
…
Make sure you have saved this password for the record. It will be needed to set up the other two nodes in the cluster later on.
Alternatively, you can reset the password, but we’ll use the generated one for our example here.
5. Get ready to start Elasticsearch
According to the installation log, you can proceed by following the series of commands provided.
Simply run the following commands:
## reload the daemon
sudo systemctl daemon-reload
## allow elasticsearch service to start whenever system boots up
sudo systemctl enable elasticsearch.service
## start the elasticsearch service
sudo systemctl start elasticsearch.service
Technically, the default setup that the Elasticsearch provides is good to start a single-node setup.
You’ll notice that the default /etc/elasticsearch/elasticsearch.yml
will have the following:
root@pupnode170:~# cat /etc/elasticsearch/elasticsearch.yml | sed -e 's/#.*$//' -e '/^$/d' -e '/^$/N;/^\n$/D' | sed '/^\t*$/d'
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl:
enabled: true
keystore.path: certs/http.p12
xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: certs/transport.p12
truststore.path: certs/transport.p12
cluster.initial_master_nodes: ["pupnode170"]
http.host: 0.0.0.0
We’ll explain later what these optional variable settings mean. Using the default configuration, you can use it without any necessary changes just to play with Elasticsearch.
For a production setup, you should adjust accordingly to your needs.
To verify your setup, you can run the following:
root@pupnode170:~# curl --cacert /etc/elasticsearch/certs/http_ca.crt -u elastic:lfmBlynaPj4UbJ9v1FFU https://localhost:9200/?pretty
{
"name" : "pupnode170",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "cICM6Xv3QmGuER9XktiUpQ",
"version" : {
"number" : "8.10.2",
"build_flavor" : "default",
"build_type" : "deb",
"build_hash" : "6d20dd8ce62365be9b1aca96427de4622e970e9e",
"build_date" : "2023-09-19T08:16:24.564900370Z",
"build_snapshot" : false,
"lucene_version" : "9.7.0",
"minimum_wire_compatibility_version" : "7.17.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "You Know, for Search"
}
Setting up your Elasticsearch 3-node cluster
An Elasticsearch cluster operates on quorum-based decision-making for the cluster to remain functional.
The quorum is based on the voting configuration, and these votes are only counted for primary-eligible nodes, whose votes should count for the election to happen. When we say primary, it means nodes that has master
role (enabled by default when node.role
is not explicitly specified) are only eligible for quorum-based voting.
For the election to proceed and successfully elect an eligible primary, it requires that at least half of the votes + 1 should remain alive or participating in the cluster.
This means that if there are three or four primary-eligible nodes, the cluster can tolerate one of them being unavailable.
If there are two or fewer primary-eligible nodes, they must all remain available.
With that being said, let’s begin editing the configuration file. At this point, ensure you have your first node’s configuration set correctly.
6. Generate the CA (certificate authority), PEM files that we need for TLS security configuration
In the first node (192.168.40.170
), let’s generate the CA files and its HTP and transport security files needed for TLS configuration. To do that, go to /usr/share/elasticsearch
directory and do the following sequence of actions.
Generate the certificate authority
This shall be your certificate to use when authorizing your certificate files to be generated through transport
and http
SSL connection.
root@pupnode170:/usr/share/elasticsearch# bin/elasticsearch-certutil ca
By default, this will generate a file namely elastic-stack-ca.p12
. You are about to ask to fill up a password. For simplicity, let’s make it empty but for security especially in a prod environment, make sure you add a password.
Generate our transport
certificate using X.509
root@pupnode170:/usr/share/elasticsearch# bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12
The argument –ca
shall be your generated certificate authority that was created earlier, and that is file /usr/share/elasticsearch/elastic-stack-ca.p12
.
When generating this certificate, this will ask for a password, but let’s let it empty and just hit enter. This will then supply a file (by default) namely elastic-certificates.p12
.
Certificates will be written to /usr/share/elasticsearch/elastic-certificates.p12
.
Again, this file will be used for the transport
SSL connection.
Generate our http
certificate per node
The http
certificate is useful for any RESTful transactions and helps your environment secure. This means that all nodes involved, which are pupnode170, pupnode171
, and pupnode172
with their respective hostnames and IP addresses will be configured to have their certificates.
root@pupnode170:/usr/share/elasticsearch# bin/elasticsearch-certutil http
This command will generate series of questions as shown below:
…
Generate a CSR? [y/N]N
….
Use an existing CA? [y/N]y
….
Just supply N
and y
respectively since we have already our CA and no need to generate a new CSR. Next, supply the path of your certificate of authority that we generated earlier in the first command.
Please enter the full pathname to the Certificate Authority that you wish to
use for signing your new http certificate. This can be in PKCS#12 (.p12), JKS
(.jks) or PEM (.crt, .key, .pem) format.
CA Path: /usr/share/elasticsearch/elastic-stack-ca.p12
Since there’s no need for a password for this exercise, let’s leave it empty and hit enter.
Reading a PKCS12 keystore requires a password.
It is possible for the keystore's password to be blank,
in which case you can simply press <ENTER> at the prompt
Password for elastic-stack-ca.p12:
It will ask for the duration of validity for your certificate. Let’s put it 365D for example:
For how long should your certificate be valid? [5y] 365D
….
Next, this is very important. It will ask you to generate a certificate per node. Just enter y and do the series of configuration for the rest of your nodes. For example:
Generate a certificate per node? [y/N]y
## What is the name of node #1?
This name will be used as part of the certificate file name, and as a
descriptive name within the certificate.
You can use any descriptive name that you like, but we recommend using the name
of the Elasticsearch node.
node #1 name: pupnode170
## Which hostnames will be used to connect to pupnode170?
These hostnames will be added as "DNS" names in the "Subject Alternative Name"
(SAN) field in your certificate.
You should list every hostname and variant that people will use to connect to
your cluster over http.
Do not list IP addresses here, you will be asked to enter them later.
If you wish to use a wildcard certificate (for example *.es.example.com) you
can enter that here.
Enter all the hostnames that you need, one per line.
When you are done, press <ENTER> once more to move on to the next step.
pupnode170
You entered the following hostnames.
- pupnode170
Is this correct [Y/n]Y
## Which IP addresses will be used to connect to pupnode170?
If your clients will ever connect to your nodes by numeric IP address, then you
can list these as valid IP "Subject Alternative Name" (SAN) fields in your
certificate.
If you do not have fixed IP addresses, or not wish to support direct IP access
to your cluster then you can just press <ENTER> to skip this step.
Enter all the IP addresses that you need, one per line.
When you are done, press <ENTER> once more to move on to the next step.
192.168.40.170
You entered the following IP addresses.
- 192.168.40.170
Is this correct [Y/n]Y
## Other certificate options
The generated certificate will have the following additional configuration
values. These values have been selected based on a combination of the
information you have provided above and secure defaults. You should not need to
change these values unless you have specific requirements.
Key Name: pupnode170
Subject DN: CN=pupnode170
Key Size: 2048
Do you wish to change any of these options? [y/N]N
Generate additional certificates? [Y/n]y
## What is the name of node #2?
This name will be used as part of the certificate file name, and as a
descriptive name within the certificate.
You can use any descriptive name that you like, but we recommend using the name
of the Elasticsearch node.
node #2 name: pupnode171
...
Now do apply and answer the rest of your remaining nodes, and as of this time, we have pupnode171
and pupnode172
for the to-dos in the sequence.
Lastly, if you do not need any host to be added, proceed with n (or “no”) to generate a PKCS #12 keystore file. Just left the password empty just like as shown below:
Generate additional certificates? [Y/n]n
## What password do you want for your private key(s)?
Your private key(s) will be stored in a PKCS#12 keystore file named "http.p12".
This type of keystore is always password protected, but it is possible to use a
blank password.
If you wish to use a blank password, simply press <enter> at the prompt below.
Provide a password for the "http.p12" file: [<ENTER> for none]
## Where should we save the generated files?
A number of files will be generated including your private key(s),
public certificate(s), and sample configuration options for Elastic Stack products.
These files will be included in a single zip archive.
What filename should be used for the output zip file? [/usr/share/elasticsearch/elasticsearch-ssl-http.zip]
Zip file written to /usr/share/elasticsearch/elasticsearch-ssl-http.zip
Once completed, unzip the file. If done correctly, you should see files similar to the following:
root@pupnode170:/usr/share/elasticsearch# ls -R elasticsearch-ssl-http.zip elasticsearch kibana/ ./elastic-certificates.p12 ./elastic-stack-ca.p12
./elastic-certificates.p12 ./elastic-stack-ca.p12 elasticsearch-ssl-http.zip
elasticsearch:
pupnode170 pupnode171 pupnode172
elasticsearch/pupnode170:
README.txt http.p12 sample-elasticsearch.yml
elasticsearch/pupnode171:
README.txt http.p12 sample-elasticsearch.yml
elasticsearch/pupnode172:
README.txt http.p12 sample-elasticsearch.yml
kibana/:
README.txt elasticsearch-ca.pem sample-kibana.yml
Take into account that we will be using these files for our nodes:
root@pupnode170:/usr/share/elasticsearch# ls -1
/usr/share/elasticsearch/elastic-certificates.p12
/usr/share/elasticsearch/elasticsearch/pupnode17[0-2]/http.p12 /usr/share/elasticsearch/kibana/elasticsearch-ca.pem
/usr/share/elasticsearch/elastic-certificates.p12
/usr/share/elasticsearch/elasticsearch/pupnode170/http.p12
/usr/share/elasticsearch/elasticsearch/pupnode171/http.p12
/usr/share/elasticsearch/elasticsearch/pupnode172/http.p12
/usr/share/elasticsearch/kibana/elasticsearch-ca.pem
We will copy these files (in accordance to its hostname) in the following sections.
7. Copy the generated certificates and files to /etc/elasticsearch/certs
directory
First, we’ll backup the old /etc/elasticsearch/certs
directory and re-create it. In our first node (pupnode170), run:
$ mv /etc/elasticsearch/certs{,.old}
$ mkdir /etc/elasticsearch/certs
Then copy the files as follows:
$ cp /usr/share/elasticsearch/elastic-certificates.p12 /usr/share/elasticsearch/elasticsearch/pupnode170/http.p12 /usr/share/elasticsearch/kibana/elasticsearch-ca.pem /etc/elasticsearch/certs
Then make sure the files are in the correct owner and group and its restrictive permissions.
$ chown -R root.elasticsearch /etc/elasticsearch/certs
$ chmod -R o-rwx,g+r /etc/elasticsearch/certs
8. Notify the keystore settings that we need to set the right password
Since we set the password empty, we need to notify these three parameter settings under xpack.security
. These settings are the following:
xpack.security.http.ssl.keystore.secure_password
xpack.security.transport.ssl.keystore.secure_password
Xpack.security.transport.ssl.truststore.secure_password
If you need to know the passwords, running the commands below will show you its own password set:
$ /usr/share/elasticsearch/bin/elasticsearch-keystore show xpack.security.http.ssl.keystore.secure_password
$ /usr/share/elasticsearch/bin/elasticsearch-keystore show xpack.security.transport.ssl.keystore.secure_password
$ /usr/share/elasticsearch/bin/elasticsearch-keystore show xpack.security.transport.ssl.truststore.secure_password
Now, since we set the password empty, we need to notify xpack.security
by running the commands below. Leave each value empty since we have no password set and hit enter. Otherwise, if you set the password during the certificate generation, make sure you have it recorded somewhere and add it here.
Take note, your Elasticsearch service won’t start if you have a wrong password or if the password was set but you have no password in your new certificate files. That means you have to make it exactly what value it has been set. Elasticsearch is very sensitive and strict to these settings.
root@pupnode170:~# /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password
root@pupnode170:~# /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
root@pupnode170:~# /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
9. Edit /etc/elasticsearch/elasticsearch.yml and add the required nodes
The host pupnode170 (192.168.40.170
), should have similar to the following configuration settings after editing:
root@pupnode170:~# cat /etc/elasticsearch/elasticsearch.yml
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl:
enabled: true
keystore.path: certs/http.p12
xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: certs/elastic-certificates.p12
truststore.path: certs/elastic-certificates.p12
http.host: 0.0.0.0
cluster.initial_master_nodes: ["192.168.40.170","192.168.40.171", "192.168.40.172"]
network.host: [_local_, "192.168.40.170"]
discovery.seed_hosts: ["192.168.40.170:9300", "192.168.40.171:9300", "192.168.40.172:9300"]
node.name: pupnode170
network.publish_host: 192.168.40.170
These files in directory /etc/elasticsearch
, i.e. certs/http.p12
and certs/elastic-certificates.p12
are assigned and set for xpack.security.http.ssl.keystore.path, xpack.security.transport.ssl.keystore.path
, and xpack.security.transport.ssl.truststore.path
accordingly.
Take note that default ports are:
transport.port: 9300-9400.
network.host: local
http.port: 9200-9300
The settings http.host
or transport.host
will default to the value assigned to the network.host
.
In this example setup, I am using network.host
to be the base value of http.host
or transport.host
.
The discovery.seed_hosts
are the hosts of the discovery process by which the cluster formation module finds other nodes with which to form a cluster.
This process runs when you start an Elasticsearch node or when a node believes the primary node failed, and continues until the primary is found or a new primary is elected.
The discovery process starts with a list of seed addresses from one or more seed host providers and addresses of any primary-eligible nodes in the last-known cluster.
Take note that in our example here, I did not set up the cluster.name which defaults to elasticsearch. If you want to change the cluster name, you can set it in /etc/elasticsearch/elasticsearch.yml
and add cluster.name=<your-desired-cluster-name>.
10. Save your superuser password to a keystore file and restart the elasticsearch service in the first node
Remember that we have our superuser password recorded earlier during the installation:
>>> The generated password for the elastic built-in superuser is : lfmBlynaPj4UbJ9v1FFU
Now it’s time to save it to your keystore file.
$ echo "lfmBlynaPj4UbJ9v1FFU" > /etc/elasticsearch/certs/keystore.tmp
$ chmod 600 /etc/elasticsearch/certs/keystore.tmp
$ chown elasticsearch.elasticsearch /etc/elasticsearch/certs/keystore.tmp
$ sudo systemctl set-environment ES_KEYSTORE_PASSPHRASE_FILE=/etc/elasticsearch/certs/keystore.tmp
Now that we’re done, restart your Elasticsearch service.
$ systemctl restart elasticsearch.service
11. Check the logs and verify if it’s running accordingly
By using the _cat/nodes
REST request, we can verify the status of the nodes as shown below:
root@pupnode170:~# curl --cacert /etc/elasticsearch/certs/elasticsearch-ca.pem -uelastic:lfmBlynaPj4UbJ9v1FFU https://192.168.40.170:9200/_cat/nodes?v
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.40.170 37 93 1 0.03 0.08 0.03 cdfhilmrstw * pupnode170
Check if the ports are used and also listening to its network IP.
root@pupnode170:~# ss -a4l6ipn|sed -n '1p;/java/p'
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
tcp LISTEN 0 4096 [::ffff:192.168.40.170]:9300 *:* users:(("java",pid=74497,fd=365))
tcp LISTEN 0 4096 [::ffff:127.0.0.1]:9300 *:* users:(("java",pid=74497,fd=364))
tcp LISTEN 0 4096 [::1]:9300 [::]:* users:(("java",pid=74497,fd=363))
tcp LISTEN 0 4096 [::ffff:192.168.40.170]:9200 *:* users:(("java",pid=74497,fd=369))
tcp LISTEN 0 4096 [::ffff:127.0.0.1]:9200 *:* users:(("java",pid=74497,fd=368))
tcp LISTEN 0 4096 [::1]:9200 [::]:* users:(("java",pid=74497,fd=367))
Alternatively, you can use the old fashioned netstat to check the ports and processes running for Elasticsearch.
Then check the log file where logfile is the cluster.name value or cluster name you assigned.
Since we are using the default cluster.name in our example, the command below will allow you to monitor the last 10 lines of your Elasticsearch node logs.
$ tail -5f /var/log/elasticsearch/elasticsearch.log
Setting up your second node out of the three-cluster nodes
In this part, we are going to set up the second node, which is pupnode171
(192.168.40.171
).
Some of the previous steps will apply here. Go to the 2nd node, then install Elasticsearch while following next steps:
12. Repeat steps 1 – 4 for your second node and configure your Elasticsearch server
Right after you’re done with step 4, copy the files from /etc/elasticsearch/certs/
from the first node.
Take note that the password generated by Elasticsearch during your installation in the next node (second node in this context) is not important at all since we’re going to sync its keystores and certificates along with the first node.
Moving through, you can skip the succeeding actions as long as you are able to copy the files to /etc/elasticsearch/certs/
directory in your second node (pupnode171).
At this point, in our second node pupnode171, we will use scp
command for convenience to copy the files from source to target node. First, make sure you set the root password:
root@pupnode171:~# passwd
New password:
Retype new password:
passwd: password updated successfully
In your /etc/ssh/sshd_config
, make sure these options are enabled like as follows:
PermitRootLogin yes
PasswordAuthentication yes
If these options are disabled, verify it with the commands below:
root@pupnode172:~# egrep -rn 'PermitRootLogin|PasswordAuthentication' /etc/ssh/sshd_config
34:#PermitRootLogin prohibit-password
58:PasswordAuthentication no
80:# PasswordAuthentication. Depending on your PAM configuration,
82:# the setting of "PermitRootLogin without-password".
84:# PAM authentication, then enable this but set PasswordAuthentication
You can then use the command below to enable it:
$ sed -i 's|PasswordAuthentication no|PasswordAuthentication yes|g' /etc/ssh/sshd_config
$ sed -i '35 i PermitRootLogin yes' /etc/ssh/sshd_config
Just make sure to restart sshd daemon:
$ systemctl restart sshd
13. Copy the certs and PEM files generated to /etc/elasticsearch/certs from the first node to the second node
First backup the old certificate directory in your second node (pupnode171) and create a new one.
$ mv /etc/elasticsearch/certs{,.old}
$ mkdir /etc/elasticsearch/certs
Next, from the first node (pupnode170), copy the files to the second node (pupnode171) by doing the following:
root@pupnode170:/usr/share/elasticsearch# scp
/usr/share/elasticsearch/elastic-certificates.p12
/usr/share/elasticsearch/kibana/elasticsearch-ca.pem /usr/share/elasticsearch/elasticsearch/pupnode171/http.p12
192.168.40.171:/etc/elasticsearch/certs/
Then on the second node (192.168.40.171), set the proper permission and ownership of the files.
chown -R root.elasticsearch /etc/elasticsearch/certs
chmod -R o-rwx,g+r /etc/elasticsearch/certs
14. In the second node, apply changes to the config file /etc/elasticsearch/elasticsearch.yml
Make sure that the settings cluster.initial_master_nodes
and network.host
, discovery.seed_hosts
variables are set correctly.
As mentioned earlier, http.host
and transport.host
will default to the value assigned on network.host
.
This setting is only applicable if the IP or hostname bind for this node is the same as your http.host
and transport.host
requirement.
Otherwise, refer to Elasticsearch documentation for more details about this setting.
At this stage, you have to set the proper variables as shown below:
root@pupnode171:/etc/elasticsearch/certs# cat /etc/elasticsearch/elasticsearch.yml | sed -e 's/#.*$//' -e '/^$/d' -e '/^$/N;/^\n$/D' | sed '/^\t*$/d'
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl:
enabled: true
keystore.path: certs/http.p12
xpack.security.transport.ssl:
enabled: true
verification_mode: certificate
keystore.path: certs/elastic-certificates.p12
truststore.path: certs/elastic-certificates.p12
http.host: 0.0.0.0
cluster.initial_master_nodes: ["192.168.40.170","192.168.40.171", "192.168.40.172"]
network.host: [_local_, "192.168.40.171"]
discovery.seed_hosts: ["192.168.40.170:9300", "192.168.40.171:9300", "192.168.40.172:9300"]
node.name: pupnode171
network.publish_host: 192.168.40.171
Make sure that the xpack.security.http.ssl.keystore.path
, xpack.security.transport.ssl.keystore.path
, and xpack.security.transport.ssl.truststore.path
are set to the correct path of the files.
15. Change the keystore passwords in the second node
Since we did not set any password while generating our certificates and PEM files, now we need to tell the xpack.security
settings about this. Just like what we have applied in step #8 we need to empty the three xpack.security
settings by running the command below:
root@pupnode171:~# /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password
Setting xpack.security.http.ssl.keystore.secure_password already exists. Overwrite? [y/N]y
Enter value for xpack.security.http.ssl.keystore.secure_password:
root@pupnode171:~# /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
Setting xpack.security.transport.ssl.keystore.secure_password already exists. Overwrite? [y/N]y
Enter value for xpack.security.transport.ssl.keystore.secure_password:
root@pupnode171:~# /usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password
Setting xpack.security.transport.ssl.truststore.secure_password already exists. Overwrite? [y/N]y
Enter value for xpack.security.transport.ssl.truststore.secure_password:
Take note that in this exercise, we left the password empty. Just set it overwrite and hit enter as no password is set.
16. Create a keystore file containing the password that was generated by Elasticsearch during the installation of the first node
Just like what we have done in step #10, we have to store the password from the first node. To do that, just do this sequence of commands:
$ echo "lfmBlynaPj4UbJ9v1FFU" > /etc/elasticsearch/certs/keystore.tmp
$ chmod 600 /etc/elasticsearch/certs/keystore.tmp
$ chown elasticsearch.elasticsearch /etc/elasticsearch/certs/keystore.tmp
$ sudo systemctl set-environment ES_KEYSTORE_PASSPHRASE_FILE=/etc/elasticsearch/certs/keystore.tmp
17. Start the Elasticsearch in the second node
$ sudo /bin/systemctl daemon-reload
$ sudo /bin/systemctl enable elasticsearch.service
$ sudo systemctl start elasticsearch.service
18. Monitor the logs
Go to /var/log/elasticsearch/
and choose the file <cluster.name>.log
, for example:
root@pupnode171:/var/log/elasticsearch# tail -5f elasticsearch.log
[2022-06-07T21:27:10,712][INFO ][o.e.h.AbstractHttpServerTransport] [pupnode171] publish_address {192.168.40.171:9200}, bound_addresses {[::1]:9200}, {127.0.0.1:9200}, {192.168.40.171:9200}
[2022-06-07T21:27:10,712][INFO ][o.e.n.Node ] [pupnode171] started
[2022-06-07T21:27:10,765][INFO ][o.e.i.g.DatabaseNodeService] [pupnode171] successfully loaded geoip database file [GeoLite2-Country.mmdb]
[2022-06-07T21:27:11,010][INFO ][o.e.i.g.DatabaseNodeService] [pupnode171] successfully loaded geoip database file [GeoLite2-ASN.mmdb]
[2022-06-07T21:27:12,781][INFO ][o.e.i.g.DatabaseNodeService] [pupnode171] successfully loaded geoip database file [GeoLite2-City.mmdb]
Setting up your third node out of the three-cluster nodes
Lastly, let’s set up the third node.
This will be much easier since we are done with the first node (pupnode170) and second node (pupnode171).
Technically, the steps done for node 192.168.40.171 will be repeated for the third node to add, i.e. pupnode172 (192.168.40.172
) in this exercise.
All you need to do is apply steps 9 – 14. Make sure the IP addresses, or hostname, or path (check step #13 during scp
command) have been replaced correctly and are in the correct format and values. For example, in your /etc/elasticsearch/elasticsearch.yml
file, the following should be correct (which at this point it shall be using IP 192.168.40.172).
network.host: [_local_, "192.168.40.172"]
node.name: pupnode172
network.publish_host: 192.168.40.172
Verifying the Elasticsearch cluster nodes (the three-node cluster)
At this point, you should have a running 3-node cluster and are ready to function as a production cluster. We’ll use the Elasticsearch /_cat/nodes API to verify the cluster:
root@pupnode172:~#
curl –cacert /etc/elasticsearch/certs/elasticsearch-ca.pem -uelastic:lfmBlynaPj4UbJ9v1FFU https://192.168.40.170:9200/_cat/nodes?v
ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
192.168.40.171 41 96 0 0.00 0.00 0.00 cdfhilmrstw - pupnode171
192.168.40.172 28 96 27 0.84 0.33 0.15 cdfhilmrstw - pupnode172
192.168.40.170 23 94 0 0.03 0.03 0.00 cdfhilmrstw * pupnode170
You can verify the health of the cluster with the same command to any of the following nodes in the cluster. i.e. either in the first node, second node, or the third node. This is where you can use the generated file /etc/elasticsearch/certs/elasticsearch-ca.pem
, which is also dedicated to be used for your Kibana – once you have already setup your Kibana. You can use this file to request through a secure connection with your Elasticsearch nodes.
The output above defines that the current primary is set to host pupnode170 (the first node) where you can notice that the master
field assigns the asterisk to the first node.
The node.role
defines the default roles of the three-node cluster since we did not specify or filter the type of roles that these nodes have to be assigned. Specifically, the roles of the nodes mean as follows:
- c (cold node)
- d (data node)
- f (frozen node)
- h (hot node)
- i (ingest node)
- l (machine learning node)
- m (primary-eligible node)
- r (remote cluster client node)
- s (content node)
- t (transform node)
- v (voting-only node)
- w (warm node)
- – (coordinating node only).
Check the Elasticsearch documentation regarding these node roles.
Using the enrollment token to join the cluster
Elasticsearch has introduced this new approach since version 8.x where you can create a cluster by using tokens. You can also use this approach to have your node join to an existing cluster. During the first node installation, the installation output log reveals the method to use the command below:
$ /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s node
Simply, run the command above on the first node to create a token. For example:
root@pupnode170:~# /usr/share/elasticsearch/bin/elasticsearch-create-enrollment-token -s node
eyJ2ZXIiOiI4LjIuMiIsImFkciI6WyIxOTIuMTY4LjQwLjE3MDo5MjAwIl0sImZnciI6IjdjNTM3OTI4MjBhZDdhZjdiNWRjNzlkYzJmZTBlZjUyOTA2MDljNDM1ZDVkMjg5MjUxY2NlY2I2YjIwMGI2ZmMiLCJrZXkiOiJJd2hzUUlFQmkwc1AwOGhvNXQzajpjSTNISDUzTlRkcWRxdDd0Q0x4dG1BIn0=
Now, in the nodes that you want to join or create a cluster, you only need to run the following example command (at this point, in the second node):
root@pupnode171:~# /usr/share/elasticsearch/bin/elasticsearch-reconfigure-node --enrollment-token eyJ2ZXIiOiI4LjIuMiIsImFkciI6WyIxOTIuMTY4LjQwLjE3MDo5MjAwIl0sImZnciI6IjdjNTM3OTI4MjBhZDdhZjdiNWRjNzlkYzJmZTBlZjUyOTA2MDljNDM1ZDVkMjg5MjUxY2NlY2I2YjIwMGI2ZmMiLCJrZXkiOiJJd2hzUUlFQmkwc1AwOGhvNXQzajpjSTNISDUzTlRkcWRxdDd0Q0x4dG1BIn0=
This node will be reconfigured to join an existing cluster, using the enrollment token that you provided.
This operation will overwrite the existing configuration. Specifically:
- Security auto configuration will be removed from elasticsearch.yml
- The [certs] config directory will be removed
- Security auto configuration related secure settings will be removed from the elasticsearch.keystore
Do you want to continue with the reconfiguration process [y/N]y
Elasticsearch will manage it for you to set up the required private and public keys and the certificates required for cluster and client communication.
It will also generate unique private and public keys in /etc/elasticsearch/certs (except for http_ca.crt as the base certificate to create the private PKCS #12 files) in contrast to what we’ve done, we just copied from the first node.
Just make sure that you have setup the settings in your configuration file /etc/elasticsearch/elasticsearch.yml
for the following parameters:
cluster.initial_master_nodes,
http.host
transport.host
network.host
discovery.seed_hosts
The steps we followed earlier, including the verification process, apply here as well.
Conclusion
The setup and installation of a single Elasticsearch node is quite simple. However, if you want a cluster of at least three nodes, it can become a more tedious and complicated experience. Especially if you lack the experience and knowledge how to manage and do this. There are helpful resources, though, such as this guide and the official documentation.
We hope you found this guide helpful and you can now set up and install a 3-node Elasticsearch cluster – not only for a testing environment, but a production environment too!
Stay on top of all things Elasticsearch by subscribing to our newsletter below.
Follow us on LinkedIn and Twitter for more great content in the coming weeks. Stay tuned!