OPC UA

Background

OPC UA (Open Platform Communications Unified Architecture) is a communication protocol for industrial automation. Akri has implemented a Discovery Handler for discovering OPC UA Servers that live at specified endpoints or are registered with specified Local Discovery Servers. Background on the OPC UA Discovery Handler implementation can be found in the proposal. To try out using Akri to discover and utilize OPC UA servers, see the OPC UA end-to-end demo.

All of Akri's components can be deployed by specifying values in its Helm chart during an installation. This section will cover the values that should be set to (1) deploy the OPC UA Discovery Handlers and (2) apply a Configuration that tells Akri to discover devices using that Discovery Handler.

Deploying the OPC UA Discovery Handler

In order for the Agent to know how to discover OPC UA servers an OPC UA Discovery Handler must exist. Akri supports an Agent image that includes all supported Discovery Handlers. This Agent will be used if agent.full=true. By default, a slim Agent without any embedded Discovery Handlers is deployed and the required Discovery Handlers can be deployed as DaemonSets. This documentation will use that strategy, deploying OPC UA Discovery Handlers by specifying opcua.discovery.enabled=true when installing Akri.

OPC UA Configuration Settings

Instead of having to assemble your own OPC UA Configuration yaml, we have provided a Helm template. Helm allows us to parametrize the commonly modified fields in our configuration files, and we have provided many for OPC UA (to see them, run helm inspect values akri-helm-charts/akri). More information about the Akri Helm charts can be found in the user guide. To apply the OPC UA Configuration to your cluster, simply set opcua.configuration.enabled=true along with any of the following additional Configuration settings when installing Akri.

Discovery Handler Discovery Details Settings

Discovery Handlers are passed discovery details that are set in a Configuration to determine what to discover, filter out of discovery, and so on. The OPC UA Discovery Handler, requires a set of DiscoveryURLs to direct its search. Every OPC UA server/application has a DiscoveryEndpoint that Clients can access without establishing a session. The address for this endpoint is defined by a DiscoveryURL. A Local Discovery Server (LDS) is a unique type of OPC UA server which maintains a list of OPC UA servers that have registered with it.

The generic OPC UA Configuration takes in a list of DiscoveryURLs, whether for LDSes or a specific servers and an optional list of application names to either include or exclude. By default, if no DiscoveryURLs are set, the Discovery Handler will attempt to reach out to the Local Discovery Server on its host at the default address from OPC UA Specification 12 of opc.tcp://localhost:4840/ and get the list of OPC UA servers registered with it.

Helm Key
Value
Default
Description

opcua.configuration.discoveryDetails.discoveryUrls

array of DiscoveryURLs

["opc.tcp://localhost:4840/"]

DiscoveryURLs for OPC UA Servers or Local Discovery Servers

opcua.configuration.discoveryDetails.applicationNames.action

Include, Exclude

Exclude

filter action to take on a set of OPC UA Applications

opcua.configuration.discoveryDetails.applicationNames.items

array of application names

empty

application names that the filter action acts upon

Broker Pod Settings

If you would like non-terminating workloads ("broker" Pods) to be deployed automatically to discovered devices, a broker image should be specified (under brokerPod) in the Configuration. Alternatively, if it meets your scenario, you could use the Akri frame server broker ("ghcr.io/project-akri/akri/opcua-video-broker"). If you would rather manually deploy pods to utilize the devices advertized by Akri, don't specify a broker pod and see our documentation on requesting resources advertized by Akri.

Note only a brokerJob OR brokerPod should be specified.

Helm Key
Value
Default
Description

opcua.configuration.brokerPod.image.repository

image string

""

image of broker Pod that should be deployed to discovered devices

opcua.configuration.brokerPod.image.tag

tag string

"latest"

image tag of broker Pod that should be deployed to discovered devices

opcua.configuration.brokerPod.resources.memoryRequest

string

"76Mi"

