feat(zfs): add capacity metrics and Grafana dashboard
Deploy an hourly systemd timer that writes pool and dataset capacity to node_exporter's textfile collector, since --collector.zfs exposes only ARC/I-O/state. Add a provisioned 'ZFS - Pools & Datasets' dashboard with per-pool totals, per-dataset used/quota and daily growth panels.
This commit is contained in:
@@ -0,0 +1,148 @@
|
|||||||
|
{
|
||||||
|
"title": "ZFS - Pools & Datasets",
|
||||||
|
"uid": "zfs",
|
||||||
|
"tags": ["zfs", "storage", "disks"],
|
||||||
|
"schemaVersion": 39,
|
||||||
|
"version": 1,
|
||||||
|
"refresh": "30m",
|
||||||
|
"time": { "from": "now-90d", "to": "now" },
|
||||||
|
"timezone": "browser",
|
||||||
|
"editable": true,
|
||||||
|
"graphTooltip": 1,
|
||||||
|
"templating": {
|
||||||
|
"list": [
|
||||||
|
{
|
||||||
|
"name": "pool",
|
||||||
|
"label": "Pool",
|
||||||
|
"type": "query",
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"query": { "query": "label_values(zfs_pool_size_bytes, pool)", "refId": "A" },
|
||||||
|
"refresh": 2,
|
||||||
|
"sort": 1,
|
||||||
|
"multi": true,
|
||||||
|
"includeAll": true,
|
||||||
|
"allValue": ".*",
|
||||||
|
"current": { "selected": true, "text": ["All"], "value": ["$__all"] }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dataset",
|
||||||
|
"label": "Dataset",
|
||||||
|
"type": "query",
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"query": { "query": "label_values(zfs_dataset_used_bytes, dataset)", "refId": "A" },
|
||||||
|
"refresh": 2,
|
||||||
|
"sort": 1,
|
||||||
|
"multi": true,
|
||||||
|
"includeAll": true,
|
||||||
|
"allValue": ".*",
|
||||||
|
"current": { "selected": true, "text": ["All"], "value": ["$__all"] }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"panels": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Pool Size",
|
||||||
|
"gridPos": { "h": 4, "w": 6, "x": 0, "y": 0 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "bytes", "color": { "mode": "none" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] } }, "overrides": [] },
|
||||||
|
"options": { "reduceOptions": { "values": false, "calcs": ["lastNotNull"], "fields": "" }, "colorMode": "value", "graphMode": "none", "textMode": "auto", "justifyMode": "auto", "orientation": "auto" },
|
||||||
|
"targets": [ { "refId": "A", "expr": "zfs_pool_size_bytes{pool=~\"$pool\"}", "legendFormat": "{{pool}}" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Pool Allocated",
|
||||||
|
"gridPos": { "h": 4, "w": 6, "x": 6, "y": 0 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "bytes", "color": { "mode": "none" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] } }, "overrides": [] },
|
||||||
|
"options": { "reduceOptions": { "values": false, "calcs": ["lastNotNull"], "fields": "" }, "colorMode": "value", "graphMode": "none", "textMode": "auto", "justifyMode": "auto", "orientation": "auto" },
|
||||||
|
"targets": [ { "refId": "A", "expr": "zfs_pool_alloc_bytes{pool=~\"$pool\"}", "legendFormat": "{{pool}}" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Pool Free",
|
||||||
|
"gridPos": { "h": 4, "w": 6, "x": 12, "y": 0 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "bytes", "color": { "mode": "none" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] } }, "overrides": [] },
|
||||||
|
"options": { "reduceOptions": { "values": false, "calcs": ["lastNotNull"], "fields": "" }, "colorMode": "value", "graphMode": "none", "textMode": "auto", "justifyMode": "auto", "orientation": "auto" },
|
||||||
|
"targets": [ { "refId": "A", "expr": "zfs_pool_free_bytes{pool=~\"$pool\"}", "legendFormat": "{{pool}}" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"type": "stat",
|
||||||
|
"title": "Pool Capacity",
|
||||||
|
"gridPos": { "h": 4, "w": 6, "x": 18, "y": 0 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "percent", "min": 0, "max": 100, "color": { "mode": "thresholds" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 80 }, { "color": "red", "value": 90 } ] } }, "overrides": [] },
|
||||||
|
"options": { "reduceOptions": { "values": false, "calcs": ["lastNotNull"], "fields": "" }, "colorMode": "background", "graphMode": "area", "textMode": "auto", "justifyMode": "auto", "orientation": "auto" },
|
||||||
|
"targets": [ { "refId": "A", "expr": "zfs_pool_capacity_percent{pool=~\"$pool\"}", "legendFormat": "{{pool}}" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "Pool usage over time",
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 4 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "bytes", "color": { "mode": "palette-classic" }, "custom": { "fillOpacity": 15, "lineWidth": 1, "drawStyle": "line", "showPoints": "never" } }, "overrides": [] },
|
||||||
|
"options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||||
|
"targets": [
|
||||||
|
{ "refId": "A", "expr": "zfs_pool_size_bytes{pool=~\"$pool\"}", "legendFormat": "{{pool}} size" },
|
||||||
|
{ "refId": "B", "expr": "zfs_pool_alloc_bytes{pool=~\"$pool\"}", "legendFormat": "{{pool}} alloc" },
|
||||||
|
{ "refId": "C", "expr": "zfs_pool_free_bytes{pool=~\"$pool\"}", "legendFormat": "{{pool}} free" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "Pool capacity %",
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 4 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "percent", "min": 0, "max": 100, "color": { "mode": "palette-classic" }, "custom": { "fillOpacity": 15, "lineWidth": 1, "drawStyle": "line", "showPoints": "never" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "orange", "value": 80 }, { "color": "red", "value": 90 } ] } }, "overrides": [] },
|
||||||
|
"options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||||
|
"targets": [ { "refId": "A", "expr": "zfs_pool_capacity_percent{pool=~\"$pool\"}", "legendFormat": "{{pool}}" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "Dataset used bytes",
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 12 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "bytes", "color": { "mode": "palette-classic" }, "custom": { "fillOpacity": 15, "lineWidth": 1, "drawStyle": "line", "showPoints": "never" } }, "overrides": [] },
|
||||||
|
"options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||||
|
"targets": [ { "refId": "A", "expr": "zfs_dataset_used_bytes{dataset=~\"$dataset\"}", "legendFormat": "{{dataset}}" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"type": "bargauge",
|
||||||
|
"title": "Dataset used (current)",
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 12 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "bytes", "min": 0, "color": { "mode": "continuous-GrYlRd" } }, "overrides": [] },
|
||||||
|
"options": { "displayMode": "gradient", "orientation": "horizontal", "reduceOptions": { "values": false, "calcs": ["lastNotNull"], "fields": "" }, "showUnfilled": true },
|
||||||
|
"targets": [ { "refId": "A", "expr": "zfs_dataset_used_bytes{dataset=~\"$dataset\"}", "legendFormat": "{{dataset}}" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "Daily growth - pool allocated (bytes/day)",
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 20 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "bytes", "color": { "mode": "palette-classic" }, "custom": { "fillOpacity": 15, "lineWidth": 1, "drawStyle": "line", "showPoints": "never" } }, "overrides": [] },
|
||||||
|
"options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||||
|
"targets": [ { "refId": "A", "expr": "deriv(zfs_pool_alloc_bytes{pool=~\"$pool\"}[1d]) * 86400", "legendFormat": "{{pool}}" } ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"type": "timeseries",
|
||||||
|
"title": "Daily growth - datasets (bytes/day)",
|
||||||
|
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 20 },
|
||||||
|
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||||
|
"fieldConfig": { "defaults": { "unit": "bytes", "color": { "mode": "palette-classic" }, "custom": { "fillOpacity": 15, "lineWidth": 1, "drawStyle": "line", "showPoints": "never" } }, "overrides": [] },
|
||||||
|
"options": { "legend": { "displayMode": "list", "placement": "bottom", "showLegend": true }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||||
|
"targets": [ { "refId": "A", "expr": "deriv(zfs_dataset_used_bytes{dataset=~\"$dataset\"}[1d]) * 86400", "legendFormat": "{{dataset}}" } ]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -260,6 +260,15 @@
|
|||||||
- systemd-dashboard.json
|
- systemd-dashboard.json
|
||||||
notify: Restart grafana
|
notify: Restart grafana
|
||||||
|
|
||||||
|
- name: Deploy ZFS dashboard
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: zfs-dashboard.json
|
||||||
|
dest: "{{ grafana_provisioning_path }}/dashboards/zfs.json"
|
||||||
|
owner: "{{ grafana_user }}"
|
||||||
|
group: "{{ grafana_group }}"
|
||||||
|
mode: "0644"
|
||||||
|
notify: Restart grafana
|
||||||
|
|
||||||
# Service management
|
# Service management
|
||||||
- name: Enable and start Grafana service
|
- name: Enable and start Grafana service
|
||||||
ansible.builtin.systemd:
|
ansible.builtin.systemd:
|
||||||
|
|||||||
+25
-1
@@ -1,4 +1,4 @@
|
|||||||
# Disks
|
# ZFS
|
||||||
|
|
||||||
Ansible community support for ZFS is limited to create filesystems, volumes and snapshots. There is no support for managing zpools, so here it is.
|
Ansible community support for ZFS is limited to create filesystems, volumes and snapshots. There is no support for managing zpools, so here it is.
|
||||||
|
|
||||||
@@ -36,6 +36,30 @@ zfs_datasets:
|
|||||||
quota: 500G
|
quota: 500G
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Prometheus metrics
|
||||||
|
|
||||||
|
The role deploys an hourly systemd timer (`zfs-metrics.timer`) running
|
||||||
|
`/usr/local/bin/zfs-metrics.sh`, which writes pool and dataset capacity to
|
||||||
|
node_exporter's textfile collector directory (`zfs_metrics_dir`). The
|
||||||
|
`node_exporter` role must be deployed on the host; the script exits silently
|
||||||
|
otherwise.
|
||||||
|
|
||||||
|
| Metric | Labels | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `zfs_pool_size_bytes` | `pool` | Total pool size |
|
||||||
|
| `zfs_pool_alloc_bytes` | `pool` | Allocated bytes |
|
||||||
|
| `zfs_pool_free_bytes` | `pool` | Free bytes |
|
||||||
|
| `zfs_pool_capacity_percent` | `pool` | Used capacity |
|
||||||
|
| `zfs_dataset_used_bytes` | `dataset` | Used bytes (incl. snapshots and children) |
|
||||||
|
| `zfs_dataset_refer_bytes` | `dataset` | Own referenced bytes |
|
||||||
|
| `zfs_dataset_quota_bytes` | `dataset` | Quota (0 = none) |
|
||||||
|
|
||||||
|
These feed the **ZFS - Pools & Datasets** Grafana dashboard. node_exporter's
|
||||||
|
built-in `--collector.zfs` exposes ARC, I/O and pool state only, not capacity.
|
||||||
|
|
||||||
|
Tunables (`defaults/main.yml`): `zfs_metrics_enabled`, `zfs_metrics_dir`,
|
||||||
|
`zfs_metrics_script_path`, `zfs_metrics_interval`.
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
- https://docs.ansible.com/ansible/latest/collections/community/general/zfs_module.html
|
- https://docs.ansible.com/ansible/latest/collections/community/general/zfs_module.html
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
# ZFS capacity metrics (Prometheus)
|
||||||
|
# ---------------------------------
|
||||||
|
# Exposes pool size/used/free and per-dataset used/quota to Prometheus via
|
||||||
|
# node_exporter's textfile collector. node_exporter's built-in --collector.zfs
|
||||||
|
# only exposes ARC, I/O and pool state — not capacity.
|
||||||
|
zfs_metrics_enabled: true
|
||||||
|
|
||||||
|
# Directory node_exporter's textfile collector reads `*.prom` files from.
|
||||||
|
# Must match node_exporter_textfile_dir in roles/node_exporter/defaults/main.yml.
|
||||||
|
zfs_metrics_dir: /var/lib/node_exporter/textfile_collector
|
||||||
|
|
||||||
|
# Where the collector script is installed.
|
||||||
|
zfs_metrics_script_path: /usr/local/bin/zfs-metrics.sh
|
||||||
|
|
||||||
|
# systemd OnCalendar expression for the collection timer. Hourly is plenty to
|
||||||
|
# track daily growth; Prometheus keeps 90d of history on andromeda.
|
||||||
|
zfs_metrics_interval: "hourly"
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
- name: Reload systemd
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
daemon_reload: true
|
||||||
@@ -5,3 +5,7 @@
|
|||||||
ansible.builtin.include_tasks: pools.yml
|
ansible.builtin.include_tasks: pools.yml
|
||||||
- name: "Setup ZFS datasets: filesystems, snapshots, volumes"
|
- name: "Setup ZFS datasets: filesystems, snapshots, volumes"
|
||||||
ansible.builtin.include_tasks: datasets.yml
|
ansible.builtin.include_tasks: datasets.yml
|
||||||
|
|
||||||
|
- name: Setup ZFS capacity metrics
|
||||||
|
ansible.builtin.include_tasks: metrics.yml
|
||||||
|
when: zfs_metrics_enabled | bool
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
---
|
||||||
|
# ZFS capacity metrics, exposed to Prometheus through node_exporter's textfile
|
||||||
|
# collector (see roles/node_exporter). Runs hourly as a root system timer.
|
||||||
|
|
||||||
|
- name: Deploy ZFS metrics script
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: zfs-metrics.sh.j2
|
||||||
|
dest: "{{ zfs_metrics_script_path }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Deploy ZFS metrics systemd service
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: zfs-metrics.service.j2
|
||||||
|
dest: /etc/systemd/system/zfs-metrics.service
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
notify: Reload systemd
|
||||||
|
|
||||||
|
- name: Deploy ZFS metrics systemd timer
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: zfs-metrics.timer.j2
|
||||||
|
dest: /etc/systemd/system/zfs-metrics.timer
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
notify: Reload systemd
|
||||||
|
|
||||||
|
- name: Flush handlers before enabling the timer
|
||||||
|
ansible.builtin.meta: flush_handlers
|
||||||
|
|
||||||
|
- name: Enable and start ZFS metrics timer
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: zfs-metrics.timer
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
|
||||||
|
- name: Collect ZFS metrics now
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: zfs-metrics.service
|
||||||
|
state: started
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Collect ZFS pool and dataset capacity metrics
|
||||||
|
After=zfs.target zfs-import.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart={{ zfs_metrics_script_path }}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Managed by Ansible - DO NOT EDIT MANUALLY
|
||||||
|
#
|
||||||
|
# Writes ZFS pool and dataset capacity metrics as Prometheus textfile metrics
|
||||||
|
# into node_exporter's textfile collector directory. node_exporter's built-in
|
||||||
|
# --collector.zfs exposes ARC, pool I/O and pool state only, not capacity.
|
||||||
|
set -eu
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
metrics_dir="{{ zfs_metrics_dir }}"
|
||||||
|
|
||||||
|
# node_exporter may not be deployed on this host.
|
||||||
|
[ -d "$metrics_dir" ] || exit 0
|
||||||
|
|
||||||
|
out="$metrics_dir/zfs.prom"
|
||||||
|
tmp="$out.tmp"
|
||||||
|
|
||||||
|
# Written atomically (tmp + mv) so the collector never reads a half-written file.
|
||||||
|
{
|
||||||
|
echo "# HELP zfs_pool_size_bytes Total size of the ZFS pool."
|
||||||
|
echo "# TYPE zfs_pool_size_bytes gauge"
|
||||||
|
echo "# HELP zfs_pool_alloc_bytes Allocated bytes in the ZFS pool."
|
||||||
|
echo "# TYPE zfs_pool_alloc_bytes gauge"
|
||||||
|
echo "# HELP zfs_pool_free_bytes Free bytes in the ZFS pool."
|
||||||
|
echo "# TYPE zfs_pool_free_bytes gauge"
|
||||||
|
echo "# HELP zfs_pool_capacity_percent Used capacity of the ZFS pool, in percent."
|
||||||
|
echo "# TYPE zfs_pool_capacity_percent gauge"
|
||||||
|
echo "# HELP zfs_dataset_used_bytes Used bytes of a ZFS dataset, including snapshots and children."
|
||||||
|
echo "# TYPE zfs_dataset_used_bytes gauge"
|
||||||
|
echo "# HELP zfs_dataset_refer_bytes Bytes referenced by a ZFS dataset itself."
|
||||||
|
echo "# TYPE zfs_dataset_refer_bytes gauge"
|
||||||
|
echo "# HELP zfs_dataset_quota_bytes Quota of a ZFS dataset in bytes (0 = no quota)."
|
||||||
|
echo "# TYPE zfs_dataset_quota_bytes gauge"
|
||||||
|
|
||||||
|
zpool list -Hp -o name,size,alloc,free,capacity | while read -r pool size alloc free capacity; do
|
||||||
|
echo "zfs_pool_size_bytes{pool=\"$pool\"} $size"
|
||||||
|
echo "zfs_pool_alloc_bytes{pool=\"$pool\"} $alloc"
|
||||||
|
echo "zfs_pool_free_bytes{pool=\"$pool\"} $free"
|
||||||
|
echo "zfs_pool_capacity_percent{pool=\"$pool\"} $capacity"
|
||||||
|
done
|
||||||
|
|
||||||
|
zfs list -Hp -o name,used,refer,quota -t filesystem | while read -r dataset used refer quota; do
|
||||||
|
echo "zfs_dataset_used_bytes{dataset=\"$dataset\"} $used"
|
||||||
|
echo "zfs_dataset_refer_bytes{dataset=\"$dataset\"} $refer"
|
||||||
|
echo "zfs_dataset_quota_bytes{dataset=\"$dataset\"} $quota"
|
||||||
|
done
|
||||||
|
} > "$tmp"
|
||||||
|
|
||||||
|
mv "$tmp" "$out"
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Timer for ZFS capacity metrics collection
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar={{ zfs_metrics_interval }}
|
||||||
|
Persistent=true
|
||||||
|
Unit=zfs-metrics.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
Reference in New Issue
Block a user