Compartir vía


Tutorial: Incorporación de recursos de OPC UA al clúster de operaciones de Azure IoT

En este tutorial, agregará manualmente recursos de OPC UA al clúster de operaciones de Azure IoT. Estos recursos publican mensajes en el corredor MQTT en el clúster de Operaciones de IoT de Azure. Normalmente, un usuario de OT sigue estos pasos.

Un recurso es un dispositivo físico o una entidad lógica que representa un dispositivo, una máquina, un sistema o un proceso. Por ejemplo, un recurso físico podría ser una bomba, un motor, un tanque o una línea de producción. Un recurso lógico que usted define puede tener propiedades y telemetría de flujo o generar eventos.

Los servidores OPC UA son aplicaciones de software que se comunican con recursos. Las etiquetas de OPC UA son puntos de datos que los servidores OPC UA exponen. Las etiquetas de OPC UA pueden proporcionar datos históricos o en tiempo real sobre el estado, el rendimiento, la calidad o la condición de los recursos.

En este tutorial, usará la interfaz de usuario web de la experiencia de operaciones para crear los recursos. También puede usar la CLI de Azure para completar algunas de estas tareas.

Requisitos previos

Una instancia de Operaciones de IoT de Azure implementada en un clúster de Kubernetes. Para crear una instancia, use una de las siguientes opciones para implementar Operaciones de IoT de Azure:

Para iniciar sesión en la experiencia de operaciones, necesita una cuenta de Id. de Microsoft Entra con al menos permisos de colaborador para el grupo de recursos que contiene la instancia de Kubernetes - Azure Arc. Para más información, consulte Experiencia de operaciones de la interfaz de usuario web.

A menos que se indique lo contrario, puede ejecutar los comandos de consola de este tutorial en un entorno de Bash o PowerShell.

¿Qué problema resolveremos?

Los datos que los servidores OPC UA exponen pueden tener una estructura compleja y ser difíciles de entender. Operaciones de IoT de Azure proporciona una manera de modelar los recursos de OPC UA, como las etiquetas, los eventos y las propiedades. Este modelado facilita la comprensión de los datos y su uso en procesos de bajada, como el corredor MQTT y las canalizaciones del procesador de datos.

Implementación del simulador de OPC PLC

En este tutorial se usa el simulador de OPC PLC para generar datos de ejemplo. Para implementar el simulador de OPC PLC, ejecute el siguiente comando:

kubectl apply -f https://raw.githubusercontent.com/Azure-Samples/explore-iot-operations/main/samples/quickstarts/opc-plc-deployment.yaml

En el fragmento de código siguiente se muestra el archivo YAML que aplicaste:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: opc-plc-000000
  namespace: azure-iot-operations
  labels:
    app.kubernetes.io/component: opcplc-000000
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/component: opcplc-000000
  template:
    metadata:
      labels:
        app.kubernetes.io/component: opcplc-000000
    spec:
      containers:
      - name: opc-plc
        image: mcr.microsoft.com/iotedge/opc-plc:latest
        args:
          - "--ph=opcplc-000000"
          - "--cdn=opcplc-000000"
          - "--ut"
          - "--sn=25"
          - "--sr=10"
          - "--fn=2000"
          - "--veryfastrate=1000"
          - "--gn=5"
          - "--pn=50000"
          - "--maxsessioncount=100"
          - "--maxsubscriptioncount=100"
          - "--maxqueuedrequestcount=2000"
          - "--ses"
          - "--alm"
          - "--at=FlatDirectory"
          - "--drurs"
          - "--ll-debug"
          - "--nodesfile"
          - "/app/config/nodesfile.json"
        ports:
        - containerPort: 50000
        volumeMounts:
          - name: opc-plc-default-application-cert
            mountPath: /app/pki/own
          - name: opc-plc-trust-list
            mountPath: /app/pki/trusted
          - name: config-volume
            mountPath: /app/config
      volumes:
        - name: opc-plc-default-application-cert
          secret:
            secretName: opc-plc-default-application-cert
        - name: opc-plc-trust-list
          secret:
            secretName: opc-plc-trust-list
        - name: config-volume
          configMap:
            name: opc-plc-config
      serviceAccountName: opcplc-000000-service-account
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: opc-plc-config
  namespace: azure-iot-operations
  labels:
    app.kubernetes.io/component: opcplc-000000
