Skip to main content
版本:Next

云原生管理端设备

本文档主要讲述如何在已有的OpenYurt集群上使用PlatformAdmin部署EdgeX系统和YurtIoTDock组件。 在 OpenYurt v1.4 版本中,我们升级了原来的 yurt-edgex-manager 和 yurt-device-controller 组件。前者已经内置于 yurt-manager 中,用户可以通过编写 Yaml 文件来创建 PlatformAdmin 资源,简单几行配置就可以往节点池内构建一套完整的 EdgeX 系统;后者更名为 yurt-iot-dock ,会在 PlatformAdmin 创建时自动下发到边缘侧,实现帮助用户一键实现端设备托管的能力。

如果你还没有OpenYurt集群,你可以使用yurtadm工具来初始化一个OpenYurt集群或将一个Kubernetes集群转换为OpenYurt集群。

环境要求

  • OpenYurt v1.4.0+

  • 安装了yurt-manager组件

  • 与master不在同一局域网下的节点都需要部署coreDNS pod

  • 将访问coreDNS service的流量改为节点池内闭环,参考教程

安装YurtIoTDock环境

如果想要使用PlatformAdmin来部署yurt-iot-dock,需要先将yurt-iot-dock相关的helm包安装到集群中。

helm install yurt-iot-dock ./charts/yurt-iot-dock

端设备平台管理

1. 创建节点池

首先创建两个节点池,一个是名为beijing的云端节点池,一个是名为hangzhou的边缘节点池。

# 创建beijing节点池
cat << EOF | kubectl apply -f -
apiVersion: apps.openyurt.io/v1beta1
kind: NodePool
metadata:
  name: beijing
spec:
  type: Cloud
EOF

# 创建hangzhou节点池
cat << EOF | kubectl apply -f -
apiVersion: apps.openyurt.io/v1beta1
kind: NodePool
metadata:
  name: hangzhou
spec:
  type: Edge
EOF

然后将指定的节点加入节点池,标记openyurt-worker节点为云端节点,标记openyurt-worker2节点为边缘节点

# 将openyurt-worker标记为云端节点
kubectl label node openyurt-worker apps.openyurt.io/nodepool=beijing
# 将openyurt-worker2标记为边缘节点
kubectl label node openyurt-worker2 apps.openyurt.io/nodepool=hangzhou

最后检查节点池状态,确保节点池状态正常

# 检查节点池状态
kubectl get np
NAME       TYPE    READYNODES   NOTREADYNODES   AGE
beijing    Cloud   1            0               4d18h
hangzhou   Edge    1            0               4d18h

2. 在节点池内创建IoT系统PlatformAdmin

配置好使用EdgeX版本,选择在hangzhou节点池中创建

# 在节点池hangzhou中创建minnesota版本的EdgeX
cat <<EOF | kubectl apply -f -
apiVersion: iot.openyurt.io/v1alpha2
kind: PlatformAdmin
metadata:
  name: edgex-sample
spec:
  version: minnesota
  poolName: hangzhou
EOF

# 检查部署情况
kubectl get po
NAME                                                              READY   STATUS    RESTARTS   AGE
edgex-core-command-hangzhou-4j6pz-8668ff94d7-hqw2r                1/1     Running   0          61s
edgex-core-common-config-bootstrapper-hangzhou-jnw2q-57bd99xr9p   1/1     Running   0          61s
edgex-core-consul-hangzhou-6p9tj-798489c647-6xz4m                 1/1     Running   0          61s
edgex-core-metadata-hangzhou-6l7v5-6f964fc4f-67f9p                1/1     Running   0          61s
edgex-redis-hangzhou-cwgsw-5c7d7fc478-fsgp9                       1/1     Running   0          61s

3. 部署可选组件

目前v1.4.0的PlatformAdmin支持通过components字段一键部署可选组件,下面是通过components字段部署yurt-iot-dock、edgex-device-virtual、edgex-device-rest的例子

可选组件的组件名参考Component文档

# 在刚才部署的PlatformAdmin之上增加components字段
cat <<EOF | kubectl apply -f -
apiVersion: iot.openyurt.io/v1alpha2
kind: PlatformAdmin
metadata:
  name: edgex-sample
spec:
  version: minnesota
  poolName: hangzhou
  components:
  - name: yurt-iot-dock
  - name: edgex-device-virtual
  - name: edgex-device-rest
EOF

