Merge "Add dynamic retention policies to curator"

This commit is contained in:
Zuul 2018-07-15 04:18:41 +00:00 committed by Gerrit Code Review
commit 93463d6efc
7 changed files with 193 additions and 165 deletions

View File

@ -16,6 +16,10 @@
body: "{{ item.index_options | to_json }}" body: "{{ item.index_options | to_json }}"
status_code: 200,400 status_code: 200,400
body_format: json body_format: json
register: elk_indexes
until: elk_indexes is success
retries: 3
delay: 5
with_items: with_items:
- name: "osprofiler-notifications" - name: "osprofiler-notifications"
index_options: index_options:

View File

@ -16,6 +16,7 @@
- name: Install Curator - name: Install Curator
hosts: "elastic-logstash" hosts: "elastic-logstash"
become: true become: true
gather_facts: false
vars: vars:
haproxy_ssl: false haproxy_ssl: false
@ -25,6 +26,47 @@
environment: "{{ deployment_environment_variables | default({}) }}" environment: "{{ deployment_environment_variables | default({}) }}"
pre_tasks: pre_tasks:
- include_tasks: common_task_data_node_hosts.yml
tags:
- always
- name: Query es storage
uri:
url: "http://127.0.0.1:9200/_nodes/{{ (data_nodes | map('extract', hostvars, 'ansible_host') | list) | join(',') }}/stats/fs"
method: GET
register: elk_data
until: elk_data is success
retries: 3
delay: 5
run_once: true
- name: Set available storage fact
set_fact:
es_total_available_storage: "{{ ((elk_data['json']['nodes'].values() | list) | map(attribute='fs.total.total_in_bytes') | list | sum) // 1024 // 1024 }}"
- name: Set assumed buffer storage fact
set_fact:
es_assumed_buffer_storage: "{{ ((es_total_available_storage | int) * 0.25) | round | int }}"
- name: Set usable buffer storage fact(s)
set_fact:
es_usable_buffer_storage: "{{ (es_total_available_storage | int) - (es_assumed_buffer_storage | int) }}"
es_expected_storage: "{{ ((elastic_beat_retention_policy_hosts.values() | map('int') | list) | sum) * (elastic_beat_storage_constant | int) }}"
- name: Set buffer storage fact
set_fact:
es_assumed_usable_storage_per_node: "{{ (es_usable_buffer_storage | int) // (data_nodes | length | int) }}"
- name: Set storage the mulitplier
set_fact:
es_storage_multiplier: "{{ ((es_usable_buffer_storage | int) < (es_expected_storage | int)) | ternary(((elastic_beat_storage_constant | int) * 2), elastic_beat_storage_constant | int) }}"
- name: Set retention facts
set_fact: "elastic_{{ item.key }}_retention={{ (es_assumed_usable_storage_per_node | int) // ((item.value | int) * (es_storage_multiplier | int)) }}"
when:
- hostvars[inventory_hostname]["elastic_" + item.key + "_retention"] is undefined
with_dict: "{{ elastic_beat_retention_policy_hosts }}"
- name: Ensure virtualenv is installed - name: Ensure virtualenv is installed
apt: apt:
name: "{{ item }}" name: "{{ item }}"

View File

@ -14,8 +14,8 @@
# limitations under the License. # limitations under the License.
- import_playbook: installElastic.yml - import_playbook: installElastic.yml
- import_playbook: installCurator.yml
- import_playbook: installLogstash.yml - import_playbook: installLogstash.yml
- import_playbook: installCurator.yml
- import_playbook: installKibana.yml - import_playbook: installKibana.yml
- import_playbook: installAPMserver.yml - import_playbook: installAPMserver.yml
- import_playbook: createElasticIndexes.yml - import_playbook: createElasticIndexes.yml

View File

