树莓派CM5 集群管理笔记
前言
最近工作中用到了super4c的设备,使用了4片CM5进行测试,挨个远程登录实在是有点儿麻烦。 所以决定在一台树莓派5的设备上配置ansible playbook来集中管理。 下面是最小配置。
阶段 0 硬件与网络拓扑
1. 树莓派 5(8 GB 版即可)作为 Ansible 控制节点
- 4 块 Compute Module 5 + Super4C I/O 板或官方底板,烧录同版本 64-bit Raspberry Pi OS Lite
- 所有设备接入同一交换机,控制节点 eth0 固定 192.168.3.x/24,CM5 节点依次:
CM501 192.168.3.90 CM502 192.168.3.60 CM503 192.168.3.58 CM504 192.168.3.59
阶段 1 控制节点系统准备
阶段 1 的所有命令 只在“控制节点”(就是你要拿来做 Ansible 指挥机的那台树莓派 5)上执行一次即可。
4 块 CM5 模块(被管节点)在这个阶段什么都不用做,它们只需要:
- 烧好系统
- 能联网、能被控制节点的 SSH 访问
后续阶段 2 开始,Ansible 才会通过 SSH 批量去“遥控”它们。
-
- 更新系统
sudo apt update && sudo apt full-upgrade -y
-
- 安装 Ansible(官方源比 apt 新)
sudo apt install -y python3-pip
pip3 install --user ansible-core==2.16
echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc && source ~/.bashrc
-
- 创建项目目录
mkdir -p ~/cm5-cluster/{inventory,group_vars,playbooks,roles}
cd ~/cm5-cluster
阶段 2 Inventory 与 SSH 通信打通
-
- inventory/hosts.yml
all:
children:
cm5_cluster:
hosts:
CM501: {ansible_host: 192.168.3.90, node_id: 1}
CM502: {ansible_host: 192.168.3.60, node_id: 2}
CM503: {ansible_host: 192.168.3.58, node_id: 3}
CM504: {ansible_host: 192.168.3.59, node_id: 4}
vars:
ansible_user: pi
ansible_ssh_pass: raspberry # 首次用密码
-
- 一键做 ssh-copy-id(仅第一次需要密码)
安装个sshpass包
sudo apt -y install sshpass
生成密钥
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ''
-
- 创建一个公钥拷贝的yaml文件
文件放在:playbook/init-ssh.yml
---
- hosts: cm5_cluster
gather_facts: no
tasks:
- name: 推送公钥
ansible.posix.authorized_key:
user: pi
key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
你很可能遇到提示说posix模块没有安装,ansible.posix.authorized_key 属于 ansible.posix 这个集合(collection)。 在树莓派上用 pip3 install ansible-core 时,只会安装最精简的“核心”,很多集合默认没装,所以找不到模块。 所以直接安装就好了。
ansible-galaxy collection install ansible.posix
安装完在执行playbook就行。
执行通过密码把公钥推送过去:
ansible-playbook -i inventory/hosts.yaml playbooks/init-ssh.yml
执行结果如下;
更进一步
如果想要批量安装virtualenv,并初始化virtualenv生成一个venv的虚拟环境,并激活虚拟环境后安装pandas,numpy, opencv-python, matplotlib, seaborn, xgboost, pillow, onnxruntime,jupyter的库来搭建我自己的机器学习的平台的话,只要修改playbook的yaml文件就可以实现。
下面给出一份可直接放到 ~/cm5-cluster/playbooks/venv.yml
的完整 Playbook。
它会在 所有 CM5 节点 上完成:
- 用 apt 批量安装
virtualenv
(提供 venv 命令) - 创建名为
venv
的虚拟环境 - 激活虚拟环境后,用
pip
安装指定库 - 把虚拟环境路径写入
/etc/profile.d/venv.sh
,以后登录自动激活
playbooks/venv.yml
---
- name: 批量创建虚拟环境并安装数据科学库
hosts: cm5_cluster
become: yes # 需要 root 安装系统包
vars:
venv_path: "/home/{{ ansible_user }}/venv"
python_packages:
- pandas
- numpy
- opencv-python
- matplotlib
- seaborn
- xgboost
- pillow
- onnxruntime
- jupyter
tasks:
- name: 安装 virtualenv和编译依赖
apt:
name:
- virtualenv
- python3-venv
- python3-dev # 某些包需要头文件
- build-essential # 编译扩展时用
update_cache: yes
state: present
- name: 创建虚拟环境(如已存在则跳过)
command: "virtualenv -p python3 {{ venv_path }}"
args:
creates: "{{ venv_path }}/bin/activate"
- name: 升级虚拟环境中的 pip
pip:
executable: "{{ venv_path }}/bin/pip"
name: pip
state: latest
- name: 安装 Python 库到虚拟环境
pip:
executable: "{{ venv_path }}/bin/pip"
name: "{{ python_packages }}"
state: present
- name: 写入自动激活脚本
copy:
dest: /etc/profile.d/venv.sh
owner: root
group: root
mode: '0644'
content: |
# Automatically activate Python venv for all login shells
if [ -d "{{ venv_path }}" ]; then
source {{ venv_path }}/bin/activate
fi
执行方式
cd ~/cm5-cluster
ansible-playbook -i inventory/hosts.yaml playbooks/venv.yml
跑完后,SSH 登录任意 CM5 节点即可直接进入已激活的虚拟环境:
ssh pi@CM501
# 登录后提示符前面会出现 (venv)
python -c "import pandas, cv2, xgboost; print('OK')"
如需针对特定用户或路径,只要修改 venv_path
变量即可。
执行过程如下:
测试效果:
后续思路
如果我做个刷题盒子,你们觉得可以买多少银子?哈哈
设备谍照
数据采集
集群配置好了,我需要一个采集的脚本,能够随时能够查看设备的主机名和磁盘状态,思路是把结果汇总到控制节点的本地文件里面。 规划:把所有设备的主机名,ip地址,磁盘信息汇总到本地一个host-info.json文件,方便后续查看或者入库。
目录结构:
cm5-cluster/ └── playbooks/ ├── gather-host-info.yml # 主 playbook └── templates/ └── host-info.json.j2 # Jinja2 模板,用于生成最终 JSON
- 先构建获取脚本的yaml文件
---
- name: 批量采集主机名、IP、磁盘信息
hosts: cm5_cluster
gather_facts: yes # 需要 Ansible facts
vars:
report_dir: "{{ playbook_dir }}/../report"
tasks:
# 1. 确保本地存放目录存在
- name: 创建本地 report 目录
delegate_to: localhost
file:
path: "{{ report_dir }}"
state: directory
run_once: yes
# 2. 用 template 把每台机器的信息渲染成一行 JSON
- name: 生成本机信息文件
template:
src: host-info.json.j2
dest: "{{ report_dir }}/{{ inventory_hostname }}.json"
delegate_to: localhost
- 创建templates并创建一个j2文件 playbooks/templates/host-info.json.j2
{# 取根分区 / 的信息 #}
{% set root = ansible_mounts | selectattr('mount','equalto','/') | first %}
{"hostname":"{{ ansible_hostname }}","ipv4":{{ ansible_all_ipv4_addresses | to_json }},"disk_GB":"{{ (root.block_total * root.block_size / 1024 / 1024 / 1024) | round(2) }}","used_GB":"{{ (root.block_used * root.block_size / 1024 / 1024 / 1024) | round(2) }}","usage":"{{ (root.block_used / root.block_total * 100) | round(1) }}%"}
验证结果
cd ~/cm5_cluster
ansible-playbook -i inventory/hosts.yaml playbooks/gather-host-info.yml
执行成功后,要用jq命令查看,需要先安装一下。
sudo apt -y install jq
cat report/*.json | jq -s .
然后结果会看到类似:
(venv) pi@raspberrypi:~/cm5-cluster $ ansible-playbook -i inventory/hosts.yaml playbooks/gather-host-info.yml
PLAY [批量采集主机名、IP、磁盘信息] ********************************************
TASK [Gathering Facts] *********************************************************
ok: [CM502]
ok: [CM504]
ok: [CM503]
ok: [CM501]
TASK [创建本地 report 目录] ****************************************************
ok: [CM501 -> localhost]
TASK [生成本机信息文件] ********************************************************
changed: [CM502 -> localhost]
changed: [CM501 -> localhost]
changed: [CM504 -> localhost]
changed: [CM503 -> localhost]
PLAY RECAP *********************************************************************
CM501 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
CM502 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
CM503 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
CM504 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
我们再看看结果:
(venv) pi@raspberrypi:~/cm5-cluster $ cat report/*.json | jq -s .
[
{
"hostname": "CM501",
"ipv4": [
"192.168.3.90"
],
"disk_GB": "28.09",
"used_GB": "17.47",
"usage": "62.2%"
},
{
"hostname": "CM502",
"ipv4": [
"192.168.3.87",
"192.168.3.60"
],
"disk_GB": "28.09",
"used_GB": "16.19",
"usage": "57.6%"
},
{
"hostname": "CM503",
"ipv4": [
"192.168.3.46",
"192.168.3.58"
],
"disk_GB": "28.09",
"used_GB": "7.35",
"usage": "26.2%"
},
{
"hostname": "CM504",
"ipv4": [
"192.168.3.47",
"192.168.3.59"
],
"disk_GB": "28.09",
"used_GB": "7.41",
"usage": "26.4%"
}
]
ansible配合playbook
实在是太方便了,管理集群强烈推荐。