the minimum amount of RAM that must be available to this Pod for it to be scheduled by the Kubernetes Scheduler. Default based on the Akri OPC UA sample broker. Adjust to the size of your broker.

opcua.configuration.brokerPod.resources.cpuRequest

string

"9m"

the minimum amount of CPU that must be available to this Pod for it to be scheduled by the Kubernetes Scheduler. Default based on the Akri OPC UA sample broker. Adjust to the size of your broker.

opcua.configuration.brokerPod.resources.memoryLimit

string

"200Mi"

the maximum amount of RAM this Pod can consume. Default based on the Akri OPC UA sample broker. Adjust to the size of your broker.

opcua.configuration.brokerPod.resources.cpuLimit

string

"30m"

the maximum amount of CPU this Pod can consume. Default based on the Akri OPC UA sample broker. Adjust to the size of your broker.

Broker Job Settings

If you would like terminating Jobs to be deployed automatically to discovered servers, a broker image should be specified (under brokerJob) in the Configuration. A Kubernetes Job deploys a set number of terminating Pods.

Note only a brokerJob OR brokerPod should be specified.

Helm Key
Value
Default
Description

opcua.configuration.brokerJob.image.repository

image string

""

image of broker Job that should be deployed to discovered devices

opcua.configuration.brokerJob.image.tag

tag string

"latest"

image tag of broker Job that should be deployed to discovered devices

opcua.configuration.brokerJob.resources.memoryRequest

string

"76Mi"

the minimum amount of RAM that must be available to this Pod for it to be scheduled by the Kubernetes Scheduler. Default based on the Akri OPC UA sample broker. Adjust to the size of your broker.

opcua.configuration.brokerJob.resources.cpuRequest

string

"9m"

the minimum amount of CPU that must be available to this Pod for it to be scheduled by the Kubernetes Scheduler. Default based on the Akri OPC UA sample broker. Adjust to the size of your broker.

opcua.configuration.brokerJob.resources.memoryLimit

string

"200Mi"

the maximum amount of RAM this Pod can consume. Default based on the Akri OPC UA sample broker. Adjust to the size of your broker.

opcua.configuration.brokerJob.resources.cpuLimit

string

"30m"

the maximum amount of CPU this Pod can consume. Default based on the Akri OPC UA sample broker. Adjust to the size of your broker.

opcua.configuration.brokerJob.command

string array

Empty

command to be executed in the Pod

opcua.configuration.brokerJob.restartPolicy

string array

OnFailure

RestartPolicy for the Job. Can either be OnFailure or Never for Jobs.

opcua.configuration.brokerJob.backoffLimit

number

2

opcua.configuration.brokerJob.parallelism

number

1

opcua.configuration.brokerJob.completions

number

1

Mounting Credentials Settings

See Mounting OPC UA credentials to enable security for more details on how to use this setting.

Helm Key
Value
Default
Description

opcua.configuration.mountCertificates

true, false

false

specify whether to mount a secret named opcua-broker-credentials into the OPC UA brokers

Disabling Automatic Service Creation

By default, if a broker Pod is specified, the generic OPC UA Configuration will create services for all the brokers of a specific Akri Instance and all the brokers of an Akri Configuration. The creation of these services can be disabled.

Helm Key
Value
Default
Description

opcua.configuration.createInstanceServices

true, false

true

a service should be automatically created for each broker Pod

opcua.configuration.createConfigurationService

true, false

true

a single service should be created for all brokers of a Configuration

Capacity Setting

By default, if a broker Pod is specified, a single broker Pod is deployed to each device. To modify the Configuration so that an OPC UA server is accessed by more or fewer nodes via broker Pods, update the opcua.configuration.capacity setting to reflect the correct number. For example, if your high availability needs are met by having 1 redundant pod, you can update the Configuration like this by setting opcua.configuration.capacity=2.

Helm Key
Value
Default
Description

opcua.configuration.capacity

number

1

maximum number of brokers that can be deployed to utilize a device (up to 1 per Node)