# 可以看到可选的components已经部署起来了
kubectl get po
NAME                                                              READY   STATUS    RESTARTS   AGE
edgex-core-command-hangzhou-cwgs2-77bb5d9cdd-zp89r                1/1     Running   0          20m
edgex-core-common-config-bootstrapper-hangzhou-bqhnb-57bd9c4q5q   1/1     Running   0          20m
edgex-core-consul-hangzhou-5rl7c-66dbc9c7d7-dqvm8                 1/1     Running   0          20m
edgex-core-metadata-hangzhou-srpff-dd6c6f9cb-2cj9k                1/1     Running   0          20m
edgex-device-rest-hangzhou-v7p99-7b8bb4f5d4-kz8sq                 1/1     Running   0          7m49s
edgex-device-virtual-hangzhou-ssz59-796f948c69-5k4tc              1/1     Running   0          7m49s
edgex-redis-hangzhou-bk5g5-5fbdf6fffb-cmf6d                       1/1     Running   0          20m
yurt-iot-dock-hangzhou-56f98-8549f848f5-v2pjn                     1/1     Running   0          7m49s

4. 修改组件配置

PlatfromAdmin给高阶用户提供了自定义配置的入口,所有PlatformAdmin的配置都通过一个名为platformadmin-framework的configmap控制,通过修改这个configmap的值用户可以修改每个组件的配置,下面是platformadmin-framework的一个例子

apiVersion: v1
data:
  framework: |
    components:
    - deployment:
        selector:
          matchLabels:
            app: edgex-core-command
        strategy: {}
        template:
          metadata:
            creationTimestamp: null
            labels:
              app: edgex-core-command
          spec:
            containers:
            - env:
              - name: SERVICE_HOST
                value: edgex-core-command
              - name: EXTERNALMQTT_URL
                value: tcp://edgex-mqtt-broker:1883
              envFrom:
              - configMapRef:
                  name: common-variables
              image: openyurt/core-command:3.0.0
              imagePullPolicy: IfNotPresent
              name: edgex-core-command
              ports:
              - containerPort: 59882
                name: tcp-59882
                protocol: TCP
              resources: {}
            hostname: edgex-core-command
      name: edgex-core-command
      service:
        ports:
        - name: tcp-59882
          port: 59882
          protocol: TCP
          targetPort: 59882
        selector:
          app: edgex-core-command
...

5. 手动添加组件

考虑到某些用户可能需要新增一些自己编写或修改的组件,PlatformAdmin的component机制也支持用户新增组件。新增组件需要遵守如下步骤:

配置PlatformAdmin

在PlatformAdmin的components字段中加入需要新增的组件的名字,比如我们想要增加一个名为nginx-demo的组件

# 在components字段中增加nginx-demo
cat <<EOF | kubectl apply -f -
apiVersion: iot.openyurt.io/v1alpha2
kind: PlatformAdmin
metadata:
  name: edgex-sample
spec:
  version: minnesota
  poolName: hangzhou
  components:
  - name: yurt-iot-dock
  - name: edgex-device-virtual
  - name: edgex-device-rest
  - name: nginx-demo
EOF

填写PlatformAdminFramework

由于AutoCollector收集的标准配置文件并不存在nginx-demo这个组件,所以platformadmin-framework中并没有对应的配置,这时用户可以手动增加这个组件

# 使用kubectl edit修改configmap中的内容
kubectl edit cm platformadmin-framework

# 新增nginx-demo配套的deployment和service
apiVersion: v1
data:
  framework: |
    components:
    - deployment:
        selector:
          matchLabels:
            app: nginx-demo
        strategy: {}
        template:
          metadata:
            creationTimestamp: null
            labels:
              app: nginx-demo
          spec:
            containers:
            - image: nginx
              imagePullPolicy: IfNotPresent
              name: nginx-demo
              ports:
              - containerPort: 80
                name: nginx
                protocol: TCP
              resources: {}
            hostname: nginx-demo
      name: nginx-demo
      service:
        ports:
        - name: nginx
          port: 80
          protocol: TCP
          targetPort: 80
        selector:
          app: nginx-demo
...

保存退出后可以看到nginx-demo这个组件已经被部署起来了

# deployment成功创建,pod已经成功部署
kubectl get po
NAME                                                              READY   STATUS    RESTARTS   AGE
edgex-core-command-hangzhou-2mvhc-77bb5d9cdd-7xtgp                1/1     Running   0          4m17s
edgex-core-common-config-bootstrapper-hangzhou-tp2qc-57bd9cpj8p   1/1     Running   0          4m17s
edgex-core-consul-hangzhou-hhnvv-66dbc9c7d7-cp5c9                 1/1     Running   0          4m17s
edgex-core-metadata-hangzhou-pd9b2-dd6c6f9cb-xzx45                1/1     Running   0          4m17s
edgex-device-rest-hangzhou-l55qd-7b8bb4f5d4-s7pw6                 1/1     Running   0          4m17s
edgex-device-virtual-hangzhou-ftrg9-796f948c69-rfpnk              1/1     Running   0          4m17s
edgex-redis-hangzhou-9hnpn-5fbdf6fffb-vzh5k                       1/1     Running   0          4m17s
nginx-demo-hangzhou-p5p2k-5cd7c897d6-49ss9                        1/1     Running   0          108s
yurt-iot-dock-hangzhou-gg85j-8549f848f5-sbhmk                     1/1     Running   0          4m17s

