alloy(role): pull in alloy role that works from fux (#112)
All checks were successful
/ build (push) Successful in 26s
/ Ansible Lint (push) Successful in 2m39s

Reviewed-on: #112
Reviewed-by: June <june@noreply.git.hamburg.ccc.de>
This commit is contained in:
chris 2026-07-23 20:34:02 +02:00 committed by chris
commit 900971ebe9
246 changed files with 222 additions and 19245 deletions

21
roles/alloy/README.md Normal file
View file

@ -0,0 +1,21 @@
# `Grafana Alloy` role
Installs and configures [Grafana Alloy](https://grafana.com/docs/alloy/latest/) on Debian-based systems.
Optionally deploys a [Blackbox exporter](https://github.com/prometheus/blackbox_exporter) config.
## Supported Distributions
Should work on Debian-based distributions.
## Required Arguments
- `alloy_config_default`: The default Alloy configuration. Recommended for configuration that hosts of a groupe share.
## Optional Arguments
- `alloy_config_additional`: Additional Alloy configuration appended to the default config. Recommended for per host configuration
- `alloy_cap_net_bind_service`: Grant Alloy the `CAP_NET_BIND_SERVICE` capability, allowing it to bind to privileged ports (<1024).
### Blackbox Exporter
- `alloy_blackbox_exporter_config_default`: Default blackbox exporter configuration.
- `alloy_blackbox_exporter_config_additional`: Additional blackbox exporter configuration appended to the default blackbox exporter config.

View file

@ -1,44 +1,49 @@
alloy_config_default: |
prometheus.remote_write "default" {
endpoint {
url = "https://metrics.hamburg.ccc.de/api/v1/write"
basic_auth {
username = "chaos"
password = "chaos_password"
}
}
}
prometheus.relabel "common" {
forward_to = [prometheus.remote_write.default.receiver]
rule {
target_label = "org"
replacement = "noorg"
}
rule {
target_label = "site"
replacement = "nosite"
}
rule {
source_labels = ["instance"]
target_label = "instance"
regex = "([^:]+)"
replacement = "${1}.hosts.test"
action = "replace"
}
}
logging {
level = "info"
}
prometheus.exporter.unix "local_system" {
enable_collectors = ["systemd"]
}
prometheus.scrape "scrape_metrics" {
targets = prometheus.exporter.unix.local_system.targets
forward_to = [prometheus.relabel.common.receiver]
}
---
alloy_cap_net_bind_service: false
alloy_config_default: ""
alloy_config_additional: ""
alloy_blackbox_exporter_config_default: |
modules:
https4_2xx:
prober: http
http:
valid_status_codes: [] # Defaults to 2xx
method: GET
follow_redirects: true
fail_if_ssl: false
fail_if_not_ssl: true
preferred_ip_protocol: "ip4"
ip_protocol_fallback: false
https6_2xx:
prober: http
http:
valid_status_codes: [] # Defaults to 2xx
method: GET
follow_redirects: true
fail_if_ssl: false
fail_if_not_ssl: true
preferred_ip_protocol: "ip6"
ip_protocol_fallback: false
tcp4_connect:
prober: tcp
tcp:
preferred_ip_protocol: "ip4"
ip_protocol_fallback: false
icmp4:
prober: icmp
icmp:
preferred_ip_protocol: "ip4"
ip_protocol_fallback: false
icmp6:
prober: icmp
icmp:
preferred_ip_protocol: "ip6"
ip_protocol_fallback: false
alloy_blackbox_exporter_config_additional: ""

View file

@ -0,0 +1,31 @@
---
- name: Alloy.enabled
become: true
ansible.builtin.systemd:
name: alloy
enabled: true
- name: Alloy.restarted
become: true
ansible.builtin.systemd:
name: alloy
state: restarted
enabled: true
- name: Alloy.reloaded
become: true
ansible.builtin.systemd:
name: alloy
state: reloaded
enabled: true
- name: Systemd.daemon_reload
become: true
ansible.builtin.systemd_service:
daemon_reload: true
- name: Unpoller.restarted
become: true
ansible.builtin.systemd_service:
name: unpoller.service
state: restarted

View file

@ -0,0 +1,19 @@
argument_specs:
main:
options:
alloy_config_default:
type: str
required: true
alloy_config_additional:
type: str
required: false
alloy_blackbox_exporter_config_default:
type: str
required: false
alloy_blackbox_exporter_config_additional:
type: str
required: false
alloy_cap_net_bind_service:
type: bool
required: false
default: false

View file

@ -0,0 +1,10 @@
---
- name: Render blackbox exporter config
become: true
ansible.builtin.template:
src: config.blackbox-exporter.j2
dest: /etc/alloy/blackbox-exporter.yaml
mode: "0644"
owner: root
notify:
- Alloy.reloaded

View file

@ -0,0 +1,20 @@
---
- name: Add grafana apt repo with signing key
become: true
ansible.builtin.deb822_repository:
name: grafana
types: deb
uris: https://apt.grafana.com
suites: "{{ ansible_facts['distribution_release'] }}"
components:
- main
signed_by: https://apt.grafana.com/gpg.key
- name: Run cache update
ansible.builtin.apt:
update_cache: true
- name: Install alloy
become: true
ansible.builtin.package:
name: alloy

View file

@ -1,50 +1,74 @@
# https://github.com/grafana/grafana-ansible-collection/blob/main/roles/alloy/tasks/deploy.yml#L124
- name: ensure alloy user exists
ansible.builtin.user:
name: alloy
system: true
append: true
create_home: false
state: present
- name: ensure the `/etc/alloy/` config directory exists
ansible.builtin.file:
path: /etc/alloy
state: directory
mode: "0770"
owner: root
group: alloy
become: true
- name: synchronize the additional configuration files directory, if present
when: alloy__additional_configs_dir is defined and alloy__additional_configs_dir != ""
---
- name: Deploy Grafana Alloy with config
block:
- name: ensure rsync is installed
ansible.builtin.apt:
name: rsync
- name: Install Alloy
ansible.builtin.include_tasks: install.yaml
- name: Create systemd override for alloy
become: true
when: alloy_cap_net_bind_service
notify: Systemd.daemon_reload
block:
- name: Create systemd override directory
ansible.builtin.file:
path: /etc/systemd/system/alloy.service.d
state: directory
mode: "0755"
owner: root
group: root
- name: Add CAP_NET_BIND_SERVICE capability
ansible.builtin.copy:
dest: /etc/systemd/system/alloy.service.d/override.conf
mode: "0755"
owner: root
group: root
content: |
[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE
- name: synchronize the additional configuration files directory, if present
ansible.posix.synchronize:
src: "{{ alloy__additional_configs_dir }}"
dest: /etc/alloy/additional
delete: true
recursive: true
use_ssh_args: true
rsync_opts:
- "--chown=root:alloy"
- name: Deploy the Alloy config file
become: true
ansible.builtin.template:
src: "config.alloy.j2"
dest: "/etc/alloy/config.alloy"
owner: "alloy"
group: "alloy"
mode: "0640"
notify:
- Alloy.restarted
- Alloy.enabled
- name: delete the additional configuration files directory, if not present
when: alloy__additional_configs_dir is not defined or alloy__additional_configs_dir == ""
ansible.builtin.file:
path: /etc/alloy/additional
state: absent
become: true
- name: Validate Alloy configuration and print error if failed
block:
- name: Validate Alloy configuration
become: true
register: alloy_validation
changed_when: false
ansible.builtin.command: alloy validate /etc/alloy/config.alloy
rescue:
- name: Show error if validation failed
when: alloy_validation.rc != 0
ansible.builtin.fail:
msg: |
Alloy configuration validation failed!
Return code: {{ alloy_validation.rc }}
Stdout:
{{ alloy_validation.stdout }}
Stderr:
{{ alloy_validation.stderr }}
- name: Setup Alloy
ansible.builtin.import_role:
name: grafana.grafana.alloy
vars:
alloy_config: "{{ alloy_config_default ~ alloy_config_additional }}"
become: true
- name: Deploy blackbox-exporter config
when: alloy_enable_blackbox_exporter
ansible.builtin.include_tasks: blackbox-exporter.yaml
- name: Flush handlers
ansible.builtin.meta: flush_handlers
- name: Ensure that Alloy is working
ansible.builtin.uri:
url: "http://localhost:12345/-/ready"
method: GET
register: alloy_status_code
retries: 8
delay: 6
until: not alloy_status_code.failed

View file

@ -0,0 +1,3 @@
// Ansible Managed
{{ alloy_config_default }}
{{ alloy_config_additional }}

View file

@ -0,0 +1,3 @@
# {{ ansible_managed }}
{{ alloy_blackbox_exporter_config_default }}
{{ alloy_blackbox_exporter_config_additional }}

View file

@ -0,0 +1,3 @@
---
alloy_enable_blackbox_exporter: "{{ 'prometheus.exporter.blackbox' in (alloy_config_default + alloy_config_additional) }}"
alloy_do_we_have_v6: "{{ (ansible_facts['all_ipv6_addresses'] | select('match', '^[23]') | list | length > 0) | ternary('true', 'false') }}"