Installing Akri with the OPC UA Configuration and Discovery Handler

Leveraging the above settings, Akri can be installed with the OPC UA Discovery Handler and an OPC UA Configuration that specifies discovery via the default LDS DiscoveryURL:

helm repo add akri-helm-charts https://project-akri.github.io/akri/
helm install akri akri-helm-charts/akri \
    --set opcua.discovery.enabled=true \
    --set opcua.configuration.enabled=true

If you have a workload that you would like to automatically be deployed to each discovered server, specify the workload image when installing Akri. As an example, the installation below will deploy an empty nginx pod for each server. Instead, you should point to your image, say ghcr.io/<USERNAME>/opcua-broker.

helm repo add akri-helm-charts https://project-akri.github.io/akri/
helm install akri akri-helm-charts/akri \
    --set opcua.discovery.enabled=true \
    --set opcua.configuration.enabled=true \
    --set opcua.configuration.brokerPod.image.repository=nginx

Note: set opcua.configuration.brokerPod.image.tag to specify an image tag (defaults to latest).

The following installation examples have been given to show how to the OPC UA Configuration can be tailored to you cluster:

  • Specifying the DiscoveryURLs for OPC UA Local Discovery Servers

  • Specifying the DiscoveryURLs for specific OPC UA servers

  • Specifying the DiscoveryURLs for both Local Discovery Servers and servers

  • Filtering the servers by application name

  • Mounting OPC UA credentials to enable security

Specifying the DiscoveryURLs for OPC UA LocalDiscoveryServers

If no DiscoveryURLs are passed as Helm values, the default DiscoveryURL for LocalDiscoveryServers is used. Instead of using the default opc.tcp://localhost:4840/ LDS DiscoveryURL, an operator can specify the addresses of one or more Local Discovery Servers, like in the following example:

helm repo add akri-helm-charts https://project-akri.github.io/akri/
helm install akri akri-helm-charts/akri \
    --set opcua.discovery.enabled=true \
    --set opcua.configuration.enabled=true \
    --set opcua.configuration.discoveryDetails.discoveryUrls[0]="opc.tcp://10.1.2.3:4840/" \
    --set opcua.configuration.discoveryDetails.discoveryUrls[1]="opc.tcp://10.1.3.4:4840/"

Specifying the DiscoveryURLs for specific OPC UA Servers

If you know the DiscoveryURLs for the OPC UA Servers you want Akri to discover, manually list them when deploying Akri, like in the following:

helm repo add akri-helm-charts https://project-akri.github.io/akri/
helm install akri akri-helm-charts/akri \
    --set opcua.discovery.enabled=true \
    --set opcua.configuration.enabled=true \
    --set opcua.configuration.discoveryDetails.discoveryUrls[0]="opc.tcp://10.123.456.7:4855/"

Specifying the DiscoveryURLs for both LocalDiscoveryServers and Servers

OPC UA discovery can also receive a list of both OPC UA LDS DiscoveryURLs and specific Server urls, as in the following.

helm repo add akri-helm-charts https://project-akri.github.io/akri/
helm install akri akri-helm-charts/akri \
    --set opcua.discovery.enabled=true \
    --set opcua.configuration.enabled=true \
    --set opcua.configuration.discoveryDetails.discoveryUrls[0]="opc.tcp://10.1.2.3:4840/" \
    --set opcua.configuration.discoveryDetails.discoveryUrls[1]="opc.tcp://10.1.3.4:4840/" \
    --set opcua.configuration.discoveryDetails.discoveryUrls[2]="opc.tcp://10.123.456.7:4855/"

Note: The Agent's OPC UA discovery method only supports tcp DiscoveryURLs, since the Rust OPC UA library has yet to support http(s).

Filtering the Servers by application name