# 对应的service也成功创建
kubectl get svc
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
edgex-core-command     ClusterIP   10.96.146.121   <none>        59882/TCP   4m54s
edgex-core-consul      ClusterIP   10.96.39.123    <none>        8500/TCP    4m54s
edgex-core-metadata    ClusterIP   10.96.58.12     <none>        59881/TCP   4m54s
edgex-device-rest      ClusterIP   10.96.39.152    <none>        59986/TCP   4m54s
edgex-device-virtual   ClusterIP   10.96.165.130   <none>        59900/TCP   4m54s
edgex-redis            ClusterIP   10.96.159.68    <none>        6379/TCP    4m54s
kubernetes             ClusterIP   10.96.0.1       <none>        443/TCP     8d
nginx-demo             ClusterIP   10.96.40.228    <none>        80/TCP      2m25s

如果想要一键移除这个组件的话,只需要在components字段中去掉对应的name就行,PlatformAdmin会自动回收对应名字的组件

# 在components字段中删除nginx-demo
cat <<EOF | kubectl apply -f -
apiVersion: iot.openyurt.io/v1alpha2
kind: PlatformAdmin
metadata:
  name: edgex-sample
spec:
  version: minnesota
  poolName: hangzhou
  components:
  - name: yurt-iot-dock
  - name: edgex-device-virtual
  - name: edgex-device-rest
  # - name: nginx-demo
EOF

# 可以看到对应的deployment和service都回收了
kubectl get deploy
NAME                                                   READY   UP-TO-DATE   AVAILABLE   AGE
edgex-core-command-hangzhou-2mvhc                      1/1     1            1           7m50s
edgex-core-common-config-bootstrapper-hangzhou-tp2qc   1/1     1            1           7m50s
edgex-core-consul-hangzhou-hhnvv                       1/1     1            1           7m50s
edgex-core-metadata-hangzhou-pd9b2                     1/1     1            1           7m50s
edgex-device-rest-hangzhou-l55qd                       1/1     1            1           7m50s
edgex-device-virtual-hangzhou-ftrg9                    1/1     1            1           7m50s
edgex-redis-hangzhou-9hnpn                             1/1     1            1           7m50s
yurt-iot-dock-hangzhou-gg85j                           1/1     1            1           7m50s

kubectl get svc
NAME                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
edgex-core-command     ClusterIP   10.96.146.121   <none>        59882/TCP   8m1s
edgex-core-consul      ClusterIP   10.96.39.123    <none>        8500/TCP    8m1s
edgex-core-metadata    ClusterIP   10.96.58.12     <none>        59881/TCP   8m1s
edgex-device-rest      ClusterIP   10.96.39.152    <none>        59986/TCP   8m1s
edgex-device-virtual   ClusterIP   10.96.165.130   <none>        59900/TCP   8m1s
edgex-redis            ClusterIP   10.96.159.68    <none>        6379/TCP    8m1s
kubernetes             ClusterIP   10.96.0.1       <none>        443/TCP     8d

注:不建议在platformadmin-framework中直接修改组件名,这会导致组件脱离platformadmin管控!

端设备管理

接下来,我们将以虚拟设备为例,介绍 yurt-iot-dock 在端设备管理功能。

1. 手动添加 device-virtual 组件

为了方便起见,我们只需部署一个虚拟设备驱动程序 device-virtual-go。 它可以模拟不同类型的设备,生成设备数据,用户可以发送命令,从设备获得响应或对设备执行控制指令。

首先,我们需要确保在 PlatformAdmin 框架的 configmap 中存在 edgex-device-virtual:

# 使用 kubectl edit 获取 configmap 中的内容
kubectl get cm platformadmin-framework -o yaml

