第二章:环境准备与基础搭建

好,咱们正式开始动手了。这一章我把它叫做「地基工程」。你想想看,边缘设备的环境跟云端不一样,资源有限、网络复杂、安全要求还高。如果地基没打好,后面消息队列跑起来,三天两头出问题,那可就头疼了。

我个人习惯,在搭建任何分布式系统之前,先把容器化环境理清楚。Docker 和 Docker Compose 是标配,但怎么配、配多少、怎么限制资源,这里面门道不少。我带大家一步步走。

2.1 Docker 基础:不只是装个软件

Docker 大家都熟,但在边缘计算场景下,我建议你多留个心眼。边缘设备的操作系统五花八门,有的还是 ARM 架构。我曾经在一个工业网关项目上,就因为镜像没选对架构,折腾了一整天。

先确认你的 Docker 版本:

docker --version
# 我建议至少 20.10 以上版本

安装其实很简单,但要注意一点:千万别用系统自带的旧版本。我习惯用官方脚本安装:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
注意: 在树莓派这类 ARM 设备上,安装完成后记得执行 sudo usermod -aG docker $USER,然后重新登录。不然每次都要 sudo,很烦。

装好之后,跑个 hello-world 验证一下:

docker run hello-world

看到那个 "Hello from Docker!" 了吗?嗯,基础环境通了。

2.2 Docker Compose 编排:让多容器协作

单容器好办,但我们的消息队列方案里,至少需要几个组件:消息代理(比如 RabbitMQ 或 EMQX)、数据持久化服务、可能还有监控代理。手动一个个启动?不现实。

Docker Compose 就是干这个的。我建议你安装最新稳定版:

sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

验证一下:

docker-compose --version

这里有个小坑:边缘设备上可能没有 curl,或者网络受限。我曾经在某个工厂内网环境,只能手动下载二进制包传上去。所以,提前准备好离线安装包,是个好习惯。

2.3 网络规划:别让消息走错路

边缘设备的网络环境,说白了就是「乱」。有的设备在 192.168.1.x 段,有的在 10.0.0.x 段,还有的可能通过 4G 模块上网。消息队列要跨设备通信,网络规划必须提前想好。

我一般用 Docker 的 overlay 网络,或者干脆用 host 网络模式。但 host 模式有安全隐患,你想想看,容器直接暴露在宿主机网络上,端口冲突是小事,被扫描到就麻烦了。

我的建议方案:

  • 同一台设备上的容器:用 bridge 网络,端口映射到宿主机
  • 跨设备通信:用 overlay 网络 + 服务发现(比如 Consul 或 etcd)
  • 安全要求高的场景:用 macvlan 网络,给容器分配独立 MAC 地址

举个例子,一个典型的 docker-compose 网络配置:

networks:
  edge-mq-net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16
          gateway: 172.20.0.1
小技巧: 我习惯把消息队列的端口固定下来,比如 5672(AMQP)、1883(MQTT)。这样防火墙规则好写,排查问题也方便。

2.4 资源限制策略:别让消息队列吃掉所有内存

边缘设备的内存通常只有 512MB 到 2GB。消息队列如果没限制,一旦流量突增,直接 OOM 把设备搞死。我见过不止一次这样的惨案。

Docker 提供了很精细的资源限制能力。我建议你至少设置以下参数:

参数 说明 推荐值(边缘设备)
--memory 最大内存 256MB ~ 512MB
--memory-reservation 软限制(内存压力时保证) 128MB
--cpus CPU 核心数 0.5 ~ 1.0
--pids-limit 最大进程数 100

在 docker-compose 里这样写:

services:
  message-broker:
    image: rabbitmq:3-management
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 256M
        reservations:
          memory: 128M
警告: 别把 memory 设得太低。我曾经把 RabbitMQ 限制在 128MB,结果一跑起来就崩溃。后来查日志才发现,RabbitMQ 本身就需要至少 256MB 才能正常工作。每个组件都有它的「最低生存内存」,你得先摸清楚。

2.5 安全基线配置:别裸奔

边缘设备往往部署在无人值守的现场,物理安全都难保证,更别说网络安全了。但正因为这样,安全基线才更重要。我的原则是:默认拒绝,按需开放

几个必须做的安全配置:

  1. 不要用 root 运行容器。创建专用用户,比如 uid 1000。
  2. 只暴露必要端口。管理端口(比如 15672)只在内网开放。
  3. 启用 TLS。消息队列的通信必须加密,哪怕是在内网。
  4. 设置文件系统只读。除非必要,否则把容器的根文件系统设为只读。

一个安全加固的 docker-compose 示例:

services:
  message-broker:
    image: rabbitmq:3-management
    user: "1000:1000"
    read_only: true
    tmpfs:
      - /var/lib/rabbitmq
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE

核心思路: 给容器最小的权限,只给它能干活的那部分。比如消息队列需要绑定端口,那就只给 NET_BIND_SERVICE 权限,其他全部丢掉。

嗯,说到这里,环境准备这块基本就齐了。你可能会问:「这么多配置,每次都要手写吗?」别急,下一章我会带大家做一个自动化脚本,把这些配置一键搞定。但今天,先把这些概念吃透。

记住一句话:边缘计算的环境准备,不是「能跑就行」,而是「跑得稳、跑得久、跑得安全」。我在项目里吃过太多亏,希望你别重蹈覆辙。

我的习惯: 每配置完一个环境,我都会写一个 README 文档,把网络拓扑、端口映射、资源限制都记下来。半年后回来维护,你会感谢当时的自己。