diff --git a/.github/workflows/promtail-molecule.yml b/.github/workflows/promtail-molecule.yml new file mode 100644 index 00000000..e8168b45 --- /dev/null +++ b/.github/workflows/promtail-molecule.yml @@ -0,0 +1,44 @@ +--- +name: Promtail Molecule + +on: + push: + branches: + - main + pull_request: + branches: + - main + +defaults: + run: + working-directory: roles/promtail + +jobs: + molecule: + name: Molecule + runs-on: ubuntu-latest + strategy: + matrix: + distro: + - rockylinux9 + - ubuntu2204 + - debian12 + + steps: + - name: Check out the codebase. + uses: actions/checkout@v4 + + - name: Set up Python 3. + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install test dependencies. + run: pip3 install ansible molecule molecule-plugins[docker] docker + + - name: Run Molecule tests. + run: molecule test + env: + PY_COLORS: '1' + ANSIBLE_FORCE_COLOR: '1' + MOLECULE_DISTRO: ${{ matrix.distro }} diff --git a/CODEOWNERS b/CODEOWNERS index 0be0ae86..9be7737a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -5,3 +5,4 @@ /roles/opentelemetry_collector @ishanjainn /roles/loki @voidquark @ishanjainn /roles/mimir @GVengelen @gardar @ishanjainn +/roles/promtail @voidquark @ishanjainn diff --git a/README.md b/README.md index 8b0df350..ceef02c7 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![GitHub Last Commit](https://img.shields.io/github/last-commit/grafana/grafana-ansible-collection)](https://github.com/grafana/grafana-ansible-collection/tags) [![GitHub Contributors](https://img.shields.io/github/contributors/grafana/grafana-ansible-collection)](https://github.com/grafana/grafana-ansible-collection/tags) -This collection (`grafana.grafana`) contains modules and roles to assist in automating the management of resources in **Grafana**, **Grafana Agent**, **OpenTelemetry Collector**, and **Loki** with Ansible. +This collection (`grafana.grafana`) contains modules and roles to assist in automating the management of resources in **Grafana**, **Grafana Agent**, **OpenTelemetry Collector**, **Loki**, **Mimir**, and **Promtail** with Ansible. - [Ansible collection Documentation](https://docs.ansible.com/ansible/latest/collections/grafana/grafana/) - [Grafana](https://grafana.com) @@ -43,12 +43,14 @@ collections: ## Roles included in the collection -This collection includes the following roles to help set up and manage Grafana, Grafana Agent, OpenTelemetry Collector, and Loki: +This collection includes the following roles to help set up and manage Grafana, Grafana Agent, OpenTelemetry Collector, Loki, Mimir and Promtail: - **Grafana**: Installs and configures Grafana on your target hosts. - **Grafana Agent**: Deploys and configures Grafana Agent, allowing for efficient metrics, logs, and trace data shipping to Grafana Cloud or other endpoints. - **OpenTelemetry Collector**: Sets up and configures the OpenTelemetry Collector, enabling advanced observability features through data collection and transmission. - **Loki**: Deploy and manage Loki, the log aggregation system. +- **Mimir**: Deploy and manage Mimir, the scalable long-term storage for Prometheus. +- **Promtail**: Deploy and manage Promtail, the agent which ships the contents of local logs to a private Grafana Loki. ## Using this collection diff --git a/examples/promtail-multiple-logs.yml b/examples/promtail-multiple-logs.yml new file mode 100644 index 00000000..d49f542a --- /dev/null +++ b/examples/promtail-multiple-logs.yml @@ -0,0 +1,24 @@ +--- +- name: Deploy Promtail to ship logs to the local Loki instance + hosts: all + become: true + roles: + - role: grafana.grafana.promtail + vars: + promtail_clients: + - url: http://localhost:3100/loki/api/v1/push + promtail_scrape_configs: + - job_name: system + static_configs: + - targets: + - localhost + labels: + job: messages + instance: "{{ ansible_fqdn }}" + __path__: /var/log/messages + - targets: + - localhost + labels: + job: nginx + instance: "{{ ansible_fqdn }}" + __path__: /var/log/nginx/*.log diff --git a/roles/promtail/README.md b/roles/promtail/README.md new file mode 100644 index 00000000..1fbcb550 --- /dev/null +++ b/roles/promtail/README.md @@ -0,0 +1,164 @@ +# Ansible role - Promtail + +[![License](https://img.shields.io/github/license/grafana/grafana-ansible-collection)](LICENSE) + +The Ansible Promtail Role allows you to effortlessly deploy and manage Promtail, agent which ships contents of local logs to private Loki. +This role is tailored for operating systems such as **RedHat**, **Rocky Linux**, **AlmaLinux**, **Ubuntu**, and **Debian**. + +**๐Ÿ”‘ Key Features** +- **โšก Root-less/Root runtime**: By default, Promtail operates in root-less mode, utilizing ACL (Access Control List) to securely access logs without requiring root permissions. You have the option to configure root mode if necessary. +- **๐Ÿงน Effortless Uninstall**: Easily remove Promtail from your system using the "promtail_uninstall" tag. + +๐Ÿ“ข **[Check the blog post](https://voidquark.com/blog/rootless-promtail-with-ansible/)** ๐Ÿ“ **Learn more about root-less mode.** + +## Table of Content + +- [Requirements](#requirements) +- [Role Variables](#role-variables) +- [Playbook](#playbook) + +## Requirements + +- Ansible 2.10+ + +## Role Variables + +```yaml +promtail_version: "latest" +``` +The version of Promtail to download and deploy. Supported standard version "3.0.0" format or "latest". + +```yaml +promtail_http_listen_port: 9080 +``` +The TCP port on which Promtail listens. By default, it listens on port `9080`. + +```yaml +promtail_http_listen_address: "0.0.0.0" +``` +The address on which Promtail listens for HTTP requests. By default, it listens on all interfaces. + +```yaml +promtail_expose_port: false +``` +By default, this is set to `false`. It supports only simple `firewalld` configurations. If set to `true`, a firewalld rule is added to expose the TCP `promtail_http_listen_port`. If set to `false`, configuration is skipped. If the `firewalld.service` is not active, all firewalld tasks are skipped. + +```yaml +promtail_positions_path: "/var/lib/promtail" +``` +Promtail path for position file. File indicating how far it has read into a file. It is needed for when Promtail is restarted to allow it to continue from where it left off. + +```yaml +promtail_runtime_mode: "acl" +``` +By default, Promtail runs in root-less mode. It supports two modes: +- `acl`: Root-less mode, utilizing ACL permission model to read target log files. +- `root`: Root mode, where Promtail runs as root and ACL configuration is skipped. + +```yaml +promtail_user_append_groups: + - "systemd-journal" +``` +Appends the promtail user to specific groups in root-less mode. By default, it appends the user to the `systemd-journal` group, granting permission to read system journal logs. + +```yaml +promtail_download_url_rpm: "https://github.com/grafana/loki/releases/download/v{{ promtail_version }}/promtail-{{ promtail_version }}.{{ __promtail_arch }}.rpm" +``` +The default download URL for the Promtail rpm package from GitHub. + +```yaml +promtail_download_url_deb: "https://github.com/grafana/loki/releases/download/v{{ promtail_version }}/promtail_{{ promtail_version }}_{{ __promtail_arch }}.deb" +``` +The default download URL for the Promtail deb package from GitHub. + +```yaml +promtail_server: + http_listen_port: "{{ promtail_http_listen_port }}" + http_listen_address: "{{ promtail_http_listen_address }}" +``` +The `server` block configures Promtail behavior as an HTTP server. [All possible values for `server`](https://grafana.com/docs/loki/latest/clients/promtail/configuration/#server) + +```yaml +promtail_positions: + filename: "{{ promtail_positions_path }}/positions.yaml" +``` +The `positions` block configures where Promtail will save a file indicating how far it has read into a file. It is needed for when Promtail is restarted to allow it to continue from where it left off. [All possible values for `positions`](https://grafana.com/docs/loki/latest/clients/promtail/configuration/#positions) + +```yaml +promtail_clients: + - url: http://localhost:3100/loki/api/v1/push +``` +The `clients` block configures how Promtail connects to instances of Loki. [All possible values for `clients`](https://grafana.com/docs/loki/latest/clients/promtail/configuration/#clients). โš ๏ธ This configuration is mandatory. By default, it's empty, and the example above serves as a simple illustration for inspiration. + +```yaml +promtail_scrape_configs: + - job_name: system + static_configs: + - targets: + - localhost + labels: + job: messages + instance: "{{ ansible_fqdn }}" + __path__: /var/log/messages + - targets: + - localhost + labels: + job: nginx + instance: "{{ ansible_fqdn }}" + __path__: /var/log/nginx/*.log +``` +The `scrape_configs` block configures how Promtail can scrape logs from a series of targets using a specified discovery method. [All possible values for `scrape_configs`](https://grafana.com/docs/loki/latest/clients/promtail/configuration/#scrape_configs). โš ๏ธ This configuration is mandatory. By default, it's empty, and the example above serves as a simple illustration for inspiration. + +| Variable Name | Description +| ----------- | ----------- | +| `promtail_limits_config` | The optional limits_config block configures global limits for this instance of Promtail. ๐Ÿ“š [documentation](https://grafana.com/docs/loki/latest/clients/promtail/configuration/#limits_config). +| `promtail_target_config` | The target_config block controls the behavior of reading files from discovered targets. ๐Ÿ“š [documentation](https://grafana.com/docs/loki/latest/clients/promtail/configuration/#target_config). + +## Dependencies + +No Dependencies + +## Playbook + +```yaml +- name: Manage promtail service + hosts: all + become: true + vars: + promtail_clients: + - url: http://localhost:3100/loki/api/v1/push + promtail_scrape_configs: + - job_name: system + static_configs: + - targets: + - localhost + labels: + job: messages + instance: "{{ ansible_fqdn }}" + __path__: /var/log/messages + - targets: + - localhost + labels: + job: nginx + instance: "{{ ansible_fqdn }}" + __path__: /var/log/nginx/*.log + roles: + - role: grafana.grafana.promtail +``` + +- Playbook execution example +```shell +# Deploy Promtail +ansible-playbook function_promtail_play.yml + +# Uninstall Promtail +ansible-playbook function_promtail_play.yml -t promtail_uninstall +``` + +## License + +See [LICENSE](https://github.com/grafana/grafana-ansible-collection/blob/main/LICENSE) + +## Author Information + +- [VoidQuark](https://github.com/voidquark) diff --git a/roles/promtail/defaults/main.yml b/roles/promtail/defaults/main.yml new file mode 100644 index 00000000..277037bf --- /dev/null +++ b/roles/promtail/defaults/main.yml @@ -0,0 +1,47 @@ +--- +# defaults file for promtail +promtail_version: "latest" +promtail_http_listen_port: 9080 +promtail_http_listen_address: "0.0.0.0" +promtail_expose_port: false +promtail_positions_path: "/var/lib/promtail" +promtail_runtime_mode: "acl" # Supported "root" or "acl" + +promtail_user_append_groups: + - "systemd-journal" + +promtail_download_url_rpm: "https://github.com/grafana/loki/releases/download/v{{ promtail_version }}/promtail-{{ promtail_version }}.{{ __promtail_arch }}.rpm" +promtail_download_url_deb: "https://github.com/grafana/loki/releases/download/v{{ promtail_version }}/promtail_{{ promtail_version }}_{{ __promtail_arch }}.deb" + +# default variables for /etc/promtail/config.yml +promtail_server: + http_listen_port: "{{ promtail_http_listen_port }}" + http_listen_address: "{{ promtail_http_listen_address }}" + +promtail_positions: + filename: "{{ promtail_positions_path }}/positions.yaml" + +promtail_clients: [] +# promtail_clients: +# - url: http://localhost:3100/loki/api/v1/push + +promtail_scrape_configs: [] +# promtail_scrape_configs: +# - job_name: system +# static_configs: +# - targets: +# - localhost +# labels: +# job: messages +# instance: "{{ ansible_fqdn }}" +# __path__: /var/log/messages +# - targets: +# - localhost +# labels: +# job: nginx +# instance: "{{ ansible_fqdn }}" +# __path__: /var/log/nginx/*.log + +# not set by default +# promtail_limits_config: +# promtail_target_config: diff --git a/roles/promtail/handlers/main.yml b/roles/promtail/handlers/main.yml new file mode 100644 index 00000000..d9f17243 --- /dev/null +++ b/roles/promtail/handlers/main.yml @@ -0,0 +1,9 @@ +--- +# handlers file for promtail +- name: Restart promtail + listen: "restart promtail" + ansible.builtin.systemd: + daemon_reload: true + name: promtail.service + state: restarted + enabled: true diff --git a/roles/promtail/meta/main.yml b/roles/promtail/meta/main.yml new file mode 100644 index 00000000..c7cee9a2 --- /dev/null +++ b/roles/promtail/meta/main.yml @@ -0,0 +1,28 @@ +--- +galaxy_info: + role_name: promtail + author: voidquark + description: Manage Grafana Promtail Application + license: "GPL-3.0-or-later" + min_ansible_version: "2.10" + platforms: + - name: EL + versions: + - "9" + - "8" + - name: Fedora + versions: + - all + - name: Debian + versions: + - all + - name: Ubuntu + versions: + - all + galaxy_tags: + - promtail + - grafana + - logging + - monitoring + +dependencies: [] diff --git a/roles/promtail/molecule/default/converge.yml b/roles/promtail/molecule/default/converge.yml new file mode 100644 index 00000000..d9945b10 --- /dev/null +++ b/roles/promtail/molecule/default/converge.yml @@ -0,0 +1,15 @@ +--- +- name: Converge + hosts: all + vars: + promtail_scrape_configs: + - job_name: test + static_configs: + - targets: + - localhost + labels: + job: test + instance: "{{ ansible_fqdn }}" + __path__: /var/log/last* + roles: + - role: grafana.grafana.promtail diff --git a/roles/promtail/molecule/default/molecule.yml b/roles/promtail/molecule/default/molecule.yml new file mode 100644 index 00000000..339965a5 --- /dev/null +++ b/roles/promtail/molecule/default/molecule.yml @@ -0,0 +1,20 @@ +--- +dependency: + name: galaxy + options: + ignore-errors: true +driver: + name: docker +platforms: + - name: instance + image: "geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux8}-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 + playbooks: + converge: converge.yml diff --git a/roles/promtail/tasks/acl_configuration.yml b/roles/promtail/tasks/acl_configuration.yml new file mode 100644 index 00000000..65516b92 --- /dev/null +++ b/roles/promtail/tasks/acl_configuration.yml @@ -0,0 +1,116 @@ +--- +# tasks file for promtail deploy - acl configuration + +- name: Extract log files from static_configs - labels - path + ansible.builtin.set_fact: + __promtail_acl_log_files: >- + {{ + promtail_scrape_configs + | selectattr('static_configs', 'defined') + | map(attribute='static_configs') + | flatten + | map(attribute='labels') + | map(attribute='__path__') + | list + }} + +- name: Extract log dirs paths from static_configs - labels - path + ansible.builtin.set_fact: + __promtail_acl_log_dirs: >- + {{ + promtail_scrape_configs + | selectattr('static_configs', 'defined') + | map(attribute='static_configs') + | flatten + | map(attribute='labels') + | map(attribute='__path__') + | map('dirname') + | unique + | list + }} + +- name: Stat log dirs + ansible.builtin.stat: + path: "{{ item }}" + loop: "{{ __promtail_acl_log_dirs }}" + register: __promtail_stat_acl_log_dirs + +- name: Set recursive default ACL permission for log dirs + ansible.posix.acl: + path: "{{ item.item }}" + recursive: true + entity: promtail + etype: user + permissions: rx + default: true + state: present + loop: "{{ __promtail_stat_acl_log_dirs.results }}" + when: + - __promtail_stat_acl_log_dirs | length > 0 + - item.stat.exists + notify: restart promtail + +- name: Set ACL permission for log dirs + ansible.posix.acl: + path: "{{ item.item }}" + entity: promtail + etype: user + permissions: rx + state: present + loop: "{{ __promtail_stat_acl_log_dirs.results }}" + when: + - __promtail_stat_acl_log_dirs | length > 0 + - item.stat.exists + notify: restart promtail + +- name: Find all existing ACL log files + ansible.builtin.find: + paths: "{{ item | dirname }}" + patterns: "{{ item | basename }}" + loop: "{{ __promtail_acl_log_files }}" + register: __promtail_find_files + +- name: Define existing ACL log files + ansible.builtin.set_fact: + __promtail_existing_acl_log_files: "{{ __promtail_find_files.results | map(attribute='files') | flatten | map(attribute='path') }}" + +- name: Set ACL permission for existing log files + ansible.posix.acl: + path: "{{ item }}" + entity: promtail + etype: user + permissions: r + state: present + loop: "{{ __promtail_existing_acl_log_files }}" + when: + - __promtail_existing_acl_log_files | length > 0 + notify: restart promtail + +- name: Promtail ACL Logrotate + when: + - __promtail_acl_log_dirs | length > 0 + - __promtail_acl_log_files | length > 0 + block: + - name: Template promtail ACL config for Logrotate + ansible.builtin.template: + src: "promtail_acl.j2" + dest: "/etc/logrotate.d/promtail_acl" + owner: "root" + group: "root" + mode: "0644" + + - name: Ensure that Promtail dummy dir for logrotate ACL configuration exist + ansible.builtin.file: + path: "/var/log/dummy_promtail_acl" + state: directory + owner: "promtail" + group: "root" + mode: "0750" + + - name: Create dummy empty log file for logrotate ACL configuration to work + ansible.builtin.copy: + content: "" + dest: "/var/log/dummy_promtail_acl/dummy_promtail_acl.log" + owner: "promtail" + group: "root" + mode: 0600 diff --git a/roles/promtail/tasks/deploy.yml b/roles/promtail/tasks/deploy.yml new file mode 100644 index 00000000..483a9b1b --- /dev/null +++ b/roles/promtail/tasks/deploy.yml @@ -0,0 +1,139 @@ +--- +# tasks file for promtail deploy + +- name: Obtain the latest version from the GitHub repo + when: promtail_version == "latest" + block: + - name: Scrape Github API endpoint to obtain latest Promtail version + ansible.builtin.uri: + url: "https://api.github.com/repos/grafana/loki/releases/latest" + method: GET + body_format: json + become: false + delegate_to: localhost + run_once: true + register: __github_latest_version + + - name: Latest available Promtail version + ansible.builtin.set_fact: + promtail_version: "{{ __github_latest_version.json.tag_name | regex_replace('^v?(\\d+\\.\\d+\\.\\d+)$', '\\1') }}" + +- name: Verify current deployed version + block: + - name: Check if Promtail binary is present + ansible.builtin.stat: + path: "/usr/bin/promtail" + register: __already_deployed + + - name: Obtain current deployed Promtail version + ansible.builtin.command: + cmd: "/usr/bin/promtail --version" + changed_when: false + register: __current_deployed_version + when: __already_deployed.stat.exists | bool + +- name: Include RedHat/Rocky setup + ansible.builtin.include_tasks: + file: setup-RedHat.yml + when: ansible_os_family in ['RedHat', 'Rocky'] + +- name: Include Debian/Ubuntu setup + ansible.builtin.include_tasks: + file: setup-Debian.yml + when: ansible_os_family == 'Debian' + +- name: Ensure that Promtail position path exists + ansible.builtin.file: + path: "{{ promtail_positions_path }}" + state: directory + owner: "promtail" + group: "root" + mode: "0750" + notify: restart promtail + +- name: Template Promtail config - /etc/promtail/config.yml + ansible.builtin.template: + src: "config.yml.j2" + dest: "/etc/promtail/config.yml" + owner: "promtail" + group: "root" + mode: "0644" + validate: "/usr/bin/promtail -check-syntax -config.file %s" + notify: restart promtail + +- name: Template Promtail systemd - /etc/systemd/system/promtail.service + ansible.builtin.template: + src: "promtail.service.j2" + dest: "/etc/systemd/system/promtail.service" + owner: "root" + group: "root" + mode: "0644" + notify: restart promtail + +- name: Add the Promtail system user to additional group + ansible.builtin.user: + name: "promtail" + groups: "{{ item }}" + system: true + append: true + create_home: false + state: present + loop: "{{ promtail_user_append_groups }}" + when: + - promtail_user_append_groups | length > 0 + - promtail_runtime_mode == "acl" + +- name: Include Promtail ACL permission configuration + ansible.builtin.include_tasks: + file: "acl_configuration.yml" + when: + - promtail_scrape_configs | length > 0 + - promtail_runtime_mode == "acl" + +- name: Get firewalld state + ansible.builtin.systemd: + name: "firewalld" + register: __firewalld_service_state + +- name: Enable firewalld rule to expose Promtail tcp port {{ promtail_http_listen_port }} + ansible.posix.firewalld: + immediate: true + permanent: true + port: "{{ promtail_http_listen_port }}/tcp" + state: enabled + when: + - __firewalld_service_state.status.ActiveState == "active" + - promtail_expose_port | bool + +- name: Flush handlers after deployment + ansible.builtin.meta: flush_handlers + +- name: Ensure that Promtail is started + ansible.builtin.systemd: + name: promtail.service + state: started + +- name: Stat position file + ansible.builtin.stat: + path: "{{ promtail_positions_path }}/positions.yaml" + register: __promtail_stat_position_file + +- name: Ensure correct owner and group for Promtail position file + ansible.builtin.file: + path: "{{ promtail_positions_path }}/positions.yaml" + state: file + owner: "promtail" + notify: restart promtail + when: + - __promtail_stat_position_file.stat.exists + - promtail_runtime_mode == "acl" + +- name: Verify that Promtail URL is responding + ansible.builtin.uri: + url: "http://{{ promtail_http_listen_address }}:{{ promtail_http_listen_port }}/ready" + method: GET + register: promtail_verify_url_status_code + retries: 5 + delay: 8 + until: promtail_verify_url_status_code.status == 200 + when: promtail_expose_port | bool diff --git a/roles/promtail/tasks/main.yml b/roles/promtail/tasks/main.yml new file mode 100644 index 00000000..11bfdbf1 --- /dev/null +++ b/roles/promtail/tasks/main.yml @@ -0,0 +1,23 @@ +--- +# tasks file for promtail +- name: Include OS specific variables + ansible.builtin.include_vars: + file: "{{ ansible_os_family }}.yml" + +- name: Deploy Promtail service + ansible.builtin.include_tasks: + file: "deploy.yml" + apply: + tags: promtail_deploy + tags: promtail_deploy + +- name: Uninstall Promtail service + ansible.builtin.include_tasks: + file: "uninstall.yml" + apply: + tags: + - promtail_uninstall + - never + tags: + - promtail_uninstall + - never diff --git a/roles/promtail/tasks/setup-Debian.yml b/roles/promtail/tasks/setup-Debian.yml new file mode 100644 index 00000000..3192279e --- /dev/null +++ b/roles/promtail/tasks/setup-Debian.yml @@ -0,0 +1,14 @@ +--- +- name: APT - Ensure that ACL is present + ansible.builtin.apt: + name: "acl" + state: present + update_cache: yes + when: promtail_runtime_mode == "acl" + +- name: APT - Install Promtail + ansible.builtin.apt: + deb: "{{ promtail_download_url_deb }}" + state: present + notify: restart promtail + when: __current_deployed_version.stdout is not defined or promtail_version not in __current_deployed_version.stdout diff --git a/roles/promtail/tasks/setup-RedHat.yml b/roles/promtail/tasks/setup-RedHat.yml new file mode 100644 index 00000000..b50573da --- /dev/null +++ b/roles/promtail/tasks/setup-RedHat.yml @@ -0,0 +1,9 @@ +--- +- name: DNF - Install Promtail from remote URL + ansible.builtin.dnf: + name: "{{ promtail_download_url_rpm }}" + state: present + disable_gpg_check: true + notify: restart promtail + when: + - __current_deployed_version.stdout is not defined or promtail_version not in __current_deployed_version.stdout diff --git a/roles/promtail/tasks/uninstall.yml b/roles/promtail/tasks/uninstall.yml new file mode 100644 index 00000000..0cac84d8 --- /dev/null +++ b/roles/promtail/tasks/uninstall.yml @@ -0,0 +1,119 @@ +--- +# tasks file for promtail uninstall +- name: Stop Promtail service + ansible.builtin.systemd: # noqa ignore-errors + name: promtail + state: stopped + ignore_errors: true + +- name: Extract log files from static_configs - labels - path + ansible.builtin.set_fact: + __promtail_acl_log_files: >- + {{ + promtail_scrape_configs + | selectattr('static_configs', 'defined') + | map(attribute='static_configs') + | flatten + | map(attribute='labels') + | map(attribute='__path__') + | list + }} + +- name: Extract log dirs paths from static_configs - labels - path + ansible.builtin.set_fact: + __promtail_acl_log_dirs: >- + {{ + promtail_scrape_configs + | selectattr('static_configs', 'defined') + | map(attribute='static_configs') + | flatten + | map(attribute='labels') + | map(attribute='__path__') + | map('dirname') + | list + }} + +- name: Remove ACL Permission for log dirs - default + ansible.posix.acl: # noqa ignore-errors + path: "{{ item }}" + recursive: true + entity: promtail + etype: user + default: true + state: absent + loop: "{{ __promtail_acl_log_dirs }}" + ignore_errors: true + +- name: Remove ACL permission for log dirs + ansible.posix.acl: # noqa ignore-errors + path: "{{ item }}" + entity: promtail + etype: user + state: absent + loop: "{{ __promtail_acl_log_dirs }}" + ignore_errors: true + +- name: Find all existing ACL log files + ansible.builtin.find: + paths: "{{ item | dirname }}" + patterns: "{{ item | basename }}" + loop: "{{ __promtail_acl_log_files }}" + register: __promtail_find_files + +- name: Define existing ACL log files + ansible.builtin.set_fact: + __promtail_existing_acl_log_files: "{{ __promtail_find_files.results | map(attribute='files') | flatten | map(attribute='path') }}" + +- name: Remove ACL Permission for existing log files + ansible.posix.acl: # noqa ignore-errors + path: "{{ item }}" + entity: promtail + etype: user + state: absent + loop: "{{ __promtail_existing_acl_log_files }}" + ignore_errors: true + +- name: Uninstall Promtail rpm package + ansible.builtin.dnf: + name: "promtail" + state: absent + autoremove: true + when: ansible_os_family in ['RedHat', 'Rocky'] + +- name: Uninstall Promtail deb package + ansible.builtin.apt: + name: "promtail" + state: absent + purge: true + when: ansible_os_family == 'Debian' + +- name: Ensure that Promtail firewalld rule is not present - tcp port {{ promtail_http_listen_port }} + ansible.posix.firewalld: # noqa ignore-errors + immediate: true + permanent: true + port: "{{ promtail_http_listen_port }}/tcp" + state: disabled + ignore_errors: true + +- name: Remove Promtail directories" + ansible.builtin.file: + path: "{{ remove_me }}" + state: absent + loop: + - "/etc/promtail" + - "{{ promtail_positions_path }}" + - "/etc/logrotate.d/promtail_acl" + - "/var/log/dummy_promtail_acl" + loop_control: + loop_var: remove_me + +- name: Remove the Promtail system user + ansible.builtin.user: + name: "promtail" + force: true + state: absent + +- name: Remove Promtail system group + ansible.builtin.group: + name: "promtail" + state: absent diff --git a/roles/promtail/templates/config.yml.j2 b/roles/promtail/templates/config.yml.j2 new file mode 100644 index 00000000..83681310 --- /dev/null +++ b/roles/promtail/templates/config.yml.j2 @@ -0,0 +1,22 @@ +server: + {{ promtail_server | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }} +{% if promtail_positions is defined %} +positions: + {{ promtail_positions | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }} +{% endif %} +{% if promtail_clients is defined %} +clients: + {{ promtail_clients | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }} +{% endif %} +{% if promtail_scrape_configs is defined %} +scrape_configs: + {{ promtail_scrape_configs | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }} +{% endif %} +{% if promtail_limits_config is defined %} +limits_config: + {{ promtail_limits_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }} +{% endif %} +{% if promtail_target_config is defined %} +target_config: + {{ promtail_target_config | to_nice_yaml(indent=2,sort_keys=False) | indent(2, False) }} +{% endif %} diff --git a/roles/promtail/templates/promtail.service.j2 b/roles/promtail/templates/promtail.service.j2 new file mode 100644 index 00000000..6dc8384d --- /dev/null +++ b/roles/promtail/templates/promtail.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=Promtail service +After=network.target + +[Service] +Type=simple +{% if promtail_runtime_mode == "acl" %} +User=promtail +{% elif promtail_runtime_mode == "root" %} +User=root +{% endif %} +ExecStart=/usr/bin/promtail -config.file /etc/promtail/config.yml + +TimeoutSec = 60 +Restart = on-failure +RestartSec = 2 + +[Install] diff --git a/roles/promtail/templates/promtail_acl.j2 b/roles/promtail/templates/promtail_acl.j2 new file mode 100644 index 00000000..40090658 --- /dev/null +++ b/roles/promtail/templates/promtail_acl.j2 @@ -0,0 +1,13 @@ +/var/log/dummy_promtail_acl/dummy_promtail_acl.log +{ + copytruncate + postrotate +{% for each_dir in __promtail_acl_log_dirs %} + /usr/bin/setfacl -R -m d:u:promtail:rx {{ each_dir }} + /usr/bin/setfacl -m u:promtail:rx {{ each_dir }} +{% endfor %} +{% for each_log in __promtail_acl_log_files %} + /usr/bin/setfacl -m u:promtail:r {{ each_log }} +{% endfor %} + endscript +} diff --git a/roles/promtail/vars/Debian.yml b/roles/promtail/vars/Debian.yml new file mode 100644 index 00000000..f9d41b28 --- /dev/null +++ b/roles/promtail/vars/Debian.yml @@ -0,0 +1,5 @@ +--- +__promtail_arch_map: + x86_64: 'amd64' + +__promtail_arch: "{{ __promtail_arch_map[ansible_architecture] | default(ansible_architecture) }}" diff --git a/roles/promtail/vars/RedHat.yml b/roles/promtail/vars/RedHat.yml new file mode 100644 index 00000000..0954ee3d --- /dev/null +++ b/roles/promtail/vars/RedHat.yml @@ -0,0 +1,2 @@ +--- +__promtail_arch: "{{ ansible_architecture }}"