树莓派CM5 集群管理笔记

前言

最近工作中用到了super4c的设备,使用了4片CM5进行测试,挨个远程登录实在是有点儿麻烦。 所以决定在一台树莓派5的设备上配置ansible playbook来集中管理。 下面是最小配置。

阶段 0 硬件与网络拓扑

1 1. 树莓派 5(8 GB 版即可)作为 Ansible 控制节点

  1. 4 块 Compute Module 5 + Super4C I/O 板或官方底板,烧录同版本 64-bit Raspberry Pi OS Lite
  2. 所有设备接入同一交换机,控制节点 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 模块(被管节点)在这个阶段什么都不用做,它们只需要:

  1. 烧好系统
  2. 能联网、能被控制节点的 SSH 访问

后续阶段 2 开始,Ansible 才会通过 SSH 批量去“遥控”它们。

    1. 更新系统
sudo apt update && sudo apt full-upgrade -y
    1. 安装 Ansible(官方源比 apt 新)
sudo apt install -y python3-pip
pip3 install --user ansible-core==2.16
echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc && source ~/.bashrc
    1. 创建项目目录
mkdir -p ~/cm5-cluster/{inventory,group_vars,playbooks,roles}
cd ~/cm5-cluster

阶段 2 Inventory 与 SSH 通信打通

    1. 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   # 首次用密码
    1. 一键做 ssh-copy-id(仅第一次需要密码)

安装个sshpass包

sudo apt -y install sshpass

生成密钥

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ''
    1. 创建一个公钥拷贝的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

执行结果如下;

result

更进一步

如果想要批量安装virtualenv,并初始化virtualenv生成一个venv的虚拟环境,并激活虚拟环境后安装pandas,numpy, opencv-python, matplotlib, seaborn, xgboost, pillow, onnxruntime,jupyter的库来搭建我自己的机器学习的平台的话,只要修改playbook的yaml文件就可以实现。 下面给出一份可直接放到 ~/cm5-cluster/playbooks/venv.yml 的完整 Playbook。 它会在 所有 CM5 节点 上完成:

  1. 用 apt 批量安装 virtualenv(提供 venv 命令)
  2. 创建名为 venv 的虚拟环境
  3. 激活虚拟环境后,用 pip 安装指定库
  4. 把虚拟环境路径写入 /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 变量即可。 执行过程如下:

result2

测试效果:

result3

后续思路

如果我做个刷题盒子,你们觉得可以买多少银子?哈哈

设备谍照

2 3 4

数据采集

集群配置好了,我需要一个采集的脚本,能够随时能够查看设备的主机名和磁盘状态,思路是把结果汇总到控制节点的本地文件里面。 规划:把所有设备的主机名,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

实在是太方便了,管理集群强烈推荐。