diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..c9a9aed --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,15 @@ +--- +cloud_apps: /opt +cloud_storage: /opt/storage +cloud_stage: prod +cloud_update: false + +elastic_data_location: "{{ cloud_storage }}/elastic-data" +elastic_logs_location: "{{ cloud_storage }}/elastic-logs" + +elastic_version: 8.17.1 +elastic_platform_suffix: linux-x86_64 + +elastic_source: "https://artifacts.elastic.co/downloads/elasticsearch" + +elastic_cluster_size: 3 diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..9dc8040 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart elasticsearch + systemd: + name: elasticsearch + state: restarted \ No newline at end of file diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..909a213 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,15 @@ +--- +galaxy_info: + role_name: elasticsearch + namespace: hahn-cloud + author: Lars Hahn + company: OpenDevChain + license: MIT + description: Role to setup elasticsearch node/cluster + min_ansible_version: 2.7 + platforms: + - name: Debian + versions: + - 11 + galaxy_tags: + - elasticsearch \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..b6f92a5 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,72 @@ +--- +- name: setup elastic group + group: + name: "{{ elastic_grp }}" + state: "present" + +- name: setup elastic user + user: + name: "{{ elastic_usr }}" + home: "{{ elastic_home }}" + group: "{{ elastic_grp }}" + groups: + - "{{ elastic_grp }}" + comment: Virtual Elastic User + shell: /bin/bash + state: present + system: yes + +- name: setup ElasticSearch directories + file: + state: directory + path: "{{ item }}" + owner: "{{ elastic_usr }}" + group: "{{ elastic_grp }}" + mode: 0750 + loop: + - "{{ elastic_path }}" + - "{{ elastic_home }}" + - "{{ elastic_conf }}" + - "{{ elastic_data_location }}" + - "{{ elastic_logs_location }}" + +- name: download ElasticSearch + unarchive: + src: "{{ elastic_source }}/elasticsearch-{{ elastic_version }}-{{ elastic_platform_suffix }}.tar.gz" + dest: "{{ elastic_path }}" + creates: "{{ elastic_inst }}" + remote_src: true + owner: "{{ elastic_usr }}" + group: "{{ elastic_grp }}" + mode: 0755 + +- name: configure ElasticSearch + template: + src: "opt/elastic/home/config/{{ item }}.j2" + dest: "{{ elastic_conf }}/{{ item }}" + owner: "{{ elastic_usr }}" + group: "{{ elastic_grp }}" + mode: 0644 + loop: + - elasticsearch.yml + - jvm.options + + +- name: setup generic ElasticSearch link + file: + state: link + src: "{{ elastic_inst }}" + dest: "{{ elastic_link }}" + +- name: setup ElasticSearch systemd unit + template: + src: etc/systemd/system/elasticsearch.service.j2 + dest: /etc/systemd/system/elasticsearch.service + notify: restart elasticsearch + +- name: enable elasticsearch systemd unit + systemd: + name: elasticsearch + enabled: yes + daemon_reload: yes + state: started \ No newline at end of file diff --git a/templates/etc/systemd/system/elasticsearch.service.j2 b/templates/etc/systemd/system/elasticsearch.service.j2 new file mode 100644 index 0000000..47b2d9b --- /dev/null +++ b/templates/etc/systemd/system/elasticsearch.service.j2 @@ -0,0 +1,68 @@ +[Unit] +Description=Elasticsearch +Documentation=https://www.elastic.co +Wants=network-online.target +After=network-online.target + +[Service] +Type=notify +# the elasticsearch process currently sends the notifications back to systemd +# and for some reason exec does not work (even though it is a child). We should change +# this notify access back to main (the default), see https://github.com/elastic/elasticsearch/issues/86475 +NotifyAccess=all +RuntimeDirectory=elasticsearch +PrivateTmp=true +Environment=ES_HOME={{ elastic_home }} +Environment=ES_PATH_CONF={{ elastic_conf }} +Environment=PID_DIR={{ elastic_home }} +Environment=ES_SD_NOTIFY=true +EnvironmentFile=-@path.env@ + +WorkingDirectory={{ elastic_home }} + +User={{ elastic_usr }} +Group={{ elastic_grp }} + +ExecStart={{ elastic_link }}/bin/systemd-entrypoint -p ${PID_DIR}/elasticsearch.pid --quiet + +# StandardOutput is configured to redirect to journalctl since +# some error messages may be logged in standard output before +# elasticsearch logging system is initialized. Elasticsearch +# stores its logs in /var/log/elasticsearch and does not use +# journalctl by default. If you also want to enable journalctl +# logging, you can simply remove the "quiet" option from ExecStart. +StandardOutput=journal +StandardError=inherit + +# Specifies the maximum file descriptor number that can be opened by this process +LimitNOFILE=65535 + +# Specifies the maximum number of processes +LimitNPROC=4096 + +# Specifies the maximum size of virtual memory +LimitAS=infinity + +# Specifies the maximum file size +LimitFSIZE=infinity + +# Disable timeout logic and wait until process is stopped +TimeoutStopSec=0 + +# SIGTERM signal is used to stop the Java process +KillSignal=SIGTERM + +# Send the signal only to the JVM rather than its control group +KillMode=process + +# Java process is never killed +SendSIGKILL=no + +# When a JVM receives a SIGTERM signal it exits with code 143 +SuccessExitStatus=143 + +# Allow a slow startup before the systemd notifier module kicks in to extend the timeout +TimeoutStartSec=900 + +[Install] +WantedBy=multi-user.target diff --git a/templates/opt/elastic/home/config/elasticsearch.yml.j2 b/templates/opt/elastic/home/config/elasticsearch.yml.j2 new file mode 100644 index 0000000..17efb29 --- /dev/null +++ b/templates/opt/elastic/home/config/elasticsearch.yml.j2 @@ -0,0 +1,140 @@ +--- +# ======================== 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: {{ cloud_name | default('elasticsearch') }}.{{ cloud_stage }} +# +# ------------------------------------ Node ------------------------------------ +# +# Use a descriptive name for the node: +# +node: + name: {{ ansible_hostname }} +# +# 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: {{ elastic_data_location }} + logs: {{ elastic_logs_location }} +# +# ----------------------------------- 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 ----------------------------------- +# +# By default Elasticsearch is only accessible on localhost. Set a different +# address here to expose this node on the network: +# +network: + host: {{ ansible_default_ipv4.address }} +# +# By default Elasticsearch listens for HTTP traffic on the first free port it +# finds starting at 9200. Set a specific HTTP port here: +# +http: + port: 9200 +# Allow HTTP API connections from anywhere +# Connections are encrypted and require user authentication + host: 0.0.0.0 +# +# 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: +{%- for node in ansible_hostname.split('-')[:-1] | join('-') | split('\n') | product(range(size)) | map('join', '-') %} + - {{ node }}.hnw +{% endfor -%} +# +# Bootstrap the cluster using an initial set of master-eligible nodes: +# +cluster: + initial_master_nodes: +{%- for node in ansible_hostname.split('-')[:-1] | join('-') | split('\n') | product(range(size)) | map('join', '-') %} + - {{ node }} +{% endfor %} +# +# For more information, consult the discovery and cluster formation module documentation. +# +# ---------------------------------- Various ----------------------------------- +# +# Allow wildcard deletion of indices: +# +#action.destructive_requires_name: false + +#----------------------- BEGIN SECURITY AUTO CONFIGURATION ----------------------- +# +# The following settings, TLS certificates, and keys have been automatically +# generated to configure Elasticsearch security features on 03-02-2025 20:51:51 +# +# -------------------------------------------------------------------------------- + +# Enable security features +xpack: + security: + enabled: true + enrollment: + enabled: true +# Enable encryption for HTTP API client connections, such as Kibana, Logstash, and Agents + http: + ssl: + enabled: true + keystore: + path: certs/http.p12 + +# Enable encryption and mutual authentication between cluster nodes + transport: + ssl: + enabled: true + verification_mode: certificate + keystore: + path: certs/transport.p12 + truststore: + path: certs/transport.p12 +# Create a new cluster with the current node only +# Additional nodes can still join the cluster later +cluster: + name: {{ cloud_name | default('elasticsearch') }}.{{ cloud_stage }} + initial_master_nodes: +{%- for node in ansible_hostname.split('-')[:-1] | join('-') | split('\n') | product(range(size)) | map('join', '-') %} + - {{ node }} +{% endfor %} + +# Allow other nodes to join the cluster from anywhere +# Connections are encrypted and mutually authenticated +#transport.host: 0.0.0.0 + +#----------------------- END SECURITY AUTO CONFIGURATION ------------------------- \ No newline at end of file diff --git a/templates/opt/elastic/home/config/jvm.options.j2 b/templates/opt/elastic/home/config/jvm.options.j2 new file mode 100644 index 0000000..920209f --- /dev/null +++ b/templates/opt/elastic/home/config/jvm.options.j2 @@ -0,0 +1,83 @@ +################################################################ +## +## JVM configuration +## +################################################################ +## +## WARNING: DO NOT EDIT THIS FILE. If you want to override the +## JVM options in this file, or set any additional options, you +## should create one or more files in the jvm.options.d +## directory containing your adjustments. +## +## See https://www.elastic.co/guide/en/elasticsearch/reference/8.17/advanced-configuration.html#set-jvm-options +## for more information. +## +################################################################ + + + +################################################################ +## IMPORTANT: JVM heap size +################################################################ +## +## The heap size is automatically configured by Elasticsearch +## based on the available memory in your system and the roles +## each node is configured to fulfill. If specifying heap is +## required, it should be done through a file in jvm.options.d, +## which should be named with .options suffix, and the min and +## max should be set to the same value. For example, to set the +## heap to 4 GB, create a new file in the jvm.options.d +## directory containing these lines: +## +## -Xms4g +## -Xmx4g +## +## See https://www.elastic.co/guide/en/elasticsearch/reference/8.17/heap-size.html +## for more information +## +################################################################ + + +################################################################ +## Expert settings +################################################################ +## +## All settings below here are considered expert settings. Do +## not adjust them unless you understand what you are doing. Do +## not edit them in this file; instead, create a new file in the +## jvm.options.d directory containing your adjustments. +## +################################################################ + +-XX:+UseG1GC + +## JVM temporary directory +-Djava.io.tmpdir=${ES_TMPDIR} + +# Leverages accelerated vector hardware instructions; removing this may +# result in less optimal vector performance +20-:--add-modules=jdk.incubator.vector + +# Required to workaround performance issue in JDK 23, https://github.com/elastic/elasticsearch/issues/113030 +23:-XX:CompileCommand=dontinline,java/lang/invoke/MethodHandle.setAsTypeCache +23:-XX:CompileCommand=dontinline,java/lang/invoke/MethodHandle.asTypeUncached + +## heap dumps + +# generate a heap dump when an allocation from the Java heap fails; heap dumps +# are created in the working directory of the JVM unless an alternative path is +# specified +-XX:+HeapDumpOnOutOfMemoryError + +# exit right after heap dump on out of memory error +-XX:+ExitOnOutOfMemoryError + +# specify an alternative path for heap dumps; ensure the directory exists and +# has sufficient space +-XX:HeapDumpPath=data + +# specify an alternative path for JVM fatal error logs +-XX:ErrorFile=logs/hs_err_pid%p.log + +## GC logging +-Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,level,pid,tags:filecount=32,filesize=64m \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml new file mode 100644 index 0000000..d9caceb --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,9 @@ +--- +elastic_usr: elastic +elastic_grp: "{{ elastic_usr }}" + +elastic_path: "{{ cloud_apps }}/elastic" +elastic_link: "{{ elastic_path }}/inst" +elastic_inst: "{{ elastic_path }}/elasticsearch-{{ elastic_version }}" +elastic_home: "{{ elastic_path }}/home" +elastic_conf: "{{ elastic_home }}/config" \ No newline at end of file