邊緣計算平臺 KubeEdge 雲邊協同機制解析

本文作者:周浩,中國移動雲能力中心軟件研發工程師,專注於雲原生、微服務、算力網絡等領域。

KubeEdge 介紹

KubeEdge 是一個致力於解決邊緣場景問題的開源系統,在 Kubernetes 原生的容器編排和調度能力之上,實現了雲邊協同、計算下沉、海量邊緣設備管理、邊緣自治等能力。KubeEdge 架構如下圖所示,包括雲端和邊緣端兩部分。

KubeEdge 架構圖

其中:

CloudHub:WebSocket 服務器,負責監控雲端的變化、緩存併發送消息到 EdgeHub。

EdgeController:擴展的 Kubernetes 控制器:負責管理邊緣節點和 pods 的元數據,因此數據才能被髮送到指定的邊緣節點。

DeviceController:擴展的 Kubernetes 控制器,負責管理邊緣設備,實現邊緣設備元數據 / 狀態數據在雲端與邊緣端的同步。

EdgeHub:WebSocket 客戶端,負責與雲邊服務交互實現邊緣計算。其中包括將雲邊資源同步更新到邊緣端以及將邊端主機、設備狀態變化廣播至雲端。

Edged:負責 pod 生命週期的管理,可以看成一個簡易版的 kubelet。

EventBus:EventBus 是一個 MQTT 客戶端負責與 MQTT 服務器 mosquitto 的交互,爲其他組件提供發佈與訂閱功能。

ServiceBus:ServiceBus 是一個 HTTP 客戶端與 HTTP 服務器使用 REST 進行交互,爲雲端組件提供 HTTP 客戶端功能,使其請求到達運行在邊緣端的 HTTP 服務器。

DeviceTwin:負責存儲設備狀態,並將設備狀態同步到雲端,同時也提供了了應用的查詢接口。

MetaManager:MetaManager 是 edged 與 edgehub 之間的 message 處理器,同時,也負責將元數據存儲 / 查詢到 / 從一個輕量級數據庫 SQLite。

基於 WebSocket + 消息封裝,同時優化了原生 Kubernetes 中一些不必要的請求,KubeEdge 實現了邊緣場景下的雲邊可靠通信。本文從邊緣設備管理和雲邊自定義消息傳遞兩個方面,來解析 KubeEdge 的雲邊協同機制。

邊緣設備管理

DeviceModel 和 Device

KubeEdge 通過 Kubernetes 的 CRD,增加了 DeviceModel 和 Device 兩個資源,分別來描述設備元信息和設備實例信息,DeviceController 負責邊緣設備管理,在雲和邊之間傳遞這些信息。用戶可以通過 Kubernetes API 從雲中創建、更新和刪除設備元數據,也可以通過 CRD API 控制設備屬性的預期 (desired) 狀態,從雲端對設備進行 CRUD 操作。

DeviceModel 描述了設備屬性,例如 “溫度” 或 “壓力”, 類似一個可重複使用的模板,使用它可以創建和管理許多設備。DeviceModel 示例如下:

apiVersion: devices.kubeedge.io/v1alpha2
kind: DeviceModel

metadata:
  name: counter-model
  namespace: default
spec:
 properties:
 - name: status
  description: counter status
  type:
    string:
      accessMode: ReadWrite
      defaultValue: ''

示例定義了一個計數器的 DeviceModel,它包含一個 string 類型的屬性‘status’。

一個 Device 實例代表一個實際的設備對象。它就像 device model 的實例化,引用了 model 中定義的屬性。計數器的 Device 示例如下:

apiVersion: devices.kubeedge.io/v1alpha2
kind: Device

metadata:
  name: counter
  labels:
    description: 'counter'
spec:
  deviceModelRef:
    name: counter-model
  nodeSelector:
    nodeSelectorTerms:
    - matchExpressions:
     - key: 'kubernetes.io/hostname'
       operator: In
       values:
       - kube-edge-1
status:
  twins:
    - propertyName: status
     desired:
       metadata:
         type: string
       value: 'OFF'
     reported:
       metadata:
         type: string
       value: '0'

yaml 中的 device status 包含兩份數據,一個是雲端希望設置的狀態數據(‘desired’),一個是邊緣端上報的狀態數據(‘reported’)。雲端的 DeviceController 通過 Kubernetes API 監聽 device 設備的創建事件,會自動創建一個新的 configmap,存儲該 device 的 status 等屬性信息,並保存到 ectd 中。EdgeController 將 configmap 同步到邊緣節點,因而邊緣節點的應用也能夠獲取設備的屬性信息。‘desired’值將初始化到邊緣節點數據庫以及邊緣設備中,因而即使邊緣節點重啓,也能自動恢復到之前的狀態。當然這個‘desired’值也會隨着雲端用戶對設備的 CRUD 而更改。

設備信息雲邊同步流程

