From 0a651b8cb863253736c6848528043fc32ca4c929 Mon Sep 17 00:00:00 2001 From: transcaffeine Date: Sat, 8 Jun 2024 17:03:59 +0200 Subject: [PATCH] feat(vmalert): add role for deployment in docker --- README.md | 3 ++ playbooks/vmalert.yml | 6 +++ roles/vmalert/README.md | 11 ++++++ roles/vmalert/defaults/main.yml | 57 +++++++++++++++++++++++++++ roles/vmalert/handlers/main.yml | 0 roles/vmalert/tasks/main.yml | 69 +++++++++++++++++++++++++++++++++ 6 files changed, 146 insertions(+) create mode 100644 playbooks/vmalert.yml create mode 100644 roles/vmalert/README.md create mode 100644 roles/vmalert/defaults/main.yml create mode 100644 roles/vmalert/handlers/main.yml create mode 100644 roles/vmalert/tasks/main.yml diff --git a/README.md b/README.md index de7a924..8b2017c 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,9 @@ metrics or alerting. - [`vmtsdb`](roles/vmtsdb/README.md): VictoriaMetrics time series database. +- [`vmalert`](roles/vmalert/README.md): VictoriaMetrics alerting and + ruling engine. + - [`postgres_exporter`](roles/postgres_exporter/README.md): Prometheus exporter for postgres databases, in a docker container. diff --git a/playbooks/vmalert.yml b/playbooks/vmalert.yml new file mode 100644 index 0000000..0dde51b --- /dev/null +++ b/playbooks/vmalert.yml @@ -0,0 +1,6 @@ +--- +- name: Install vmalert using docker + hosts: "{{ vmalert_hosts | default('vmalert') }}" + become: "{{ vmalert_become | default(false) }}" + roles: + - role: finallycoffee.observability.vmalert diff --git a/roles/vmalert/README.md b/roles/vmalert/README.md new file mode 100644 index 0000000..ff02a0a --- /dev/null +++ b/roles/vmalert/README.md @@ -0,0 +1,11 @@ +# `finallycoffee.observability.vmalert` ansible role + +## Description + +This role configures `vmalert` and runs it in the officially distributed docker container. + +The default configuration file for recording rules is `vmalert_recording_config` and the default file for alerts is `vmalert_alert_config`. To set rules in a prometheus-like syntax, supply them to the role using `vmalert_alerts` or `vmalert_records`. + +It is also possible to pass extra rule-files to load using `vmalert_rule_files`, though care must be taken to also mount them to the location in the container by populating `vmalert_container_volumes`. + +VM alert runs with the `envflag.enable` flag by default, so configuration to vmalert can be passed using `vmalert_container_env` with the syntax found on the official victoriametrics documentation. diff --git a/roles/vmalert/defaults/main.yml b/roles/vmalert/defaults/main.yml new file mode 100644 index 0000000..1506ae5 --- /dev/null +++ b/roles/vmalert/defaults/main.yml @@ -0,0 +1,57 @@ +--- +vmalert_state: present +vmalert_user: vmalert +vmalert_version: "1.87.5" +vmalert_base_path: "/opt/vmalert" +vmalert_config_path: "{{ vmalert_base_path }}/config" +vmalert_alert_config: "{{ vmalert_config_path }}/alerts.yml" +vmalert_recording_config: "{{ vmalert_config_path }}/records.yml" + +vmalert_alerts: {} +vmalert_records: {} +vmalert_rule_files: [] +vmalert_default_rule_files: + - "{{ vmalert_alert_config }}" + - "{{ vmalert_recording_config }}" +vmalert_merged_rule_files: >- + {{ vmalert_default_rule_files + vmalert_rule_files }} + +vmalert_container_image_server: docker.io +vmalert_container_image_namespace: "victoriametrics" +vmalert_container_image_container: "vmalert" +vmalert_container_image_name: >-2 + {{ + vmalert_container_image_server + + ((vmalert_container_image_namespace is defined) + | ternary('/' ~ vmalert_container_image_namespace, '')) + + '/' + vmalert_container_image_container + }} +#vmalert_container_image_tag: +vmalert_container_image: >-2 + {{ vmalert_container_image_name }}:{{ vmalert_container_image_tag | default('v' + vmalert_version, false) }} + +vmalert_user_id: >- + {{ (vmalert_user_info is defined and 'uid' in vmalert_user_info) | ternary(vmalert_user_info.uid, vmalert_user) }} +vmalert_group_id: >- + {{ (vmalert_user_info is defined and 'group' in vmalert_user_info) | ternary(vmalert_user_info.group, vmalert_user) }} +vmalert_container_user: "{{ vmalert_user_id }}" +vmalert_container_group: "{{ vmalert_group_id }}" +vmalert_container_name: "vmalert" +vmalert_container_command: [] +vmalert_container_default_command: + - "-enableTCP6" + - "-envflag.enable" +vmalert_container_merged_command: >- + {{ vmalert_container_default_command + (vmalert_container_command | default([], false)) }} +vmalert_container_env: {} +vmalert_container_default_env: + PATH: "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + rule: "{{ vmalert_merged_rule_files | join(',') }}" +vmalert_container_merged_env: >- + {{ vmalert_container_default_env | combine(vmalert_container_env) }} +vmalert_container_volumes: [] +vmalert_container_default_volumes: + - "{{ vmalert_config_path }}:{{ vmalert_config_path }}:z" +vmalert_container_merged_volumes: >- + {{ vmalert_container_default_volumes | combine(vmalert_container_volumes) }} +vmalert_container_restart_policy: "unless-stopped" diff --git a/roles/vmalert/handlers/main.yml b/roles/vmalert/handlers/main.yml new file mode 100644 index 0000000..e69de29 diff --git a/roles/vmalert/tasks/main.yml b/roles/vmalert/tasks/main.yml new file mode 100644 index 0000000..6d5c546 --- /dev/null +++ b/roles/vmalert/tasks/main.yml @@ -0,0 +1,69 @@ +--- +- name: Ensure user {{ vmalert_user }} is {{ vmalert_state }} + ansible.builtin.user: + name: "{{ vmalert_user }}" + state: present + system: true + create_home: false + register: vmalert_user_info + +- name: Ensure directories for vmalert are {{ vmalert_state }} + ansible.builtin.file: + path: "{{ item.path }}" + state: "{{ (vmalert_state == 'present') | ternary('directory', 'absent') }}" + owner: "{{ item.owner | default(vmalert_user_id) }}" + group: "{{ item.group | default(vmalert_group_id) }}" + mode: "{{ item.mode | default('0775') }}" + loop: + - path: "{{ vmalert_base_path }}" + - path: "{{ vmalert_config_path }}" + mode: "0755" + loop_control: + label: "{{ item.path }}" + +- name: Ensure alert configuration is present + ansible.builtin.copy: + dest: "{{ vmalert_alert_config }}" + content: | + {{ ({ 'groups': vmalert_alerts}) + | to_nice_yaml(indent=2, width=1024, default_style='"') }} + owner: "{{ item.owner | default(vmalert_user_id) }}" + group: "{{ item.group | default(vmalert_group_id) }}" + mode: "{{ item.mode | default('0775') }}" + when: vmalert_state == 'present' + +- name: Ensure recording rule configuration is present + ansible.builtin.copy: + dest: "{{ vmalert_recording_config }}" + content: | + {{ ({ 'groups': vmalert_records}) + | to_nice_yaml(indent=2, width=1024, default_style='"') }} + owner: "{{ item.owner | default(vmalert_user_id) }}" + group: "{{ item.group | default(vmalert_group_id) }}" + mode: "{{ item.mode | default('0775') }}" + when: vmalert_state == 'present' + +- name: Ensure container image {{ vmalert_container_image }} is {{ vmalert_state }} + community.docker.docker_image: + name: "{{ vmalert_container_image }}" + state: "{{ vmalert_state }}" + source: "{{ (vmalert_state == 'present') | ternary('pull', omit) }}" + force_source: >-2 + {{ (vmalert_container_image == 'present') | ternary(vmalert_container_image_tag, omit) }} + +- name: Ensure vmalert container is {{ vmalert_state }} + community.docker.docker_container: + name: "{{ vmalert_container_name}}" + image: "{{ vmalert_container_image }}" + env: "{{ vmalert_container_merged_env }}" + user: "{{ vmalert_container_user }}" + ports: "{{ vmalert_container_ports | default(omit) }}" + groups: "{{ vmalert_container_group }}" + labels: "{{ vmalert_container_labels | default(omit) }}" + volumes: "{{ vmalert_container_merged_volumes }}" + command: "{{ vmalert_container_merged_command }}" + networks: "{{ vmalert_container_networks | default(omit) }}" + etc_hosts: "{{ vmalert_container_etc_hosts | default(omit )}}" + purge_networks: "{{ vmalert_container_purge_networks | default(omit) }}" + restart_policy: "{{ vmalert_container_restart_policy | default(omit) }}" + state: "{{ (vmalert_state == 'present') | ternary('started', 'absent') }}"