data:
  nodesfile.json: |
    {
      "Folder": "MyTelemetry",
      "NodeList": [
        {
          "NodeId": "ns=3;s=FastUInt100",
          "Name": "Fryer Temperature",
          "DataType": "Double",
          "ValueRank": -1,
          "AccessLevel": "CurrentReadOrWrite",
          "Description": "Fryer Temperature with spikes",
          "Anomaly": "Spike",
          "MinValue": 150.0,
          "MaxValue": 200.0          
        }
      ]
    }
---
apiVersion: v1
kind: Service
metadata:
  name: opcplc-000000
  namespace: azure-iot-operations
  labels:
    app.kubernetes.io/component: opcplc-000000
spec:
  type: ClusterIP
  selector:
    app.kubernetes.io/component: opcplc-000000
  ports:
    - port: 50000
      protocol: TCP
      targetPort: 50000
---
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: opc-plc-self-signed-issuer
  namespace: azure-iot-operations
  labels:
    app.kubernetes.io/component: opcplc-000000
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: opc-plc-default-application-cert
  namespace: azure-iot-operations
  labels:
    app.kubernetes.io/component: opcplc-000000
spec:
  secretName: opc-plc-default-application-cert
  duration: 2160h # 90d
  renewBefore: 360h # 15d
  issuerRef:
    name: opc-plc-self-signed-issuer
    kind: Issuer
  commonName: OpcPlc
  dnsNames:
    - opcplc-000000
    - opcplc-000000.azure-iot-operations.svc.cluster.local
    - opcplc-000000.azure-iot-operations
  uris:
    - urn:OpcPlc:opcplc-000000
  usages:
    - digital signature
    - key encipherment
    - data encipherment
    - server auth
    - client auth
  privateKey:
    algorithm: RSA
    size: 2048
  encodeUsagesInRequest: true
  isCA: false
---
apiVersion: v1
kind: Secret
metadata:
  name: opc-plc-trust-list
  namespace: azure-iot-operations
  labels:
    app.kubernetes.io/component: opcplc-000000
data: {}
---
apiVersion: batch/v1
kind: Job
metadata:
  name: opcplc-000000-execute-mutual-trust
  namespace: azure-iot-operations
  labels:
    app.kubernetes.io/component: opcplc-000000
spec:
  backoffLimit: 1
  template:
    spec:
      containers:
      - name: kubectl
        image: mcr.microsoft.com/oss/kubernetes/kubectl:v1.27.1
        imagePullPolicy: Always
        command: ["/bin/sh"]
        args: ["/scripts/execute-commands.sh"]
        volumeMounts:
        - name: scripts
          mountPath: /scripts
          readOnly: true
      restartPolicy: Never
      serviceAccountName: opcplc-000000-service-account
      volumes:
      - name: scripts
        configMap:
          name: opcplc-000000-execute-commands-script
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: opcplc-000000-execute-commands-script
  namespace: azure-iot-operations
  labels:
    app.kubernetes.io/component: opcplc-000000
data:
  execute-commands.sh: |
    #!/bin/sh

    # wait 20 seconds for the resources to be created
    sleep 20

    # Extract the OPC UA connector application instance certificate and add it to the OPC PLC trust list
    cert=$(kubectl -n azure-iot-operations get secret aio-opc-opcuabroker-default-application-cert -o jsonpath='{.data.tls\.crt}' | base64 -d)
    data=$(kubectl create secret generic temp --from-literal=opcuabroker.crt="$cert" --dry-run=client -o jsonpath='{.data}')
    kubectl patch secret opc-plc-trust-list -n azure-iot-operations -p "{\"data\": $data}"

    # Extract the OPC PLC application instance certificate and add it to the OPC UA connector trust list
    cert=$(kubectl -n azure-iot-operations get secret opc-plc-default-application-cert -o jsonpath='{.data.tls\.crt}' | base64 -d)
    data=$(kubectl create secret generic temp --from-literal=opcplc-000000.crt="$cert" --dry-run=client -o jsonpath='{.data}')
    kubectl patch secret aio-opc-ua-broker-trust-list -n azure-iot-operations -p "{\"data\": $data}"
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: opcplc-000000-service-account
  namespace: azure-iot-operations
  labels:
    app.kubernetes.io/component: opcplc-000000
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: opc-plc-000000-secret-access-role
  namespace: azure-iot-operations
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: opc-plc-000000-secret-access-rolebinding
  namespace: azure-iot-operations
subjects:
- kind: ServiceAccount
  name: opcplc-000000-service-account
  namespace: azure-iot-operations
roleRef:
  kind: Role
  name: opc-plc-000000-secret-access-role
  apiGroup: rbac.authorization.k8s.io

