Ansible 自动化运维实战:多节点 Homelab 一条命令全管,告别手动 SSH
玩 Homelab 的人迟早都会撞上同一堵墙…
玩 Homelab 的人迟早都会撞上同一堵墙:机器越堆越多,手动 SSH 越来越烦。我的情况是——一台 PVE 宿主机上面跑着几个虚拟机,两台专门的 AI 推理机器插着显卡,外带一个 5G 模组的边缘节点。以前每次更新系统、改个配置、批量看一眼显存占用,都得一台台登进去敲命令,重复劳动不说,还特别容易漏掉某一台。
后来我把这批机器全交给 Ansible 管了,日常运维从”挨个 SSH”变成”一条命令全搞定”。今天就把这套东西从头讲清楚:它是什么、怎么装、怎么写清单和 playbook,最后丢几个我在生产环境里真实在跑的模板。
为什么是 Ansible,而不是别的
自动化运维工具一堆:Puppet、Chef、SaltStack、Ansible。我的判断很简单——对 Homelab 这种规模,Ansible 最轻量,理由有三条:
- 无 Agent:被管机器不用装任何客户端,靠 SSH 直连就行。装 Agent 意味着每台机器多一个常驻进程、多一份维护负担,家用环境没必要。
- 幂等:同一个任务重复跑,结果一致。装软件只装一次,改配置只在真正变了才动,不会重复执行把环境搞坏。
- 声明式:用 YAML 写 playbook,描述”目标长什么样”,而不是手把手写”第一步干什么第二步干什么”。可读性比一堆 shell 脚本强太多。
一句话总结:Ansible 是给”不想在每台机器上装 Agent、又想批量管理”的人准备的。
安装:控制端一台就够
Ansible 只需要装在控制端一台机器上,我直接装在 PVE 宿主机里。被管的机器只要开着 SSH 就行,别的什么都不用装。
sudo apt update && sudo apt install -y ansible
想用更新一点的版本,也可以用 pip 装:
pip install ansible
装完验证一下:
ansible --version
第一步:写 inventory 主机清单
inventory 就是”我到底有哪些机器”。系统默认位置在 /etc/ansible/hosts,但我建议项目化,放到自己目录里,方便随代码一起管理。建一个 inventory.ini:
[all:vars]
ansible_user=root
ansible_ssh_private_key_file=~/.ssh/id_ed25519
[ai-nodes]
gpu01 ansible_host=192.168.1.10
gpu02 ansible_host=192.168.1.11
[pve]
pve ansible_host=192.168.1.2
[edge]
edge5g ansible_host=192.168.1.20
这里的关键是分组:ai-nodes 是跑模型的显卡机器,pve 是虚拟化宿主机,edge 是边缘节点。以后按组执行不同任务,比如”只给显卡机器装驱动”、”只给边缘节点同步配置”,互不干扰。
第二步:ad-hoc 命令,先尝个甜头
不用写 playbook 就能批量执行,这叫 ad-hoc 模式。先拿它做几件小事,感受一下:
# 一次性看所有机器内存
ansible all -i inventory.ini -m shell -a "free -h"
# 只看 AI 节点的显存占用
ansible ai-nodes -i inventory.ini -m shell -a "nvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader"
-m 指定模块,-a 是模块参数。shell 模块能跑任意命令,但它是”野蛮”的——不幂等。批量更新系统这种正经事,还是用专用模块更稳:
# 批量更新所有机器,-b 表示提权
ansible all -i inventory.ini -m apt -a "update_cache=yes upgrade=dist" -b
第三步:写第一个 playbook
ad-hoc 适合临时命令,重复任务就该沉淀成 playbook。下面这个 update.yml 是我定期跑的系统更新:
---
- name: 批量更新所有节点
hosts: all
become: yes
tasks:
- name: 刷新 apt 缓存
ansible.builtin.apt:
update_cache: yes
cache_valid_time: 3600
- name: 升级所有软件包
ansible.builtin.apt:
upgrade: dist
- name: 清理无用依赖
ansible.builtin.apt:
autoremove: yes
执行它:
ansible-playbook -i inventory.ini update.yml
实战:批量更新 Ollama
光有系统更新不够。我的 AI 节点跑 Ollama,这玩意儿更新极频繁,手动一台台拉新版本很折磨人。于是有了这个 playbook:
---
- name: 批量更新 Ollama
hosts: ai-nodes
become: yes
tasks:
- name: 下载最新安装脚本
ansible.builtin.get_url:
url: https://ollama.com/install.sh
dest: /tmp/install_ollama.sh
mode: "0755"
- name: 执行安装脚本
ansible.builtin.command: /tmp/install_ollama.sh
- name: 重启 Ollama 服务
ansible.builtin.systemd:
name: ollama
state: restarted
daemon_reload: yes
注意这里用了 get_url、command、systemd 这些专用模块,而不是一条 shell 命令写死。get_url 只有在文件变化时才重新下载,systemd 能正确处理服务状态,这就是幂等性的价值。
进阶:变量、tags、handler
三个让 playbook 真正好用的概念,各举一例。
变量——把可能变的东西抽出来,放在 group_vars/ai-nodes.yml:
ollama_version: "0.5.0"
gpu_memory_gb: 24
tags——只跑 playbook 里的某一部分:
ansible-playbook -i inventory.ini update.yml --tags "ollama"
handler——只有任务真正 changed 了才触发,比如”改了配置才重启服务”,避免没事就重启:
- name: 重启 Ollama
ansible.builtin.systemd:
name: ollama
state: restarted
notify: restart ollama
handlers:
- name: restart ollama
ansible.builtin.systemd:
name: ollama
state: restarted
避坑清单
- SSH 密钥先铺好:用
ssh-copy-id把公钥推到所有机器,否则每台都要输密码,自动化就废了。 - 被管机器要有 Python:Ubuntu 默认自带 python3,但极简系统或某些精简镜像没有,得先补上。
- 权限要理清:非 root 用户要么配 sudo 免密,要么直接 root,
become才会顺畅。 - 别滥用 shell 模块:能写专用模块就写专用模块,shell 不幂等,重复跑可能翻车。
- gather_facts 能关就关:默认会收集一堆主机信息,机器多时拖慢速度,用
gather_facts: no关掉,需要时再手动setup。
小结
Ansible 是我 Homelab 里用得最顺手的工具之一。装好 inventory、沉淀几个 playbook 之后,日常运维就退化成一条命令的事:批量更新、批量部署、批量巡检,全在一个地方管,再也不用挨个 SSH。
下一步可以接着玩 Ansible Vault 加密敏感信息,或者用 ansible-pull 让机器定时自己拉配置。这些留给以后单独写。
