Ansible 批量部署 Node Exporter:从单机安装流程到远程主机统一执行
前言
当 Node Exporter 只需要装在一两台服务器上时,手动 SSH 基本没有压力;但目标主机一多,问题就会变成另一种性质:同样的安装步骤要重复多少遍,版本和服务配置又怎么保持一致?
这时候真正需要解决的,不是"Node Exporter 怎么安装",而是怎么把一套安装动作稳定地重复到多台主机上。
Ansible 正适合处理这一层。本文不会把重点放在"上百台机器三分钟全部搞定"这种结果口号上,因为原文实际演示的是:先在 Ubuntu 控制机安装 Ansible,写好 inventory、服务模板和 Playbook,再对目标主机执行 ansible-playbook node_exporter.yml,最后通过 systemctl status node_exporter 验证服务。
接下来整篇围绕几个实际问题展开:
- Ansible 控制机要先准备什么?
- Node Exporter 的手动安装步骤,如何转成 Playbook?
- 同一局域网里的目标机怎么加入 inventory?
- 如果目标机在家里、控制机却不在同一网络,Ansible 怎么继续通过 SSH 管理?
- 随机 TCP 能用以后,什么时候才有必要换成固定 TCP?
这里的职责需要一直保持清楚:Ansible 负责自动化执行,Node Exporter 负责暴露主机指标,cpolar只负责让目标主机的 SSH 从外部网络可达。 本文没有继续配置 Prometheus 抓取规则,因此不会把"已经完成整套 Prometheus 监控"写成本文结果。

1.先把 Ansible 控制机准备好
1.1 Ansible 在这里负责什么?
Ansible 是一个开源自动化运维工具,由 Red Hat 赞助开发。放到本文场景里,它负责把同一套安装和配置动作重复执行到目标主机上。
原文列出的常见用途包括:
- 配置管理(Configuration Management)
- 应用部署(Application Deployment)
- 任务自动化(Task Automation)
- IT编排(Orchestration)
它最大的特点可以概括为:控制机安装 Ansible,被控端通过 SSH 接收任务,流程使用 YAML 描述。
1.2 为什么不用继续逐台 SSH?
原文把 Ansible 的作用分成几类。对于 Node Exporter 这个场景,最直接的是两点:
- 批量执行命令
不用逐台登录服务器,再重复敲同样的命令。
- 统一配置管理
让目标主机尽量使用同一套安装流程和服务配置,例如:
- 安装指定版本的软件(如 Node Exporter、Nginx)
- 同步配置文件(如 /etc/hosts、prometheus.yml)
- 创建用户、设置权限、管理服务状态
- 自动化部署应用
- Playbook
通过 YAML 文件把"建目录、下载、解压、建用户、写 systemd、启动服务"这些动作串成固定流程。
- 幂等性(Idempotency)
原文强调,同一个 Playbook 可以重复执行,已经满足条件的任务不会每次都从头重做。
- 无需额外 Agent
Ansible 通过 SSH 与目标主机通信,控制机安装 Ansible,被控端需要具备 Python 和 SSH 环境。
- 扩展到其他自动化任务
除了本文的 Node Exporter,原文还提到云资源、Docker、Kubernetes 等场景。
1.3 安装 Ansible
本文控制机使用 Ubuntu。原文另外给出了 CentOS 参考教程:《别再手动操作了!我用Ansible+cpolar给飞牛OS装了个"遥控器》
先登录 Ubuntu,并更新系统软件包:
shell
sudo apt update
sudo apt upgrade -y
接着安装 Ansible:
shell
apt install -y ansible

安装完成后先确认 Ansible 版本:
shell
ansible --version

然后检查 /etc/ansible 是否存在:
shell
ls /etc/ansible
原文环境里没有现成目录,因此手动创建 /etc/ansible:
shell
mkdir -p /etc/ansible
接着创建最基础的 hosts inventory:
shell
cat > /etc/ansible/hosts <<EOF
[local]
localhost ansible_connection=local
EOF
再写入 ansible.cfg:
shell
cat > /etc/ansible/ansible.cfg <<EOF
[defaults]
inventory = /etc/ansible/hosts
host_key_checking = False
remote_user = root
stdout_callback = yaml
EOF
最后先用本机 ping 模块验证 Ansible 配置是否可用:
shell
ansible localhost -m ping