apiVersion: v1
data:
  framework: |
    components:
    - deployment:
        selector:
          matchLabels:
            app: edgex-device-virtual
        strategy: {}
        template:
          metadata:
            creationTimestamp: null
            labels:
              app: edgex-device-virtual
          spec:
            containers:
            - env:
              - name: SERVICE_HOST
                value: edgex-device-virtual
              envFrom:
              - configMapRef:
                  name: common-variables
              image: openyurt/device-virtual:3.0.0
              imagePullPolicy: IfNotPresent
              name: edgex-device-virtual
              ports:
              - containerPort: 59900
                name: tcp-59900
                protocol: TCP
              resources: {}
            hostname: edgex-device-virtual
      name: edgex-device-virtual
      service:
        ports:
        - name: tcp-59900
          port: 59900
          protocol: TCP
          targetPort: 59900
        selector:
          app: edgex-device-virtual
...

device-virtual-go 组件会在启动时自动创建并注册 deviceservice、5 种不同类型的 device 及其 deviceprofiles,而 yurt-iot-dock 组件会将它们都同步到 OpenYurt中。因此,你可以用 kubectl 进行检查:

$ kubectl get deviceservice
NAME                      NODEPOOL   SYNCED   AGE
hangzhou-device-virtual   hangzhou   true     2d1h

$ kubectl get device
NAME                                     NODEPOOL   SYNCED   AGE
hangzhou-random-binary-device            hangzhou   true     2d1h
hangzhou-random-boolean-device           hangzhou   true     2d1h
hangzhou-random-float-device             hangzhou   true     2d1h
hangzhou-random-integer-device           hangzhou   true     2d1h
hangzhou-random-unsignedinteger-device   hangzhou   true     2d1h

$ kubectl get deviceprofile
NAME                                     NODEPOOL   SYNCED   AGE
hangzhou-random-binary-device            hangzhou   true     2d1h
hangzhou-random-boolean-device           hangzhou   true     2d1h
hangzhou-random-float-device             hangzhou   true     2d1h
hangzhou-random-integer-device           hangzhou   true     2d1h
hangzhou-random-unsignedinteger-device   hangzhou   true     2d1h

2. 创建 Device, DeviceProfile

除了通过预配置在 edgex 中同步设备、设备配置文件和设备服务外,Openyurt 侧还提供了一种更通用的方法来创建设备和设备配置文件。

  1. 创建 DeviceProfile
apiVersion: iot.openyurt.io/v1alpha1
kind: DeviceProfile
metadata:
  name: openyurt-created-random-boolean-deviceprofile
spec:
  description: Example of Device-Virtual Created By OpenYurt
  deviceCommands:
  - isHidden: false
    name: WriteBoolValue
    readWrite: W
    resourceOperations:
    - defaultValue: ""
      deviceResource: Bool
    - defaultValue: "false"
      deviceResource: EnableRandomization_Bool
  - isHidden: false
    name: WriteBoolArrayValue
    readWrite: W
    resourceOperations:
    - defaultValue: ""
      deviceResource: BoolArray
    - defaultValue: "false"
      deviceResource: EnableRandomization_BoolArray
  deviceResources:
  - description: used to decide whether to re-generate a random value
    isHidden: true
    name: EnableRandomization_Bool
    properties:
      defaultValue: "true"
      readWrite: W
      valueType: Bool
  - description: Generate random boolean value
    isHidden: false
    name: Bool
    properties:
      defaultValue: "true"
      readWrite: RW
      valueType: Bool
  - description: used to decide whether to re-generate a random value
    isHidden: true
    name: EnableRandomization_BoolArray
    properties:
      defaultValue: "true"
      readWrite: W
      valueType: Bool
  - description: Generate random boolean array value
    isHidden: false
    name: BoolArray
    properties:
      defaultValue: '[true]'
      readWrite: RW
      valueType: BoolArray
  labels:
  - openyurt-created-device-virtual-example
  manufacturer: OpenYurt Community
  model: OpenYurt-Device-Virtual-01
  nodePool: hangzhou

此 DeviceProfile 只是 device-virtual-go 为演示目的而创建的 random-boolean DeviceProfile 的副本。

  1. 创建 Device

可以使用预先同步的 DeviceService 和上面创建的 DeviceProfile 创建一个虚拟的bool Device:

apiVersion: iot.openyurt.io/v1alpha1
kind: Device
metadata:
  name: openyurt-created-random-boolean-device
spec:
  adminState: UNLOCKED
  description: Example of Device Virtual
  labels:
  - openyurt-created-device-virtual-example
  managed: true
  nodePool: hangzhou
  notify: true
  operatingState: UP
  profileName: openyurt-created-random-boolean-deviceprofile
  protocols:
    other:
      Address: openyurt-created-device-virtual-bool-01
      Port: "300"
  serviceName: device-virtual

然后,我们可以通过 kubectl 查看 OpenYurt 中的资源对象,如下所示:

