Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README-ansible-galaxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ These roles should be called together, we advise using the `seapath_setup_harden

## Management

- `deploy_prometheus_exporters`: Deploy Prometheus exporters as Podman quadlet services
- `snmp`: Configure SNMP
- `vmmgrapi`: Configure the vm manager API

Expand Down Expand Up @@ -190,6 +191,7 @@ The other playbooks can be called alone to re-configure a specific part, when yo

## Management

- `seapath_setup_prometheus_exporters.yaml`: Deploy Prometheus exporters per host group
- `seapath_setup_snmp.yaml`: Configure SNMP on all machines
- `seapath_setup_vmmgrapi.yaml`: Configure vm-mgr API on all machines

Expand Down
3 changes: 3 additions & 0 deletions playbooks/seapath_setup_main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@
- name: Import seapath_setup_snmp playbook
import_playbook: seapath_setup_snmp.yaml

- name: Import seapath_setup_prometheus_exporters playbook
import_playbook: seapath_setup_prometheus_exporters.yaml

- name: Import cluster_setup_cephadm playbook
import_playbook: cluster_setup_cephadm.yaml

Expand Down
12 changes: 12 additions & 0 deletions playbooks/seapath_setup_prometheus_exporters.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright (C) 2026 RTE
# SPDX-License-Identifier: Apache-2.0

---
- name: Deploy prometheus exporters
hosts:
- cluster_machines
- standalone_machine
become: true
roles:
- detect_seapath_distro
- deploy_prometheus_exporters
37 changes: 32 additions & 5 deletions roles/cephadm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ The `cephadm_install` role must have been applied to `cluster_machines` before t

## Role Variables

| Variable | Required | Type | Default | Comments |
|------------------------|----------|--------|--------------|---------------------------------------------------------------------------------------|
| cephadm_release | No | String | "20.2.0" | Version of the ceph container image |
| cephadm_spec_path | No | String | spec.yaml.j2 | Path to the spec file of cephadm. Use it to override the default config |
| cephadm_network | Yes | String | | Ceph network (e.g. "192.168.55.0/24") |
| Variable | Required | Type | Default | Comments |
|-----------------------------------|----------|---------|--------------|---------------------------------------------------------------------------------------|
| seapath_distro | No | String | Not set | SEAPATH distribution |
| cephadm_release | No | String | "20.2.0" | Version of the ceph container image |
| cephadm_spec_path | No | String | spec.yaml.j2 | Path to the spec file of cephadm. Use it to override the default config |
| cephadm_network | Yes | String | | Ceph network (e.g. "192.168.55.0/24") |
| cephadm_prometheus_exporter_enabled | No | Boolean | `true` | Enable the built-in Ceph mgr prometheus module after the cluster is healthy |
| cephadm_prometheus_listen_address | No | String | see defaults | Administration IP the mgr prometheus exporter binds to on each host. Defaults to `ip_addr`, same as `deploy_prometheus_exporters_listen_address`. Override per host in inventory if needed. |

Note that for each node you want in the cluster, those host vars need to be defined:

Expand Down Expand Up @@ -68,6 +71,30 @@ the whole-disk layout, remove its OSD with `ceph orch osd rm`, remove the LVM
layout of the disk, and re-run the playbook with the disk in
`ceph_osd_disks`.

## Ceph prometheus exporter

When `cephadm_prometheus_exporter_enabled` is `true` (default), the role enables the
built-in Ceph mgr prometheus module once the cluster reaches `HEALTH_OK`:

- `ceph mgr module enable prometheus`
- `ceph config set mgr mgr/prometheus/exclude_perf_counters false`
- `ceph config set mgr.<hostname>.<id> mgr/prometheus/server_addr <admin-ip>` on each mgr
daemon, using `cephadm_prometheus_listen_address` (defaults to `ip_addr`, same as
`deploy_prometheus_exporters_listen_address`)

The role discovers mgr daemon names with `ceph orch ps --daemon-type=mgr`, matches each
daemon to an inventory host via the `hostname` host variable, and sets the listen address
to that host's administration IP.

This exporter is part of the Ceph cluster (mgr daemon, port 9283). It is separate
from the host-level exporters deployed by the `deploy_prometheus_exporters` role.

The cluster bootstrap uses `--skip-monitoring-stack`, so Ceph does not deploy its own
Prometheus server. Configure an external Prometheus scrape job for the mgr endpoints
after this role runs.

Set `cephadm_prometheus_exporter_enabled: false` to skip this step.

## Example Playbook

```yaml
Expand Down
2 changes: 2 additions & 0 deletions roles/cephadm/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@

