diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 814be8c..e00435f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,3 +24,4 @@ jobs: make init-venv make molecule-converge + make molecule-converge-integration diff --git a/Makefile b/Makefile index e03ce94..e38d82f 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,29 @@ molecule-converge-vmalert: make activate-venv; \ cd roles/vmalert && molecule converge -s docker -molecule-converge: molecule-converge-single molecule-converge-vmagent molecule-converge-vmalert +molecule-converge-vminsert: + make activate-venv; \ + cd roles/vminsert && molecule converge + +molecule-converge-vmstorage: + make activate-venv; \ + cd roles/vmstorage && molecule converge + +molecule-converge-vmselect: + make activate-venv; \ + cd roles/vmselect && molecule converge + +molecule-converge-vmauth: + make activate-venv; \ + cd roles/vmauth && molecule converge + +molecule-converge-cluster-integration: + make activate-venv; \ + cd playbooks/ && molecule converge -s cluster + +molecule-converge: molecule-converge-single molecule-converge-vmagent molecule-converge-vmalert molecule-converge-vminsert molecule-converge-vmstorage molecule-converge-vmselect molecule-converge-vmauth + +molecule-converge-integration: molecule-converge-cluster-integration molecule-destroy-single: make activate-venv; \ @@ -38,4 +60,26 @@ molecule-destroy-vmalert: make activate-venv; \ cd roles/vmalert && molecule destroy -s docker -molecule-destroy: molecule-destroy-single molecule-destroy-vmagent molecule-destroy-vmalert +molecule-destroy-vminsert: + make activate-venv; \ + cd roles/vminsert && molecule destroy + +molecule-destroy-vmstorage: + make activate-venv; \ + cd roles/vmstorage && molecule destroy + +molecule-destroy-vmselect: + make activate-venv; \ + cd roles/vmselect && molecule destroy + +molecule-destroy-vmauth: + make activate-venv; \ + cd roles/vmauth && molecule destroy + +molecule-destroy-cluster-integration: + make activate-venv; \ + cd playbooks/ && molecule destroy -s cluster + +molecule-destroy: molecule-destroy-single molecule-destroy-vmagent molecule-destroy-vmalert molecule-destroy-vminsert molecule-destroy-vmstorage molecule-destroy-vmselect molecule-destroy-vmauth molecule-destroy-cluster-integration + +molecule-destroy-integration: molecule-destroy-cluster-integration diff --git a/README.md b/README.md index c29423c..287cb77 100644 --- a/README.md +++ b/README.md @@ -16,22 +16,67 @@ ansible-galaxy collection install victoriametrics.cluster Collection includes the following roles: -- [docker](./roles/docker) - role for docker installation -- [load_balancer](./roles/load_balancer) - nginx setup for load balancing between select and insert nodes -- [cluster](./roles/cluster) - installs and configures VictoriaMetrics cluster running in docker - [single](./roles/single) - installs and configures VictoriaMetrics single node - [vmagent](./roles/vmagent) - installs and configures `vmagent` - [vmalert](./roles/vmalert) - installs and configures `vmalert` +- [vmselect](./roles/vmselect) - installs and configures `vmselect` +- [vmstorage](./roles/vmstorage) - installs and configures `vmstorage` +- [vminsert](./roles/vminsert) - installs and configures `vminsert` +- [vmauth](./roles/vmauth) - installs and configures `vmauth` + +See [cluster](playbooks/cluster.yml) and [single](playbooks/single.yml) playbooks for examples of how to use these +roles. + +Deprecated roles: + +- [docker](./roles/docker) - role for docker installation +- [load_balancer](./roles/load_balancer) - nginx setup for load balancing between select and insert nodes +- [cluster](./roles/cluster) - installs and configures VictoriaMetrics cluster running in docker + +These roles are deprecated in favor of roles for each component. They are still available in the collection, but will be +removed in future releases. +Note that per-component roles are using binary releases of VictoriaMetrics, while cluster role is using docker images. + +## Cluster deployment + +Cluster deployment example is available in [playbooks/cluster.yml](./playbooks/cluster.yml). +The playbook deploys VictoriaMetrics cluster and vmauth to act as a load balancer and authentication proxy. +See [inventory](./inventory_example/cluster-inventory) for example of inventory file. + +Here is a diagram of the cluster deployment: + +```mermaid +graph TD + A[vmauth] -- /select/* --> B[vmselect-1] + A[vmauth] -- /select/* --> B2[vmselect-2] + A -- /insert/* --> C[vminsert-1] + A -- /insert/* --> C2[vminsert-2] + C --> D[vmstorage-1] + C --> D2[vmstorage-2] + C --> D3[vmstorage-3] + C2 --> D[vmstorage-1] + C2 --> D2[vmstorage-2] + C2 --> D3[vmstorage-3] + B --> D[vmstorage-1] + B --> D2[vmstorage-1] + B --> D3[vmstorage-1] + B2 --> D[vmstorage-1] + B2 --> D2[vmstorage-1] + B2 --> D3[vmstorage-1] +``` -# TODO -- add non-docker environment -- fix hardcoded ports +It's also possible to use molecule scenario to create a local cluster for testing. +See [molecule](./playbooks/molecule/cluster) directory for details. The scenario uses docker as a driver and +sets up a container for each component. The scenario can be deployed by +using `make molecule-converge-cluster-integration` command. # Development In order to set up development environment, you need to have `docker`, `python` and `make` installed. -Run `make init-venv` to create virtual environment and install required packages for linting and testing with [molecule](https://ansible.readthedocs.io/projects/molecule). +Run `make init-venv` to create virtual environment and install required packages for linting and testing +with [molecule](https://ansible.readthedocs.io/projects/molecule). -Please, note that [cluster](./roles/cluster) role is tested with `vagrant` and `libvirt` provider and requires `vagrant` [to be installed](https://www.vagrantup.com/downloads). +Please, note that [cluster](./roles/cluster) role is tested with `vagrant` and `libvirt` provider and +requires `vagrant` [to be installed](https://www.vagrantup.com/downloads). Refer to [Makefile](./Makefile) for available commands for linting and molecule testing. diff --git a/inventory_example/cluster-inventory b/inventory_example/cluster-inventory index 1bcebcf..6670f83 100644 --- a/inventory_example/cluster-inventory +++ b/inventory_example/cluster-inventory @@ -1,30 +1,22 @@ -[victoria_storage] -victoria-storage-01 -victoria-storage-02 -victoria-storage-03 +[vmstorage] +vmstorage-01 +vmstorage-02 +vmstorage-03 -[victoria_insert] -victoria-insert-01 -victoria-insert-02 -victoria-insert-03 +[vminsert] +vminsert-01 +vminsert-02 +vminsert-03 -[victoria_select] -victoria-select-01 -victoria-select-02 - -[victoria_storage:vars] -vm_role=victoria-storage - -[victoria_insert:vars] -vm_role=victoria-insert - -[victoria_select:vars] -vm_role=victoria-select - -[load-balancer] -load-balancer-01 +[vmselect] +vmselect-01 +vmselect-02 [victoria_cluster:children] -victoria_select -victoria_insert -victoria_storage +vmselect +vminsert +vmstorage + +[vmauth] +vmauth-01 +vmauth-02 diff --git a/inventory_example/group_vars/victoria_cluster.yml b/inventory_example/group_vars/victoria_cluster.yml deleted file mode 100644 index 776121f..0000000 --- a/inventory_example/group_vars/victoria_cluster.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -vminsert_replication_factor: 2 -vmstorage_group: victoria_cluster diff --git a/playbooks/cluster.yml b/playbooks/cluster.yml new file mode 100644 index 0000000..cd7ffdf --- /dev/null +++ b/playbooks/cluster.yml @@ -0,0 +1,50 @@ +--- +- name: Setup storage + become: true + hosts: vmstorage + roles: + - vmstorage + +- name: Setup vmselect + become: true + hosts: vmselect + vars: + vmselect_cache_dir: "/var/lib/vmselect" + vmselect_config: + cacheDataPath: "/var/lib/vmselect" + storageNode: "{{ groups['vmstorage'] | join(',') }}" + roles: + - vmselect + +- name: Setup vminsert + become: true + hosts: vminsert + vars: + vminsert_config: + storageNode: "{{ groups['vmstorage'] | join(',') }}" + roles: + - vminsert + +- name: Setup vmauth + become: true + hosts: vmauth + vars: + # See: https://docs.victoriametrics.com/vmauth/#load-balancer-for-victoriametrics-cluster + vmauth_auth_config: |- + unauthorized_user: + url_map: + - src_paths: + - "/insert/.+" + url_prefix: + {% for insert in groups['vminsert'] %} + - "http://{{ insert }}:8480/" + {% endfor %} + - src_paths: + - "/select/.+" + url_prefix: + {% for select in groups['vmselect'] %} + - "http://{{ select }}:8481/" + {% endfor %} + + roles: + - vmauth diff --git a/playbooks/molecule/cluster/converge.yml b/playbooks/molecule/cluster/converge.yml new file mode 100644 index 0000000..b89a031 --- /dev/null +++ b/playbooks/molecule/cluster/converge.yml @@ -0,0 +1,50 @@ +--- +- name: Setup storage + become: true + hosts: vmstorage + roles: + - vmstorage + +- name: Setup vmselect + become: true + hosts: vmselect + vars: + vmselect_cache_dir: "/var/lib/vmselect" + vmselect_config: + cacheDataPath: "/var/lib/vmselect" + storageNode: "{{ groups['vmstorage'] | join(',') }}" + roles: + - vmselect + +- name: Setup vminsert + become: true + hosts: vminsert + vars: + vminsert_config: + storageNode: "{{ groups['vmstorage'] | join(',') }}" + roles: + - vminsert +# +- name: Setup vmauth + become: true + hosts: vmauth + vars: + # See: https://docs.victoriametrics.com/vmauth/#load-balancer-for-victoriametrics-cluster + vmauth_auth_config: |- + unauthorized_user: + url_map: + - src_paths: + - "/insert/.+" + url_prefix: + {% for insert in groups['vminsert'] %} + - "http://{{ insert }}:8480/" + {% endfor %} + - src_paths: + - "/select/.+" + url_prefix: + {% for select in groups['vmselect'] %} + - "http://{{ select }}:8481/" + {% endfor %} + + roles: + - vmauth diff --git a/playbooks/molecule/cluster/molecule.yml b/playbooks/molecule/cluster/molecule.yml new file mode 100644 index 0000000..9f22d65 --- /dev/null +++ b/playbooks/molecule/cluster/molecule.yml @@ -0,0 +1,131 @@ +--- +lint: | + yamllint . + ansible-lint . + + +dependency: + name: galaxy +driver: + name: docker + +platforms: + - name: vmstorage-1 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + networks: + - name: cluster + groups: + - vmstorage + - name: vmstorage-2 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + networks: + - name: cluster + groups: + - vmstorage + - name: vmstorage-3 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + networks: + - name: cluster + groups: + - vmstorage + + - name: vminsert-1 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + networks: + - name: cluster + groups: + - vminsert + - name: vminsert-2 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + networks: + - name: cluster + groups: + - vminsert + + - name: vmselect-1 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + networks: + - name: cluster + groups: + - vmselect + - name: vmselect-2 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + networks: + - name: cluster + groups: + - vmselect + + - name: vmauth-1 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + networks: + - name: cluster + groups: + - vmauth + - name: vmauth-2 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + networks: + - name: cluster + groups: + - vmauth + +provisioner: + name: ansible + env: + ANSIBLE_ROLES_PATH: "../../../roles" + ANSIBLE_CONFIG: ../../../ansible.cfg +verifier: + name: ansible diff --git a/playbooks/molecule/cluster/tests/test_default.yml b/playbooks/molecule/cluster/tests/test_default.yml new file mode 100644 index 0000000..a125356 --- /dev/null +++ b/playbooks/molecule/cluster/tests/test_default.yml @@ -0,0 +1,4 @@ +service: + "vmauth": + enabled: true + running: true diff --git a/playbooks/molecule/cluster/verify.yml b/playbooks/molecule/cluster/verify.yml new file mode 100644 index 0000000..1a1bce3 --- /dev/null +++ b/playbooks/molecule/cluster/verify.yml @@ -0,0 +1,93 @@ +--- +# Molecule Goss Tests + +- name: Verify + hosts: all + become: true + vars: + goss_version: v0.3.10 + goss_arch: amd64 + goss_bin: /usr/local/bin/goss + goss_sha256sum: 150f25495ca0d1d4fd2ef8d0e750dbd767a15e9a522505f99b61dd1dd40a76d4 + goss_url: "https://github.com/aelsabbahy/goss/releases/download/{{ goss_version }}/goss-linux-{{ goss_arch }}" + goss_test_directory: /tmp/molecule/goss + goss_format: documentation + tasks: + - name: Download and install Goss + ansible.builtin.get_url: + url: "{{ goss_url }}" + dest: "{{ goss_bin }}" + sha256sum: "{{ goss_sha256sum }}" # noqa: args[module] + mode: "u=rwx,go=rx" + register: download_goss + until: download_goss is succeeded + retries: 3 + + - name: Create Molecule directory for test files + ansible.builtin.file: + path: "{{ goss_test_directory }}" + state: directory + mode: "0755" + + - name: Find Goss tests on localhost + ansible.builtin.find: + paths: "{{ lookup('env', 'MOLECULE_VERIFIER_TEST_DIRECTORY') }}" + patterns: + - "test[-.\\w]*.yml" + - "test_host_{{ ansible_hostname }}[-.\\w]*.yml" + excludes: + - "test_host_(?!{{ ansible_hostname }})[-.\\w]*.yml" + use_regex: true + delegate_to: localhost + register: test_files + changed_when: false + become: false + + - name: Debug + ansible.builtin.debug: + msg: "{{ test_files.files }}" + verbosity: 3 + + - name: Copy Goss tests to remote + ansible.builtin.copy: + src: "{{ item.path }}" + dest: "{{ goss_test_directory }}/{{ item.path | basename }}" + mode: "0644" + with_items: + - "{{ test_files.files }}" + loop_control: + label: "{{ item.path | basename }}" + + - name: Register test files + ansible.builtin.find: + paths: + - "{{ goss_test_directory }}" + patterns: + - "test_*.yml" + register: test_files + + - name: Run verify + when: test_files is succeeded + block: + - name: Execute Goss tests # noqa: no-changed-when + ansible.builtin.command: "{{ goss_bin }} -g {{ item }} validate --format {{ goss_format }}" + register: test_results + with_items: "{{ test_files.files | map(attribute='path') | list }}" + loop_control: + label: "{{ item | basename }}" + failed_when: false + + - name: Display details about the Goss results + ansible.builtin.debug: + msg: "{{ item.stdout_lines }}" + with_items: "{{ test_results.results }}" + loop_control: + label: "{{ item[item.ansible_loop_var] | basename }}" + + - name: Fail when tests fail + ansible.builtin.fail: + msg: "Goss failed to validate" + when: item.rc != 0 + with_items: "{{ test_results.results }}" + loop_control: + label: "{{ item[item.ansible_loop_var] | basename }}" diff --git a/playbooks/monitoring.yml b/playbooks/monitoring.yml deleted file mode 100644 index 8fcde61..0000000 --- a/playbooks/monitoring.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -- name: Ensure docker - become: true - hosts: cluster - roles: [ docker ] - -- name: Ensure victoria_storage - become: true - hosts: cluster - roles: [ cluster ] - vars: { vm_role: victoria-storage } - tags: [ 'vm_storage', 'cluster' ] - -- name: Ensure victoria_select - become: true - hosts: cluster - roles: [ cluster ] - vars: { vm_role: victoria-select } - tags: [ 'vm_select', 'cluster' ] - -- name: Ensure victoria_insert - become: true - hosts: cluster - roles: [ cluster ] - vars: { vm_role: victoria-insert } - tags: [ 'vm_insert', 'cluster' ] - -- name: Ensure load_balancer - become: true - hosts: load_balancer - roles: [ load_balancer ] diff --git a/roles/cluster/README.md b/roles/cluster/README.md index 40867a1..18efd79 100644 --- a/roles/cluster/README.md +++ b/roles/cluster/README.md @@ -4,6 +4,8 @@ Installs and configures VictoriaMetrics cluster running in docker. Containers are managed as systemd units. +*Deprecation notice*: this role is deprecated in favor of roles for each component. It is still available in the collection, but will be removed in future releases. + ## Requirements - Docker diff --git a/roles/load_balancer/README.md b/roles/load_balancer/README.md index 463810b..c3d9803 100644 --- a/roles/load_balancer/README.md +++ b/roles/load_balancer/README.md @@ -4,6 +4,8 @@ Configures load balancing between `vmselect` and `vminsert` instances. Hosts are discovered from ansible inventory groups, naming configured by the following vars `vminsert_group` and `vmselect_group` +*Deprecation notice*: this role is deprecated in favor vmauth. It is still available in the collection, but will be removed in future releases. + ## Parameters The following table lists the configurable parameters of the playbook and their default values. diff --git a/roles/single/tasks/install.yml b/roles/single/tasks/install.yml index d21a4e3..ca8d642 100644 --- a/roles/single/tasks/install.yml +++ b/roles/single/tasks/install.yml @@ -16,13 +16,13 @@ createhome: false when: victoriametrics_system_user != "root" -- name: Ensure existense of /usr/local/bin +- name: Ensure existence of /usr/local/bin ansible.builtin.file: path: /usr/local/bin state: directory mode: 0755 -- name: Ensure existense of VictoriaMetrics storage directory +- name: Ensure existence of VictoriaMetrics storage directory ansible.builtin.file: path: "{{ victoriametrics_data_dir }}" state: directory diff --git a/roles/vmagent/tasks/install.yml b/roles/vmagent/tasks/install.yml index f773da7..94f9185 100644 --- a/roles/vmagent/tasks/install.yml +++ b/roles/vmagent/tasks/install.yml @@ -16,7 +16,7 @@ createhome: false when: vmagent_system_user != "root" -- name: Ensure existense of /usr/local/bin +- name: Ensure existence of /usr/local/bin ansible.builtin.file: path: /usr/local/bin state: directory diff --git a/roles/vmalert/tasks/install.yml b/roles/vmalert/tasks/install.yml index 000a1cf..ea0fcd4 100644 --- a/roles/vmalert/tasks/install.yml +++ b/roles/vmalert/tasks/install.yml @@ -16,7 +16,7 @@ createhome: false when: vic_vm_alert_system_user != "root" -- name: Ensure existense of /usr/local/bin +- name: Ensure existence of /usr/local/bin ansible.builtin.file: path: /usr/local/bin state: directory diff --git a/roles/vmauth/README.md b/roles/vmauth/README.md new file mode 100644 index 0000000..2838391 --- /dev/null +++ b/roles/vmauth/README.md @@ -0,0 +1,27 @@ +# vmauth + +Role to install and configure vmauth. Installs by using binary from Github releases. + +## Parameters + +The following table lists the configurable parameters of the roles and their default values. + +| Parameter | Description | Default | +|------------------------------------|----------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------| +| vmauth_repo_url | Repository to use for download. | `https://github.com/VictoriaMetrics/VictoriaMetrics` | +| vmauth_version | vmauth version | `v1.99.0` | +| vmauth_download_url | URL to download archive | `{{ vmauth_repo_url }}/releases/download/{{ vmauth_version }}/vmutils-{{ vmauth_version }}.tar.gz` | +| vmauth_system_user | User to run vmauth | `victoriametrics` | +| vmauth_system_group | Group for user of vmauth | `{{ vmauth_system_user }}` | +| vmauth_service_state | Default state of systemd service | `started` | +| vmauth_service_enabled | Whether to enable systemd service | `true` | +| vmauth_config_dir | Location for config files | `/opt/victoriametrics-vmauth` | +| vmauth_bin_dir | Location for binary file | `/usr/local/bin` | +| vmauth_config | Config parameters to be passed via environment variables | `{}` | +| vmauth_exec_start_post | Post start hook for systemd unit | `""` | +| vmauth_exec_stop | Stop command for systemd unit | `""` | +| vmauth_auth_config | vmauth authentication config. | See [defaults.yml](./defaults/main.yml) | +| vmauth_install_download_to_control | Whether use control or remote host to download installation archive | `true` | +| vmauth_systemd_protect_home | Configure Systemd home protection. See See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome= | `"yes"` | +| vm_proxy_http | Sets environment for downloading archive | `""` | +| vm_proxy_https | Sets environment for downloading archive | `""` | diff --git a/roles/vmauth/defaults/main.yml b/roles/vmauth/defaults/main.yml new file mode 100644 index 0000000..2282ed7 --- /dev/null +++ b/roles/vmauth/defaults/main.yml @@ -0,0 +1,33 @@ +--- +vmauth_version: "v1.99.0" + +vmauth_repo_url: "https://github.com/VictoriaMetrics/VictoriaMetrics" +vmauth_platform: "{% if vmauth_version.replace('v', '') is version('1.79.0', '>=') %}-linux{% endif %}" +vmauth_download_url: "{{ vmauth_repo_url }}/releases/download/{{ vmauth_version }}/vmutils{{ vmauth_platform }}-{{ go_arch }}-{{ vmauth_version }}.tar.gz" + +vmauth_system_user: "victoriametrics" +vmauth_system_group: "{{ vmauth_system_user }}" + +vmauth_service_state: started +vmauth_service_enabled: true +vmauth_exec_start_post: "" +vmauth_exec_stop: "" + +vmauth_config_dir: "/opt/victoriametrics-vmauth" +vmauth_bin_dir: /usr/local/bin + +vmauth_config: {} + +# See: https://docs.victoriametrics.com/vmauth/#use-cases +vmauth_auth_config: |- + unauthorized_user: + url_prefix: "http://vmselect/" + +vmauth_install_download_to_control: false + +vm_proxy_http: "" +vm_proxy_https: "" + +# See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome= +# Available options: 'yes', 'read-only', 'tmpfs' +vmauth_systemd_protect_home: "yes" diff --git a/roles/vmauth/handlers/main.yml b/roles/vmauth/handlers/main.yml new file mode 100644 index 0000000..a901497 --- /dev/null +++ b/roles/vmauth/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart vmauth service + ansible.builtin.systemd: + daemon_reload: true + name: vmauth + state: restarted diff --git a/roles/vmauth/meta/main.yml b/roles/vmauth/meta/main.yml new file mode 100644 index 0000000..fffeaa2 --- /dev/null +++ b/roles/vmauth/meta/main.yml @@ -0,0 +1 @@ +dependencies: [] # noqa: meta-no-info diff --git a/roles/vmauth/molecule/default/converge.yml b/roles/vmauth/molecule/default/converge.yml new file mode 100644 index 0000000..0df0b7a --- /dev/null +++ b/roles/vmauth/molecule/default/converge.yml @@ -0,0 +1,8 @@ +--- +- name: Converge + hosts: all + become: yes + tasks: + - name: "Include vmauth" + ansible.builtin.include_role: + name: "vmauth" diff --git a/roles/vmauth/molecule/default/molecule.yml b/roles/vmauth/molecule/default/molecule.yml new file mode 100644 index 0000000..3b27c3a --- /dev/null +++ b/roles/vmauth/molecule/default/molecule.yml @@ -0,0 +1,25 @@ +--- +lint: | + yamllint . + ansible-lint . + + +dependency: + name: galaxy +driver: + name: docker + +platforms: + - name: vmauth-debian11 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + +provisioner: + name: ansible +verifier: + name: ansible diff --git a/roles/vmauth/molecule/default/tests/test_default.yml b/roles/vmauth/molecule/default/tests/test_default.yml new file mode 100644 index 0000000..a125356 --- /dev/null +++ b/roles/vmauth/molecule/default/tests/test_default.yml @@ -0,0 +1,4 @@ +service: + "vmauth": + enabled: true + running: true diff --git a/roles/vmauth/molecule/default/verify.yml b/roles/vmauth/molecule/default/verify.yml new file mode 100644 index 0000000..1a1bce3 --- /dev/null +++ b/roles/vmauth/molecule/default/verify.yml @@ -0,0 +1,93 @@ +--- +# Molecule Goss Tests + +- name: Verify + hosts: all + become: true + vars: + goss_version: v0.3.10 + goss_arch: amd64 + goss_bin: /usr/local/bin/goss + goss_sha256sum: 150f25495ca0d1d4fd2ef8d0e750dbd767a15e9a522505f99b61dd1dd40a76d4 + goss_url: "https://github.com/aelsabbahy/goss/releases/download/{{ goss_version }}/goss-linux-{{ goss_arch }}" + goss_test_directory: /tmp/molecule/goss + goss_format: documentation + tasks: + - name: Download and install Goss + ansible.builtin.get_url: + url: "{{ goss_url }}" + dest: "{{ goss_bin }}" + sha256sum: "{{ goss_sha256sum }}" # noqa: args[module] + mode: "u=rwx,go=rx" + register: download_goss + until: download_goss is succeeded + retries: 3 + + - name: Create Molecule directory for test files + ansible.builtin.file: + path: "{{ goss_test_directory }}" + state: directory + mode: "0755" + + - name: Find Goss tests on localhost + ansible.builtin.find: + paths: "{{ lookup('env', 'MOLECULE_VERIFIER_TEST_DIRECTORY') }}" + patterns: + - "test[-.\\w]*.yml" + - "test_host_{{ ansible_hostname }}[-.\\w]*.yml" + excludes: + - "test_host_(?!{{ ansible_hostname }})[-.\\w]*.yml" + use_regex: true + delegate_to: localhost + register: test_files + changed_when: false + become: false + + - name: Debug + ansible.builtin.debug: + msg: "{{ test_files.files }}" + verbosity: 3 + + - name: Copy Goss tests to remote + ansible.builtin.copy: + src: "{{ item.path }}" + dest: "{{ goss_test_directory }}/{{ item.path | basename }}" + mode: "0644" + with_items: + - "{{ test_files.files }}" + loop_control: + label: "{{ item.path | basename }}" + + - name: Register test files + ansible.builtin.find: + paths: + - "{{ goss_test_directory }}" + patterns: + - "test_*.yml" + register: test_files + + - name: Run verify + when: test_files is succeeded + block: + - name: Execute Goss tests # noqa: no-changed-when + ansible.builtin.command: "{{ goss_bin }} -g {{ item }} validate --format {{ goss_format }}" + register: test_results + with_items: "{{ test_files.files | map(attribute='path') | list }}" + loop_control: + label: "{{ item | basename }}" + failed_when: false + + - name: Display details about the Goss results + ansible.builtin.debug: + msg: "{{ item.stdout_lines }}" + with_items: "{{ test_results.results }}" + loop_control: + label: "{{ item[item.ansible_loop_var] | basename }}" + + - name: Fail when tests fail + ansible.builtin.fail: + msg: "Goss failed to validate" + when: item.rc != 0 + with_items: "{{ test_results.results }}" + loop_control: + label: "{{ item[item.ansible_loop_var] | basename }}" diff --git a/roles/vmauth/tasks/configure.yml b/roles/vmauth/tasks/configure.yml new file mode 100644 index 0000000..e47da56 --- /dev/null +++ b/roles/vmauth/tasks/configure.yml @@ -0,0 +1,43 @@ +--- +- name: "Systemd | Copy vmauth systemd unit file" + ansible.builtin.template: + src: vmauth.service.j2 + dest: /etc/systemd/system/vmauth.service + owner: root + group: root + mode: 0644 + notify: Restart vmauth service + +- name: "Systemd | ensure vmauth service is enabled" # noqa: no-handler + become: true + ansible.builtin.systemd: + name: vmauth + enabled: true + +- name: Prepare configuration dir + ansible.builtin.file: + state: directory + path: "{{ vmauth_config_dir }}" + mode: 0751 + owner: "{{ vmauth_system_user }}" + group: "{{ vmauth_system_group }}" + +- name: Template auth config + ansible.builtin.template: + src: auth.yaml.j2 + dest: "{{ vmauth_config_dir }}/auth.yaml" + owner: "{{ vmauth_system_user }}" + group: "{{ vmauth_system_group }}" + mode: 0644 + when: + - vmauth_auth_config != "" + notify: Restart vmauth service + +- name: Setup environment file + ansible.builtin.template: + dest: "{{ vmauth_config_dir }}/vmauth.conf" + src: "vmauth.conf.j2" + owner: "{{ vmauth_system_user }}" + group: "{{ vmauth_system_group }}" + mode: 0644 + notify: Restart vmauth service diff --git a/roles/vmauth/tasks/install.yml b/roles/vmauth/tasks/install.yml new file mode 100644 index 0000000..663ea7b --- /dev/null +++ b/roles/vmauth/tasks/install.yml @@ -0,0 +1,98 @@ +--- +- name: Create vmauth system group + ansible.builtin.group: + name: "{{ vmauth_system_group }}" + state: present + system: true + when: vmauth_system_group != "root" + +- name: Create vmauth system user + ansible.builtin.user: + name: "{{ vmauth_system_user }}" + groups: "{{ vmauth_system_group }}" + append: true + shell: /usr/sbin/nologin + system: true + createhome: false + when: vmauth_system_user != "root" + +- name: Ensure existence of /usr/local/bin + ansible.builtin.file: + path: /usr/local/bin + state: directory + mode: 0755 + +- name: Delete existing vmauth version if it's different. + ansible.builtin.file: + path: /usr/local/bin/vmauth-prod + state: absent + when: + - vmauth_is_installed.stat.exists | bool + - vmauth_version not in vmauth_current_version.stdout + +- name: Install via control host + when: vmauth_install_download_to_control + block: + - name: Download and unarchive vmauth release binary + environment: + http_proxy: "{{ vm_proxy_http }}" + https_proxy: "{{ vm_proxy_https }}" + ansible.builtin.unarchive: + src: "{{ vmauth_download_url }}" + dest: /tmp + remote_src: yes + delegate_to: localhost + become: no + when: + - not ansible_check_mode + - not vmauth_is_installed.stat.exists or + vmauth_version not in vmauth_current_version.stdout + + - name: Copy vmauth binary to target host + notify: Restart vmauth service + ansible.builtin.copy: + src: /tmp/vmauth-prod + dest: /tmp/vmauth-prod + mode: 0751 + owner: "{{ vmauth_system_user }}" + group: "{{ vmauth_system_group }}" + when: + - not ansible_check_mode + - not vmauth_is_installed.stat.exists or + vmauth_version not in vmauth_current_version.stdout + + - name: Replace vmauth binary at target dir # noqa: no-changed-when + notify: Restart vmauth service + ansible.builtin.shell: | + mv /tmp/vmauth-prod /usr/local/bin/vmauth-prod + when: + - not ansible_check_mode + - not vmauth_is_installed.stat.exists or + vmauth_version not in vmauth_current_version.stdout + +- name: Install directly to target host + when: not vmauth_install_download_to_control + block: + - name: Download and unarchive vmauth release binary + environment: + http_proxy: "{{ vm_proxy_http }}" + https_proxy: "{{ vm_proxy_https }}" + ansible.builtin.unarchive: + src: "{{ vmauth_download_url }}" + dest: /tmp + remote_src: yes + when: + - not ansible_check_mode + - not vmauth_is_installed.stat.exists or + vmauth_version not in vmauth_current_version.stdout + + - name: Replace vmauth binary at target dir # noqa: no-changed-when + notify: Restart vmauth service + ansible.builtin.shell: | + mv /tmp/vmauth-prod /usr/local/bin/vmauth-prod + chmod 0751 /usr/local/bin/vmauth-prod + chown {{ vmauth_system_user }}:{{ vmauth_system_group }} /usr/local/bin/vmauth-prod + when: + - not ansible_check_mode + - not vmauth_is_installed.stat.exists or + vmauth_version not in vmauth_current_version.stdout diff --git a/roles/vmauth/tasks/main.yml b/roles/vmauth/tasks/main.yml new file mode 100644 index 0000000..f9ae994 --- /dev/null +++ b/roles/vmauth/tasks/main.yml @@ -0,0 +1,7 @@ +--- +- name: Preinstall checks + ansible.builtin.import_tasks: preinstall.yml +- name: Install + ansible.builtin.import_tasks: install.yml +- name: Configure + ansible.builtin.import_tasks: configure.yml diff --git a/roles/vmauth/tasks/preinstall.yml b/roles/vmauth/tasks/preinstall.yml new file mode 100644 index 0000000..4679022 --- /dev/null +++ b/roles/vmauth/tasks/preinstall.yml @@ -0,0 +1,32 @@ +--- +- name: Assert usage of systemd or upstart as an init system + ansible.builtin.assert: + that: ansible_service_mgr == 'systemd' + msg: "This role only works with systemd" + +- name: Get systemd version + ansible.builtin.command: systemctl --version + changed_when: false + check_mode: false + register: __systemd_version + when: ansible_service_mgr == 'systemd' + +- name: Set systemd version fact + ansible.builtin.set_fact: + vmauth_systemd_version: "{{ __systemd_version.stdout_lines[0].split(' ')[-1] }}" + when: ansible_service_mgr == 'systemd' + +- name: Check if vmauth is installed + ansible.builtin.stat: + path: /usr/local/bin/vmauth-prod + changed_when: false + check_mode: false + register: vmauth_is_installed + +- name: Check current vmauth version + ansible.builtin.command: /usr/local/bin/vmauth-prod --version + changed_when: false + failed_when: false + check_mode: false + register: vmauth_current_version + when: vmauth_is_installed.stat.exists | bool diff --git a/roles/vmauth/templates/auth.yaml.j2 b/roles/vmauth/templates/auth.yaml.j2 new file mode 100644 index 0000000..d81dac3 --- /dev/null +++ b/roles/vmauth/templates/auth.yaml.j2 @@ -0,0 +1,3 @@ +{{ ansible_managed | comment }} + +{{ vmauth_auth_config | default('') | indent(2) }} diff --git a/roles/vmauth/templates/vmauth.conf.j2 b/roles/vmauth/templates/vmauth.conf.j2 new file mode 100644 index 0000000..8e7dcae --- /dev/null +++ b/roles/vmauth/templates/vmauth.conf.j2 @@ -0,0 +1,5 @@ +{{ ansible_managed | comment }} + +{% for key, value in vmauth_config.items() | default({}) %} +{{- key }}={{ value }} +{% endfor %} diff --git a/roles/vmauth/templates/vmauth.service.j2 b/roles/vmauth/templates/vmauth.service.j2 new file mode 100644 index 0000000..35fadca --- /dev/null +++ b/roles/vmauth/templates/vmauth.service.j2 @@ -0,0 +1,35 @@ +{{ ansible_managed | comment }} +[Unit] +Description=VictoriaMetrics vmauth service +After=network.target + +[Service] +Type=simple +User={{ vmauth_system_user }} +Group={{ vmauth_system_group }} +Restart=always +EnvironmentFile={{ vmauth_config_dir }}/vmauth.conf +ExecStart={{ vmauth_bin_dir }}/vmauth-prod -envflag.enable -auth.config={{ vmauth_config_dir }}/auth.yaml + +PrivateTmp=yes +ProtectHome={{ vmauth_systemd_protect_home }} +NoNewPrivileges=yes + +ProtectSystem=full + +{% if vmauth_systemd_version | int >= 232 %} +ProtectControlGroups=true +ProtectKernelModules=true +ProtectKernelTunables=yes +{% endif %} + +{% if vmauth_exec_start_post != "" %} +ExecStartPost={{ vmauth_exec_start_post }} +{% endif %} + +{% if vmauth_exec_stop != "" %} +ExecStop={{ vmauth_exec_stop }} +{% endif %} + +[Install] +WantedBy=multi-user.target diff --git a/roles/vmauth/vars/main.yml b/roles/vmauth/vars/main.yml new file mode 100644 index 0000000..f1b3a4a --- /dev/null +++ b/roles/vmauth/vars/main.yml @@ -0,0 +1,9 @@ +--- +go_arch_map: + i386: '386' + x86_64: 'amd64' + aarch64: 'arm64' + armv7l: 'arm' + armv6l: 'arm6vl' + +go_arch: "{{ go_arch_map[ansible_architecture] | default(ansible_architecture) }}" diff --git a/roles/vminsert/README.md b/roles/vminsert/README.md new file mode 100644 index 0000000..83d0fd1 --- /dev/null +++ b/roles/vminsert/README.md @@ -0,0 +1,27 @@ +# vminsert + +Role to install and configure vminsert. Installs by using binary from Github releases. + +## Parameters + +The following table lists the configurable parameters of the roles and their default values. + +| Parameter | Description | Default | +|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------| +| vminsert_repo_url | Repository to use for download. | `https://github.com/VictoriaMetrics/VictoriaMetrics` | +| vminsert_version | vminsert version | `v1.99.0` | +| vminsert_download_url | URL to download archive | `{{ vminsert_repo_url }}/releases/download/{{ vminsert_version }}/vmutils-{{ vminsert_version }}.tar.gz` | +| vminsert_system_user | User to run vminsert | `victoriametrics` | +| vminsert_system_group | Group for user of vminsert | `{{ vminsert_system_user }}` | +| vminsert_service_state | Default state of systemd service | `started` | +| vminsert_service_enabled | Whether to enable systemd service | `true` | +| vminsert_config_dir | Location for config files | `/opt/victoriametrics-vminsert` | +| vminsert_bin_dir | Location for binary file | `/usr/local/bin` | +| vminsert_config | Config parameters to be passed via environment variables | See [defaults.yml](./defaults/main.yml) | +| vminsert_relabel_config | Relabeling configuration for vminsert | `""` | +| vminsert_exec_start_post | Post start hook for systemd unit | `""` | +| vminsert_exec_stop | Stop command for systemd unit | `""` | +| vminsert_install_download_to_control | Whether use control or remote host to download installation archive | `true` | +| vminsert_systemd_protect_home | Configure Systemd home protection. See See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome= | `"yes"` | +| vm_proxy_http | Sets environment for downloading archive | `""` | +| vm_proxy_https | Sets environment for downloading archive | `""` | diff --git a/roles/vminsert/defaults/main.yml b/roles/vminsert/defaults/main.yml new file mode 100644 index 0000000..a5cf44e --- /dev/null +++ b/roles/vminsert/defaults/main.yml @@ -0,0 +1,39 @@ +--- +vminsert_version: "v1.99.0" + +vminsert_repo_url: "https://github.com/VictoriaMetrics/VictoriaMetrics" +vminsert_platform: "{% if vminsert_version.replace('v', '') is version('1.79.0', '>=') %}-linux{% endif %}" +vminsert_download_url: "{{ vminsert_repo_url }}/releases/download/{{ vminsert_version }}/victoria-metrics{{ vminsert_platform }}-{{ go_arch }}-{{ vminsert_version }}-cluster.tar.gz" + +vminsert_system_user: "victoriametrics" +vminsert_system_group: "{{ vminsert_system_user }}" + +vminsert_service_state: started +vminsert_service_enabled: true +vminsert_exec_start_post: "" +vminsert_exec_stop: "" + +vminsert_config_dir: "/opt/victoriametrics-vminsert" +vminsert_bin_dir: /usr/local/bin + +vminsert_config: + replicationFactor: 1 + storageNode: vmstorage1,vmstorage2,vmstorage3 + +vminsert_relabel_config: "" + +#vminsert_relabel_config: | +# - source_labels: [__name__] +# regex: '(.*)' +# target_label: __name__ +# replacement: '${1}' +# action: replace + +vminsert_install_download_to_control: false + +vm_proxy_http: "" +vm_proxy_https: "" + +# See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome= +# Available options: 'yes', 'read-only', 'tmpfs' +vminsert_systemd_protect_home: "yes" diff --git a/roles/vminsert/handlers/main.yml b/roles/vminsert/handlers/main.yml new file mode 100644 index 0000000..6d65173 --- /dev/null +++ b/roles/vminsert/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart vminsert service + ansible.builtin.systemd: + daemon_reload: true + name: vminsert + state: restarted diff --git a/roles/vminsert/meta/main.yml b/roles/vminsert/meta/main.yml new file mode 100644 index 0000000..fffeaa2 --- /dev/null +++ b/roles/vminsert/meta/main.yml @@ -0,0 +1 @@ +dependencies: [] # noqa: meta-no-info diff --git a/roles/vminsert/molecule/default/converge.yml b/roles/vminsert/molecule/default/converge.yml new file mode 100644 index 0000000..ac16711 --- /dev/null +++ b/roles/vminsert/molecule/default/converge.yml @@ -0,0 +1,14 @@ +--- +- name: Converge + hosts: all + become: yes + tasks: + - name: "Include vminsert" + vars: + vminsert_relabel_config: | + - source_labels: [__address__] + target_label: instance + regex: '(.+):.*' + replacement: '${1}' + ansible.builtin.include_role: + name: "vminsert" diff --git a/roles/vminsert/molecule/default/molecule.yml b/roles/vminsert/molecule/default/molecule.yml new file mode 100644 index 0000000..b43f4f1 --- /dev/null +++ b/roles/vminsert/molecule/default/molecule.yml @@ -0,0 +1,25 @@ +--- +lint: | + yamllint . + ansible-lint . + + +dependency: + name: galaxy +driver: + name: docker + +platforms: + - name: vminsert-debian11 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + +provisioner: + name: ansible +verifier: + name: ansible diff --git a/roles/vminsert/molecule/default/tests/test_default.yml b/roles/vminsert/molecule/default/tests/test_default.yml new file mode 100644 index 0000000..41d5176 --- /dev/null +++ b/roles/vminsert/molecule/default/tests/test_default.yml @@ -0,0 +1,4 @@ +service: + "vminsert": + enabled: true + running: true diff --git a/roles/vminsert/molecule/default/verify.yml b/roles/vminsert/molecule/default/verify.yml new file mode 100644 index 0000000..1a1bce3 --- /dev/null +++ b/roles/vminsert/molecule/default/verify.yml @@ -0,0 +1,93 @@ +--- +# Molecule Goss Tests + +- name: Verify + hosts: all + become: true + vars: + goss_version: v0.3.10 + goss_arch: amd64 + goss_bin: /usr/local/bin/goss + goss_sha256sum: 150f25495ca0d1d4fd2ef8d0e750dbd767a15e9a522505f99b61dd1dd40a76d4 + goss_url: "https://github.com/aelsabbahy/goss/releases/download/{{ goss_version }}/goss-linux-{{ goss_arch }}" + goss_test_directory: /tmp/molecule/goss + goss_format: documentation + tasks: + - name: Download and install Goss + ansible.builtin.get_url: + url: "{{ goss_url }}" + dest: "{{ goss_bin }}" + sha256sum: "{{ goss_sha256sum }}" # noqa: args[module] + mode: "u=rwx,go=rx" + register: download_goss + until: download_goss is succeeded + retries: 3 + + - name: Create Molecule directory for test files + ansible.builtin.file: + path: "{{ goss_test_directory }}" + state: directory + mode: "0755" + + - name: Find Goss tests on localhost + ansible.builtin.find: + paths: "{{ lookup('env', 'MOLECULE_VERIFIER_TEST_DIRECTORY') }}" + patterns: + - "test[-.\\w]*.yml" + - "test_host_{{ ansible_hostname }}[-.\\w]*.yml" + excludes: + - "test_host_(?!{{ ansible_hostname }})[-.\\w]*.yml" + use_regex: true + delegate_to: localhost + register: test_files + changed_when: false + become: false + + - name: Debug + ansible.builtin.debug: + msg: "{{ test_files.files }}" + verbosity: 3 + + - name: Copy Goss tests to remote + ansible.builtin.copy: + src: "{{ item.path }}" + dest: "{{ goss_test_directory }}/{{ item.path | basename }}" + mode: "0644" + with_items: + - "{{ test_files.files }}" + loop_control: + label: "{{ item.path | basename }}" + + - name: Register test files + ansible.builtin.find: + paths: + - "{{ goss_test_directory }}" + patterns: + - "test_*.yml" + register: test_files + + - name: Run verify + when: test_files is succeeded + block: + - name: Execute Goss tests # noqa: no-changed-when + ansible.builtin.command: "{{ goss_bin }} -g {{ item }} validate --format {{ goss_format }}" + register: test_results + with_items: "{{ test_files.files | map(attribute='path') | list }}" + loop_control: + label: "{{ item | basename }}" + failed_when: false + + - name: Display details about the Goss results + ansible.builtin.debug: + msg: "{{ item.stdout_lines }}" + with_items: "{{ test_results.results }}" + loop_control: + label: "{{ item[item.ansible_loop_var] | basename }}" + + - name: Fail when tests fail + ansible.builtin.fail: + msg: "Goss failed to validate" + when: item.rc != 0 + with_items: "{{ test_results.results }}" + loop_control: + label: "{{ item[item.ansible_loop_var] | basename }}" diff --git a/roles/vminsert/tasks/configure.yml b/roles/vminsert/tasks/configure.yml new file mode 100644 index 0000000..f8f9d9e --- /dev/null +++ b/roles/vminsert/tasks/configure.yml @@ -0,0 +1,43 @@ +--- +- name: "Systemd | Copy vminsert systemd unit file" + ansible.builtin.template: + src: vminsert.service.j2 + dest: /etc/systemd/system/vminsert.service + owner: root + group: root + mode: 0644 + notify: Restart vminsert service + +- name: "Systemd | ensure vminsert service is enabled" # noqa: no-handler + become: true + ansible.builtin.systemd: + name: vminsert + enabled: true + +- name: Prepare configuration dir + ansible.builtin.file: + state: directory + path: "{{ vminsert_config_dir }}" + mode: 0751 + owner: "{{ vminsert_system_user }}" + group: "{{ vminsert_system_group }}" + +- name: Template relabel config + ansible.builtin.template: + src: relabeling.yaml.j2 + dest: "{{ vminsert_config_dir }}/relabel.yaml" + owner: "{{ vminsert_system_user }}" + group: "{{ vminsert_system_group }}" + mode: 0644 + when: + - vminsert_relabel_config != "" + notify: Restart vminsert service + +- name: Setup environment file + ansible.builtin.template: + dest: "{{ vminsert_config_dir }}/vminsert.conf" + src: "vminsert.conf.j2" + owner: "{{ vminsert_system_user }}" + group: "{{ vminsert_system_group }}" + mode: 0644 + notify: Restart vminsert service diff --git a/roles/vminsert/tasks/install.yml b/roles/vminsert/tasks/install.yml new file mode 100644 index 0000000..543a1e5 --- /dev/null +++ b/roles/vminsert/tasks/install.yml @@ -0,0 +1,98 @@ +--- +- name: Create vminsert system group + ansible.builtin.group: + name: "{{ vminsert_system_group }}" + state: present + system: true + when: vminsert_system_group != "root" + +- name: Create vminsert system user + ansible.builtin.user: + name: "{{ vminsert_system_user }}" + groups: "{{ vminsert_system_group }}" + append: true + shell: /usr/sbin/nologin + system: true + createhome: false + when: vminsert_system_user != "root" + +- name: Ensure existence of /usr/local/bin + ansible.builtin.file: + path: /usr/local/bin + state: directory + mode: 0755 + +- name: Delete existing vminsert version if it's different. + ansible.builtin.file: + path: /usr/local/bin/vminsert-prod + state: absent + when: + - vminsert_is_installed.stat.exists | bool + - vminsert_version not in vminsert_current_version.stdout + +- name: Install via control host + when: vminsert_install_download_to_control + block: + - name: Download and unarchive vminsert release binary + environment: + http_proxy: "{{ vm_proxy_http }}" + https_proxy: "{{ vm_proxy_https }}" + ansible.builtin.unarchive: + src: "{{ vminsert_download_url }}" + dest: /tmp + remote_src: yes + delegate_to: localhost + become: no + when: + - not ansible_check_mode + - not vminsert_is_installed.stat.exists or + vminsert_version not in vminsert_current_version.stdout + + - name: Copy vminsert binary to target host + notify: Restart vminsert service + ansible.builtin.copy: + src: /tmp/vminsert-prod + dest: /tmp/vminsert-prod + mode: 0751 + owner: "{{ vminsert_system_user }}" + group: "{{ vminsert_system_group }}" + when: + - not ansible_check_mode + - not vminsert_is_installed.stat.exists or + vminsert_version not in vminsert_current_version.stdout + + - name: Replace vminsert binary at target dir # noqa: no-changed-when + notify: Restart vminsert service + ansible.builtin.shell: | + mv /tmp/vminsert-prod /usr/local/bin/vminsert-prod + when: + - not ansible_check_mode + - not vminsert_is_installed.stat.exists or + vminsert_version not in vminsert_current_version.stdout + +- name: Install directly to target host + when: not vminsert_install_download_to_control + block: + - name: Download and unarchive vminsert release binary + environment: + http_proxy: "{{ vm_proxy_http }}" + https_proxy: "{{ vm_proxy_https }}" + ansible.builtin.unarchive: + src: "{{ vminsert_download_url }}" + dest: /tmp + remote_src: yes + when: + - not ansible_check_mode + - not vminsert_is_installed.stat.exists or + vminsert_version not in vminsert_current_version.stdout + + - name: Replace vminsert binary at target dir # noqa: no-changed-when + notify: Restart vminsert service + ansible.builtin.shell: | + mv /tmp/vminsert-prod /usr/local/bin/vminsert-prod + chmod 0751 /usr/local/bin/vminsert-prod + chown {{ vminsert_system_user }}:{{ vminsert_system_group }} /usr/local/bin/vminsert-prod + when: + - not ansible_check_mode + - not vminsert_is_installed.stat.exists or + vminsert_version not in vminsert_current_version.stdout diff --git a/roles/vminsert/tasks/main.yml b/roles/vminsert/tasks/main.yml new file mode 100644 index 0000000..f9ae994 --- /dev/null +++ b/roles/vminsert/tasks/main.yml @@ -0,0 +1,7 @@ +--- +- name: Preinstall checks + ansible.builtin.import_tasks: preinstall.yml +- name: Install + ansible.builtin.import_tasks: install.yml +- name: Configure + ansible.builtin.import_tasks: configure.yml diff --git a/roles/vminsert/tasks/preinstall.yml b/roles/vminsert/tasks/preinstall.yml new file mode 100644 index 0000000..1c9853c --- /dev/null +++ b/roles/vminsert/tasks/preinstall.yml @@ -0,0 +1,32 @@ +--- +- name: Assert usage of systemd or upstart as an init system + ansible.builtin.assert: + that: ansible_service_mgr == 'systemd' + msg: "This role only works with systemd" + +- name: Get systemd version + ansible.builtin.command: systemctl --version + changed_when: false + check_mode: false + register: __systemd_version + when: ansible_service_mgr == 'systemd' + +- name: Set systemd version fact + ansible.builtin.set_fact: + vminsert_systemd_version: "{{ __systemd_version.stdout_lines[0].split(' ')[-1] }}" + when: ansible_service_mgr == 'systemd' + +- name: Check if vminsert is installed + ansible.builtin.stat: + path: /usr/local/bin/vminsert-prod + changed_when: false + check_mode: false + register: vminsert_is_installed + +- name: Check current vminsert version + ansible.builtin.command: /usr/local/bin/vminsert-prod --version + changed_when: false + failed_when: false + check_mode: false + register: vminsert_current_version + when: vminsert_is_installed.stat.exists | bool diff --git a/roles/vminsert/templates/relabeling.yaml.j2 b/roles/vminsert/templates/relabeling.yaml.j2 new file mode 100644 index 0000000..5775ba0 --- /dev/null +++ b/roles/vminsert/templates/relabeling.yaml.j2 @@ -0,0 +1,3 @@ +{{ ansible_managed | comment }} + +{{ vminsert_relabel_config | default('') | indent(2) }} diff --git a/roles/vminsert/templates/vminsert.conf.j2 b/roles/vminsert/templates/vminsert.conf.j2 new file mode 100644 index 0000000..5ed245b --- /dev/null +++ b/roles/vminsert/templates/vminsert.conf.j2 @@ -0,0 +1,9 @@ +{{ ansible_managed | comment }} + +{% for key, value in vminsert_config.items() | default({}) %} +{{- key }}={{ value }} +{% endfor %} + +{% if vminsert_relabel_config != "" %} +relabelConfig={{ vminsert_config_dir }}/relabel.yaml +{% endif %} diff --git a/roles/vminsert/templates/vminsert.service.j2 b/roles/vminsert/templates/vminsert.service.j2 new file mode 100644 index 0000000..570ccfe --- /dev/null +++ b/roles/vminsert/templates/vminsert.service.j2 @@ -0,0 +1,35 @@ +{{ ansible_managed | comment }} +[Unit] +Description=VictoriaMetrics vminsert service +After=network.target + +[Service] +Type=simple +User={{ vminsert_system_user }} +Group={{ vminsert_system_group }} +Restart=always +EnvironmentFile={{ vminsert_config_dir }}/vminsert.conf +ExecStart={{ vminsert_bin_dir }}/vminsert-prod -envflag.enable + +PrivateTmp=yes +ProtectHome={{ vminsert_systemd_protect_home }} +NoNewPrivileges=yes + +ProtectSystem=full + +{% if vminsert_systemd_version | int >= 232 %} +ProtectControlGroups=true +ProtectKernelModules=true +ProtectKernelTunables=yes +{% endif %} + +{% if vminsert_exec_start_post != "" %} +ExecStartPost={{ vminsert_exec_start_post }} +{% endif %} + +{% if vminsert_exec_stop != "" %} +ExecStop={{ vminsert_exec_stop }} +{% endif %} + +[Install] +WantedBy=multi-user.target diff --git a/roles/vminsert/vars/main.yml b/roles/vminsert/vars/main.yml new file mode 100644 index 0000000..f1b3a4a --- /dev/null +++ b/roles/vminsert/vars/main.yml @@ -0,0 +1,9 @@ +--- +go_arch_map: + i386: '386' + x86_64: 'amd64' + aarch64: 'arm64' + armv7l: 'arm' + armv6l: 'arm6vl' + +go_arch: "{{ go_arch_map[ansible_architecture] | default(ansible_architecture) }}" diff --git a/roles/vmselect/README.md b/roles/vmselect/README.md new file mode 100644 index 0000000..e3560a4 --- /dev/null +++ b/roles/vmselect/README.md @@ -0,0 +1,27 @@ +# vmselect + +Role to install and configure vmselect. Installs by using binary from Github releases. + +## Parameters + +The following table lists the configurable parameters of the roles and their default values. + +| Parameter | Description | Default | +|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------| +| vmselect_repo_url | Repository to use for download. | `https://github.com/VictoriaMetrics/VictoriaMetrics` | +| vmselect_version | vmselect version | `v1.99.0` | +| vmselect_download_url | URL to download archive | `{{ vmselect_repo_url }}/releases/download/{{ vmselect_version }}/vmutils-{{ vmselect_version }}.tar.gz` | +| vmselect_system_user | User to run vmselect | `victoriametrics` | +| vmselect_system_group | Group for user of vmselect | `{{ vmselect_system_user }}` | +| vmselect_service_state | Default state of systemd service | `started` | +| vmselect_service_enabled | Whether to enable systemd service | `true` | +| vmselect_config_dir | Location for config files | `/opt/victoriametrics-vmselect` | +| vmselect_bin_dir | Location for binary file | `/usr/local/bin` | +| vmselect_config | Config parameters to be passed via environment variables | See [defaults.yml](./defaults/main.yml) | +| vmselect_cache_dir | Cache directory to use for vmselect's cache | `"/var/lib/vmselect"` | +| vmselect_exec_start_post | Post start hook for systemd unit | `""` | +| vmselect_exec_stop | Stop command for systemd unit | `""` | +| vmselect_install_download_to_control | Whether use control or remote host to download installation archive | `true` | +| vmselect_systemd_protect_home | Configure Systemd home protection. See See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome= | `"yes"` | +| vm_proxy_http | Sets environment for downloading archive | `""` | +| vm_proxy_https | Sets environment for downloading archive | `""` | diff --git a/roles/vmselect/defaults/main.yml b/roles/vmselect/defaults/main.yml new file mode 100644 index 0000000..2c12157 --- /dev/null +++ b/roles/vmselect/defaults/main.yml @@ -0,0 +1,31 @@ +--- +vmselect_version: "v1.99.0" + +vmselect_repo_url: "https://github.com/VictoriaMetrics/VictoriaMetrics" +vmselect_platform: "{% if vmselect_version.replace('v', '') is version('1.79.0', '>=') %}-linux{% endif %}" +vmselect_download_url: "{{ vmselect_repo_url }}/releases/download/{{ vmselect_version }}/victoria-metrics{{ vmselect_platform }}-{{ go_arch }}-{{ vmselect_version }}-cluster.tar.gz" + +vmselect_system_user: "victoriametrics" +vmselect_system_group: "{{ vmselect_system_user }}" + +vmselect_service_state: started +vmselect_service_enabled: true +vmselect_exec_start_post: "" +vmselect_exec_stop: "" + +vmselect_config_dir: "/opt/victoriametrics-vmselect" +vmselect_cache_dir: "/var/lib/vmselect" +vmselect_bin_dir: /usr/local/bin + +vmselect_config: + storageNode: vmstorage1,vmstorage2 + cacheDataPath: "{{ vmselect_cache_dir }}" + +vmselect_install_download_to_control: false + +vm_proxy_http: "" +vm_proxy_https: "" + +# See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome= +# Available options: 'yes', 'read-only', 'tmpfs' +vmselect_systemd_protect_home: "yes" diff --git a/roles/vmselect/handlers/main.yml b/roles/vmselect/handlers/main.yml new file mode 100644 index 0000000..a813aeb --- /dev/null +++ b/roles/vmselect/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart vmselect service + ansible.builtin.systemd: + daemon_reload: true + name: vmselect + state: restarted diff --git a/roles/vmselect/meta/main.yml b/roles/vmselect/meta/main.yml new file mode 100644 index 0000000..fffeaa2 --- /dev/null +++ b/roles/vmselect/meta/main.yml @@ -0,0 +1 @@ +dependencies: [] # noqa: meta-no-info diff --git a/roles/vmselect/molecule/default/converge.yml b/roles/vmselect/molecule/default/converge.yml new file mode 100644 index 0000000..487bc21 --- /dev/null +++ b/roles/vmselect/molecule/default/converge.yml @@ -0,0 +1,8 @@ +--- +- name: Converge + hosts: all + become: yes + tasks: + - name: "Include vmselect" + ansible.builtin.include_role: + name: "vmselect" diff --git a/roles/vmselect/molecule/default/molecule.yml b/roles/vmselect/molecule/default/molecule.yml new file mode 100644 index 0000000..3aaf4fb --- /dev/null +++ b/roles/vmselect/molecule/default/molecule.yml @@ -0,0 +1,25 @@ +--- +lint: | + yamllint . + ansible-lint . + + +dependency: + name: galaxy +driver: + name: docker + +platforms: + - name: vmselect-debian11 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + +provisioner: + name: ansible +verifier: + name: ansible diff --git a/roles/vmselect/molecule/default/tests/test_default.yml b/roles/vmselect/molecule/default/tests/test_default.yml new file mode 100644 index 0000000..50b89a2 --- /dev/null +++ b/roles/vmselect/molecule/default/tests/test_default.yml @@ -0,0 +1,4 @@ +service: + "vmselect": + enabled: true + running: true diff --git a/roles/vmselect/molecule/default/verify.yml b/roles/vmselect/molecule/default/verify.yml new file mode 100644 index 0000000..1a1bce3 --- /dev/null +++ b/roles/vmselect/molecule/default/verify.yml @@ -0,0 +1,93 @@ +--- +# Molecule Goss Tests + +- name: Verify + hosts: all + become: true + vars: + goss_version: v0.3.10 + goss_arch: amd64 + goss_bin: /usr/local/bin/goss + goss_sha256sum: 150f25495ca0d1d4fd2ef8d0e750dbd767a15e9a522505f99b61dd1dd40a76d4 + goss_url: "https://github.com/aelsabbahy/goss/releases/download/{{ goss_version }}/goss-linux-{{ goss_arch }}" + goss_test_directory: /tmp/molecule/goss + goss_format: documentation + tasks: + - name: Download and install Goss + ansible.builtin.get_url: + url: "{{ goss_url }}" + dest: "{{ goss_bin }}" + sha256sum: "{{ goss_sha256sum }}" # noqa: args[module] + mode: "u=rwx,go=rx" + register: download_goss + until: download_goss is succeeded + retries: 3 + + - name: Create Molecule directory for test files + ansible.builtin.file: + path: "{{ goss_test_directory }}" + state: directory + mode: "0755" + + - name: Find Goss tests on localhost + ansible.builtin.find: + paths: "{{ lookup('env', 'MOLECULE_VERIFIER_TEST_DIRECTORY') }}" + patterns: + - "test[-.\\w]*.yml" + - "test_host_{{ ansible_hostname }}[-.\\w]*.yml" + excludes: + - "test_host_(?!{{ ansible_hostname }})[-.\\w]*.yml" + use_regex: true + delegate_to: localhost + register: test_files + changed_when: false + become: false + + - name: Debug + ansible.builtin.debug: + msg: "{{ test_files.files }}" + verbosity: 3 + + - name: Copy Goss tests to remote + ansible.builtin.copy: + src: "{{ item.path }}" + dest: "{{ goss_test_directory }}/{{ item.path | basename }}" + mode: "0644" + with_items: + - "{{ test_files.files }}" + loop_control: + label: "{{ item.path | basename }}" + + - name: Register test files + ansible.builtin.find: + paths: + - "{{ goss_test_directory }}" + patterns: + - "test_*.yml" + register: test_files + + - name: Run verify + when: test_files is succeeded + block: + - name: Execute Goss tests # noqa: no-changed-when + ansible.builtin.command: "{{ goss_bin }} -g {{ item }} validate --format {{ goss_format }}" + register: test_results + with_items: "{{ test_files.files | map(attribute='path') | list }}" + loop_control: + label: "{{ item | basename }}" + failed_when: false + + - name: Display details about the Goss results + ansible.builtin.debug: + msg: "{{ item.stdout_lines }}" + with_items: "{{ test_results.results }}" + loop_control: + label: "{{ item[item.ansible_loop_var] | basename }}" + + - name: Fail when tests fail + ansible.builtin.fail: + msg: "Goss failed to validate" + when: item.rc != 0 + with_items: "{{ test_results.results }}" + loop_control: + label: "{{ item[item.ansible_loop_var] | basename }}" diff --git a/roles/vmselect/tasks/configure.yml b/roles/vmselect/tasks/configure.yml new file mode 100644 index 0000000..4d9162f --- /dev/null +++ b/roles/vmselect/tasks/configure.yml @@ -0,0 +1,40 @@ +--- +- name: "Systemd | Copy vmselect systemd unit file" + ansible.builtin.template: + src: vmselect.service.j2 + dest: /etc/systemd/system/vmselect.service + owner: root + group: root + mode: 0644 + notify: Restart vmselect service + +- name: "Systemd | ensure vmselect service is enabled" # noqa: no-handler + become: true + ansible.builtin.systemd: + name: vmselect + enabled: true + +- name: Prepare configuration dir + ansible.builtin.file: + state: directory + path: "{{ vmselect_config_dir }}" + mode: 0751 + owner: "{{ vmselect_system_user }}" + group: "{{ vmselect_system_group }}" + +- name: Setup environment file + ansible.builtin.template: + dest: "{{ vmselect_config_dir }}/vmselect.conf" + src: "vmselect.conf.j2" + owner: "{{ vmselect_system_user }}" + group: "{{ vmselect_system_group }}" + mode: 0644 + notify: Restart vmselect service + +- name: Prepare cache dir + ansible.builtin.file: + state: directory + path: "{{ vmselect_cache_dir }}" + mode: 0751 + owner: "{{ vmselect_system_user }}" + group: "{{ vmselect_system_group }}" diff --git a/roles/vmselect/tasks/install.yml b/roles/vmselect/tasks/install.yml new file mode 100644 index 0000000..6856e19 --- /dev/null +++ b/roles/vmselect/tasks/install.yml @@ -0,0 +1,98 @@ +--- +- name: Create vmselect system group + ansible.builtin.group: + name: "{{ vmselect_system_group }}" + state: present + system: true + when: vmselect_system_group != "root" + +- name: Create vmselect system user + ansible.builtin.user: + name: "{{ vmselect_system_user }}" + groups: "{{ vmselect_system_group }}" + append: true + shell: /usr/sbin/nologin + system: true + createhome: false + when: vmselect_system_user != "root" + +- name: Ensure existence of /usr/local/bin + ansible.builtin.file: + path: /usr/local/bin + state: directory + mode: 0755 + +- name: Delete existing vmselect version if it's different. + ansible.builtin.file: + path: /usr/local/bin/vmselect-prod + state: absent + when: + - vmselect_is_installed.stat.exists | bool + - vmselect_version not in vmselect_current_version.stdout + +- name: Install via control host + when: vmselect_install_download_to_control + block: + - name: Download and unarchive vmselect release binary + environment: + http_proxy: "{{ vm_proxy_http }}" + https_proxy: "{{ vm_proxy_https }}" + ansible.builtin.unarchive: + src: "{{ vmselect_download_url }}" + dest: /tmp + remote_src: yes + delegate_to: localhost + become: no + when: + - not ansible_check_mode + - not vmselect_is_installed.stat.exists or + vmselect_version not in vmselect_current_version.stdout + + - name: Copy vmselect binary to target host + notify: Restart vmselect service + ansible.builtin.copy: + src: /tmp/vmselect-prod + dest: /tmp/vmselect-prod + mode: 0751 + owner: "{{ vmselect_system_user }}" + group: "{{ vmselect_system_group }}" + when: + - not ansible_check_mode + - not vmselect_is_installed.stat.exists or + vmselect_version not in vmselect_current_version.stdout + + - name: Replace vmselect binary at target dir # noqa: no-changed-when + notify: Restart vmselect service + ansible.builtin.shell: | + mv /tmp/vmselect-prod /usr/local/bin/vmselect-prod + when: + - not ansible_check_mode + - not vmselect_is_installed.stat.exists or + vmselect_version not in vmselect_current_version.stdout + +- name: Install directly to target host + when: not vmselect_install_download_to_control + block: + - name: Download and unarchive vmselect release binary + environment: + http_proxy: "{{ vm_proxy_http }}" + https_proxy: "{{ vm_proxy_https }}" + ansible.builtin.unarchive: + src: "{{ vmselect_download_url }}" + dest: /tmp + remote_src: yes + when: + - not ansible_check_mode + - not vmselect_is_installed.stat.exists or + vmselect_version not in vmselect_current_version.stdout + + - name: Replace vmselect binary at target dir # noqa: no-changed-when + notify: Restart vmselect service + ansible.builtin.shell: | + mv /tmp/vmselect-prod /usr/local/bin/vmselect-prod + chmod 0751 /usr/local/bin/vmselect-prod + chown {{ vmselect_system_user }}:{{ vmselect_system_group }} /usr/local/bin/vmselect-prod + when: + - not ansible_check_mode + - not vmselect_is_installed.stat.exists or + vmselect_version not in vmselect_current_version.stdout diff --git a/roles/vmselect/tasks/main.yml b/roles/vmselect/tasks/main.yml new file mode 100644 index 0000000..f9ae994 --- /dev/null +++ b/roles/vmselect/tasks/main.yml @@ -0,0 +1,7 @@ +--- +- name: Preinstall checks + ansible.builtin.import_tasks: preinstall.yml +- name: Install + ansible.builtin.import_tasks: install.yml +- name: Configure + ansible.builtin.import_tasks: configure.yml diff --git a/roles/vmselect/tasks/preinstall.yml b/roles/vmselect/tasks/preinstall.yml new file mode 100644 index 0000000..74eb057 --- /dev/null +++ b/roles/vmselect/tasks/preinstall.yml @@ -0,0 +1,32 @@ +--- +- name: Assert usage of systemd or upstart as an init system + ansible.builtin.assert: + that: ansible_service_mgr == 'systemd' + msg: "This role only works with systemd" + +- name: Get systemd version + ansible.builtin.command: systemctl --version + changed_when: false + check_mode: false + register: __systemd_version + when: ansible_service_mgr == 'systemd' + +- name: Set systemd version fact + ansible.builtin.set_fact: + vmselect_systemd_version: "{{ __systemd_version.stdout_lines[0].split(' ')[-1] }}" + when: ansible_service_mgr == 'systemd' + +- name: Check if vmselect is installed + ansible.builtin.stat: + path: /usr/local/bin/vmselect-prod + changed_when: false + check_mode: false + register: vmselect_is_installed + +- name: Check current vmselect version + ansible.builtin.command: /usr/local/bin/vmselect-prod --version + changed_when: false + failed_when: false + check_mode: false + register: vmselect_current_version + when: vmselect_is_installed.stat.exists | bool diff --git a/roles/vmselect/templates/vmselect.conf.j2 b/roles/vmselect/templates/vmselect.conf.j2 new file mode 100644 index 0000000..606ff14 --- /dev/null +++ b/roles/vmselect/templates/vmselect.conf.j2 @@ -0,0 +1,5 @@ +{{ ansible_managed | comment }} + +{% for key, value in vmselect_config.items() | default({}) %} +{{- key }}={{ value }} +{% endfor %} diff --git a/roles/vmselect/templates/vmselect.service.j2 b/roles/vmselect/templates/vmselect.service.j2 new file mode 100644 index 0000000..bbeb528 --- /dev/null +++ b/roles/vmselect/templates/vmselect.service.j2 @@ -0,0 +1,35 @@ +{{ ansible_managed | comment }} +[Unit] +Description=VictoriaMetrics vmselect service +After=network.target + +[Service] +Type=simple +User={{ vmselect_system_user }} +Group={{ vmselect_system_group }} +Restart=always +EnvironmentFile={{ vmselect_config_dir }}/vmselect.conf +ExecStart={{ vmselect_bin_dir }}/vmselect-prod -envflag.enable + +PrivateTmp=yes +ProtectHome={{ vmselect_systemd_protect_home }} +NoNewPrivileges=yes + +ProtectSystem=full + +{% if vmselect_systemd_version | int >= 232 %} +ProtectControlGroups=true +ProtectKernelModules=true +ProtectKernelTunables=yes +{% endif %} + +{% if vmselect_exec_start_post != "" %} +ExecStartPost={{ vmselect_exec_start_post }} +{% endif %} + +{% if vmselect_exec_stop != "" %} +ExecStop={{ vmselect_exec_stop }} +{% endif %} + +[Install] +WantedBy=multi-user.target diff --git a/roles/vmselect/vars/main.yml b/roles/vmselect/vars/main.yml new file mode 100644 index 0000000..f1b3a4a --- /dev/null +++ b/roles/vmselect/vars/main.yml @@ -0,0 +1,9 @@ +--- +go_arch_map: + i386: '386' + x86_64: 'amd64' + aarch64: 'arm64' + armv7l: 'arm' + armv6l: 'arm6vl' + +go_arch: "{{ go_arch_map[ansible_architecture] | default(ansible_architecture) }}" diff --git a/roles/vmstorage/README.md b/roles/vmstorage/README.md new file mode 100644 index 0000000..f090322 --- /dev/null +++ b/roles/vmstorage/README.md @@ -0,0 +1,27 @@ +# vmstorage + +Role to install and configure vmstorage. Installs by using binary from Github releases. + +## Parameters + +The following table lists the configurable parameters of the roles and their default values. + +| Parameter | Description | Default | +|---------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------| +| vmstorage_version | vmstorage version | `v1.99.0` | +| vmstorage_repo_url | Repository to use for download. | `https://github.com/VictoriaMetrics/VictoriaMetrics` | +| vmstorage_download_url | URL to download archive | `{{ vmstorage_repo_url }}/releases/download/{{ vmstorage_version }}/vmutils-{{ vmstorage_version }}.tar.gz` | +| vmstorage_system_user | User to run vmstorage | `victoriametrics` | +| vmstorage_system_group | Group for user of vmstorage | `{{ vmstorage_system_user }}` | +| vmstorage_service_state | Default state of systemd service | `started` | +| vmstorage_service_enabled | Whether to enable systemd service | `true` | +| vmstorage_config_dir | Location for config files | `/opt/victoriametrics-vmstorage` | +| vmstorage_bin_dir | Location for binary file | `/usr/local/bin` | +| vmstorage_config | Config parameters to be passed via environment variables | See [defaults.yml](./defaults/main.yml) | +| vmstorage_data_dir | Data directory to use for vmstorage | `"/var/lib/vmstorage"` | +| vmstorage_exec_start_post | Post start hook for systemd unit | `""` | +| vmstorage_exec_stop | Stop command for systemd unit | `""` | +| vmstorage_install_download_to_control | Whether use control or remote host to download installation archive | `true` | +| vmstorage_systemd_protect_home | Configure Systemd home protection. See See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome= | `"yes"` | +| vm_proxy_http | Sets environment for downloading archive | `""` | +| vm_proxy_https | Sets environment for downloading archive | `""` | diff --git a/roles/vmstorage/defaults/main.yml b/roles/vmstorage/defaults/main.yml new file mode 100644 index 0000000..085a399 --- /dev/null +++ b/roles/vmstorage/defaults/main.yml @@ -0,0 +1,31 @@ +--- +vmstorage_version: "v1.99.0" + +vmstorage_repo_url: "https://github.com/VictoriaMetrics/VictoriaMetrics" +vmstorage_platform: "{% if vmstorage_version.replace('v', '') is version('1.79.0', '>=') %}-linux{% endif %}" +vmstorage_download_url: "{{ vmstorage_repo_url }}/releases/download/{{ vmstorage_version }}/victoria-metrics{{ vmstorage_platform }}-{{ go_arch }}-{{ vmstorage_version }}-cluster.tar.gz" + +vmstorage_system_user: "victoriametrics" +vmstorage_system_group: "{{ vmstorage_system_user }}" + +vmstorage_service_state: started +vmstorage_service_enabled: true +vmstorage_exec_start_post: "" +vmstorage_exec_stop: "" + +vmstorage_config_dir: "/opt/victoriametrics-vmstorage" +vmstorage_data_dir: "/var/lib/vmstorage" +vmstorage_bin_dir: /usr/local/bin + +vmstorage_config: + retentionPeriod: "1" + storageDataPath: "{{ vmstorage_data_dir }}" + +vmstorage_install_download_to_control: false + +vm_proxy_http: "" +vm_proxy_https: "" + +# See https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome= +# Available options: 'yes', 'read-only', 'tmpfs' +vmstorage_systemd_protect_home: "yes" diff --git a/roles/vmstorage/handlers/main.yml b/roles/vmstorage/handlers/main.yml new file mode 100644 index 0000000..6c21bf0 --- /dev/null +++ b/roles/vmstorage/handlers/main.yml @@ -0,0 +1,6 @@ +--- +- name: Restart vmstorage service + ansible.builtin.systemd: + daemon_reload: true + name: vmstorage + state: restarted diff --git a/roles/vmstorage/meta/main.yml b/roles/vmstorage/meta/main.yml new file mode 100644 index 0000000..fffeaa2 --- /dev/null +++ b/roles/vmstorage/meta/main.yml @@ -0,0 +1 @@ +dependencies: [] # noqa: meta-no-info diff --git a/roles/vmstorage/molecule/default/converge.yml b/roles/vmstorage/molecule/default/converge.yml new file mode 100644 index 0000000..9847f9f --- /dev/null +++ b/roles/vmstorage/molecule/default/converge.yml @@ -0,0 +1,8 @@ +--- +- name: Converge + hosts: all + become: yes + tasks: + - name: "Include vmstorage" + ansible.builtin.include_role: + name: "vmstorage" diff --git a/roles/vmstorage/molecule/default/molecule.yml b/roles/vmstorage/molecule/default/molecule.yml new file mode 100644 index 0000000..b25de7d --- /dev/null +++ b/roles/vmstorage/molecule/default/molecule.yml @@ -0,0 +1,25 @@ +--- +lint: | + yamllint . + ansible-lint . + + +dependency: + name: galaxy +driver: + name: docker + +platforms: + - name: vmstorage-debian11 + image: "geerlingguy/docker-${MOLECULE_DISTRO:-debian11}-ansible:latest" + command: ${MOLECULE_DOCKER_COMMAND:-""} + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup:rw + cgroupns_mode: host + privileged: true + pre_build_image: true + +provisioner: + name: ansible +verifier: + name: ansible diff --git a/roles/vmstorage/molecule/default/tests/test_default.yml b/roles/vmstorage/molecule/default/tests/test_default.yml new file mode 100644 index 0000000..43592a3 --- /dev/null +++ b/roles/vmstorage/molecule/default/tests/test_default.yml @@ -0,0 +1,4 @@ +service: + "vmstorage": + enabled: true + running: true diff --git a/roles/vmstorage/molecule/default/verify.yml b/roles/vmstorage/molecule/default/verify.yml new file mode 100644 index 0000000..1a1bce3 --- /dev/null +++ b/roles/vmstorage/molecule/default/verify.yml @@ -0,0 +1,93 @@ +--- +# Molecule Goss Tests + +- name: Verify + hosts: all + become: true + vars: + goss_version: v0.3.10 + goss_arch: amd64 + goss_bin: /usr/local/bin/goss + goss_sha256sum: 150f25495ca0d1d4fd2ef8d0e750dbd767a15e9a522505f99b61dd1dd40a76d4 + goss_url: "https://github.com/aelsabbahy/goss/releases/download/{{ goss_version }}/goss-linux-{{ goss_arch }}" + goss_test_directory: /tmp/molecule/goss + goss_format: documentation + tasks: + - name: Download and install Goss + ansible.builtin.get_url: + url: "{{ goss_url }}" + dest: "{{ goss_bin }}" + sha256sum: "{{ goss_sha256sum }}" # noqa: args[module] + mode: "u=rwx,go=rx" + register: download_goss + until: download_goss is succeeded + retries: 3 + + - name: Create Molecule directory for test files + ansible.builtin.file: + path: "{{ goss_test_directory }}" + state: directory + mode: "0755" + + - name: Find Goss tests on localhost + ansible.builtin.find: + paths: "{{ lookup('env', 'MOLECULE_VERIFIER_TEST_DIRECTORY') }}" + patterns: + - "test[-.\\w]*.yml" + - "test_host_{{ ansible_hostname }}[-.\\w]*.yml" + excludes: + - "test_host_(?!{{ ansible_hostname }})[-.\\w]*.yml" + use_regex: true + delegate_to: localhost + register: test_files + changed_when: false + become: false + + - name: Debug + ansible.builtin.debug: + msg: "{{ test_files.files }}" + verbosity: 3 + + - name: Copy Goss tests to remote + ansible.builtin.copy: + src: "{{ item.path }}" + dest: "{{ goss_test_directory }}/{{ item.path | basename }}" + mode: "0644" + with_items: + - "{{ test_files.files }}" + loop_control: + label: "{{ item.path | basename }}" + + - name: Register test files + ansible.builtin.find: + paths: + - "{{ goss_test_directory }}" + patterns: + - "test_*.yml" + register: test_files + + - name: Run verify + when: test_files is succeeded + block: + - name: Execute Goss tests # noqa: no-changed-when + ansible.builtin.command: "{{ goss_bin }} -g {{ item }} validate --format {{ goss_format }}" + register: test_results + with_items: "{{ test_files.files | map(attribute='path') | list }}" + loop_control: + label: "{{ item | basename }}" + failed_when: false + + - name: Display details about the Goss results + ansible.builtin.debug: + msg: "{{ item.stdout_lines }}" + with_items: "{{ test_results.results }}" + loop_control: + label: "{{ item[item.ansible_loop_var] | basename }}" + + - name: Fail when tests fail + ansible.builtin.fail: + msg: "Goss failed to validate" + when: item.rc != 0 + with_items: "{{ test_results.results }}" + loop_control: + label: "{{ item[item.ansible_loop_var] | basename }}" diff --git a/roles/vmstorage/tasks/configure.yml b/roles/vmstorage/tasks/configure.yml new file mode 100644 index 0000000..72c3f5c --- /dev/null +++ b/roles/vmstorage/tasks/configure.yml @@ -0,0 +1,40 @@ +--- +- name: "Systemd | Copy vmstorage systemd unit file" + ansible.builtin.template: + src: vmstorage.service.j2 + dest: /etc/systemd/system/vmstorage.service + owner: root + group: root + mode: 0644 + notify: Restart vmstorage service + +- name: "Systemd | ensure vmstorage service is enabled" # noqa: no-handler + become: true + ansible.builtin.systemd: + name: vmstorage + enabled: true + +- name: Prepare configuration dir + ansible.builtin.file: + state: directory + path: "{{ vmstorage_config_dir }}" + mode: 0751 + owner: "{{ vmstorage_system_user }}" + group: "{{ vmstorage_system_group }}" + +- name: Setup environment file + ansible.builtin.template: + dest: "{{ vmstorage_config_dir }}/vmstorage.conf" + src: "vmstorage.conf.j2" + owner: "{{ vmstorage_system_user }}" + group: "{{ vmstorage_system_group }}" + mode: 0644 + notify: Restart vmstorage service + +- name: Prepare data dir + ansible.builtin.file: + state: directory + path: "{{ vmstorage_data_dir }}" + mode: 0751 + owner: "{{ vmstorage_system_user }}" + group: "{{ vmstorage_system_group }}" diff --git a/roles/vmstorage/tasks/install.yml b/roles/vmstorage/tasks/install.yml new file mode 100644 index 0000000..650ebd9 --- /dev/null +++ b/roles/vmstorage/tasks/install.yml @@ -0,0 +1,98 @@ +--- +- name: Create vmstorage system group + ansible.builtin.group: + name: "{{ vmstorage_system_group }}" + state: present + system: true + when: vmstorage_system_group != "root" + +- name: Create vmstorage system user + ansible.builtin.user: + name: "{{ vmstorage_system_user }}" + groups: "{{ vmstorage_system_group }}" + append: true + shell: /usr/sbin/nologin + system: true + createhome: false + when: vmstorage_system_user != "root" + +- name: Ensure existence of /usr/local/bin + ansible.builtin.file: + path: /usr/local/bin + state: directory + mode: 0755 + +- name: Delete existing vmstorage version if it's different. + ansible.builtin.file: + path: /usr/local/bin/vmstorage-prod + state: absent + when: + - vmstorage_is_installed.stat.exists | bool + - vmstorage_version not in vmstorage_current_version.stdout + +- name: Install via control host + when: vmstorage_install_download_to_control + block: + - name: Download and unarchive vmstorage release binary + environment: + http_proxy: "{{ vm_proxy_http }}" + https_proxy: "{{ vm_proxy_https }}" + ansible.builtin.unarchive: + src: "{{ vmstorage_download_url }}" + dest: /tmp + remote_src: yes + delegate_to: localhost + become: no + when: + - not ansible_check_mode + - not vmstorage_is_installed.stat.exists or + vmstorage_version not in vmstorage_current_version.stdout + + - name: Copy vmstorage binary to target host + notify: Restart vmstorage service + ansible.builtin.copy: + src: /tmp/vmstorage-prod + dest: /tmp/vmstorage-prod + mode: 0751 + owner: "{{ vmstorage_system_user }}" + group: "{{ vmstorage_system_group }}" + when: + - not ansible_check_mode + - not vmstorage_is_installed.stat.exists or + vmstorage_version not in vmstorage_current_version.stdout + + - name: Replace vmstorage binary at target dir # noqa: no-changed-when + notify: Restart vmstorage service + ansible.builtin.shell: | + mv /tmp/vmstorage-prod /usr/local/bin/vmstorage-prod + when: + - not ansible_check_mode + - not vmstorage_is_installed.stat.exists or + vmstorage_version not in vmstorage_current_version.stdout + +- name: Install directly to target host + when: not vmstorage_install_download_to_control + block: + - name: Download and unarchive vmstorage release binary + environment: + http_proxy: "{{ vm_proxy_http }}" + https_proxy: "{{ vm_proxy_https }}" + ansible.builtin.unarchive: + src: "{{ vmstorage_download_url }}" + dest: /tmp + remote_src: yes + when: + - not ansible_check_mode + - not vmstorage_is_installed.stat.exists or + vmstorage_version not in vmstorage_current_version.stdout + + - name: Replace vmstorage binary at target dir # noqa: no-changed-when + notify: Restart vmstorage service + ansible.builtin.shell: | + mv /tmp/vmstorage-prod /usr/local/bin/vmstorage-prod + chmod 0751 /usr/local/bin/vmstorage-prod + chown {{ vmstorage_system_user }}:{{ vmstorage_system_group }} /usr/local/bin/vmstorage-prod + when: + - not ansible_check_mode + - not vmstorage_is_installed.stat.exists or + vmstorage_version not in vmstorage_current_version.stdout diff --git a/roles/vmstorage/tasks/main.yml b/roles/vmstorage/tasks/main.yml new file mode 100644 index 0000000..f9ae994 --- /dev/null +++ b/roles/vmstorage/tasks/main.yml @@ -0,0 +1,7 @@ +--- +- name: Preinstall checks + ansible.builtin.import_tasks: preinstall.yml +- name: Install + ansible.builtin.import_tasks: install.yml +- name: Configure + ansible.builtin.import_tasks: configure.yml diff --git a/roles/vmstorage/tasks/preinstall.yml b/roles/vmstorage/tasks/preinstall.yml new file mode 100644 index 0000000..e189c51 --- /dev/null +++ b/roles/vmstorage/tasks/preinstall.yml @@ -0,0 +1,32 @@ +--- +- name: Assert usage of systemd or upstart as an init system + ansible.builtin.assert: + that: ansible_service_mgr == 'systemd' + msg: "This role only works with systemd" + +- name: Get systemd version + ansible.builtin.command: systemctl --version + changed_when: false + check_mode: false + register: __systemd_version + when: ansible_service_mgr == 'systemd' + +- name: Set systemd version fact + ansible.builtin.set_fact: + vmstorage_systemd_version: "{{ __systemd_version.stdout_lines[0].split(' ')[-1] }}" + when: ansible_service_mgr == 'systemd' + +- name: Check if vmstorage is installed + ansible.builtin.stat: + path: /usr/local/bin/vmstorage-prod + changed_when: false + check_mode: false + register: vmstorage_is_installed + +- name: Check current vmstorage version + ansible.builtin.command: /usr/local/bin/vmstorage-prod --version + changed_when: false + failed_when: false + check_mode: false + register: vmstorage_current_version + when: vmstorage_is_installed.stat.exists | bool diff --git a/roles/vmstorage/templates/vmstorage.conf.j2 b/roles/vmstorage/templates/vmstorage.conf.j2 new file mode 100644 index 0000000..bc6ff40 --- /dev/null +++ b/roles/vmstorage/templates/vmstorage.conf.j2 @@ -0,0 +1,5 @@ +{{ ansible_managed | comment }} + +{% for key, value in vmstorage_config.items() | default({}) %} +{{- key }}={{ value }} +{% endfor %} diff --git a/roles/vmstorage/templates/vmstorage.service.j2 b/roles/vmstorage/templates/vmstorage.service.j2 new file mode 100644 index 0000000..6284d40 --- /dev/null +++ b/roles/vmstorage/templates/vmstorage.service.j2 @@ -0,0 +1,35 @@ +{{ ansible_managed | comment }} +[Unit] +Description=VictoriaMetrics vmstorage service +After=network.target + +[Service] +Type=simple +User={{ vmstorage_system_user }} +Group={{ vmstorage_system_group }} +Restart=always +EnvironmentFile={{ vmstorage_config_dir }}/vmstorage.conf +ExecStart={{ vmstorage_bin_dir }}/vmstorage-prod -envflag.enable + +PrivateTmp=yes +ProtectHome={{ vmstorage_systemd_protect_home }} +NoNewPrivileges=yes + +ProtectSystem=full + +{% if vmstorage_systemd_version | int >= 232 %} +ProtectControlGroups=true +ProtectKernelModules=true +ProtectKernelTunables=yes +{% endif %} + +{% if vmstorage_exec_start_post != "" %} +ExecStartPost={{ vmstorage_exec_start_post }} +{% endif %} + +{% if vmstorage_exec_stop != "" %} +ExecStop={{ vmstorage_exec_stop }} +{% endif %} + +[Install] +WantedBy=multi-user.target diff --git a/roles/vmstorage/vars/main.yml b/roles/vmstorage/vars/main.yml new file mode 100644 index 0000000..f1b3a4a --- /dev/null +++ b/roles/vmstorage/vars/main.yml @@ -0,0 +1,9 @@ +--- +go_arch_map: + i386: '386' + x86_64: 'amd64' + aarch64: 'arm64' + armv7l: 'arm' + armv6l: 'arm6vl' + +go_arch: "{{ go_arch_map[ansible_architecture] | default(ansible_architecture) }}"