1 Commits

Author SHA1 Message Date
bafa282482 Add grafana_alloy role: scrape log files to Loki 2026-07-06 13:07:50 +03:00
11 changed files with 264 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
# grafana_alloy
Install Grafana Alloy binary from GitHub.
Install Grafana Alloy from the release binary and configures it to scrape log files and push them to Loki. RHEL / CentOS / Rocky.
## Variables
```yaml
alloy_version: "1.17.1"
alloy_config_dir: "/etc/alloy"
alloy_data_dir: "/var/lib/alloy"
alloy_loki_url: "http://localhost:3100/loki/api/v1/push"
alloy_log_paths:
- "/var/log/*.log"
```
## Usage
```yaml
- hosts: log_shippers
become: true
roles:
- role: grafana_alloy
vars:
alloy_loki_url: "http://loki.example.com:3100/loki/api/v1/push"
alloy_log_paths:
- "/var/log/*.log"
- "/var/log/myapp/*.log"
```

View File

@@ -0,0 +1,7 @@
---
grafana_alloy_version: "1.17.1"
grafana_alloy_config_dir: "/etc/alloy"
grafana_alloy_data_dir: "/var/lib/alloy"
grafana_alloy_loki_url: "http://localhost:3100/loki/api/v1/push"
grafana_alloy_log_paths:
- "/var/log/*.log"

View File

@@ -0,0 +1,7 @@
---
- name: "(Re)start Alloy service"
ansible.builtin.systemd:
name: alloy.service
state: restarted
enabled: true
daemon_reload: true

View File

@@ -0,0 +1,6 @@
---
- name: Converge
hosts: all
roles:
- role: genlab.common.grafana_alloy

View File

@@ -0,0 +1,27 @@
---
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: rocky
image: geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux9}-ansible:latest
pre_build_image: true
command: ${MOLECULE_DOCKER_COMMAND:-""}
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:rw
cgroupns_mode: host
privileged: true
provisioner:
name: ansible
verifier:
name: ansible
lint: |
set -e
yamllint .
ansible-lint .

View File

@@ -0,0 +1,43 @@
---
- name: Verify
hosts: all
gather_facts: false
any_errors_fatal: true
tasks:
- name: "Include default vars"
ansible.builtin.include_vars:
dir: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') }}/defaults/"
extensions: ['yml']
- name: "Check if Alloy is installed"
changed_when: false
ansible.builtin.command: "alloy --version"
register: grafana_alloy_installed_version
- name: "Check Alloy version"
ansible.builtin.assert:
that: "grafana_alloy_version in grafana_alloy_installed_version.stdout"
success_msg: "Alloy version {{ grafana_alloy_version }} is available and executable"
fail_msg: "Alloy version {{ grafana_alloy_version }} not found or not executable"
- name: "Check if Alloy service is active"
ansible.builtin.systemd:
name: alloy
register: grafana_alloy_service
failed_when: "grafana_alloy_service.status.ActiveState != 'active'"
# kics-scan ignore-block
- name: "Check if Alloy is ready"
ansible.builtin.uri:
url: "http://localhost:12345/-/ready"
return_content: true
status_code: 200
method: GET
register: grafana_alloy_ready
- name: "Assert Alloy readiness"
ansible.builtin.assert:
that: "grafana_alloy_ready.content | trim == 'Alloy is ready.'"
success_msg: "Alloy is ready"
fail_msg: "Alloy is not ready"

View File

@@ -0,0 +1,10 @@
---
- name: "Configure | Deploy Alloy configuration"
notify: "(Re)start Alloy service"
ansible.builtin.template:
src: config.alloy.j2
dest: "{{ grafana_alloy_config_dir }}/config.alloy"
owner: "alloy"
group: "alloy"
mode: "0660"
validate: "alloy fmt %s"

View File

@@ -0,0 +1,71 @@
---
- name: "Install | Create Alloy system user"
ansible.builtin.user:
name: "alloy"
system: true
shell: "/sbin/nologin"
groups: "adm,systemd-journal"
append: true
create_home: false
state: present
- name: "Install | Create configuration and data directories"
loop:
- "{{ grafana_alloy_config_dir }}"
- "{{ grafana_alloy_data_dir }}"
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "alloy"
group: "alloy"
mode: "0755"
- name: "Install | Install the binary"
block:
- name: "Install | Check Alloy version"
changed_when: false
ansible.builtin.command:
cmd: "alloy --version"
register: grafana_alloy_ver
- name: "Install | Assert version correctness"
ansible.builtin.assert:
that: "grafana_alloy_version in grafana_alloy_ver.stdout"
success_msg: "alloy version {{ grafana_alloy_version }} is installed and working"
fail_msg: "alloy version {{ grafana_alloy_version }} is not installed or not working correctly"
rescue:
- name: "Install | Ensure unzip is present"
ansible.builtin.package:
name: "unzip"
state: present
- name: "Install | Fetch and unpack the distribution"
ansible.builtin.unarchive:
src: "https://github.com/grafana/alloy/releases/download/v{{ grafana_alloy_version }}/alloy-linux-amd64.zip"
dest: "/tmp"
remote_src: true
- name: "Install | Put the binary under the PATH"
notify: "(Re)start Alloy service"
ansible.builtin.copy:
remote_src: true
src: "/tmp/alloy-linux-amd64"
dest: "/usr/bin/alloy"
owner: "alloy"
group: "alloy"
mode: "0755"
- name: "Install | Clean up the downloads"
ansible.builtin.file:
path: "/tmp/alloy-linux-amd64"
state: absent
- name: "Install | Create a systemd service unit"
notify: "(Re)start Alloy service"
ansible.builtin.template:
src: alloy.service.j2
dest: /etc/systemd/system/alloy.service
owner: "alloy"
group: "alloy"
mode: "0660"

View File

@@ -0,0 +1,9 @@
---
- name: "Install Grafana Alloy from binary"
ansible.builtin.include_tasks: install.yml
- name: "Configure Alloy"
ansible.builtin.include_tasks: configure.yml
- name: "Flush handlers"
ansible.builtin.meta: "flush_handlers"

View File

@@ -0,0 +1,30 @@
[Unit]
Description=Grafana Alloy
Wants=network-online.target
After=network-online.target
Documentation="https://grafana.com/docs/alloy/"
[Service]
User=alloy
Group=alloy
Type=simple
Environment=HOSTNAME=%H
ExecStart=/usr/bin/alloy run {{ grafana_alloy_config_dir }}/config.alloy \
--storage.path={{ grafana_alloy_data_dir }} \
--server.http.listen-addr=127.0.0.1:12345 \
--disable-reporting
ExecReload=/bin/kill -HUP $MAINPID
# Security hardening
ReadWritePaths={{ grafana_alloy_data_dir }}
ProtectSystem=strict
NoNewPrivileges=true
PrivateTmp=true
ProtectKernelModules=true
ProtectControlGroups=true
ProtectKernelTunables=true
ProtectClock=yes
RestrictSUIDSGID=true
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,24 @@
// {{ ansible_managed }}
local.file_match "logs" {
path_targets = [
{% for path in grafana_alloy_log_paths %}
{__path__ = "{{ path }}", job = "varlogs", host = constants.hostname},
{% endfor %}
]
}
loki.source.file "logs" {
targets = local.file_match.logs.targets
forward_to = [loki.process.default.receiver]
}
loki.process "default" {
forward_to = [loki.write.default.receiver]
}
loki.write "default" {
endpoint {
url = "{{ grafana_alloy_loki_url }}"
}
}