---
cephadm_release: "20.2.0"
cephadm_prometheus_exporter_enabled: true
cephadm_prometheus_listen_address: "{{ ip_addr | default(ansible_host) }}"
69 changes: 69 additions & 0 deletions roles/cephadm/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,75 @@
delegate_to: "{{ cephadm_first_node }}"
until: cephadm_cephs.stdout | from_json | community.general.json_query('health.status') == "HEALTH_OK"

- name: Enable Ceph prometheus exporter
when: cephadm_prometheus_exporter_enabled | bool
block:
- name: List enabled Ceph mgr modules
ansible.builtin.command: ceph mgr module ls --format json
register: cephadm_mgr_modules
changed_when: false
run_once: true
delegate_to: "{{ cephadm_first_node }}"

- name: Enable prometheus mgr module
ansible.builtin.command: ceph mgr module enable prometheus
when: >-
'prometheus' not in (
cephadm_mgr_modules.stdout | from_json
).enabled_modules | default([])
changed_when: true
run_once: true
delegate_to: "{{ cephadm_first_node }}"

- name: Get prometheus perf counter exclusion setting
ansible.builtin.command: ceph config get mgr mgr/prometheus/exclude_perf_counters
register: cephadm_prometheus_exclude_perf_counters
changed_when: false
failed_when: false
run_once: true
delegate_to: "{{ cephadm_first_node }}"

- name: Include all perf counters in prometheus exporter metrics
ansible.builtin.command: ceph config set mgr mgr/prometheus/exclude_perf_counters false
when: >-
cephadm_prometheus_exclude_perf_counters.rc != 0
or cephadm_prometheus_exclude_perf_counters.stdout | trim != 'false'
changed_when: true
run_once: true
delegate_to: "{{ cephadm_first_node }}"

- name: Get Ceph mgr daemons
ansible.builtin.command: ceph orch ps --daemon-type=mgr --format json
register: cephadm_mgr_ps
changed_when: false
run_once: true
delegate_to: "{{ cephadm_first_node }}"

- name: Bind mgr prometheus exporter to administration IP on each host
ansible.builtin.include_tasks: prometheus_mgr_bind.yml
vars:
host_hostname: "{{ hostvars[cephadm_target_host].hostname | default(cephadm_target_host) }}"
mgr_daemon: >-
{{
cephadm_mgr_ps.stdout | from_json
| selectattr('hostname', 'equalto', host_hostname)
| list | first | default(none)
}}
listen_address: >-
{{
hostvars[cephadm_target_host]['cephadm_prometheus_listen_address']
| default(
hostvars[cephadm_target_host]['ip_addr']
| default(hostvars[cephadm_target_host]['ansible_host'])
)
}}
when: mgr_daemon is not none
loop: "{{ groups['cluster_machines'] }}"
loop_control:
loop_var: cephadm_target_host
label: "{{ mgr_daemon.daemon_name | default(cephadm_target_host) }}"
run_once: true

- name: Check if RBD pool exists
ansible.builtin.shell:
cmd: set -o pipefail && ceph osd lspools | grep -w rbd
Expand Down
21 changes: 21 additions & 0 deletions roles/cephadm/tasks/prometheus_mgr_bind.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright (C) 2026 RTE
# SPDX-License-Identifier: Apache-2.0

---
- name: Get mgr prometheus server_addr
ansible.builtin.command: >-
ceph config get {{ mgr_daemon.daemon_name }} mgr/prometheus/server_addr
register: cephadm_mgr_prometheus_server_addr
failed_when: false
changed_when: false
delegate_to: "{{ cephadm_first_node }}"

- name: Set mgr prometheus server_addr to administration IP
ansible.builtin.command: >-
ceph config set {{ mgr_daemon.daemon_name }}
mgr/prometheus/server_addr {{ listen_address }}
when: >-
cephadm_mgr_prometheus_server_addr.rc != 0
or cephadm_mgr_prometheus_server_addr.stdout | trim != listen_address
changed_when: true
delegate_to: "{{ cephadm_first_node }}"
5 changes: 5 additions & 0 deletions roles/deploy_cukinia_tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ No requirement.
| `deploy_cukinia_tests_extra_essential_services` | list | `[]` | Additional systemd services to whitelist in the unrecognized services check (SEAPATH-00200). |
| `deploy_cukinia_tests_extra_essential_packages` | list | `[]` | Additional apt packages to whitelist in the unrecognized packages check (SEAPATH-00198). |

