找回密码
立即注册
搜索
发回帖 发新帖

6265

积分

0

好友

792

主题
发表于 昨天 23:36 | 查看: 4| 回复: 0

5 台机器要装同一个软件,你还在逐台 SSH?Ansible 让你一条命令搞定所有机器,零 Agent、纯 SSH、上手即用。

周末给 HomeLab 的 5 台机器做系统更新,常规做法是打开 5 个终端窗口,逐台 ssh 进去,敲 apt update && apt upgrade -y。结果经常是等第一台跑完,第三台早就断连了,只能重连、重来。说真的,这不是运维,是体力活。

如果你管理超过 2 台服务器,就该上 Ansible 了。

为什么是 Ansible

特性 Ansible Puppet/Chef Shell 脚本
Agent 不需要 需要 不需要
学习曲线 低 高 看你脚本能力
幂等性 内置 内置 自己写
模板引擎 Jinja2 ERB/HCL envsubst
适合场景 批量操作+配置 持续配置管理 简单任务

Ansible 最大优势:不需要在目标机器装任何 Agent,纯 SSH 通信,装完 Ansible 就能用。

安装

控制端(你的工作机)安装 Ansible:

# Ubuntu/Debian
sudo apt update && sudo apt install -y ansible

# macOS
brew install ansible

# pip(推荐,版本最新)
pip install ansible

# 验证
ansible --version

目标机器只需要满足两个条件:SSH 可达 + Python 3 已安装(大部分 Linux 发行版自带)。

编写 Inventory

Inventory 告诉 Ansible 你有哪些机器。创建 hosts.ini:

[homelab]
k3s-master    ansible_host=192.168.1.101
k3s-node1     ansible_host=192.168.1.102
k3s-node2     ansible_host=192.168.1.103

[docker-host]
dell-3430     ansible_host=192.168.1.104

[nas]
synology      ansible_host=192.168.1.105

[homelab:vars]
ansible_user=root
ansible_ssh_private_key_file=~/.ssh/id_ed25519

[all:vars]
ansible_python_interpreter=/usr/bin/python3

测试连通性:

ansible all -i hosts.ini -m ping

输出:

k3s-master | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
k3s-node1 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
...

全部 pong,说明所有机器就绪。

Ad-hoc 命令:批量操作一步到位

不想写脚本,只想快速执行一条命令?用 ad-hoc:

# 所有机器同时更新包索引
ansible all -i hosts.ini -m apt -a "update_cache=yes" --become

# 查看所有机器磁盘使用
ansible all -i hosts.ini -m shell -a "df -h / | tail -1"

# 批量重启 K3s 节点上的容器运行时
ansible homelab -i hosts.ini -m systemd -a "name=containerd state=restarted" --become

# 批量安装 htop
ansible all -i hosts.ini -m apt -a "name=htop state=present" --become

常用的 -m 模块:

模块 用途 示例
ping 测试连通性 ansible all -m ping
shell 执行 shell 命令 -m shell -a "uptime"
apt 管理包(Debian 系) -m apt -a "name=nginx state=present"
copy 拷贝文件 -m copy -a "src=app.conf dest=/etc/"
file 管理文件/目录 -m file -a "path=/data state=directory"
systemd 管理服务 -m systemd -a "name=nginx state=started"
user 管理用户 -m user -a "name=deploy state=present"

第一个 Playbook:一键更新所有机器

Ad-hoc 适合临时操作。复杂任务需要 Playbook——YAML 格式的任务编排。

创建 update-all.yml:

---
- name: 批量更新 HomeLab 所有机器
  hosts: all
  become: yes
  tasks:
    - name: 更新包索引
      apt:
        update_cache: yes
        cache_valid_time: 3600

    - name: 升级所有包
      apt:
        upgrade: dist

    - name: 清理不需要的包
      apt:
        autoremove: yes

    - name: 检查是否需要重启
      stat:
        path: /var/run/reboot-required
      register: reboot_flag

    - name: 提示需要重启的机器
      debug:
        msg: "{{ inventory_hostname }} 需要重启!"
      when: reboot_flag.stat.exists

    - name: 显示磁盘使用情况
      shell: df -h / --output=pcent | tail -1
      register: disk_usage

    - name: 打印磁盘使用率
      debug:
        msg: "{{ inventory_hostname }}: 根分区已用 {{ disk_usage.stdout | trim }}"

执行:

ansible-playbook -i hosts.ini update-all.yml

Ansible 会逐台执行,每步都打印结果。register 可以保存命令输出,后面用 when 做条件判断——这就是 Playbook 比 Shell 脚本强的地方:逻辑编排 + 幂等性。

进阶:用模板批量配置

假设你要给 3 台 K3s 节点配置不同的 hostname 和 hosts 文件。用 Jinja2 模板:

创建 templates/hosts.j2:

127.0.0.1 localhost
{{ ansible_host }} {{ inventory_hostname }}

{% for host in groups['homelab'] %}
{{ hostvars[host]['ansible_host'] }} {{ host }}
{% endfor %}

在 Playbook 中使用:

- name: 配置 hosts 文件
  template:
    src: hosts.j2
    dest: /etc/hosts
    backup: yes
    notify: reboot

template 模块会自动渲染 Jinja2 模板,变量从 inventory 和 facts 中来。notify 会在文件变更时触发 handler:

handlers:
  - name: reboot
    reboot:
      msg: "配置变更,重启中"

实战:HomeLab 初始化 Playbook

把上面所有招数组合起来,写一个完整的初始化脚本:

---
- name: HomeLab 机器初始化
  hosts: all
  become: yes
  vars:
    common_packages:
      - htop
      - vim
      - curl
      - wget
      - net-tools
      - python3-pip

  tasks:
    - name: 安装常用工具
      apt:
        name: "{{ common_packages }}"
        state: present

    - name: 创建运维用户
      user:
        name: ops
        groups: sudo
        shell: /bin/bash

    - name: 部署 SSH 公钥
      authorized_key:
        user: ops
        key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"

    - name: 禁止 root 密码登录
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: "^PermitRootLogin"
        line: "PermitRootLogin prohibit-password"
        notify: restart sshd

  handlers:
    - name: restart sshd
      service:
        name: sshd
        state: restarted

一条命令,所有机器初始化完毕。下次加新机器,加到 inventory 里重跑一次就行——这就是幂等性的好处。

小结

Ansible 的核心思路:用声明式的方式描述"机器应该是什么状态",而不是"怎么变成这个状态"。

  • Inventory 管理机器列表
  • Module 执行具体操作
  • Playbook 编排任务流程
  • Template 生成配置文件
  • Handler 处理变更后的动作

下一篇,我们聊 Terraform——用同样的思路管理基础设施资源(VM、网络、存储),让 HomeLab 的环境搭建也变成代码。




上一篇:Terraform 入门实战:用代码定义你的 HomeLab 基础设施
下一篇:AI 写 K8s YAML 只需 30 秒,运维人的出路在哪?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-8 01:48 , Processed in 0.074380 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表