• 云原生边缘设备解决方案Akri on k3s初体验


    作者:
    涂家英,SUSE 资深架构师,专注 Cloud-Native 相关产品和解决方案设计,在企业级云原生平台建设领域拥有丰富的经验。

    写在前面

    k3s 是 SUSE 推出的为物联网和边缘计算构建的经过认证的 Kubernetes 发行版,它可以帮助用户在资源受限的场景下使用 kubernetes,并结合 SUSE Rancher 实现云边协同。

    将 k3s 与微软开源的 kubernetes 边缘项目 Akri 结合使用,用户就拥有了在边缘环境发现和使用各种 IOT 设备的能力。

    架构

    Akri 目前是 CNCF 的一个开源项目,其功能简单地说就是可以根据配置自动地寻找到相应的 iot 设备,为其创建关联的工作负载,并且通过不断地检测实现工作负载的动态变化。引用一句官方的描述为:You name it, Akri finds it, you use it.

    架构如下:
    在这里插入图片描述

    包含了 Controller 服务、Agent 服务和 Discovery Handlers 服务以及两个 CRD 资源。

    具体的组件解析可以查看官方文档:https://docs.akri.sh/architecture/architecture-overview

    下面我们通过一个示例来更好地理解 Akri 的工作方式。

    体验

    示例使用了官方提供的一个 OPC UA 温度计 Demo,OPC UA 是现在使用比较广泛的工业自动化通信协议,我们可以通过 Akri 自动发现使用 OPU CA 协议的温度计设备,并为其创建工作负载,采集和使用其产生的温度数据。

    示例中体现的大致工作流程如下:

    首先需要模拟出两台 OPC UA 的服务设备,然后在 k3s 集群上部署 Akri 服务,基础工作完成后:

    1. 向集群配置用于发现 OPC UA 设备的 CRD(Configuration)
    2. CRD 下发后,Akri 的相应 Discovery 服务会按照规则寻找 OPC UA 设备
    3. 在找到 OPC UA 设备后,Agent 服务会生成设备对应的 CRD(Instance),Controller 服务查看到 Instance CRD 资源后,将创建对应的工作负载

    OPC UA 设备模拟

    使用了一个.NET 类型的开源项目模拟实现 OPU CA 设备,项目地址为:https://gitee.com/leotuss/opcua-donet

    克隆到本地后,需要修改以下文件:

    # /opcua-dotnet/Applications/ConsoleReferenceServer/Quickstarts.ReferenceServer.Config.xml文件第76、77行
    将替换为节点地址
    
    #/opcua-dotnet/Applications/ReferenceServer/Quickstarts.ReferenceServer.Config.xml文件第77、78行
    将替换为节点地址` 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Linux 要运行这个程序,需要安装.NET core 的 SDK 和 runtime

    可以使用以下命令运行此程序:

    dotnet run --project /opcua-dotnet/Applications/ConsoleReferenceServer/NetCoreReferenceServer.csproj
    
    • 1

    运行后,可以看到如下提示:

    root@edge-iot1:~/opcua-dotnet/Applications/ConsoleReferenceServer# dotnet run --project NetCoreReferenceServer.csproj
    .Net Core OPC UA Reference Server
    opc.tcp://192.168.6.151:62541/Quickstarts/ReferenceServer
    https://192.168.6.151:62540/Quickstarts/ReferenceServer/
    Server started. Press Ctrl-C to exit...
    
    • 1
    • 2
    • 3
    • 4
    • 5

    至此程序运行成功,应用可以通过订阅opc.tcp://:62541/Quickstarts/ReferenceServer获得数据

    安装 Akri

    可以通过 Helm 安装 Akri:

    # 添加Akri repo
    helm repo add akri-helm-charts https://project-akri.github.io/akri/
    
    # 部署Akri
    helm install akri akri-helm-charts/akri\
        --set kubernetesDistro=k3s \
        --set opcua.discovery.enabled=true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    关于 kubernetesDistro 配置,Akri 依赖 crictl 跟踪 pod 信息,所以必须知道容器运行时 socket 的位置。目前 Akri 支持四种类型:

    • 标准 kuberentes,对应配置为:--set kubernetesDistro=k8s
    • k3s,对应配置为:--set kubernetesDistro=k3s
    • microk8s,对应配置为:--set kubernetesDistro=microk8s
    • 其它,对应配置为:--set agent.host.containerRuntimeSocket=/container/runtime.sock

    关于 xxx.discovery.enabled 配置,Akri 目前支持三种设备发现:

    • onvif:IP Cameras 的主流协议
    • opc ua:工业自动化通信协议
    • udev:linux 设备管理器

    如我们需要 Akri 发现 onvif 设备,就可以配置 --set onvif.discovery.enabled=true,配置后 Akri 会在集群中部署相应的 Discovery 服务,以 Daemonset 的方式运行,支持叠加部署,如需要发现上述三种类型设备,部署命令可以修改为:

    helm install akri akri-helm-charts/akri\
        --set kubernetesDistro=k3s \
        --set opcua.discovery.enabled=true \
        --set onvif.discovery.enabled=true \
        --set udev.discovery.enabled=true
    
    • 1
    • 2
    • 3
    • 4
    • 5

    部署完成后查看集群 Pods 可以看到:

    root@edge-k3s:~# kubectl get pods
    NAME                                         READY   STATUS    RESTARTS       AGE
    akri-controller-deployment-d4f7847b6-rlgrr   1/1     Running   11 (25h ago)   4d2h
    akri-agent-daemonset-9s9m9                   1/1     Running   10 (25h ago)   3d23h
    akri-opcua-discovery-daemonset-tv84d         1/1     Running   8 (25h ago)    3d17h
    
    • 1
    • 2
    • 3
    • 4
    • 5

    部署 CRD

    使用 Akri 发现设备需要部署类型为 Configuration 的 CRD:

    apiVersion: akri.sh/v0
    kind: Configuration
    metadata:
     name: akri-opcua-monitoring
     namespace: default
    spec:
     brokerProperties:
       IDENTIFIER: Thermometer_Temperature
       NAMESPACE_INDEX: "2"
     brokerSpec:
       brokerPodSpec:
         containers:
         - image: ghcr.io/project-akri/akri/opcua-monitoring-broker:latest
           name: akri-opcua-monitoring-broker
           resources:
             limits:
               '{{PLACEHOLDER}}': "1"
               cpu: 30m
               memory: 200Mi
             requests:
               '{{PLACEHOLDER}}': "1"
               cpu: 9m
               memory: 76Mi
     capacity: 1
     configurationServiceSpec:
       ports:
       - name: grpc
         port: 80
         protocol: TCP
         targetPort: 8083
       type: ClusterIP
     discoveryHandler:
       name: opcua
       discoveryDetails: |+
         opcuaDiscoveryMethod:
           standard:
             discoveryUrls:
             - opc.tcp://192.168.6.151:62541/Quickstarts/ReferenceServer/
             - opc.tcp://192.168.6.152:62541/Quickstarts/ReferenceServer/
         applicationNames:
           action: Exclude
           items: []
       name: opcua
     instanceServiceSpec:
       ports:
       - name: grpc
         port: 80
         protocol: TCP
         targetPort: 8083
       type: ClusterIP
    
    • 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
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    需要关注的配置:

    • spec.brokerProperties: 用于定义需要采集数据的 ID 信息,本演示中 opcua 程序中添加了 IDENTIFIER:为Thermometer_TemperatureNAMESPACE_INDEX: "2"的数据输出,数据输出内容为 70-80 的随机数,并且在随机到 75 时,将 75 替换为 120
    • spec.brokerSpec.brokerPodSpec.containers.image: 设备对应工作负载的镜像,演示使用的是官方提供的镜像,作用是订阅 opcua 所产生的相应数据,此镜像是可以自定义的,实现更多可能
    • spec.capacity:针对设备的工作负载副本数量,用于实现工作负载高可用
    • spec.discoveryHandler: 这部分主要定义了发现 opuca 设备的规则,支持一些过滤规则
    • spec.configurationServiceSpec:Akri Controller 服务会为所有设备的工作负载创建一个总 svc,这段用于定义相应的 svc 的配置
    • spec.instanceServiceSpec: Akri Controller 服务会为每一个工作负载创建 svc,这段用于定义相应 svc 的配置

    示例中可以看到 opuca 的发现规则是具体的服务地址,如果要支持批量的 opuca 设备发现,可以使用 Local discovery server(LDS),将 opcua 的设备注册到 LDS 中,然后在 discoveryUrls 配置中使用 LDS 的地址。采用 LDS 方式的话,可以实现过滤能力,如排除掉哪些 opcua 服务或者包含哪些 opcua 服务,示例如下:

    # 发现LDS中的所有opcua设备,除了以外
    discoveryDetails: |+
     opcuaDiscoveryMethod:
       standard:
         discoveryUrls:
         - opc.tcp://:4840
     applicationNames:
       action: Exclude
       items:
       -
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    将 akri-opcua-monitoring 的 crd 部署到集群后,可以通过 kubectl get akric 查看:

    root@edge-k3s:~/akric-crd# kubectl get akric
    NAME                    CAPACITY   AGE
    akri-opcua-monitoring   1          2m13s
    
    • 1
    • 2
    • 3

    查看 Discovery 的服务日志可以看到,两个 opcua 设备已经被发现:

    [2022-11-10T08:26:26Z TRACE akri_opcua::discovery_impl] get_discovery_url_from_application - found server : Quickstart Reference Server
    [2022-11-10T08:26:26Z TRACE akri_opcua::discovery_impl] get_discovery_url_from_application - server has [UAString { value: Some("https://192.168.6.151:62540/Quickstarts/ReferenceServer/discovery") }, UAString { value: Some("opc.tcp://192.168.6.151:62541/Quickstarts/ReferenceServer") }] DiscoveryUrls
    [2022-11-10T08:26:26Z TRACE akri_opcua::discovery_impl] get_discovery_urls - Server at opc.tcp://192.168.6.152:62541/Quickstarts/ReferenceServer/ responded with 1 Applications
    [2022-11-10T08:26:26Z TRACE akri_opcua::discovery_impl] get_discovery_url_from_application - found server : Quickstart Reference Server
    [2022-11-10T08:26:26Z TRACE akri_opcua::discovery_impl] get_discovery_url_from_application - server has [UAString { value: Some("https://192.168.6.152:62540/Quickstarts/ReferenceServer/discovery") }, UAString { value: Some("opc.tcp://192.168.6.152:62541/Quickstarts/ReferenceServer") }] DiscoveryUrls
    [2022-11-10T08:26:26Z TRACE akri_opcua::discovery_handler] discover - found OPC UA server at DiscoveryURL opc.tcp://192.168.6.151:62541/Quickstarts/ReferenceServer
    [2022-11-10T08:26:26Z TRACE akri_opcua::discovery_handler] discover - found OPC UA server at DiscoveryURL opc.tcp://192.168.6.152:62541/Quickstarts/ReferenceServer
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    可以通过 kubectl get akrii 查看由 Agent 自动生成的 opcua 的 instance crd 资源:

    root@edge-k3s:~/akric-crd# kubectl get akrii
    NAME                           CONFIG                  SHARED   NODES          AGE
    akri-opcua-monitoring-7aa6fb   akri-opcua-monitoring   true     ["edge-k3s"]   5m10s
    akri-opcua-monitoring-20f7e0   akri-opcua-monitoring   true     ["edge-k3s"]   5m9s` 
    
    • 1
    • 2
    • 3
    • 4

    于此同时,使用 kubectl get pods 可以查看到为设备自动创建的工作负载:

    NAME                                         READY   STATUS    RESTARTS       AGE
    akri-controller-deployment-d4f7847b6-rlgrr   1/1     Running   11 (27h ago)   4d4h
    akri-agent-daemonset-9s9m9                   1/1     Running   10 (27h ago)   4d1h
    akri-opcua-discovery-daemonset-tv84d         1/1     Running   8 (27h ago)    3d19h
    edge-k3s-akri-opcua-monitoring-7aa6fb-pod    1/1     Running   0              6m44s  <---
    edge-k3s-akri-opcua-monitoring-20f7e0-pod    1/1     Running   0              6m43s  <---
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    部署数据展示服务

    部署数据展示服务查看效果:

    kubectl apply -f https://raw.githubusercontent.com/project-akri/akri/main/deployment/samples/akri-anomaly-detection-app.yaml
    
    • 1

    部署完成后,查看一下展示服务 SVC 的 NodePort 端口:

    root@edge-k3s:~# kubectl get svc
    NAME                               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
    kubernetes                         ClusterIP   10.43.0.1               443/TCP        5d6h
    akri-opcua-monitoring-7aa6fb-svc   ClusterIP   10.43.152.214           80/TCP         13m
    akri-opcua-monitoring-svc          ClusterIP   10.43.242.118           80/TCP         13m
    akri-opcua-monitoring-20f7e0-svc   ClusterIP   10.43.22.196            80/TCP         13m
    akri-anomaly-detection-app         NodePort    10.43.248.164           80:32007/TCP   7s <---
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    访问 NodePort 端口,查看效果:

    这个展示服务原理是通过连接工作负载的 SVC 获取工作负载采集到的设备数据,当值为 70-80 中任意数值时表示正常,用黑体展示;当值为 120 时表示异常,用红体展示

    当设备下线时,Akri 会自动删除设备对应的工作负载,删除的时间大约为 5 分钟,以便应对可能出现的临时网络故障。

    总 结

    Akri 其实可以理解为是一种设备自动发现的框架,它可以通过云原生的方式帮助我们发现并使用 IOT 设备,目前支持 onvif、udev、opcua 三种类型。其它包括 Bluetooth、CoAP、IP、LoRaWAN、Zeroconf、acpid、MQTT 也正在开发中。

    使用 k3s 可以帮助用户实现在边缘侧使用 kubernetes 的能力,通过 Akri 可以解决边缘场景下发现和使用设备的问题,这样用户就能将更多的精力专注在数据处理的应用上。

  • 相关阅读:
    【机器学习-周志华】学习笔记-第五章
    go mod 使用三方包、go get命令
    NLP教程(5) - 语言模型、RNN、GRU与LSTM
    Java编程实战12:解数独
    朋友圈为什么会被折叠?
    Android自定义控件(五) 自定义View实现Android Loading效果
    【链表OJ 10】环形链表Ⅱ(求入环节点)
    设计模式_spring框架中常用的8种设计模式
    [ubuntu]修改主机名
    邦芒攻略:面试迟到该如何补救
  • 原文地址:https://blog.csdn.net/RancherLabs/article/details/127978154