2.怎样把 Node Exporter 的手动安装变成 Playbook?
控制机能正常执行 Ansible 以后,下一步才是把 Node Exporter 的安装过程自动化。
先进入 Playbook 所在目录(原文假设为 /etc/ansible):
shell
cd /etc/ansible
创建 templates 目录:
shell
mkdir -p templates
先准备 Node Exporter 的 systemd 服务模板:
shell
cat > templates/node_exporter.service.j2 <<'EOF'
[Unit]
Description=Node Exporter
After=network.target
[Service
User=node_exporter
Group=node_exporter
Type=simple
ExecStart={{ install_dir }}/node_exporter --collector.systemd --collector.processes
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF

在直接看 Playbook 之前,原文先完整过了一遍 Node Exporter 的手动安装步骤。这样做有一个好处:后面能看清 Playbook 到底替代了哪些人工操作。
shell
mkdir /shan
cd /shan
shell
curl -LO https://github.com/prometheus/node_exporter/releases/download/v1.10.2/node_exporter-1.10.2.linux-amd64.tar.gz
shell
tar -zxvf node_exporter-1.10.2.linux-amd64.tar.gz
shell
rm -rf node_exporter-1.10.2.linux-amd64.tar.gz
mv node_exporter-1.10.2.linux-amd64/ node_exporter
shell
sudo vi /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
Documentation=https://github.com/prometheus/node_exporter
After=network.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/shan/node_exporter/node_exporter
[Install]
WantedBy=default.target
shell
useradd --no-create-home --shell /bin/false node_exporter
shell
systemctl start node_exporter
systemctl enable node_exporter
如果目标只有一台,前面的手动流程还能接受;目标主机一多,真正需要自动化的就是这些重复动作。
接下来把目标主机和部署步骤分别放进 inventory 与 Playbook。
先编辑 hosts 文件,加入目标主机 IP、用户名和密码:
[test]
ip ansible_ssh_user=用户名 ansible_ssh_pass=密码

然后创建 Node Exporter Playbook:
shell
---
- name: 安装node_exporter
hosts: test
become: yes
vars:
node_exporter_version: "1.8.2"
node_exporter_url: "https://ghproxy.net/https://github.com/prometheus/node_exporter/releases/download/v{{ node_exporter_version }}/node_exporter-{{ node_exporter_version }}.linux-amd64.tar.gz"
install_dir: "/shan"
tasks:
- name: 创建存储目录
file:
path: "{{ install_dir }}"
state: directory
mode: '0755'
- name: 下载node_exporter
get_url:
url: "{{ node_exporter_url }}"
dest: "{{ install_dir }}/node_exporter.tar.gz"
mode: '0644'
timeout: 30
retries: 3
delay: 10
- name: 解压node_exporter
unarchive:
src: "{{ install_dir }}/node_exporter.tar.gz"
dest: "{{ install_dir }}"
remote_src: yes
- name: 清理压缩包
file:
path: "{{ install_dir }}/node_exporter.tar.gz"
state: absent
- name: 重命名解压目录为 node_exporter
command: mv "{{ install_dir }}/node_exporter-{{ node_exporter_version }}.linux-amd64" "{{ install_dir }}/node_exporter"
args:
creates: "{{ install_dir }}/node_exporter"
- name: 删除旧目录
file:
path: "{{ install_dir }}/node_exporter-{{ node_exporter_version }}.linux-amd64"
state: absent
- name: 创建专用用户
user:
name: node_exporter
system: yes
shell: /sbin/nologin
createhome: no
- name: 配置systemd服务
template:
src: node_exporter.service.j2
dest: /etc/systemd/system/node_exporter.service
owner: root
group: root
mode: '0644'
- name: 重载systemd配置
systemd:
daemon_reload: yes
- name: 启动并启用node_exporter服务
systemd:
name: node_exporter
enabled: yes
state: started

Playbook 准备好以后执行:
shell
ansible-playbook node_exporter.yml

任务跑完以后,不要只看 Ansible 输出,还要到目标主机确认服务状态:
shell
systemctl status node_exporter

到这里,原文已经完成了一次通过 Ansible 部署 Node Exporter 的验证。
如果后续增加更多目标主机,可以继续扩展 hosts inventory;但原文并没有真的对"上百台主机"做规模压测,因此这里更准确的说法是:这套 Playbook 可以继续复用于更多主机。
接下来处理另一个问题:如果目标机不在同一局域网,Ansible 又该怎么通过 SSH 访问它?
这时才需要增加 cpolar。
3.安装 cpolar:只解决 SSH 可达性
Ansible 本身仍然是通过 SSH 管理目标机。问题只在于:目标机如果藏在家庭内网,控制机无法直接访问它的 22 端口。
下面安装 cpolar,把目标机的 SSH 端口映射到公网。这样 Ansible 仍然使用原来的 SSH 机制,只是 inventory 里的主机地址和端口发生变化。
以下按照原文步骤安装 cpolar:
使用一键脚本安装命令:
shell
sudo curl https://get.cpolar.sh | sh

安装完成后,执行下方命令查看 cpolar 服务状态:
shell
sudo systemctl status cpolar

cpolar 安装并启动以后,通过主机 IP 加 9200 端口访问 Web 管理界面。登录账号后,后面的 TCP 隧道都在这里配置。
打开浏览器访问本地 9200 端口,登录后即可管理隧道。

4.公网 SSH 能不能直接交给 Ansible 使用?
可以。只要目标机的 SSH 已经通过 TCP 隧道暴露出来,Ansible inventory 就可以继续使用对应域名和端口。
原文的隧道配置如下:
- 隧道名称:可自定义,本例使用了:ssh,注意不要与已有的隧道名称重复
- 协议:tcp
- 本地地址:22
- 端口类型:随机临时TCP端口
- 地区:China Top

创建成功后,打开在线隧道列表,可以看到刚刚生成的公网 TCP 地址。
-
tcp 表示使用的协议类型
-
2.tcp.cpolar.top是 Cpolar 提供的域名
-
16198是随机分配的公网端口号

接下来把这组公网域名和端口直接写进 Ansible inventory,再验证原来的 Playbook 能不能继续执行。
修改 hosts 配置:
shell
[dbservers]
2.tcp.cpolar.top ansible_user=root ansible_port=16198 ansible_password=***

然后再次执行同一个 Node Exporter Playbook:
shell
ansible-playbook node_exporter.yml

Ansible 执行完成后,继续到目标主机检查 Node Exporter 服务状态:

原文验证结果显示,目标主机已经完成 Node Exporter 安装。这说明公网 TCP 地址可以继续作为 Ansible 的 SSH 入口。
5.什么时候需要固定 TCP 地址?
随机 TCP 已经证明远程部署链路可用。如果只是临时测试,这一步不是必须的。
如果准备长期把某台远程机器放进 Ansible inventory,固定 TCP 地址更合适,因为 inventory 不需要随着随机地址变化反复修改。

选择区域和描述:有一个下拉菜单,当前选择的是"China VIP"。
右侧输入框,用于填写描述信息。
保留按钮:在右侧有一个橙色的"保留"按钮,点击该按钮可以保留所选的TCP地址。
列表中显示了一条已保留的TCP地址记录。
-
地区:显示为"China VIP"。
-
地址:显示为"15.tcp.cpolar.top:13633"。

登录cpolar web UI管理界面,点击左侧仪表盘的隧道管理------隧道列表,找到所要配置的隧道ssh,点击右侧的编辑。

修改隧道信息,将保留成功的TCP端口配置到隧道中。
- 端口类型:选择固定TCP端口
- 预留的TCP地址:填写保留成功的TCP地址
点击更新。

更新以后再打开在线隧道列表,可以看到原来的随机公网地址已经切换成保留的固定 TCP 地址。

到这里,局域网主机和通过公网 TCP 接入的远程主机,都可以继续复用同一套 Ansible 部署思路。
总结
这篇文章真正完成的,不是"上百台机器三分钟全部接入 Prometheus",而是把 Node Exporter 的重复安装过程变成一套可以复用的 Ansible Playbook,并继续验证了"目标机不在同一局域网时"该怎么处理。
全文可以拆成三层:
- Ansible:负责把创建目录、下载、解压、建用户、写 systemd 服务和启动服务这些动作自动执行到目标主机;
- Node Exporter:负责在目标 Linux 主机上提供系统指标;
- cpolar :只负责让远程目标机的 SSH
22端口通过公网 TCP 可达。
原文先手动演示了一遍 Node Exporter 安装步骤,再把这些动作整理进 Playbook。随后在同网段目标机上执行 ansible-playbook node_exporter.yml,并通过 systemctl status node_exporter 验证服务。远程场景里,又把 2.tcp.cpolar.top:16198 写进 inventory,再执行同一 Playbook,目标机仍然完成安装。
这证明的核心不是"cpolar 帮 Ansible 部署了 Node Exporter",而是:
只要 SSH 入口可达,Ansible 原来的自动化流程就可以继续复用。
如果后面真要扩展到几十台、上百台主机,下一步重点应该是 inventory 组织、凭据管理、批次执行、失败重试、版本统一和 Prometheus 抓取配置,而不是简单继续增加 IP。
另外,原文中的手动示例使用 node_exporter 1.10.2,Playbook 变量使用的是 1.8.2;这一版按全文改写规则保留原始技术内容,不主动改版本或替换配置。