Update 4 files
- /roles/proxmox_base_setup/tasks/main.yml - /roles/proxmox_base_setup/templates/node_exporter.service.j2 - /roles/proxmox_base_setup/templates/storcli_metrics.sh.j2 - /roles/proxmox_base_setup/handlers/main.yml
This commit is contained in:
parent
cf6e70603e
commit
906555ab4b
19
roles/proxmox_base_setup/handlers/main.yml
Normal file
19
roles/proxmox_base_setup/handlers/main.yml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
- name: restart ssh
|
||||||
|
systemd:
|
||||||
|
name: ssh
|
||||||
|
state: restarted
|
||||||
|
|
||||||
|
- name: restart node_exporter
|
||||||
|
systemd:
|
||||||
|
name: node_exporter
|
||||||
|
state: restarted
|
||||||
|
daemon_reload: yes
|
||||||
|
enabled: yes
|
||||||
|
|
||||||
|
- name: restart storcli_metrics
|
||||||
|
systemd:
|
||||||
|
name: storcli_metrics.timer
|
||||||
|
state: restarted
|
||||||
|
daemon_reload: yes
|
||||||
|
when: storcli_available | default(false)
|
||||||
302
roles/proxmox_base_setup/tasks/main.yml
Normal file
302
roles/proxmox_base_setup/tasks/main.yml
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
---
|
||||||
|
- name: Update package cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
cache_valid_time: 86400
|
||||||
|
|
||||||
|
- name: Upgrade installed packages (safe — не трогает pve-kernel и pve-пакеты)
|
||||||
|
apt:
|
||||||
|
upgrade: safe
|
||||||
|
notify: reboot if kernel updated
|
||||||
|
|
||||||
|
- name: Install essential base packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- curl
|
||||||
|
- wget
|
||||||
|
- gnupg
|
||||||
|
- apt-transport-https
|
||||||
|
- ca-certificates
|
||||||
|
- lsb-release
|
||||||
|
- net-tools
|
||||||
|
- iproute2
|
||||||
|
- pciutils
|
||||||
|
- smartmontools
|
||||||
|
- htop
|
||||||
|
- vim
|
||||||
|
- bash-completion
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure 'locales' is installed (required for locale_gen)
|
||||||
|
apt:
|
||||||
|
name: locales
|
||||||
|
state: present
|
||||||
|
when: system_locale is defined and system_locale | length > 0
|
||||||
|
|
||||||
|
- name: Remove unused packages
|
||||||
|
apt:
|
||||||
|
autoremove: yes
|
||||||
|
autoclean: yes
|
||||||
|
|
||||||
|
- name: Disable IPv6 via sysctl
|
||||||
|
sysctl:
|
||||||
|
name: "{{ item.name }}"
|
||||||
|
value: "{{ item.value }}"
|
||||||
|
sysctl_set: yes
|
||||||
|
state: present
|
||||||
|
reload: yes
|
||||||
|
loop:
|
||||||
|
- { name: 'net.ipv6.conf.all.disable_ipv6', value: '1' }
|
||||||
|
- { name: 'net.ipv6.conf.default.disable_ipv6', value: '1' }
|
||||||
|
|
||||||
|
- name: Ensure /root/.bashrc exists
|
||||||
|
file:
|
||||||
|
path: /root/.bashrc
|
||||||
|
state: touch
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Add custom aliases and env to ~/.bashrc
|
||||||
|
blockinfile:
|
||||||
|
path: /root/.bashrc
|
||||||
|
marker: "# {mark} ANSIBLE MANAGED BLOCK: PROXMOX CUSTOM ALIASES"
|
||||||
|
block: |
|
||||||
|
# ——— Общие ———
|
||||||
|
alias rm='rm -i' # Защита от случайного удаления
|
||||||
|
alias cp='cp -i'
|
||||||
|
alias mv='mv -i'
|
||||||
|
alias ls='ls --color=auto'
|
||||||
|
alias ll='ls -lah'
|
||||||
|
alias l.='ls -d .* --color=auto'
|
||||||
|
alias mount='mount | column -t'
|
||||||
|
alias h='history'
|
||||||
|
alias c='clear'
|
||||||
|
alias now='date +%T'
|
||||||
|
alias nowdate='date +%Y-%m-%d'
|
||||||
|
alias ping5='ping -c 5'
|
||||||
|
alias ports='ss -tulnp' # современная замена netstat
|
||||||
|
alias meminfo='free -h'
|
||||||
|
alias psmem='ps aux --sort=-%mem | head -11'
|
||||||
|
|
||||||
|
# ——— Proxmox ———
|
||||||
|
alias lxcstat='pct list'
|
||||||
|
alias qmstat='qm list'
|
||||||
|
alias ha='pvecm status && pve-ha-manager status'
|
||||||
|
alias stor='pvesm status'
|
||||||
|
|
||||||
|
# ——— RAID / Диски ———
|
||||||
|
alias storcli='/opt/MegaRAID/storcli/storcli64'
|
||||||
|
|
||||||
|
# ——— Обновление ———
|
||||||
|
alias aptup='apt update && apt list --upgradable'
|
||||||
|
|
||||||
|
owner: root
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Configure timezone
|
||||||
|
timezone:
|
||||||
|
name: "{{ timezone }}"
|
||||||
|
|
||||||
|
- name: Generate system locale
|
||||||
|
locale_gen:
|
||||||
|
name: "{{ system_locale }}"
|
||||||
|
state: present
|
||||||
|
when: system_locale is defined and system_locale | length > 0
|
||||||
|
|
||||||
|
- name: Set default LANG in /etc/default/locale
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/default/locale
|
||||||
|
regexp: '^LANG='
|
||||||
|
line: "LANG={{ system_locale }}"
|
||||||
|
state: present
|
||||||
|
create: yes
|
||||||
|
when: system_locale is defined and system_locale | length > 0
|
||||||
|
|
||||||
|
- name: Ensure common dirs exist
|
||||||
|
file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
loop:
|
||||||
|
- /opt/scripts
|
||||||
|
- /etc/apt/keyrings
|
||||||
|
|
||||||
|
- name: Ensure python3-requests is available (for custom scripts)
|
||||||
|
apt:
|
||||||
|
name: python3-requests
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure SSH directory exists
|
||||||
|
file:
|
||||||
|
path: /root/.ssh
|
||||||
|
state: directory
|
||||||
|
mode: '0700'
|
||||||
|
|
||||||
|
- name: Add authorized SSH keys for root
|
||||||
|
authorized_key:
|
||||||
|
user: root
|
||||||
|
state: present
|
||||||
|
key: "{{ item }}"
|
||||||
|
loop: "{{ ssh_public_keys | default([]) }}"
|
||||||
|
|
||||||
|
- name: Harden SSH configuration
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/ssh/sshd_config
|
||||||
|
regexp: "^{{ item.key }}\\s"
|
||||||
|
line: "{{ item.key }} {{ item.value }}"
|
||||||
|
state: present
|
||||||
|
loop:
|
||||||
|
- { key: 'PasswordAuthentication', value: 'no' }
|
||||||
|
- { key: 'PermitRootLogin', value: 'prohibit-password' }
|
||||||
|
- { key: 'PubkeyAuthentication', value: 'yes' }
|
||||||
|
- { key: 'X11Forwarding', value: 'no' }
|
||||||
|
notify: restart ssh
|
||||||
|
|
||||||
|
# ========== Node Exporter ==========
|
||||||
|
- name: Create node_exporter user
|
||||||
|
user:
|
||||||
|
name: node_exporter
|
||||||
|
system: yes
|
||||||
|
shell: /usr/sbin/nologin
|
||||||
|
create_home: no
|
||||||
|
|
||||||
|
- name: Download node_exporter
|
||||||
|
get_url:
|
||||||
|
url: "https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz"
|
||||||
|
dest: /tmp/node_exporter-1.8.2.linux-amd64.tar.gz
|
||||||
|
checksum: "sha256:https://github.com/prometheus/node_exporter/releases/download/v1.8.2/sha256sums.txt"
|
||||||
|
mode: '0644'
|
||||||
|
timeout: 60
|
||||||
|
|
||||||
|
- name: Extract node_exporter
|
||||||
|
unarchive:
|
||||||
|
src: /tmp/node_exporter-1.8.2.linux-amd64.tar.gz
|
||||||
|
dest: /tmp/
|
||||||
|
remote_src: yes
|
||||||
|
creates: /tmp/node_exporter-1.8.2.linux-amd64/node_exporter
|
||||||
|
|
||||||
|
- name: Install node_exporter binary
|
||||||
|
copy:
|
||||||
|
src: /tmp/node_exporter-1.8.2.linux-amd64/node_exporter
|
||||||
|
dest: /usr/local/bin/node_exporter
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0755'
|
||||||
|
remote_src: yes
|
||||||
|
notify: restart node_exporter
|
||||||
|
|
||||||
|
- name: Create textfile_collector directory
|
||||||
|
file:
|
||||||
|
path: /var/lib/node_exporter/textfile_collector
|
||||||
|
state: directory
|
||||||
|
owner: node_exporter
|
||||||
|
group: node_exporter
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Deploy node_exporter systemd service
|
||||||
|
template:
|
||||||
|
src: node_exporter.service.j2
|
||||||
|
dest: /etc/systemd/system/node_exporter.service
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
notify: restart node_exporter
|
||||||
|
|
||||||
|
# ========== storcli — проверка и сбор метрик (без установки) ==========
|
||||||
|
- name: Detect MegaRAID controller (lspci check)
|
||||||
|
command: lspci -d 1000: | grep -q "MegaRAID"
|
||||||
|
register: lspci_megaraid
|
||||||
|
ignore_errors: yes
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Check storcli binary exists
|
||||||
|
stat:
|
||||||
|
path: /opt/MegaRAID/storcli/storcli64
|
||||||
|
register: storcli_bin
|
||||||
|
when: lspci_megaraid.rc == 0
|
||||||
|
|
||||||
|
- name: Ensure storcli symlink in PATH
|
||||||
|
file:
|
||||||
|
src: /opt/MegaRAID/storcli/storcli64
|
||||||
|
dest: /usr/local/bin/storcli
|
||||||
|
state: link
|
||||||
|
force: yes
|
||||||
|
when:
|
||||||
|
- lspci_megaraid.rc == 0
|
||||||
|
- storcli_bin.stat.exists
|
||||||
|
|
||||||
|
- name: Verify storcli functionality
|
||||||
|
command: storcli /call show
|
||||||
|
register: storcli_test
|
||||||
|
changed_when: false
|
||||||
|
failed_when:
|
||||||
|
- storcli_test.rc != 0
|
||||||
|
- "'Controller' not in storcli_test.stdout"
|
||||||
|
when:
|
||||||
|
- lspci_megaraid.rc == 0
|
||||||
|
- storcli_bin.stat.exists
|
||||||
|
|
||||||
|
- name: Set fact — storcli is available
|
||||||
|
set_fact:
|
||||||
|
storcli_available: true
|
||||||
|
when:
|
||||||
|
- lspci_megaraid.rc == 0
|
||||||
|
- storcli_bin.stat.exists
|
||||||
|
- storcli_test is success
|
||||||
|
|
||||||
|
- name: Set fact — storcli NOT available
|
||||||
|
set_fact:
|
||||||
|
storcli_available: false
|
||||||
|
when: not (lspci_megaraid.rc == 0 and storcli_bin.stat.exists)
|
||||||
|
|
||||||
|
# Сбор метрик ТОЛЬКО при наличии storcli
|
||||||
|
- name: Deploy storcli metrics script
|
||||||
|
template:
|
||||||
|
src: storcli_metrics.sh.j2
|
||||||
|
dest: /opt/scripts/storcli_metrics.sh
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0755'
|
||||||
|
when: storcli_available | default(false)
|
||||||
|
|
||||||
|
- name: Deploy storcli_metrics systemd units
|
||||||
|
block:
|
||||||
|
- name: Create storcli_metrics.service
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Collect RAID/disk metrics via storcli
|
||||||
|
After=network.target
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/opt/scripts/storcli_metrics.sh
|
||||||
|
User=root
|
||||||
|
StandardOutput=journal
|
||||||
|
StandardError=journal
|
||||||
|
dest: /etc/systemd/system/storcli_metrics.service
|
||||||
|
owner: root
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Create storcli_metrics.timer (every 5 min)
|
||||||
|
copy:
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Run storcli metrics collector every 5 minutes
|
||||||
|
Requires=storcli_metrics.service
|
||||||
|
[Timer]
|
||||||
|
OnBootSec=60
|
||||||
|
OnUnitActiveSec=5m
|
||||||
|
AccuracySec=1s
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
|
dest: /etc/systemd/system/storcli_metrics.timer
|
||||||
|
owner: root
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Enable & start storcli_metrics.timer
|
||||||
|
systemd:
|
||||||
|
name: storcli_metrics.timer
|
||||||
|
state: started
|
||||||
|
enabled: yes
|
||||||
|
daemon_reload: yes
|
||||||
|
when: storcli_available | default(false)
|
||||||
|
notify: restart storcli_metrics
|
||||||
31
roles/proxmox_base_setup/templates/node_exporter.service.j2
Normal file
31
roles/proxmox_base_setup/templates/node_exporter.service.j2
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Prometheus Node Exporter
|
||||||
|
Documentation=https://github.com/prometheus/node_exporter
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=node_exporter
|
||||||
|
Group=node_exporter
|
||||||
|
ExecStart=/usr/local/bin/node_exporter \
|
||||||
|
--collector.systemd \
|
||||||
|
--collector.processes \
|
||||||
|
--collector.cpu \
|
||||||
|
--collector.meminfo \
|
||||||
|
--collector.diskstats \
|
||||||
|
--collector.netdev \
|
||||||
|
--collector.filesystem \
|
||||||
|
--collector.loadavg \
|
||||||
|
--collector.time \
|
||||||
|
--collector.textfile.directory=/var/lib/node_exporter/textfile_collector \
|
||||||
|
--web.listen-address=0.0.0.0:9100
|
||||||
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
|
# Защита от атак и случайных ошибок
|
||||||
|
NoNewPrivileges=yes
|
||||||
|
ProtectSystem=strict
|
||||||
|
ProtectHome=yes
|
||||||
|
PrivateTmp=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
64
roles/proxmox_base_setup/templates/storcli_metrics.sh.j2
Normal file
64
roles/proxmox_base_setup/templates/storcli_metrics.sh.j2
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if (enc != "" && slot != "") {
|
||||||
|
# Вывести предыдущий диск
|
||||||
|
gsub(/ /, "_", model);
|
||||||
|
printf "storcli_disk_temp{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, (temp ~ /^[0-9]+$/ ? temp : 0)
|
||||||
|
printf "storcli_disk_state{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, state_num
|
||||||
|
printf "storcli_disk_media_error_count{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, media_err
|
||||||
|
printf "storcli_disk_other_error_count{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, other_err
|
||||||
|
}
|
||||||
|
enc=""; slot=""; model=""; temp=""; media_err=0; other_err=0; state_num=0
|
||||||
|
}
|
||||||
|
/Enclosure Device ID:/ { enc = $4 }
|
||||||
|
/Slot Number:/ { slot = $3 }
|
||||||
|
/Device Id:/ { if (enc == "") enc = $3 } # fallback
|
||||||
|
/Model Number:/ { model = $3 }
|
||||||
|
/Drive Temperature/ {
|
||||||
|
match($0, /([0-9]+)C/);
|
||||||
|
if (RSTART) temp = substr($0, RSTART, RLENGTH-1)
|
||||||
|
}
|
||||||
|
/Firmware state:/ {
|
||||||
|
state = $3
|
||||||
|
if (state ~ /Online/) state_num = 2
|
||||||
|
else if (state ~ /Unconfigured.*Good/) state_num = 1
|
||||||
|
else if (state ~ /Failed/) state_num = 3
|
||||||
|
else if (state ~ /Rebuild/) state_num = 4
|
||||||
|
else if (state ~ /Offline/) state_num = 0
|
||||||
|
else state_num = -1
|
||||||
|
}
|
||||||
|
/Media Error Count:/ { media_err = $4 }
|
||||||
|
/Other Error Count:/ { other_err = $4 }
|
||||||
|
END {
|
||||||
|
if (enc != "" && slot != "") {
|
||||||
|
gsub(/ /, "_", model);
|
||||||
|
printf "storcli_disk_temp{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, (temp ~ /^[0-9]+$/ ? temp : 0)
|
||||||
|
printf "storcli_disk_state{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, state_num
|
||||||
|
printf "storcli_disk_media_error_count{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, media_err
|
||||||
|
printf "storcli_disk_other_error_count{controller=\"%s\",enclosure=\"%s\",slot=\"%s\",model=\"%s\"} %s\n", c, enc, slot, model, other_err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
' c="$c")
|
||||||
|
|
||||||
|
echo "$disks_info" >> "$OUT_FILE"
|
||||||
|
|
||||||
|
# Виртуальные диски (массивы)
|
||||||
|
vds=$(storcli /c$c/vall show | awk '
|
||||||
|
NR>8 && $1 ~ /^[0-9]+$/ {
|
||||||
|
vd = $1; state = $2; size = $3;
|
||||||
|
gsub(/,/,"", size);
|
||||||
|
# state: Optl=Online(1), Dgrd=Degraded(2), Offln=Offline(0), Ft=Failed(3)
|
||||||
|
state_num = 1;
|
||||||
|
if (state == "Dgrd") state_num = 2;
|
||||||
|
else if (state ~ /Offln|Pdgd/) state_num = 0;
|
||||||
|
else if (state == "Ft") state_num = 3;
|
||||||
|
printf "storcli_array_state{controller=\"%s\",vd=\"%s\",size=\"%s\"} %s\n", c, vd, size, state_num
|
||||||
|
}
|
||||||
|
')
|
||||||
|
echo "$vds" >> "$OUT_FILE"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Атомарная замена
|
||||||
|
mv "$OUT_FILE" "$FINAL_FILE"
|
||||||
|
chmod 644 "$FINAL_FILE"
|
||||||
|
|
||||||
|
echo "$(date -Iseconds) storcli metrics updated" >&2
|
||||||
Loading…
Reference in New Issue
Block a user