Precaución

Esta configuración no es segura. No uses esta configuración en un entorno de producción.

Inicio de sesión en la experiencia de operaciones

Para crear puntos de conexión de recursos, activos y suscribirse a etiquetas y eventos de OPC UA, use la experiencia de operaciones.

Vaya a la experiencia de operaciones en el explorador e inicie sesión con sus credenciales de Microsoft Entra ID.

Selección del sitio

Un sitio es una colección de instancias de Operaciones de IoT de Azure. Los sitios suelen agrupar instancias por ubicación física y facilitar a los usuarios de OT la búsqueda y administración de recursos. El administrador de TI crea sitios y les asigna instancias de Operaciones de IoT de Azure. Dado que está trabajando con una nueva implementación, aún no hay sitios. Para encontrar el clúster que creó anteriormente, seleccione Ver instancias sin asignar. En la experiencia de operaciones, una instancia representa un clúster donde implementó Operaciones de IoT de Azure.

Captura de pantalla que muestra el nodo instancias sin asignar en la experiencia de operaciones.

Selección de la instancia

Seleccione la instancia en la que implementó Operaciones de IoT de Azure en el tutorial anterior:

Captura de pantalla de la lista de instancias de Operaciones de IoT de Azure.

Sugerencia

Si no viera ninguna instancia, es posible que no esté en el inquilino de Microsoft Entra ID adecuado. Puede cambiar el inquilino desde el menú superior derecho en la experiencia de operaciones.

Adición de un punto de conexión de recurso

Al implementar operaciones de Azure IoT en el artículo anterior, incluyó un simulador OPC PLC integrado. En este paso, agregará un punto de conexión de recurso que le permite conectarse al simulador de OPC PLC.

Para agregar un punto de conexión de recurso:

  1. Seleccione Puntos de conexión de recursos y, a continuación, Crear punto de conexión de recurso:

    Captura de pantalla que muestra la página puntos de conexión del recurso en la experiencia de operaciones.

  2. Escriba la siguiente información del punto de conexión:

    Campo Value
    Nombre del punto de conexión del recurso opc-ua-connector-0
    URL del servidor OPC UA opc.tcp://opcplc-000000:50000
    Modo de autenticación de usuario Anonymous
  3. Para guardar la definición, seleccione Crear.

    Esta configuración implementa un nuevo punto de conexión de recurso denominado opc-ua-connector-0 en el clúster. Puede usar kubectl para ver los puntos de conexión de recursos:

    kubectl get assetendpointprofile -n azure-iot-operations
    

Administración de recursos

Después de seleccionar la instancia en la experiencia de operaciones, verá la lista disponible de recursos en la página Activos. Si aún no hay recursos, esta lista está vacía:

Captura de pantalla de la lista de recursos vacíos de operaciones de Azure IoT.

Crear un activo

Para crear un recurso, seleccione Crear recurso. A continuación, escriba la siguiente información del recurso:

Campo Value
Punto de conexión de recurso opc-ua-connector-0
Nombre de activo thermostat
Descripción A simulated thermostat asset
Tema de MQTT predeterminado azure-iot-operations/data/thermostat

Quite las Propiedades personalizadas existentes y agregue las siguientes propiedades personalizadas. Tenga cuidado de usar los nombres de propiedad exactos, ya que la plantilla de Power BI en un tutorial posterior las consulta:

Nombre de propiedad Detalles de la propiedad
proceso por lotes 102
cliente Contoso
equipment Caldera
isSpare true
ubicación Seattle

Captura de pantalla de la página de detalles del recurso de operaciones de IoT de Azure.

Seleccione Siguiente para ir a la página Agregar etiquetas.

Creación de etiquetas de OPC UA

Agregue dos etiquetas de OPC UA en la página Agregar etiquetas. Para agregar cada etiqueta, seleccione Agregar etiqueta o CSV y, después, seleccione Agregar etiqueta. Proporcione los detalles de la etiqueta que se indican en la siguiente tabla:

Id. de nodo Nombre de etiqueta Modo de observabilidad
ns=3;s=FastUInt10 temperatura Ninguno
ns=3;s=FastUInt100 Etiqueta 10 Ninguno

El modo Observabilidad es uno de los siguientes valores: None, Gauge, Counter, Histogram o Log.

Puede seleccionar Administrar la configuración predeterminada para cambiar el intervalo de muestreo predeterminado y el tamaño de cola de cada etiqueta.