@ -13,156 +13,112 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
actions: {% set action_items = [] -%}
1: {# Delete index loop #}
action: delete_indices {% for key in elastic_beat_retention_policy_hosts.keys() -%}
description: >- {% set delete_indices = {} -%}
Delete indices older than 60 days (based on index name), for logstash- {% set index_retention = hostvars[inventory_hostname]['elastic_' + key + '_retention'] -%}
prefixed indices. Ignore the error if the filter does not result in an {% set _ = delete_indices.update(
actionable list of indices (ignore_empty_list) and exit cleanly. {
options: 'action': 'delete_indices',
ignore_empty_list: True 'description': 'Prune indices for ' + key + ' after ' ~ ((index_retention | int) * 2) ~ ' days.',
disable_action: False 'options': {
filters: 'ignore_empty_list': true,
- filtertype: pattern 'disable_action': false
kind: prefix }
value: logstash- }
- filtertype: age )
source: name -%}
direction: older {# add the filter loop #}
timestring: '%Y.%m.%d' {% set filters = [] -%}
unit: days {% set _ = filters.append(
unit_count: {{ elastic_logstash_retention }} {
2: 'filtertype': 'pattern',
action: delete_indices 'kind': 'prefix',
description: >- 'value': key + '-'
Delete indices older than 10 days (based on index name), for apm- }
prefixed indices. Ignore the error if the filter does not result in an )
actionable list of indices (ignore_empty_list) and exit cleanly. -%}
options: {% set _ = filters.append(
ignore_empty_list: True {
disable_action: False 'filtertype': 'age',
filters: 'source': 'name',
- filtertype: pattern 'direction': 'older',
kind: prefix 'timestring': '%Y.%m.%d',
value: apm- 'unit': 'days',
- filtertype: age 'unit_count': (index_retention | int)
source: name }
direction: older )
timestring: '%Y.%m.%d' -%}
unit: days {% set _ = delete_indices.update({'filters': filters}) -%}
unit_count: {{ elastic_apm_retention }} {% set _ = action_items.append(delete_indices) -%}
3:
action: delete_indices {# Set shrink curator options #}
description: >- {% set shrink_indices = {} -%}
Delete indices older than 15 days (based on index name), for auditbeat- {% set _ = shrink_indices.update(
prefixed indices. Ignore the error if the filter does not result in an {
actionable list of indices (ignore_empty_list) and exit cleanly. 'action': 'shrink',
options: 'description': 'Shrink ' + key + ' indices older than ' ~ (index_retention | int) // 4 ~ ' days',
ignore_empty_list: True 'options': {
disable_action: False "disable_action": false,
filters: "ignore_empty_list": true,
- filtertype: pattern "shrink_node": "DETERMINISTIC",
kind: prefix "node_filters": {
value: auditbeat- "permit_masters": ((master_nodes | length) < (data_nodes | length)) | ternary(true, false),
- filtertype: age "exclude_nodes": (groups['kibana'] | map('extract', hostvars, 'ansible_host') | list)
source: name },
direction: older "number_of_shards": 1,
timestring: '%Y.%m.%d' "number_of_replicas": 1,
unit: days "shrink_suffix": '-shrink',
unit_count: {{ elastic_auditbeat_retention }} "copy_aliases": true,
4: "delete_after": true,
action: delete_indices "post_allocation": {
description: >- "allocation_type": "include",
Delete indices older than 15 days (based on index name), for filebeat- "key": "node_tag",
prefixed indices. Ignore the error if the filter does not result in an "value": "cold"
actionable list of indices (ignore_empty_list) and exit cleanly. },
options: "wait_for_active_shards": 1,
ignore_empty_list: True "extra_settings": {
disable_action: False "settings": {
filters: "index.codec": "best_compression"
- filtertype: pattern }
kind: prefix },
value: filebeat- "wait_for_completion": true,
- filtertype: age "wait_for_rebalance": true,
source: name "wait_interval": 9,
direction: older "max_wait": -1
timestring: '%Y.%m.%d' }
unit: days }
unit_count: {{ elastic_filebeat_retention }} )
5: -%}
action: delete_indices {% set filters = [] -%}
description: >- {% set _ = filters.append(
Delete indices older than 10 days (based on index name), for heartbeat- {
prefixed indices. Ignore the error if the filter does not result in an 'filtertype': 'pattern',
actionable list of indices (ignore_empty_list) and exit cleanly. 'kind': 'prefix',
options: 'value': key + '-'
ignore_empty_list: True }
disable_action: False )
filters: -%}
- filtertype: pattern {% set _ = filters.append(
kind: prefix {
value: heartbeat- 'filtertype': 'age',
- filtertype: age 'source': 'creation_date',
source: name 'direction': 'older',
direction: older 'unit': 'days',
timestring: '%Y.%m.%d' 'unit_count': (index_retention | int) // 4
unit: days }
unit_count: {{ elastic_heartbeat_retention }} )
6: -%}
action: delete_indices {% set _ = shrink_indices.update({'filters': filters}) -%}
description: >- {% set _ = action_items.append(shrink_indices) -%}
Delete indices older than 15 days (based on index name), for journalbeat- {% endfor -%}
prefixed indices. Ignore the error if the filter does not result in an
actionable list of indices (ignore_empty_list) and exit cleanly. {% set actions = {} -%}
options: {% for action_item in action_items -%}
ignore_empty_list: True {% set _ = actions.update({loop.index: action_item}) -%}
disable_action: False {% endfor -%}
filters:
- filtertype: pattern {# Render all actions #}
kind: prefix {% set curator_actions = {'actions': actions} -%}
value: journalbeat- {{ curator_actions | to_nice_yaml(indent=2) }}
- filtertype: age
source: name
direction: older
timestring: '%Y.%m.%d'
unit: days
unit_count: {{ elastic_journalbeat_retention }}
7:
action: delete_indices
description: >-
Delete indices older than 10 days (based on index name), for metricbeat-
prefixed indices. Ignore the error if the filter does not result in an
actionable list of indices (ignore_empty_list) and exit cleanly.
options:
ignore_empty_list: True
disable_action: False
filters:
- filtertype: pattern
kind: prefix
value: metricbeat-
- filtertype: age
source: name
direction: older
timestring: '%Y.%m.%d'
unit: days
unit_count: {{ elastic_metricbeat_retention }}
8:
action: delete_indices
description: >-
Delete indices older than 5 days (based on index name), for packetbeat-
prefixed indices. Ignore the error if the filter does not result in an
actionable list of indices (ignore_empty_list) and exit cleanly.
options:
ignore_empty_list: True
disable_action: False
filters:
- filtertype: pattern
kind: prefix
value: packetbeat-
- filtertype: age
source: name
direction: older
timestring: '%Y.%m.%d'
unit: days
unit_count: {{ elastic_packetbeat_retention }}

View File

@ -28,7 +28,7 @@ appender.rolling.strategy.action.basepath = ${sys:es.logs.base_path}
appender.rolling.strategy.action.condition.type = IfFileName appender.rolling.strategy.action.condition.type = IfFileName
appender.rolling.strategy.action.condition.glob = ${sys:es.logs.cluster_name}-* appender.rolling.strategy.action.condition.glob = ${sys:es.logs.cluster_name}-*
appender.rolling.strategy.action.condition.nested_condition.type = IfLastModified appender.rolling.strategy.action.condition.nested_condition.type = IfLastModified
appender.rolling.strategy.action.condition.nested_condition.age = {{ elastic_logstash_retention }}D appender.rolling.strategy.action.condition.nested_condition.age = {{ elastic_logstash_retention | default(1) }}D
rootLogger.level = info rootLogger.level = info

View File

@ -1011,8 +1011,11 @@ filebeat.prospectors:
# Make sure not file is defined twice as this can lead to unexpected behaviour. # Make sure not file is defined twice as this can lead to unexpected behaviour.
paths: paths:
- /var/log/beats/*.log - /var/log/beats/*.log
- /openstack/log/*/beats/*.log
- /var/log/curator/curator - /var/log/curator/curator
- /openstack/log/*/curator/curator
- /var/log/elasticsearch/*.log - /var/log/elasticsearch/*.log
- /openstack/log/*/elasticsearch/*.log
# Optional additional fields. These fields can be freely picked # Optional additional fields. These fields can be freely picked
# to add additional information to the crawled log files for filtering # to add additional information to the crawled log files for filtering

View File

@ -13,16 +13,39 @@ elastic_hap_port: 9201
cluster_name: openstack_elk cluster_name: openstack_elk
node_name: ${HOSTNAME} node_name: ${HOSTNAME}
# elastic curator vars ### Elastic curator variables
# all retention options are in days ## Default retention policy options. All retention options are in days.
elastic_logstash_retention: 14 # elastic_logstash_retention: 1
elastic_apm_retention: 3 # elastic_apm_retention: 1
elastic_auditbeat_retention: 7 # elastic_auditbeat_retention: 1
elastic_filebeat_retention: 7 # elastic_filebeat_retention: 1
elastic_heartbeat_retention: 7 # elastic_heartbeat_retention: 1
elastic_journalbeat_retention: 14 # elastic_journalbeat_retention: 1
elastic_metricbeat_retention: 3 # elastic_metricbeat_retention: 1
elastic_packetbeat_retention: 3 # elastic_packetbeat_retention: 1
# This is used to calculate the storage a beat could generate per node, per day.
# This constant is used as a multiplier. If the expected storage is larger than
# the actual available storage after the buffer is calculated the multiplier
# will be doubled there-by cutting the potential storage days in half.
elastic_beat_storage_constant: 512
## If any retention policy option is undefined a dynamic fact will be generated.
## Fact will be generated for the general retention using the storage constant
## per node, per index, where a given collector is expected to be deployed. The
## equation used will take the total available storage from the ES data nodes
## subtract 25% divided by the total number of data nodes. That is then divided
## by number of hosts assumed to be a beat target which is multiplied by the
## storage constant.
elastic_beat_retention_policy_hosts:
logstash: "{{ groups['elastic-logstash'] | default([null]) | length }}"
apm: "{{ groups['apm-server'] | default([null]) | length }}"
auditbeat: "{{ groups['hosts'] | default([null]) | length }}"
filebeat: "{{ groups['hosts'] | default([null]) | length }}"
heartbeat: "{{ groups['utility_all'] | default([null]) | length }}"
journalbeat: "{{ groups['all'] | default([null]) | length }}"
metricbeat: "{{ groups['all'] | default([null]) | length }}"
packetbeat: "{{ groups['hosts'] | default([null]) | length }}"
# This is the URL external services can use to communicate with the # This is the URL external services can use to communicate with the
# elasticsearch cluster. # elasticsearch cluster.