Roles may also publish extra essential services as drop-in files under
`/etc/cukinia/extra-essential-services.d/`. These files are read at
cukinia test runtime, even when tests are deployed or executed later in a
separate playbook run.

## Example Playbook
```yaml
- name: deploy cukinia tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,23 @@ cukinia_log "$(_colorize yellow "--- check systemd settings ---")"

test_id "SEAPATH-00199" as "No systemd service failed" cukinia_systemd_failed

ESSENTIAL_SERVICES_EXTRA=""
_cukinia_extra_services_dir="/etc/cukinia/extra-essential-services.d"
if [ -d "$_cukinia_extra_services_dir" ]; then
for _cukinia_extra_services_file in "$_cukinia_extra_services_dir"/*; do
[ -f "$_cukinia_extra_services_file" ] || continue
while IFS= read -r _cukinia_extra_service || [ -n "$_cukinia_extra_service" ]; do
case "$_cukinia_extra_service" in
''|\#*) continue ;;
esac
ESSENTIAL_SERVICES_EXTRA="${ESSENTIAL_SERVICES_EXTRA}|${_cukinia_extra_service}"
done < "$_cukinia_extra_services_file"
done
fi

{% if deploy_cukinia_tests_extra_essential_services | default([]) %}
ESSENTIAL_SERVICES_EXTRA="|\
ESSENTIAL_SERVICES_EXTRA="${ESSENTIAL_SERVICES_EXTRA}|\
{{ deploy_cukinia_tests_extra_essential_services | join('|\\\n') }}"
{% else %}
ESSENTIAL_SERVICES_EXTRA=""
{% endif %}

ESSENTIAL_SERVICES_DEBIAN="\
Expand Down
1 change: 1 addition & 0 deletions roles/deploy_cukinia_tests/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
group: false
rsync_opts:
- "--exclude=*.j2"
- "--exclude=extra-essential-services.d/"
- "--chmod=D0755,F0644"

- name: Copy Cukinia's tests templates
Expand Down
5 changes: 5 additions & 0 deletions roles/deploy_cukinia_tests/vars/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (C) 2026 RTE
# SPDX-License-Identifier: Apache-2.0
---
# Drop-in directory read at cukinia test runtime by systemd.conf (SEAPATH-00200).
deploy_cukinia_tests_extra_essential_services_dir: /etc/cukinia/extra-essential-services.d
141 changes: 141 additions & 0 deletions roles/deploy_prometheus_exporters/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Deploy Prometheus exporters Role

This role deploys Prometheus exporters as Podman quadlet container units under
`/etc/containers/systemd/`, then starts the corresponding systemd services.
Activation at boot comes from the `[Install]` section of the quadlet units.

The exporters are bound to the administration IP address, which defaults to the
standard SEAPATH `ip_addr` inventory variable.

## Requirements

- Podman with quadlet/systemd container support
- Yocto and SLES are not supported yet; the role is skipped when
`seapath_distro` is `Yocto` or `SLES` until compatibility is added
- `podman.socket` for the podman exporter (API socket at `/run/podman/podman.sock`)
- Libvirt socket access for libvirt and insatomcat exporters (`libvirtd.service` on
Debian, `virtqemud.service` on Oracle Linux)
- Pacemaker/Corosync tools on the host for the HA cluster exporter
- `seapath_distro` should be set, typically by calling `detect_seapath_distro`
before this role

## Role Variables

| Variable | Required | Type | Default | Comments |
|---|---|---|---|---|
| `deploy_prometheus_exporters_enabled` | No | Boolean | `true` | Set to `false` on Yocto and SLES until support is added |
| `deploy_prometheus_exporters_exporters` | No | List | see below | Exporters to deploy on the host |
| `deploy_prometheus_exporters_listen_address` | No | String | `"{{ ip_addr \| default(ansible_host) }}"` | IP address exporters listen on |
| `deploy_prometheus_exporters_images` | No | Dict | `{}` | Container images keyed by exporter name |
| `deploy_prometheus_exporters_node_exporter_image` | No | String | see defaults | Node exporter container image |
| `deploy_prometheus_exporters_podman_exporter_image` | No | String | see defaults | Podman exporter container image |
| `deploy_prometheus_exporters_libvirt_exporter_image` | No | String | see defaults | Libvirt exporter container image |
| `deploy_prometheus_exporters_insatomcat_exporter_image` | No | String | see defaults | Insatomcat exporter container image |
| `deploy_prometheus_exporters_ha_cluster_exporter_image` | No | String | see defaults | HA cluster exporter container image |
| `deploy_prometheus_exporters_manage_services` | No | Boolean | `true` | Start systemd units and restart them on unit file changes |
| `deploy_prometheus_exporters_register_essential_services` | No | Boolean | `true` | Publish deployed services for cukinia tests |
| `deploy_prometheus_exporters_libvirt_exporter_socket` | No | String | see vars | Host libvirt socket mounted in libvirt exporter |
| `deploy_prometheus_exporters_insatomcat_libvirt_socket` | No | String | see vars | Host libvirt socket mounted in insatomcat exporter |
| `deploy_prometheus_exporters_insatomcat_qemu_dir` | No | String | `/var/run/libvirt/qemu` | Host QEMU runtime dir for insatomcat exporter |
| `deploy_prometheus_exporters_libvirt_systemd_unit` | No | String | see vars | Libvirt systemd unit to order exporter startup after |

Default upstream images are defined in `vars/main.yml` under
`deploy_prometheus_exporters_default_images`. Libvirt socket paths and the
related systemd unit are defined in `vars/<seapath_distro>.yml`. Override them
per exporter with
either `deploy_prometheus_exporters_images` or the dedicated `*_image`
variables.

### Supported exporters

| Name | Port | Hosts |
|---|---|---|
| `node-exporter` | 9100 | all |
| `podman-exporter` | 9882 | hypervisors |
| `libvirt-exporter` | 9177 | hypervisors |
| `insatomcat-exporter` | 9184 | hypervisors |
| `ha_cluster_exporter` | 9664 | cluster machines |

### Default exporter selection

When `deploy_prometheus_exporters_exporters` is not overridden, exporters are
added from the inventory groups the host belongs to:

| Exporter | Added when the host is in |
|---|---|
| `node-exporter` | always |
| `ha_cluster_exporter` | `cluster_machines` |
| `podman-exporter`, `libvirt-exporter`, `insatomcat-exporter` | `hypervisors` |

Examples:

| Host | Groups | Result |
|---|---|---|
| Cluster hypervisor | `cluster_machines`, `hypervisors` | all exporters |
| Observer | `cluster_machines` only | node + ha cluster |
| Standalone hypervisor | `hypervisors` | node + podman + libvirt + insatomcat |
| VM | `VMs` | node only |

The mapping is defined in `vars/main.yml` as
`deploy_prometheus_exporters_group_exporters`.

### Libvirt socket paths per flavor

| Flavor | Libvirt exporter socket | insatomcat libvirt socket | systemd unit |
|---|---|---|---|
| Debian, CentOS, SLES | `/var/run/libvirt/libvirt-sock-ro` | `/var/run/libvirt/libvirt-sock` | `libvirtd.service` |
| Oracle Linux | `/run/libvirt/virtqemud-sock` | `/run/libvirt/virtqemud-sock` | `virtqemud.service` |

## Example Playbook

```yaml
- name: Deploy prometheus exporters
hosts:
- cluster_machines
- standalone_machine
- VMs
become: true
roles:
- detect_seapath_distro
- deploy_prometheus_exporters
```

The role derives the exporter list from the inventory groups. Override it
explicitly when needed:

```yaml
deploy_prometheus_exporters_exporters:
- node-exporter
```

## Offline or internal registry

When nodes cannot reach public registries, mirror the exporter images on a
local registry and override the image references from the inventory.

Override all images at once:

```yaml
# group_vars/all.yml
deploy_prometheus_exporters_images:
node-exporter: registry.local/seapath/node-exporter:1.8.2
podman-exporter: registry.local/seapath/prometheus-podman-exporter:1.14.0
libvirt-exporter: registry.local/seapath/prometheus-libvirt-exporter:2.3.1
insatomcat-exporter: registry.local/seapath/insatomcat-exporter:1.0.0
ha_cluster_exporter: registry.local/seapath/ha-cluster-exporter:0.0.1
```

Override a single exporter:

```yaml
deploy_prometheus_exporters_node_exporter_image: registry.local/seapath/node-exporter:1.8.2
```

Podman pulls the image when systemd starts each quadlet service. In offline
environments, point the image URLs to a reachable internal registry where the
images have been mirrored.

When cukinia tests are used, deployed exporter services are written to
`/etc/cukinia/extra-essential-services.d/deploy_prometheus_exporters`.
This drop-in is read at test runtime, so it still applies when cukinia tests
are deployed or executed in a separate playbook run.
Loading