Captura de pantalla de la página agregar etiqueta de operaciones de IoT de Azure.

Seleccione Siguiente para ir a la página Agregar eventos y, después, seleccione Siguiente para ir a la página Revisión.

Revisar

Revise los detalles del recurso y la etiqueta y realice los ajustes necesarios antes de seleccionar Crear:

Captura de pantalla de la página de revisión de creación de recursos de operaciones de Azure IoT.

Esta configuración implementa un nuevo punto de conexión de recurso denominado thermostat en el clúster. Puede usar kubectl para ver los recursos:

kubectl get assets -n azure-iot-operations

Visualización de recursos en Azure Portal

Para ver el punto de conexión del recurso y el recurso que creó en Azure Portal, vaya al grupo de recursos que contiene la instancia de Operaciones de IoT de Azure. Puede ver el recurso termostato en el grupo de recursos de Operaciones de IoT de Azure. Si selecciona Mostrar tipos ocultos, también puede ver el punto de conexión del recurso:

Captura de pantalla de Azure Portal en la que se muestra el grupo de recursos de Operaciones de IoT de Azure, incluido el recurso y el punto de conexión del recurso.

El portal le habilita ver los detalles del recurso. Seleccione Vista JSON para obtener más detalles:

Captura de pantalla de los detalles del recurso de Azure IoT Operations en Azure Portal.

Comprobar que los datos fluyan

Comprueba que los datos fluyen al corredor MQTT mediante la herramienta de mosquitto_sub. En este ejemplo, ejecutas la herramienta de mosquitto_sub dentro de su clúster de Kubernetes:

  1. Ejecuta el siguiente comando para implementar un pod que incluya las herramientas de mosquitto_pub y mosquitto_sub que son útiles para interactuar con el corredor MQTT en el clúster:

    kubectl apply -f https://raw.githubusercontent.com/Azure-Samples/explore-iot-operations/main/samples/quickstarts/mqtt-client.yaml
    

    En el fragmento de código siguiente se muestra el archivo YAML que aplicaste:

    # Important: do not use in production environments
    # Create a service account
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: mqtt-client
      namespace: azure-iot-operations
    ---
    # Creates a pod with mosquitto-clients and mqttui utilities in your cluster
    apiVersion: v1
    kind: Pod
    metadata:
      name: mqtt-client
      # The namespace must match the IoT MQ BrokerListener's namespace
      # Otherwise use the long hostname: aio-broker.azure-iot-operations.svc.cluster.local
      namespace: azure-iot-operations
    spec:
      # Use the "mqtt-client" service account which comes with default deployment
      # Otherwise create it with `kubectl create serviceaccount mqtt-client -n azure-iot-operations`
      serviceAccountName: mqtt-client
      containers:
        # Install mosquitto and mqttui utilities on Alpine linux
      - image: alpine
        name: mqtt-client
        command: ["sh", "-c"]
        args: ["apk add mosquitto-clients mqttui && sleep infinity"]
        resources:
          limits:
            cpu: 500m
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 100Mi
        volumeMounts:
        - name: broker-sat
          mountPath: /var/run/secrets/tokens
        - name: trust-bundle
          mountPath: /var/run/certs
      volumes:
      - name: broker-sat
        projected:
          sources:
          - serviceAccountToken:
              path: broker-sat
              audience: aio-internal # Must match audience in BrokerAuthentication
              expirationSeconds: 86400
      - name: trust-bundle
        configMap:
          name: azure-iot-operations-aio-ca-trust-bundle # Default root CA cert
    

    Precaución

    Esta configuración no es segura. No uses esta configuración en un entorno de producción.

  2. Cuando se ejecute el pod de mqtt-client, ejecuta el siguiente comando para crear un entorno de shell en el pod que creaste:

    kubectl exec --stdin --tty mqtt-client -n azure-iot-operations -- sh
    
  3. En el shell del pod mqtt-client, ejecute el siguiente comando para conectarse al corredor MQTT mediante la herramienta mosquitto_sub suscrita al tema data/thermostat:

    mosquitto_sub --host aio-broker --port 18883 --topic "azure-iot-operations/data/#" -v --debug --cafile /var/run/certs/ca.crt -D CONNECT authentication-method 'K8S-SAT' -D CONNECT authentication-data $(cat /var/run/secrets/tokens/broker-sat)
    

    Este comando continúa ejecutándose y muestra los mensajes a medida que llegan al tema data/thermostat hasta que presione Ctrl+C para detenerlo. Para salir del entorno de shell, escriba exit.

