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_urlcommandsystemd 这些专用模块,而不是一条 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 让机器定时自己拉配置。这些留给以后单独写。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注