kubeedge之EdgeSite

kubeedge默认在云端部署edgeController和deviceController,然后通过websocket/quic隧道连接云端和边缘端,通过云端一个中心来统一调度应用到特定edge node上运行。但是,就像Rancher K3S的应用场景,有些时候边缘端也希望运行一套完整的k8s集群。K3S的方案只是提供了一套精简的k8s集群,而kubeedge的edgesite模式,除了运行k8s集群之外,还提供了对IOT设备的适配和支持。

架构

kubeedge-edgesite-arch.pnguploading.4e448015.gif转存失败重新上传取消

如上图所示,edgesite与传统的部署模式的差异在于edgeController与edged等之前边缘端的组件部署在一起;另外,k8s master虽然与下边的组件组没有画在一起,但是它们也被部署在边缘端。所以,没有了cloudHub和edgeHub之间基于隧道的通信。

这里可以看到,k8s master,也就是上面部分几乎是原生的k8s,不需要做任何改动;而下面部署就是kubeedge除cloudHub和edgeHub之外的所有组件。那代码能够直接复用?这在最后原理部分再来分析。

实验

这种架构,特别适合于已部署了一个k8s server端,在本地开发调试kubeedge组件的情况。在代码中加一些调试信息,本地快速编译,然后执行查看,方便快速理解代码逻辑。这里,我就要演示一把如何在本地运行kubeedge来对接到远端的k8s集群。

云端

我依然是使用在aliyun-vm上部署好的k3s集群,唯一需要注意的是,我在启动命令行中指定了参数,让api-server暴露了insecure-port 8080(这样本地就不需要指定各种证书信息了,当然为了安全,你也可以严格使用证书),具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
~ $ cat /etc/systemd/system/k3s.service
[Unit]
Description=Lightweight Kubernetes
Documentation=https://k3s.io
After=network-online.target

[Service]
...
ExecStart=/usr/local/bin/k3s \
    server \
    --kube-apiserver-arg insecure-bind-address=0.0.0.0 \  # 指定监听地址
    --kube-apiserver-arg insecure-port=8080               # 指定insecure-port

等待k3s启动之后,通过下面的node.yaml文件在k3s上kubectl apply -f node.yaml添加节点,注意节点的名称,后续edge端的配置文件需要设置为该名字。

1
2
3
4
5
6
7
apiVersion: v1
kind: Node
metadata:
  labels:
    name: edge-site
    node-role.kubernetes.io/edge: ""
  name: edge-site

边缘端

也就是我的本地笔记本,在kubeedge源码包中,有edgesite目录。需要进入到cmd目录中编译代码(这需要golang环境,这块不再介绍)、准备配置文件,并执行。

1
2
3
4
5
6
7
8
9
10
11
~ $ ls
Makefile  README.md cmd       conf

~ $ cd cmd
# 如果是golang 1.12版本,需要手动关闭go mod模式,因为该项目是基于go vendor的
~ $ GO111MODULE=off go build  

# 从上级目录复制conf目录中的配置文件到cmd目录中,并修改配置
~ $ cp -rf ../conf ./
~ $ ls conf
edgeSite.yaml logging.yaml  modules.yaml

这里只需要修改edgeSite.yaml, 具体配置修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
mqtt:
    server: tcp://127.0.0.1:1883 # external mqtt broker url.
    internal-server: tcp://127.0.0.1:1884 # internal mqtt broker url.
    mode: 0 # 0: internal mqtt broker enable only. 1: internal and external mqtt broker enable. 2: external mqtt broker enable only.
    qos: 0 # 0: QOSAtMostOnce, 1: QOSAtLeastOnce, 2: QOSExactlyOnce.
    retain: false # if the flag set true, server will store the message and can be delivered to future subscribers.
    session-queue-size: 100 # A size of how many sessions will be handled. default to 100.

controller:
    kube:
       master: http://${k3s-api-server}:8080  # 这里是k3s的insecure-port的访问URL
       namespace: "default"
       content_type: "application/vnd.kubernetes.protobuf"
       qps: 5
       burst: 10
       node_update_frequency: 10
       node-id: edge-site
       node-name: edge-site  # 该名称为预先在k8s上创建的node名称
    context:
       send-module: metaManager
       receive-module: controller
       response-module: metaManager

