树莓派上安装 kubeedge
安装 docker
参考资料:树莓派4B raspberrypi在线安装Docker
安装完成后,在 /etc/docker/daemon.json 中添加 : :"exec-opts": ["native.cgroupdriver=systemd"],使用 systemd 驱动
安装 kubeedge
参考 kubeedege 的离线安装文档,注意下载的资源包时注意要一定要下载 arm64 的
边缘节点 join 时,指定 cgroupdriver 为 systemd
keadm join --cloudcore-ipport=xxxxx:10000 --cgroupdriver=systemd --edgenode-name=raspberrypi --kubeedge-versinotallow=1.10.2 --token=3cca11140cab1c229d……
Note:
在 join 后,如果出现报错:
Failed to start container manager, err: system validation failed - Following Cgroup subsystem not mounted: [memory] E0125 16:42:09.131414 1655 edged.go:291] initialize module error: system validation failed - Following Cgroup subsystem not mounted: [memory]
则修改树莓派的 /boot/cmdline.txt 文件,添加如下内容
cgroup_enable=memory cgroup_memory=1
在同一行的最后面,接着内容后空格后添加,注意:不要换行添加,重启机器配置生效
控制 USB 摄像头
实验介绍
本示例根据官方实验中的计数器实验代码修改而来,实验架构图如下(省略了一部分 kubeedge 组件)
页面 web app 以 Pod 的方式运行在云端的 K8S 集群节点,用户访问 web app 的页面执行操作,向 k8s 的 API server 发起修改 device instance 的动作,当 cloudcore 中的 deviceController 观察到设备发生变化,就通过 cloud hub 和 edge hub 通信,最终将该变化动作通过 EventBus 向 MQTT Broker 发布一条 topic,边端的 camera.py 进程中初始了一个 MQTT Client 订阅了该 topic,就能接收到云端对于摄像头的操作动作,根据接收到的消息内容,对摄像头发起相应的操作。
camera.py 的实现内容如下:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import cv2
import numpy as np
import paho.mqtt.client as mqtt
import json
import threading
import time
last_status = "Nothing"
picture_flag = False
lock = threading.Lock()
# 连接成功回调函数
def on_connect(client, userdata, flags, rc):
print("Connected with result code " + str(rc))
# 连接完成之后订阅主题
client.subscribe('$hw/events/device/camera/twin/update/document')
# 消息处理回调函数
def on_message(client, userdata, msg):
global last_status
global picture_flag
# 获得负载中的 和
json_obj = json.loads(msg.payload.decode('utf-8').strip('\t\r\n'))
action = json_obj['twin']['status']['current']['expected']['value']
print("当前操作:" + action + ", 上次操作:" + last_status)
if action == "ON" and last_status != action:
last_status = action
t = threading.Thread(target=open_camera)
t.start()
if action == "OFF" and last_status != action:
last_status = action
if action == "STATUS" and (last_status == "ON" or last_status == "STATUS"):
picture_flag = True
def open_camera():
global picture_flag
cap = cv2.VideoCapture(0) # 0 代表 /dev/video0 这个设备,也可以使用 url
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
if cap.isOpened():
while 1:
# 图像处理
ret, frame = cap.read()
rows, cols, channels = frame.shape
# 灰度化
gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 平滑滤波
blur = cv2.blur(gray_img, (3, 3))
# 二值化
ret1, th1 = cv2.threshold(blur, 190, 255, cv2.THRESH_BINARY)
# 透视变换
b = 50
pts1 = np.float32([[b, 0], [cols - b, 0], [0, rows], [cols, rows]])
pts2 = np.float32([[0, 0], [cols, 0], [0, rows], [cols, rows]])
M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(blur, M, (cols, rows))
# 展示窗口
cv2.imshow('usb camera', dst) # 在操作系统界面展示图像
if cv2.waitKey(1) and last_status == "OFF":
break
if cv2.waitKey(1) and picture_flag:
lock.acquire()
try:
# time.sleep(10)
date_str = time.strftime('%Y-%m-%d_%H:%M:%S', time.localtime())
filename = r'./camera/' + date_str + '.jpg'
cv2.imwrite(filename, frame)
print("截图保存为: " + filename)
finally:
picture_flag = False
lock.release()
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
try:
# 请根据实际情况改变MQTT代理服务器的IP地址
client.connect("127.0.0.1", 1883, 60)
client.loop_forever()
except KeyboardInterrupt:
client.disconnect()
先决条件
硬件需求
- 树莓派(树莓派3/4可用于此演示)。
- USB 摄像头
软件需求
- kubernetes 集群
- KubeEdge 1.5+
实验现象
web app 运行后可以通过 IP:port 访问
该页面通过 kubeedge-counter-demo 的例子修改而来,主要修改的内容如下:
前端页面修改:
前端控制器 controller
在边端运行 test.py 程序
在云端点击执行开启摄像头,收到了来自云端的操作,并打开了摄像头
点击拍照后,显示图片已经保存
边缘节点交通信号灯
实验描述
LED 灯与树莓派的连接方式
下图左侧4根线是LED的线。(最左侧的黑色线是地线。其余3根线对应红黄绿三个灯。)
GPIO 的编号如下所示,注意 BCM 的编号和 wiringPi 的编号不太一样。
示例代码中使用的是 23,24,25 编号,采用的是 wiringPi 的编号方式,对应到物理口为 33 35 37 39 接口。
先决条件
硬件需求
- 树莓派(树莓派3/4可用于此演示)。
- LED 三色信号灯
软件需求
- kubernetes 集群
- KubeEdge 1.5+
实验步骤
- 在边缘节点通过 make 命令构建:
$ make
make 的内容
- 在云端创建 crd 只有
$ cd crd
$ kubectl apply -f model.yaml
# 替换 "<your edge node name>" 为边缘节点名称
$ sed -i 's#raspberrypi#<your edge node name>#' instance.yaml
$ kubectl apply -f instance.yaml
Note:实例必须在模型之后创建,在模型之前删除.
- 在云端部署创建示例程序:
# 启动一个 pod 作为 mapper 的作用运行在边缘
$ kubectl apply -f deploy.yaml
- 修改 instance.yaml 对应灯的期望值为ON,
- kubectl apply -f crd/instance.yaml 更新配置后对应的灯点亮。如将灯的状态由绿灯变为红灯:
边缘节点温度传感器实验
实验描述
温度映射器包含从温度传感器采集温度的代码,温度传感器通过 gpio 连接到树莓派。
根据温度传感器的预期状态,程序收集温度。
先决条件
硬件需求
- 树莓派(树莓派3/4可用于此演示)。
- GPIO(树莓派自带的 gpio 即可)
- 温度传感器 (DHT11)
软件需求
- Golang 1.14+
- KubeEdge 1.5+
实验步骤
- 根据上面的电路图将温度传感器和树莓派通过 GPIO 连接
- 克隆 KubeEdge 代码并运行
- 克隆 kubeedge/example 代码
$ git clone https://github.com/kubeedge/examples.git
- 创建温度传感器的 device model 和 device instance.
$ cd $GOPATH/src/github.com/kubeedge/examples/temperature-demo/crds
$ kubectl apply -f devicemodel.yaml
$ sed -i "s#edge-node#<your-edge-node-name>#g" instance.yaml
$ kubectl apply -f device.yaml
- 构建运行在树莓派上的温度传感器 mapper
$ cd $GOPATH/src/github.com/kubeedge/examples/temperature-demo
$ docker build -t <your_registry>/kubeedge-temperature-mapper:<your_tag> .
- 部署 mapper
$ cd $GOPATH/src/github.com/kubeedge/examples/temperature-demo/
# 修改 deployment.yaml 文件中的下述内容:
# 1. 替换 "edge-node" 为边缘节点名称
# 2. 替换 "kubeedge/temperature-mapper-demo:arm32" 为 mapper 镜像的名字
$ kubectl create -f deployment.yaml
- 映射器将在更新后向云报告温度,通过在云端查看设备的属性来查看温度
$ kubectl get device temperature -o yaml -w