$ kubectl get deviceprofile openyurt-created-random-boolean-deviceprofile
NAME                                            NODEPOOL   SYNCED   AGE
openyurt-created-random-boolean-deviceprofile   hangzhou   true     15h

$ kubectl get device openyurt-created-random-boolean-device
NAME                                     NODEPOOL   SYNCED   AGE
openyurt-created-random-boolean-device   hangzhou   true     14h

4. 读取设备生成的数据

我们已经建立了环境并模拟了一个虚拟的布尔设备。

在 OpenYurt 中,我们只需像这样检查设备资源对象的状态子资源,就能轻松获取设备生成的最新数据:

$ kubectl get device openyurt-created-random-boolean-device -o yaml
apiVersion: iot.openyurt.io/v1alpha1
kind: Device
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"iot.openyurt.io/v1alpha1","kind":"Device","metadata":{"annotations":{},"name":"openyurt-boolean-device","namespace":"default"},"spec":{"adminState":"UNLOCKED","description":"Example of Device Virtual","labels":["openyurt-device-boolean-virtual"],"managed":true,"nodePool":"hangzhou","notify":true,"operatingState":"UP","profileName":"Random-Boolean-Device","protocols":{"other":{"Address":"openyurt-device-boolean-virtual-01","Port":"301"}},"serviceName":"openyurt-boolean-device"}}
  creationTimestamp: "2023-09-14T06:25:10Z"
  finalizers:
  - iot.openyurt.io/device
  generation: 2
  name: openyurt-boolean-device
  namespace: default
  resourceVersion: "1717015"
  uid: 6677eb4a-b644-4d5d-970a-1446f141a353
spec:
  adminState: UNLOCKED
  description: Example of Device Virtual
  deviceProperties:
    Bool:
      desiredValue: "true"
      name: Bool
  labels:
  - openyurt-created-device-virtual-example
  managed: false
  nodePool: hangzhou
  notify: true
  operatingState: UP
  profileName: openyurt-created-random-boolean-deviceprofile
  protocols:
    other:
      Address: openyurt-created-device-virtual-bool-01
      Port: "300"
  serviceName: device-virtual
status:
  adminState: UNLOCKED
  deviceProperties:
    Bool:
      actualValue: "true"
      getURL: http://edgex-core-command:59882/api/v3/device/name/openyurt-boolean-device/Bool
      name: Bool
    BoolArray:
      actualValue: '[true, true, true, false, false]'
      getURL: http://edgex-core-command:59882/api/v3/device/name/openyurt-boolean-device/BoolArray
      name: BoolArray
  edgeId: 5e63effd-deeb-4505-890e-17ec32f02511
  operatingState: UP
  synced: true

deviceProperties 显示该设备的所有属性。

例如,Bool 属性的最新值是 false,该值是从 EdgeX rest api http://edgex-core-command:59882/api/v2/device/name/openyurt-created-random-boolean-device/Bool 获取的。

5. 更新设备属性

如果要通过更新设备的可写属性来控制该设备,应首先将 Device.Spec.Managed 字段设置为 true,以表示 yurt-iot-dock 接管设备,否则所有更新操作都将被忽略。

  1. 将设备的 managed 字段设置为 true
kubectl patch device openyurt-created-random-boolean-device -p '{"spec":{"managed":true}}'  --type=merge
  1. 更改设备的管理状态

管理状态(又称 admin 状态)可由人工或其他系统控制设备服务。它可以设置为 "锁定"(LOCKED)或 "解锁"(UNLOCKED)。当设备服务被设置为锁定状态时,它不能响应任何命令请求,也不能从设备发送数据。

kubectl patch device openyurt-created-random-boolean-device -p '{"spec":{"adminState":"UNLOCKED"}}'  --type=merge

设置设备属性以控制/更新设备

kubectl patch device openyurt-created-random-boolean-device --type=merge -p '{"spec":{"managed":true,"deviceProperties":{"Bool": {"name":"Bool", "desiredValue":"false"}}}}'

在命令中,我们将 Bool DeviceProperty 值设置为 false,yurt-iot-dock 就会触发 EdgeX 命令并更改设备属性。我们可以多次观察设备的状态来检查这一点,你会发现该值始终为 false,除非你再次将该属性改为 true。

watch "kubectl get device openyurt-created-random-boolean-device -o json | jq '.status.deviceProperties.Bool.actualValue'"

# output
Every 2.0s: kubectl get device openyurt-boolean-device -o json | jq '.status.deviceProperties.Bool.actualValue'                                VM-16-6-ubuntu: Sat Sep 16 16:39:58 2023

"false"