Para comprobar que el recurso de termostato que agregó está publicando datos, vea la telemetría en el tema azure-iot-operations/data:

Client $server-generated/05a22b94-c5a2-4666-9c62-837431ca6f7e received PUBLISH (d0, q0, r0, m0, 'azure-iot-operations/data/thermostat', ... (152 bytes))
{"temperature":{"SourceTimestamp":"2024-07-29T15:02:17.1858435Z","Value":4558},"Tag 10":{"SourceTimestamp":"2024-07-29T15:02:17.1858869Z","Value":4558}}
Client $server-generated/05a22b94-c5a2-4666-9c62-837431ca6f7e received PUBLISH (d0, q0, r0, m0, 'azure-iot-operations/data/thermostat', ... (152 bytes))
{"temperature":{"SourceTimestamp":"2024-07-29T15:02:18.1838125Z","Value":4559},"Tag 10":{"SourceTimestamp":"2024-07-29T15:02:18.1838523Z","Value":4559}}
Client $server-generated/05a22b94-c5a2-4666-9c62-837431ca6f7e received PUBLISH (d0, q0, r0, m0, 'azure-iot-operations/data/thermostat', ... (152 bytes))
{"temperature":{"SourceTimestamp":"2024-07-29T15:02:19.1834363Z","Value":4560},"Tag 10":{"SourceTimestamp":"2024-07-29T15:02:19.1834879Z","Value":4560}}
Client $server-generated/05a22b94-c5a2-4666-9c62-837431ca6f7e received PUBLISH (d0, q0, r0, m0, 'azure-iot-operations/data/thermostat', ... (152 bytes))
{"temperature":{"SourceTimestamp":"2024-07-29T15:02:20.1861251Z","Value":4561},"Tag 10":{"SourceTimestamp":"2024-07-29T15:02:20.1861709Z","Value":4561}}
Client $server-generated/05a22b94-c5a2-4666-9c62-837431ca6f7e received PUBLISH (d0, q0, r0, m0, 'azure-iot-operations/data/thermostat', ... (152 bytes))
{"temperature":{"SourceTimestamp":"2024-07-29T15:02:21.1856798Z","Value":4562},"Tag 10":{"SourceTimestamp":"2024-07-29T15:02:21.1857211Z","Value":4562}}

Si no fluye ningún dato, reinicie el pod de aio-opc-opc.tcp-1:

  1. Busque el nombre del pod de aio-opc-opc.tcp-1 mediante el comando siguiente:

    kubectl get pods -n azure-iot-operations
    

    El nombre del pod es similar a aio-opc-opc.tcp-1-849dd78866-vhmz6.

  2. Reinicie el pod aio-opc-opc.tcp-1 mediante un comando similar al ejemplo siguiente. Use el nombre del pod aio-opc-opc.tcp-1 del paso anterior:

    kubectl delete pod aio-opc-opc.tcp-1-849dd78866-vhmz6 -n azure-iot-operations
    

Las etiquetas de ejemplo que agregó en el tutorial anterior generan mensajes del recurso que tienen un aspecto similar al siguiente ejemplo:

{
    "temperature": {
        "SourceTimestamp": "2024-08-02T13:52:15.1969959Z",
        "Value": 2696
    },
    "Tag 10": {
        "SourceTimestamp": "2024-08-02T13:52:15.1970198Z",
        "Value": 2696
    }
}

¿Cómo solucionamos el problema?

En este tutorial, ha agregado un punto de conexión de recurso y luego ha definido un recurso y etiquetas. Los recursos y las etiquetas modelan los datos del servidor OPC UA para facilitar el uso de esos datos en un MQTT broker y otros procesos posteriores. Use el recurso termostato que definió en el siguiente tutorial.

Limpieza de recursos

Si continúa con el siguiente tutorial, mantenga todos los activos.

Si quiere eliminar la implementación de Operaciones de IoT de Azure, pero quiere mantener el clúster, use el comando az iot ops delete:

az iot ops delete --cluster $CLUSTER_NAME --resource-group $RESOURCE_GROUP

Si quiere eliminar todos los recursos que ha creado para este inicio rápido, elimine el clúster de Kubernetes donde ha implementado Operaciones de IoT de Azure y quite el grupo de recursos de Azure que contenía el clúster.

Si usó Codespaces para estas guías de inicio rápido, elimine Codespace de GitHub.

Paso siguiente

Tutorial: Envío de telemetría de recursos a la nube mediante un flujo de datos.