雲端更新設備的操作同步到邊緣端,流程如下圖:

流程圖

雲端的 DeviceController 監聽 device 設備的變更事件,並將更新的 twin 數據通過 CloudHub 發送給邊緣節點。邊緣節點首先將數據存儲到本地數據庫,再通過 mqttbroker 同步到邊緣設備中。

邊緣端設備狀態信息上報到雲端,流程如下圖:

流程圖

邊緣端上報的數據首先也要存儲到本地數據庫,再通過 EdgeHub 發送給雲端。

雲邊自定義消息傳遞

ruleEndpoint 和 rule

在一些使用場景中,用戶需要在雲邊應用之間傳遞一些自定義的信息。基於 K8s 的 CRD,KubeEdge 增加了 ruleEndpoint 和 rule 兩個資源。ruleEndpoint 定義了信息源端和目的端,rule 定義了路由規則,從而實現雲邊應用間消息的傳遞。

ruleEndpoint 有三種類型:rest, eventbus, servicebus。其中:

rest:僅用於表示雲端的 rest 接口端點。既可以作爲源端,發送請求到邊緣節點,也可以作爲目的端,接收邊緣節點發來的信息。

eventbus:僅用於表示邊緣節點的端點。既可以作爲源端,發送數據到雲端,也可以作爲目的端,接收雲端發來的信息。

servicebus: 僅用於表示邊緣節點的 rest 接口端點。可作爲目的端,接收雲端發來的信息。

rule 描述了信息是如何從源端發送到目的端的,目前有三條路徑,如下圖所示,其中:

rest -> enventbus: 用戶在雲端通過 rest 接口,發送信息到邊緣端的 mqttbroker。

eventbus -> rest: 用戶在邊緣端通過 mqttbroker 發送信息,最終信息發送到雲端的 rest 接口。

rest -> servicebus: 用戶在雲端通過 rest 接口,發送信息到邊緣端的 rest 接口。

消息傳遞機制

如何傳遞自定義消息

首先,通過修改 cloudcore 的配置文件 cloudcore.yaml,在路由器模塊中加”enable:true”,表示啓動路由器模塊,然後重啓 cloudcore。

下面分別演示 rule 定義的三條消息傳遞路徑的使用方式。

雲端通過 rest 接口發送信息到邊緣端 mqttbroker

首先需要創建 rest 和 eventbus 類型的 ruleEndpoint。執行命令:

kubectl create -f ruleEndpoint-rest.yaml
kubectl create -f ruleEndpoint-eventbus.yaml

ruleEndpoint-rest.yaml 的內容如下:

apiVersion: rules.kubeedge.io/v1 
kind: RuleEndpoint 

metadata: 
  name: my-rest 
  labels: 
    description: cloud-endpoint 
spec: 
  ruleEndpointType: "rest" 
  properties: {}

ruleEndpoint-eventbus.yaml 的內容如下:

apiVersion: rules.kubeedge.io/v1
kind: RuleEndpoint 

metadata: 
  name: my-eventbus
  labels: 
    description: edge-endpoint
spec: 
  ruleEndpointType: "eventbus" 
  properties: {}

然後創建規則,執行命令:

kubectl create -f rule-rest-eventbus.yaml

rule-rest-eventbus.yaml 的內容如下:

apiVersion: rules.kubeedge.io/v1 
kind: Rule 

metadata: 
  name: my-rule 
  labels: 
    description: cloud-rest-edge-eventbus 
spec: 
  source: "my-rest" 
  sourceResource: {"path":"/a"} 
  target: "my-eventbus"
  targetResource: {"topic":"test"}

在雲端調用 rest 接口向邊緣端發送信息,rest 接口定義:

方法:POST

URL: http://{rest_endpoint}/{node_name}/{namespace}/{path}, {rest_endpoint} 是 {cloudcore_ip}:9443, {node_name} 是 edgenode 的名字,{namespace} 是規則的命名空間,{ path} 的前綴是 source ruleEndpoint 的 sourceResource。

Body: {user_message}, {user_message} 是用戶的消息,

例如:

curl -X POST -d'{"message": "123"}' http://localhost:9443/kube-edge-1/default/a

邊緣端應用訂閱 mqttbroker 的 topic,執行命令

mosquitto_sub -t 'test' -d

即可接收雲端消息:{“message”:“123”}

邊緣端通過 mqttbroker 到雲端 rest 接口

創建 rest 和 eventbus 類型 ruleEndpoint,執行命令

kubectl create -f ruleEndpoint-rest.yaml
kubectl create -f ruleEndpoint-eventbus.yaml

ruleEndpoint-rest.yaml 的內容如下:

apiVersion: rules.kubeedge.io/v1 
kind: RuleEndpoint 

metadata: 
  name: my-rest 
  labels: 
    description: cloud-endpoint 
spec: 
  ruleEndpointType: "rest" 
  properties: {}