edged:
    register-node-namespace: default
    hostname-override: edge-site
    interface-name: eth0
    node-status-update-frequency: 10 # second
    device-plugin-enabled: false
    gpu-plugin-enabled: false
    image-gc-high-threshold: 80 # percent
    image-gc-low-threshold: 40 # percent
    maximum-dead-containers-per-container: 1
    docker-address: unix:///var/run/docker.sock
    runtime-type: docker
    version: 2.0.0

metamanager:
    context-send-group: controller
    context-send-module: controller
    edgesite: true

然后就在cmd目录下直接运行生成的cmd二进制文件了(记得要使用sudo,因为需要创建pods目录)。

1
~ $ sudo ./cmd

原理

前面有讲到,从kubeedge的云边模式,切换到纯边缘部署,代码方面是否可以复用?答案是肯定的,这块kubeedge设计的非常好。要理解这块的原理,需要理解beehive的消息转发。

模块与消息

模块 module name group name
deviceTwin twin twin
edged edged edged
cloudHub cloudhub cloudhub
edgeHub websocket hub
eventbus eventbus bus
servicebus servicebus bus
metaManager metaManager meta
edgeController controller controller
deviceController devicecontroller controller

模块之间通信的每一个消息都有如下关键组成:

  • 消息头信息
    1. 消息ID
    2. 消息父ID(请求的返回消息也有同样的该ID)
    3. 时间戳(消息创建时间)
    4. 同步消息标识
  • 消息路由信息
    1. 消息来源模块
    2. 消息目的广播组
    3. 操作
    4. 操作资源名称

在之前的架构中,metaManager的消息发送到controller需要经过edgeHub再到cloudHub,然后才能够送到controller。而当前在edgesite中直接取消掉了edgeHub和cloudHub,也就意味着,controller现在是直接将消息送到metaManager。

我们在来看一段controller读取配置文件时候的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const(
    DefaultContextSendModuleName     = "cloudhub"
	DefaultContextReceiveModuleName  = "controller"
	DefaultContextResponseModuleName = "cloudhub"
)

func init() {
	if smn, err := config.CONFIG.GetValue("controller.context.send-module").ToString(); err != nil {
		ContextSendModule = constants.DefaultContextSendModuleName // cloudhub
	} else {
		ContextSendModule = smn
	}
	log.LOGGER.Infof(" send module name: %s", ContextSendModule)

	if rmn, err := config.CONFIG.GetValue("controller.context.receive-module").ToString(); err != nil {
		ContextReceiveModule = constants.DefaultContextReceiveModuleName // controller
	} else {
		ContextReceiveModule = rmn
	}
	log.LOGGER.Infof("receive module name: %s", ContextReceiveModule)

	if rmn, err := config.CONFIG.GetValue("controller.context.response-module").ToString(); err != nil {
		ContextResponseModule = constants.DefaultContextResponseModuleName // cloudhub
	} else {
		ContextResponseModule = rmn
	}
	log.LOGGER.Infof("response module name: %s", ContextResponseModule)
}

云边模式的情况下使用默认配置,也就是controller发送消息以及发送响应都是往cloudHub发送,而接收都是订阅模块名为controller的消息。在edgesite模式下,配置文件有所变化,我截取edgeSite.yaml的关键部分:

1
2
3
4
5
6
7
8
9
10
controller:
    kube:
       ......
    context:
       send-module: metaManager     # controller消息不再中转,直接发送到metaManager
       receive-module: controller   # 订阅controller模块消息
       response-module: metaManager # response消息也一样
metamanager:
    context-send-group: controller  # 边缘端消息发送到controller group
    context-send-module: controller # 边缘端消息发送到controller module

至此,我们当值了解了edgesite的大概架构设计,适用场景,以及其代码的巧妙设计。当然,kubeedge还有更多目标,比如对serverless以及serviceMesh的支持等,待后续再慢慢分解。

发布了0 篇原创文章 · 获赞 0 · 访问量 548

猜你喜欢

转载自blog.csdn.net/qingdao666666/article/details/104551648