Create server, configure inventory
Create Droplet on Digital Ocean using CentOS 8.3 x64 with 4GB memory and 2 vCPUs configuring an SSH key to make easy access to it.
We can probably use other version of CentOS as well, but this is what I tried it with.
From the Digital Ocean web site copy the IP address of the drolet and add it to the inventory file replacing the IP address you find there:
examples/ansible/elk/inventory.yml
elastic:
hosts:
68.183.26.18
all:
children:
elastic:
Verify that we have access to the server using Ansible Ping
ansible NAME -m ping
First it will want to verify the fingerprint of the server:
The authenticity of host '134.122.123.157 (134.122.123.157)' can't be established.
ECDSA key fingerprint is SHA256:L1jIJx45fOP3lFH/qQysD7tAdY9/rNoeC+eA2mO4ijY.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
Type in "yes" and press enter.
Then the response is expected to look like this:
134.122.123.157 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
Try the same with our first playbook:
ansible-playbook playbooks/ping.yml
The response is expected to be:
PLAY [all] ****************************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [104.236.61.19]
TASK [Ping] ***************************************************************************************
ok: [104.236.61.19]
PLAY RECAP ****************************************************************************************
104.236.61.19 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
examples/ansible/elk/playbooks/ping.yml
---
- hosts: all
tasks:
- name: Ping
ansible.builtin.ping:
See Ping module
Fetch the hostname of the server
OK, so this is not necessary to our task, but I like to see it working.
examples/ansible/elk/playbooks/hostname.yml
---
- hosts: all
tasks:
- name: Bash
ansible.builtin.shell: hostname
register: response
- debug: msg="{{ response.stdout }}"
ansible-playbook playbooks/hostname.yml
Output:
PLAY [all] ***************************************************************************************
TASK [Gathering Facts] ***************************************************************************
ok: [104.236.61.19]
TASK [Bash] **************************************************************************************
changed: [104.236.61.19]
TASK [debug] *************************************************************************************
ok: [104.236.61.19] => {
"msg": "elk1"
}
PLAY RECAP ***************************************************************************************
104.236.61.19 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
See Ansible shell module.
Install Elasticsearch
The version of ElasticSearch is baked into the playbook file. You can visit the download page of Elasticsearch to pick a different version.
examples/ansible/elk/playbooks/elasticsearch.yml
---
- hosts: all
gather_facts : no
vars:
elastic: elasticsearch-7.11.2-x86_64.rpm
project_root: /root
tasks:
- get_url:
url="https://artifacts.elastic.co/downloads/elasticsearch/{{elastic}}"
dest="{{project_root}}/{{elastic}}"
- name: Check if Elastic is installed
command: rpm -q elasticsearch
ignore_errors: True
register: rpm_check
- name: Install
ansible.builtin.shell: rpm -vi {{elastic}}
when: rpm_check.rc != 0
- name: Enable and Start
ansible.builtin.service:
name: elasticsearch
state: started
enabled: yes
- name: Copy configuration file
copy:
src: ../files/etc/elasticsearch/elasticsearch.yml
dest: /etc/elasticsearch/elasticsearch.yml
# - name: Configure Elasticsearch Cluster
# lineinfile:
# destfile: /etc/elasticsearch/elasticsearch.yml
# regexp: 'cluster.name:'
# line: 'cluster.name: code-maven-demo'
#
# - name: Configure Elasticsearch Node
# lineinfile:
# destfile: /etc/elasticsearch/elasticsearch.yml
# regexp: 'node.name:'
# line: 'node.name: code-maven-elastic-1'
#
# - name: Configure Elasticsearch Node Master
# lineinfile:
# destfile: /etc/elasticsearch/elasticsearch.yml
# regexp: 'node.master:'
# line: 'node.master: true'
#
# - name: Configure Elasticsearch Node Data
# lineinfile:
# destfile: /etc/elasticsearch/elasticsearch.yml
# regexp: 'node.data:'
# line: 'node.data: true'
#
# - name: Configure Elasticsearch Single-host
# lineinfile:
# destfile: /etc/elasticsearch/elasticsearch.yml
# regexp: 'discovery.type:'
# line: 'discovery.type: single-node'
- name: Restart
ansible.builtin.service:
name: elasticsearch
state: restarted
- name: Verify Elasticsearch
ansible.builtin.shell: curl http://localhost:9200
register: response
- debug: msg="{{ response.stdout }}"
ansible-playbook playbooks/elasticsearch.yml
examples/ansible/elk/files/etc/elasticsearch/elasticsearch.yml
# ======================== Elasticsearch Configuration =========================
#
# NOTE: Elasticsearch comes with reasonable defaults for most settings.
# Before you set out to tweak and tune the configuration, make sure you
# understand what are you trying to accomplish and the consequences.
#
# The primary way of configuring a node is via this file. This template lists
# the most important settings you may want to configure for a production cluster.
#
# Please consult the documentation for further information on configuration options:
# https://www.elastic.co/guide/en/elasticsearch/reference/index.html
#
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
#
cluster.name: code-maven-demo
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
#
node.name: code-maven-elastic-1
#
# Add custom attributes to the node:
#
#node.attr.rack: r1
#
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
path.data: /var/lib/elasticsearch
#
# Path to log files:
#
path.logs: /var/log/elasticsearch
#
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#
#bootstrap.memory_lock: true
#
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
#network.host: 192.168.0.1
#
# Set a custom port for HTTP:
#
#http.port: 9200
#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when this node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
#discovery.seed_hosts: ["host1", "host2"]
#
# Bootstrap the cluster using an initial set of master-eligible nodes:
#
#cluster.initial_master_nodes: ["node-1", "node-2"]
#
# For more information, consult the discovery and cluster formation module documentation.
#
# ---------------------------------- Gateway -----------------------------------
#
# Block initial recovery after a full cluster restart until N nodes are started:
#
#gateway.recover_after_nodes: 3
#
# For more information, consult the gateway module documentation.
#
# ---------------------------------- Various -----------------------------------
#
# Require explicit names when deleting indices:
#
#action.destructive_requires_name: true
node.master: true
node.data: true
discovery.type: single-node
#network.host: 0.0.0.0
#discovery.seed_hosts: ["1.2.3.4"]
Setup Nginx with simple authentication
Follow the instructions on how to configure http basic authentication for Nginx create one or more username/password pairs:
$ htpasswd -c .htpasswd user1 (pw: secret1)
$ htpasswd .htpasswd user2 (pw: secret2)
examples/ansible/elk/files/etc/nginx/nginx.conf
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
# server {
# listen 80 default_server;
# listen [::]:80 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# location / {
# }
#
# error_page 404 /404.html;
# location = /404.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2 default_server;
# listen [::]:443 ssl http2 default_server;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# location / {
# }
#
# error_page 404 /404.html;
# location = /404.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
examples/ansible/elk/files/etc/nginx/conf.d/nginx-elk.conf
server {
listen [::]:80;
listen 80;
# server_name _;
location / {
auth_basic "Kibana area";
auth_basic_user_file /usr/share/nginx/html/.htpasswd;
proxy_pass http://localhost:5601;
proxy_redirect off;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection "Keep-Alive";
proxy_set_header Proxy-Connection "Keep-Alive";
}
}
server {
listen [::]:81;
listen 81;
# server_name _;
location / {
auth_basic "Elasticsearch";
auth_basic_user_file /usr/share/nginx/html/.htpasswd;
proxy_pass http://localhost:9200;
proxy_redirect off;
proxy_buffering off;
proxy_http_version 1.1;
proxy_set_header Connection "Keep-Alive";
proxy_set_header Proxy-Connection "Keep-Alive";
}
}
Then run the playbook:
ansible-playbook playbooks/nginx.yml
examples/ansible/elk/playbooks/nginx.yml
---
- hosts: all
gather_facts : no
vars:
project_root: /root
tasks:
- name: Enable epel
yum:
name: epel-release
state: present
- name: Install Nginx
yum:
name: nginx
state: present
- name: Enable and Start
ansible.builtin.service:
name: nginx
state: started
enabled: yes
- name: Nginx config file
copy:
src: ../files/etc/nginx/nginx.conf
dest: /etc/nginx/nginx.conf
- name: Nginx config file
copy:
src: ../files/etc/nginx/conf.d/nginx-elk.conf
dest: /etc/nginx/conf.d/nginx-elk.conf
- name: Nginx users file
copy:
src: ../files/usr/share/nginx/html/.htpasswd
dest: /usr/share/nginx/html/.htpasswd
- name: Allow Nginx to work as a reverse proxy
ansible.builtin.shell: setsebool httpd_can_network_connect on -P
- name: Restart
ansible.builtin.service:
name: nginx
state: restarted
Visit http://IP:81 after replacing IP with the IP address of your host to get access to Elasticsearch
Kibana
examples/ansible/elk/playbooks/kibana.yml
---
- hosts: all
gather_facts : no
vars:
kibana: kibana-7.11.2-x86_64.rpm
project_root: /root
tasks:
- get_url:
url="https://artifacts.elastic.co/downloads/kibana/{{kibana}}"
dest="{{project_root}}/{{kibana}}"
- name: Check if Kibana is installed
command: rpm -q kibana
ignore_errors: True
register: rpm_check
- name: Install
ansible.builtin.shell: rpm -vi {{kibana}}
when: rpm_check.rc != 0
- name: Enable and Start
ansible.builtin.service:
name: kibana
state: started
enabled: yes
- name: Copy configuration file
copy:
src: ../files/etc/kibana/kibana.yml
dest: /etc/kibana/kibana.yml
- name: Restart
ansible.builtin.service:
name: kibana
state: restarted
Metricbeat
examples/ansible/elk/playbooks/metricbeat.yml
---
- hosts: all
vars:
metricbeat: metricbeat-7.11.2-x86_64.rpm
project_root: /root
tasks:
- get_url:
url="https://artifacts.elastic.co/downloads/beats/metricbeat/{{metricbeat}}"
dest="{{project_root}}/{{metricbeat}}"
- name: Check if Metricbeat is installed
command: rpm -q metricbeat
ignore_errors: True
register: rpm_check
- name: Install
ansible.builtin.shell: rpm -vi {{metricbeat}}
when: rpm_check.rc != 0
- name: Enable and Start
ansible.builtin.service:
name: metricbeat
state: started
enabled: yes
- name: Copy config file
copy:
src: ../files/etc/metricbeat/metricbeat.yml
dest: /etc/metricbeat/metricbeat.yml
- name: Restart
ansible.builtin.service:
name: metricbeat
state: restarted
ELK
examples/ansible/elk/playbooks/elk.yml
---
- include: nginx.yml
- include: elasticsearch.yml
- include: kibana.yml
- include: metricbeat.yml
Ansible Configuration file
examples/ansible/elk/ansible.cfg
[defaults]
deprecation_warnings = False
inventory = inventory.yml
host_key_checking = True
remote_user=root
#ask_pass = True