ruleEndpoint-eventbus.yaml 的內容如下:

apiVersion: rules.kubeedge.io/v1 
kind: RuleEndpoint 

metadata: 
  name: my-eventbus 
  labels: 
    description: edge-endpoint 
spec: 
  ruleEndpointType: "eventbus" 
  properties: {}

創建規則,執行命令:

kubectl create -f rule-eventbus-rest.yaml

rule-eventbus-rest.yaml 的內容如下:

apiVersion: rules.kubeedge.io/v1 
kind: Rule 

metadata: 
  name: my-rule-eventbus-rest 
  labels: 
    description: edge-eventbus-cloud-rest 
spec: 
  source: "my-eventbus" 
  sourceResource: {"topic""test","node_name""k8s-edge-1"} 
  target: "my-rest" 
  targetResource: {"resource":"http://k8s-master:8080/b"}

邊緣端的應用可發佈信息到 topic,消息將傳遞到雲端應用的 rest 接口地址。

使用 mosquitto 發佈數據,執行命令:

mosquitto_pub -t 'default/test' -d -m '{"edgemsg":"msgtocloud"}'

雲端應用的 rest 接口定義:

方法:POST

URL:目標 ruleEndpoint 的 targetResource。

正文:{user_api_body}

一個簡單的用 go 寫的 httpserver 如下,實現了該 rest 接口:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"

)

func sayReceived(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()           // 解析參數
    bytes, err := ioutil.ReadAll(r.Body)
    if err != nil {
        log.Fatal(err)
    }
    r.Body.Close()
    fmt.Println(string(bytes));
    fmt.Fprintf(w, "雲端收到!")
}

func main() {
    http.HandleFunc("/b", sayReceived)
    err := http.ListenAndServe(":8080", nil)
   if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

雲端運行 httpserver 應用後,在邊緣端發送信息,即可在雲端收到。

雲端 rest 接口到邊緣端 rest 接口

創建 rest 和 servicebus 類型的 ruleEndpoint。執行命令:

kubectl create -f ruleEndpoint-rest.yaml
kubectl create -f ruleEndpoint-servicebus.yaml

ruleEndpoint-rest.yaml 的內容如下:

apiVersion: rules.kubeedge.io/v1
kind: RuleEndpoint

metadata:  
  name: my-rest 
  labels:   
    description: cloud-endpoint
spec:  
  ruleEndpointType: "rest" 
  properties: {}

ruleEndpoint-servicebus.yaml 的內容如下:

apiVersion: rules.kubeedge.io/v1
kind: RuleEndpoint

metadata:  
  name: my-servicebus 
  labels:   
    description: edge-endpoint
spec:  
  ruleEndpointType: "servicebus" 
  properties: {"service_port":"6666"}

創建規則。執行命令:

kubectl create -f rule-rest-servicebus.yaml

rule-rest-servicebus.yaml 的內容如下:

apiVersion: rules.kubeedge.io/v1
kind: Rule

metadata:  
  name: my-rule-rest-servicebus 
  labels:   
    description: cloud-rest-end-servicebus
spec:  
  source: "my-rest" 
  sourceResource: {"path":"/source"} 
  target: "my-servicebus" 
  targetResource: {"path":"/target"}

可以在雲端調用 rest 接口向邊緣節點上的 servicebus 發送消息。

方法:POST/GET/DELETE/PUT

URL:http://{rest_endpoint}/{node_name}/{namespace}/{path}{rest_endpoint} 是 {cloudcore_ip}:9443{node_name} 是 edgenode 的名稱,{namespace} 是規則的命名空間。{path} 是 source ruleEndpoint 的 sourceResource。

Body: {user_message}, {user_message} 是用戶的消息。

最後,kubeedge 的 servicebus 會調用邊緣節點上應用的接口 targetResource,用戶的應用程序在邊緣節點即可獲得 API 的請求。

總結

本文從邊緣設備管理和雲邊自定義消息傳遞兩個方面,介紹了 KubeEdge 的雲邊協同機制,可根據實際場景選擇使用。另外就是受篇幅所限,本文並未介紹 KubeEdge 邊緣端之間的通信框架 EdgeMesh,這個將在後續文章中介紹。

參考資料

引用鏈接

[1] KubeEdge 文檔 - kubedege.io: https://kubeedge.io/en/docs
[2] KubeEdge Proposals - github.com: https://github.com/kubeedge/kubeedge/tree/master/docs/proposals
[3] Kubeedge 設備添加以及 mapper 管理 - blog.csdn.net: https://blog.csdn.net/qq_33690342/article/details/125226572
[4] KubeEdge 整體介紹 - zhuanlan.zhihu.com: https://zhuanlan.zhihu.com/p/350335104

雲原生社區動態 雲原生社區是國內最大獨立第三方雲原生終端用戶社區。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/CM5qjHIROHrsLRU_JSxkDw