Instead of discovering all servers registered with specified Local Discovery Servers, you can choose to include or exclude a list of application names (the applicationName property of a server's ApplicationDescription as specified by OPC UA Specification). For example, to discover all servers registered with the default LDS except for the server named "Duke", do the following.

helm repo add akri-helm-charts https://project-akri.github.io/akri/
helm install akri akri-helm-charts/akri \
    --set opcua.discovery.enabled=true \
    --set opcua.configuration.enabled=true \
    --set opcua.configuration.discoveryDetails.applicationNames.action=Exclude \
    --set opcua.configuration.discoveryDetails.applicationNames.items[0]="Duke"

Alternatively, to only discover the server named "Go Tar Heels!", do the following:

helm repo add akri-helm-charts https://project-akri.github.io/akri/
helm install akri akri-helm-charts/akri \
    --set opcua.discovery.enabled=true \
    --set opcua.configuration.enabled=true \
    --set opcua.configuration.discoveryDetails.applicationNames.action=Include \
    --set opcua.configuration.discoveryDetails.applicationNames.items[0]="Go Tar Heels!"

Mounting OPC UA credentials to enable security

For your broker pod to utilize a discovered OPC UA server, it will need to contain an OPC UA Client. OPC UA Clients and Servers can establish an insecure connection so long as the OPC UA Servers support a Security Policy of None. However, if you would like your broker's OPC UA Client to establish a secure connection with an OPC UA server, the Client and Server must trust each other's x509 v3 certificates. This can be done in one of the three ways explained in the OPC UA proposal. The simplest method is to sign the OPC UA broker's certificate with the same Certificate Authority (CA) as the Server with which it wishes to connect. The certificates are passed to the broker via a Kubernetes Secret mounted as a volume to the directory /etc/opcua-certs/client-pki.

It is the operator's responsibility to generate the certificates and securely create a Kubernetes Secret named opcua-broker-credentials, ideally using a KMS. More information about using Kubernetes Secrets securely can be found in the credentials passing proposal. The following is an example kubectl command to create the Kubernetes Secret, projecting each certificate/crl/private key with the expected key name (ie client_certificate, client_key, ca_certificate, and ca_crl).

kubectl create secret generic opcua-broker-credentials \
--from-file=client_certificate=/path/to/AkriBroker.der \
--from-file=client_key=/path/to/AkriBroker.pfx \
--from-file=ca_certificate=/path/to/SomeCA.der \
--from-file=ca_crl=/path/to/SomeCA.crl

Certificates can be created and signed with a CA manually using openssl, by using the OPC Foundation certificate generator tool, or Akri's certificate generator. Be sure that the certificates are in the format expected by your OPC UA Client.

Finally, when mounting certificates is enabled with Helm via --set opcua.configuration.mountCertificates='true', the secret named opcua-broker-credentials will be mounted into the OPC UA brokers. It is mounted to the volume credentials at the mountPath /etc/opcua-certs/client-pki, as shown in the OPC UA Helm template. This is the path where the broker expects to find the certificates. The following is an example how to enable security:

helm repo add akri-helm-charts https://project-akri.github.io/akri/
helm install akri akri-helm-charts/akri \
    --set opcua.discovery.enabled=true \
    --set opcua.configuration.enabled=true \
    --set opcua.configuration.mountCertificates='true'

Note: If the Helm template for the OPC UA Configuration is too specific, you can customize the Configuration yaml to suit your needs.

Modifying a Configuration

Akri has provided further documentation on modifying the broker PodSpec, instanceServiceSpec, or configurationServiceSpec More information about how to modify an installed Configuration, add additional Configurations to a cluster, or delete a Configuration can be found in the Customizing an Akri Installation document.

Implementation details

The OPC UA implementation can be understood by looking at several things:

  1. OpcuaDiscoveryDetails defines the required properties.

  2. OpcuaDiscoveryHandler defines OPC UA Server discovery.

  3. sample-brokers/opcua-monitoring-broker defines a sample OPC UA protocol broker that monitors an OPC UA Variable with a specific NodeID.

Last updated