Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions molecule/elasticsearch_default/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,34 @@
Got: {{ cluster_settings.json.persistent }}
run_once: true
when: elasticstack_release | int >= 9

# OS tuning checks — skipped in containers where sysctl is restricted
- name: Verify vm.max_map_count # noqa: run-once[task]
ansible.builtin.command: sysctl -n vm.max_map_count
register: _max_map_count
changed_when: false
run_once: true
when: ansible_facts.virtualization_type | default('') not in ['docker', 'container', 'containerd', 'lxc', 'podman']

- name: Assert vm.max_map_count is 262144 # noqa: run-once[task]
ansible.builtin.assert:
that:
- _max_map_count.stdout | int == 262144
fail_msg: "vm.max_map_count is {{ _max_map_count.stdout }}, expected 262144"
run_once: true
when: _max_map_count is not skipped

- name: Verify vm.swappiness # noqa: run-once[task]
ansible.builtin.command: sysctl -n vm.swappiness
register: _swappiness
changed_when: false
run_once: true
when: ansible_facts.virtualization_type | default('') not in ['docker', 'container', 'containerd', 'lxc', 'podman']

- name: Assert vm.swappiness is 1 # noqa: run-once[task]
ansible.builtin.assert:
that:
- _swappiness.stdout | int == 1
fail_msg: "vm.swappiness is {{ _swappiness.stdout }}, expected 1"
run_once: true
when: _swappiness is not skipped
6 changes: 6 additions & 0 deletions roles/elasticsearch/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ elasticsearch_create_logpath: false
elasticsearch_heap: "{{ [[(ansible_facts.memtotal_mb // 1024) // 2, 30] | min, 1] | max }}"
# @var elasticsearch_pamlimits:description: Configure PAM limits for the elasticsearch user (open files, max processes)
elasticsearch_pamlimits: true
# @var elasticsearch_os_tuning:description: >
# Apply OS-level sysctl settings required for production Elasticsearch.
# Sets vm.max_map_count (required for mmapfs), vm.swappiness, disables
# Transparent Huge Pages, and tunes TCP retries for faster fault detection.
# @end
elasticsearch_os_tuning: true
# @var elasticsearch_check_calculation:description: Enable heap calculation verification and display debug output
elasticsearch_check_calculation: false
# @var elasticsearch_clustername:description: Name of the Elasticsearch cluster
Expand Down
43 changes: 43 additions & 0 deletions roles/elasticsearch/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
name: oddly.elasticstack.elasticstack
when: not hostvars[inventory_hostname]._elasticstack_role_imported | default(false)

- name: main | Propagate stack-level security setting

Check warning on line 47 in roles/elasticsearch/tasks/main.yml

View workflow job for this annotation

GitHub Actions / lint

name[casing]

All names should start with an uppercase letter.

Check warning on line 47 in roles/elasticsearch/tasks/main.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

name[casing]

All names should start with an uppercase letter.

Check warning on line 47 in roles/elasticsearch/tasks/main.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

name[casing]

All names should start with an uppercase letter.

Check warning on line 47 in roles/elasticsearch/tasks/main.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

name[casing]

All names should start with an uppercase letter.

Check warning on line 47 in roles/elasticsearch/tasks/main.yml

View workflow job for this annotation

GitHub Actions / lint_elasticsearch / lint

name[casing]

All names should start with an uppercase letter.
ansible.builtin.set_fact:
elasticsearch_security: "{{ elasticstack_security | bool }}"
when:
Expand Down Expand Up @@ -198,6 +198,49 @@
when:
- elasticsearch_pamlimits | bool

# OS-level tuning required for production Elasticsearch.
# vm.max_map_count is required — ES refuses to start without it.
# The rest are strongly recommended by Elastic's production checklist.
- name: Apply OS-level sysctl settings for Elasticsearch
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
sysctl_set: true
state: present
reload: true
loop:
- { name: vm.max_map_count, value: "262144" }
- { name: vm.swappiness, value: "1" }
- { name: net.ipv4.tcp_retries2, value: "5" }
loop_control:
label: "{{ item.name }}={{ item.value }}"
when:
- elasticsearch_os_tuning | bool
- ansible_facts.virtualization_type | default('') not in ['docker', 'container', 'containerd', 'lxc', 'podman']

- name: Disable Transparent Huge Pages (runtime)
ansible.builtin.shell: |
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
changed_when: false
when:
- elasticsearch_os_tuning | bool
- ansible_facts.virtualization_type | default('') not in ['docker', 'container', 'containerd', 'lxc', 'podman']
failed_when: false # may fail where sysfs is read-only

- name: Disable Transparent Huge Pages (persistent via tmpfiles)
ansible.builtin.copy:
dest: /etc/tmpfiles.d/elasticsearch-thp.conf
content: |
w /sys/kernel/mm/transparent_hugepage/enabled - - - - never
w /sys/kernel/mm/transparent_hugepage/defrag - - - - never
owner: root
group: root
mode: "0644"
when:
- elasticsearch_os_tuning | bool
- ansible_facts.virtualization_type | default('') not in ['docker', 'container', 'containerd', 'lxc', 'podman']

- name: Construct exact name of Elasticsearch package
ansible.builtin.set_fact:
elasticsearch_package: >-
Expand Down
Loading