Skip to content

Commit ef072a2

Browse files
Merge pull request #283921 from ryanwinterms/main
AIO Dapr updates for improved troubleshooting and simpler deployment
2 parents 0ae6898 + 470faaf commit ef072a2

File tree

4 files changed

+106
-108
lines changed

4 files changed

+106
-108
lines changed

articles/iot-operations/create-edge-apps/howto-deploy-dapr.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Azure IoT Operations supports two of these building blocks, powered by [MQTT bro
2020
- Publish and subscribe
2121
- State management
2222

23-
To use the Dapr pluggable components, define the component spec for each of the APIs and then [register this to the cluster](https://docs.dapr.io/operations/components/pluggable-components-registration/). The Dapr components listen to a Unix domain socket placed on the shared volume. The Dapr runtime connects with each socket and discovers all services from a given building block API that the component implements.
23+
To use the Dapr pluggable components, define the component spec for each of the APIs and then [register with the cluster](https://docs.dapr.io/operations/components/pluggable-components-registration/). The Dapr components listen to a Unix domain socket placed on the shared volume. The Dapr runtime connects with each socket and discovers all services from a given building block API that the component implements.
2424

2525
## Install Dapr runtime
2626

@@ -44,15 +44,15 @@ To create the yaml file, use the following component definitions:
4444
> [!div class="mx-tdBreakAll"]
4545
> | Component | Description |
4646
> |-|-|
47-
> | `metadata.name` | The component name is important and is how a Dapr application references the component. |
48-
> | `metadata.annotations` | Component annotations used by Dapr sidecar injector, defining the image location and required volume mounts
49-
> | `spec.type` | [The type of the component](https://docs.dapr.io/operations/components/pluggable-components-registration/#define-the-component), which needs to be declared exactly as shown |
50-
> | `spec.metadata.keyPrefix` | Defines the key prefix used when communicating to the statestore backend. See the [Dapr documentation](https://docs.dapr.io/developing-applications/building-blocks/state-management/howto-share-state) for more information |
51-
> | `spec.metadata.hostname` | The MQTT broker hostname. Defaults to `aio-mq-dmqtt-frontend` |
52-
> | `spec.metadata.tcpPort` | The MQTT broker port number. Default is `8883` |
53-
> | `spec.metadata.useTls` | Define if TLS is used by the MQTT broker. Defaults to `true` |
54-
> | `spec.metadata.caFile` | The certificate chain path for validating the MQTT broker. Required if `useTls` is `true`. This file must be mounted in the pod with the specified volume name |
55-
> | `spec.metadata.satAuthFile ` | The Service Account Token (SAT) file is used to authenticate the Dapr components with the MQTT broker. This file must be mounted in the pod with the specified volume name |
47+
> | `metadata:name` | The component name is important and is how a Dapr application references the component. |
48+
> | `metadata:annotations:dapr.io/component-container` | Component annotations used by Dapr sidecar injector, defining the image location, volume mounts and logging configuration |
49+
> | `spec:type` | [The type of the component](https://docs.dapr.io/operations/components/pluggable-components-registration/#define-the-component), which needs to be declared exactly as shown |
50+
> | `spec:metadata:keyPrefix` | Defines the key prefix used when communicating to the statestore backend. See more information, see [Dapr documentation](https://docs.dapr.io/developing-applications/building-blocks/state-management/howto-share-state) for more information |
51+
> | `spec:metadata:hostname` | The MQTT broker hostname. Default is `aio-mq-dmqtt-frontend` |
52+
> | `spec:metadata:tcpPort` | The MQTT broker port number. Default is `8883` |
53+
> | `spec:metadata:useTls` | Define if TLS is used by the MQTT broker. Default is `true` |
54+
> | `spec:metadata:caFile` | The certificate chain path for validating the MQTT broker. Required if `useTls` is `true`. This file must be mounted in the pod with the specified volume name |
55+
> | `spec:metadata:satAuthFile ` | The Service Account Token (SAT) file is used to authenticate the Dapr components with the MQTT broker. This file must be mounted in the pod with the specified volume name |
5656
5757
1. Save the following yaml, which contains the Azure IoT Operations component definitions, to a file named `components.yaml`:
5858

@@ -70,6 +70,10 @@ To create the yaml file, use the following component definitions:
7070
"volumeMounts": [
7171
{ "name": "mqtt-client-token", "mountPath": "/var/run/secrets/tokens" },
7272
{ "name": "aio-ca-trust-bundle", "mountPath": "/var/run/certs/aio-mq-ca-cert" }
73+
],
74+
"env": [
75+
{ "name": "pubSubLogLevel", "value": "Information" },
76+
{ "name": "stateStoreLogLevel", "value": "Information" }
7377
]
7478
}
7579
spec:
@@ -163,4 +167,4 @@ To configure authorization policies to MQTT broker, first you create a [BrokerAu
163167

164168
## Next steps
165169

166-
Now that you have deployed the Dapr components, you can [Use Dapr to develop distributed applications](howto-develop-dapr-apps.md).
170+
Now that the Dapr components are deployed to the cluster, you can [Use Dapr to develop distributed applications](howto-develop-dapr-apps.md).

articles/iot-operations/create-edge-apps/howto-develop-dapr-apps.md

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ The first step is to write an application that uses a Dapr SDK to publish/subscr
3636

3737
After you finish writing the Dapr application, build the container:
3838

39-
1. To package the application into a container, run the following command:
39+
1. Package the application into a container with the following command:
4040

4141
```bash
4242
docker build . -t my-dapr-app
@@ -50,17 +50,20 @@ After you finish writing the Dapr application, build the container:
5050

5151
## Deploy a Dapr application
5252

53-
The following [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) definition contains the volumes required to deploy the application along with the required containers. This deployment utilizes the Dapr sidecar injector to automatically add the pluggable component pod.
53+
The following [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) definition contains volumes for SAT authentication and TLS certificate chain, and utilizes Dapr sidecar injection to automatically add the pluggable components to the Pod.
5454

55-
The yaml contains both a ServiceAccount, used to generate SATs for authentication with MQTT broker and the Dapr application Deployment.
56-
57-
To create the yaml file, use the following definitions:
55+
The following definition components might require customization to your specific application:
5856

5957
> | Component | Description |
6058
> |-|-|
61-
> | `volumes.mqtt-client-token` | The System Authentication Token used for authenticating the Dapr pluggable components with the MQTT broker |
62-
> | `volumes.aio-ca-trust-bundle` | The chain of trust to validate the MQTT broker TLS cert. This defaults to the test certificate deployed with Azure IoT Operations |
63-
> | `containers.mq-dapr-app` | The Dapr application container you want to deploy |
59+
> | `template:metadata:annotations:dapr.io/inject-pluggable-components` | Allows the IoT Operations pluggable components to be [automatically injected](https://docs.dapr.io/operations/components/pluggable-components-registration/) into the pod |
60+
> | `template:metadata:annotations:dapr.io/app-port` | Tells Dapr which port your application is listening on. If your application us not using this feature (such as a pubsub subscription), then remove this line |
61+
> | `volumes:mqtt-client-token` | The System Authentication Token used for authenticating the Dapr pluggable components with the MQTT broker |
62+
> | `volumes:aio-ca-trust-bundle` | The chain of trust to validate the MQTT broker TLS cert. This defaults to the test certificate deployed with Azure IoT Operations |
63+
> | `containers:mq-dapr-app` | The Dapr application container you want to deploy |
64+
65+
> [!CAUTION]
66+
> If your Dapr application is not listening for traffic from the Dapr sidecar, then remove the `dapr.io/app-port` and `dapr.io/app-protocol` [annotations](https://docs.dapr.io/reference/arguments-annotations-overview/) otherwise the Dapr sidecar will fail to initialize.
6467

6568
1. Save the following yaml to a file named `dapr-app.yaml`:
6669

@@ -76,21 +79,20 @@ To create the yaml file, use the following definitions:
7679
apiVersion: apps/v1
7780
kind: Deployment
7881
metadata:
79-
name: mq-dapr-app
82+
name: my-dapr-app
8083
namespace: azure-iot-operations
8184
spec:
82-
replicas: 1
8385
selector:
8486
matchLabels:
85-
app: mq-dapr-app
87+
app: my-dapr-app
8688
template:
8789
metadata:
8890
labels:
89-
app: mq-dapr-app
91+
app: my-dapr-app
9092
annotations:
9193
dapr.io/enabled: "true"
9294
dapr.io/inject-pluggable-components: "true"
93-
dapr.io/app-id: "mq-dapr-app"
95+
dapr.io/app-id: "my-dapr-app"
9496
dapr.io/app-port: "6001"
9597
dapr.io/app-protocol: "grpc"
9698
spec:
@@ -124,23 +126,22 @@ To create the yaml file, use the following definitions:
124126
kubectl get pods -w
125127
```
126128

127-
The workload pod should report all pods running after a short interval, as shown in the following example output:
129+
The pod should report three containers running after a short interval, as shown in the following example output:
128130

129131
```output
130-
pod/dapr-workload created
131132
NAME READY STATUS RESTARTS AGE
132133
...
133-
dapr-workload 3/3 Running 0 30s
134+
my-dapr-app 3/3 Running 0 30s
134135
```
135136

136137
## Troubleshooting
137138

138-
If the application doesn't start or you see the pods in `CrashLoopBackoff`, the logs for `daprd` are most helpful. The `daprd` is a container that automatically deploys with your Dapr application.
139+
If the application doesn't start or you see the containers in `CrashLoopBackoff` state, the log for the `daprd` container often contains useful information.
139140
140-
Run the following command to view the logs:
141+
Run the following command to view the logs for the daprd component:
141142
142143
```bash
143-
kubectl logs dapr-workload daprd
144+
kubectl logs -l app=my-dapr-app -c daprd
144145
```
145146
146147
## Next steps

articles/iot-operations/create-edge-apps/howto-develop-mqttnet-apps.md

Lines changed: 57 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -16,52 +16,45 @@ ms.date: 07/02/2024
1616

1717
[!INCLUDE [public-preview-note](../includes/public-preview-note.md)]
1818

19-
[MQTTnet](https://dotnet.github.io/MQTTnet/) is an open-source, high performance .NET library for MQTT based communication. This article uses a Kubernetes service account token and MQTTnet to connect to MQTT broker. You should use service account tokens to connect to in-cluster clients.
19+
[MQTTnet](https://dotnet.github.io/MQTTnet/) is an open-source, high performance .NET library for MQTT based communication. This article uses a Kubernetes service account token and MQTTnet to connect to MQTT broker. You should use service account tokens to connect in-cluster applications.
2020

2121
## Sample code
2222

2323
The [sample code](https://github.com/Azure-Samples/explore-iot-operations/tree/main/samples/mqtt-client-dotnet/Program.cs) performs the following steps:
2424

25-
1. Creates an MQTT client using the `MQTTFactory` class:
25+
1. Creates an MQTT client using the `MqttFactory` class:
2626

2727
```csharp
2828
var mqttFactory = new MqttFactory();
2929
var mqttClient = mqttFactory.CreateMqttClient();
3030
```
3131

32-
1. The following Kubernetes pod specification mounts the service account token to the specified path on the container file system. The mounted token is used as the password with well-known username `K8S-SAT`:
32+
1. The [Kubernetes pod specification](#pod-specification) mounts the service account on the container file system. The contents of the file are read:
33+
##3. The mounted token is used as the password with well-known username `K8S-SAT`:
3334

3435
```csharp
35-
string token_path = "/var/run/secrets/tokens/mqtt-client-token";
36+
static string sat_auth_file = "/var/run/secrets/tokens/mqtt-client-token";
3637
...
37-
38-
static async Task<int> MainAsync()
39-
{
40-
...
41-
42-
// Read SAT Token
43-
var satToken = File.ReadAllText(token_path);
38+
var satToken = File.ReadAllBytes(sat_auth_file);
4439
```
4540

46-
1. All options for the MQTT client are bundled in the class named `MqttClientOptions`. It's possible to fill options manually in code via the properties but you should use the `MqttClientOptionsBuilder` as advised in the [client](https://github.com/dotnet/MQTTnet/wiki/Client) documentation. The following code shows how to use the builder with the following options:
41+
1. The MQTT client options are configured using the `MqttClientOptions` class. Using the `MqttClientOptionsBuilder` as advised in the [client](https://github.com/dotnet/MQTTnet/wiki/Client) documentation is the advised way of setting the options:
4742
4843
```csharp
49-
# Create TCP based options using the builder amd connect to broker
5044
var mqttClientOptions = new MqttClientOptionsBuilder()
51-
.WithTcpServer(broker, 1883)
45+
.WithTcpServer(hostname, tcp_port)
5246
.WithProtocolVersion(MqttProtocolVersion.V500)
53-
.WithClientId("sampleid")
54-
.WithCredentials("K8S-SAT", satToken)
55-
.Build();
47+
.WithClientId("mqtt-client-dotnet")
48+
.WithAuthentication("K8S-SAT", satToken);
5649
```
5750

58-
1. After setting up the MQTT client options, a connection can be established. The following code shows how to connect with a server. You can replace the *CancellationToken.None* with a valid *CancellationToken*, if needed.
51+
5. After setting up the MQTT client options, a connection can be established. The following code shows how to connect with a server. You can replace the `CancellationToken.None` with a valid CancellationToken if needed.
5952

6053
```csharp
61-
var response = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
54+
var response = await mqttClient.ConnectAsync(mqttClientOptions.Build(), CancellationToken.None);
6255
```
6356

64-
1. MQTT messages can be created using the properties directly or via using `MqttApplicationMessageBuilder`. This class has some useful overloads that allow dealing with different payload formats. The API of the builder is a fluent API. The following code shows how to compose an application message and publish them to a topic called *sampletopic*:
57+
6. MQTT messages can be created using the properties directly or using `MqttApplicationMessageBuilder`. This class has overloads that allow dealing with different payload formats. The API of the builder is a fluent API. The following code shows how to compose an application message and publish them to an article called *sampletopic*:
6558

6659
```csharp
6760
var applicationMessage = new MqttApplicationMessageBuilder()
@@ -70,61 +63,68 @@ The [sample code](https://github.com/Azure-Samples/explore-iot-operations/tree/m
7063
.Build();
7164

7265
await mqttClient.PublishAsync(applicationMessage, CancellationToken.None);
73-
Console.WriteLine("The MQTT client published a message.");
7466
```
7567

7668
## Pod specification
7769

78-
The `serviceAccountName` field in the pod configuration must match the service account associated with the token being used. Also, note the `serviceAccountToken.expirationSeconds` is set to **86400 seconds**, and once it expires, you need to reload the token from disk. This logic isn't currently implemented in the sample.
70+
The `serviceAccountName` field in the pod configuration must match the service account associated with the token being used. Also, note the `serviceAccountToken.expirationSeconds` is set to **86400 seconds**, and once it expires, you need to reload the token from disk. This logic isn't implemented in this sample.
7971

8072
```yaml
8173
apiVersion: v1
74+
kind: ServiceAccount
75+
metadata:
76+
name: mqtt-client
77+
namespace: azure-iot-operations
78+
79+
---
80+
apiVersion: v1
8281
kind: Pod
8382
metadata:
8483
name: mqtt-client-dotnet
85-
labels:
86-
app: publisher
84+
namespace: azure-iot-operations
8785
spec:
8886
serviceAccountName: mqtt-client
8987

90-
volumes:
91-
# SAT token used to authenticate between the application and the MQTT broker
92-
- name: mqtt-client-token
93-
projected:
94-
sources:
95-
- serviceAccountToken:
96-
path: mqtt-client-token
97-
audience: aio-mq-dmqtt
98-
expirationSeconds: 86400
99-
100-
# Certificate chain for the application to validate the MQTT broker
101-
- name: aio-mq-ca-cert-chain
102-
configMap:
103-
name: aio-mq-ca-cert-chain
88+
volumes:
89+
90+
# SAT token used to authenticate between the application and the MQTT broker
91+
- name: mqtt-client-token
92+
projected:
93+
sources:
94+
- serviceAccountToken:
95+
path: mqtt-client-token
96+
audience: aio-mq
97+
expirationSeconds: 86400
98+
99+
# Certificate chain for the application to validate the MQTT broker
100+
- name: aio-ca-trust-bundle
101+
configMap:
102+
name: aio-ca-trust-bundle-test-only
104103

105104
containers:
106-
- name: mqtt-client-dotnet
107-
image: ghcr.io/azure-samples/explore-iot-operations/mqtt-client-dotnet:latest
108-
imagePullPolicy: IfNotPresent
109-
volumeMounts:
110-
- name: mqtt-client-token
111-
mountPath: /var/run/secrets/tokens
112-
- name: aio-mq-ca-cert-chain
113-
mountPath: /certs/aio-mq-ca-cert/
114-
env:
115-
- name: IOT_MQ_HOST_NAME
116-
value: "aio-mq-dmqtt-frontend"
117-
- name: IOT_MQ_PORT
118-
value: "8883"
119-
- name: IOT_MQ_TLS_ENABLED
120-
value: "true"
105+
- name: mqtt-client-dotnet
106+
image: ghcr.io/azure-samples/explore-iot-operations/mqtt-client-dotnet:latest
107+
volumeMounts:
108+
- name: mqtt-client-token
109+
mountPath: /var/run/secrets/tokens/
110+
- name: aio-ca-trust-bundle
111+
mountPath: /var/run/certs/aio-mq-ca-cert/
112+
env:
113+
- name: hostname
114+
value: "aio-mq-dmqtt-frontend"
115+
- name: tcpPort
116+
value: "8883"
117+
- name: useTls
118+
value: "true"
119+
- name: caFile
120+
value: "/var/run/certs/aio-mq-ca-cert/ca.crt"
121+
- name: satAuthFile
122+
value: "/var/run/secrets/tokens/mqtt-client-token"
121123
```
122124

123-
The token is mounted into the container at the path specified in `containers[].volumeMount.mountPath`
124-
125125
To run the sample, follow the instructions in its [README](https://github.com/Azure-Samples/explore-iot-operations/tree/main/samples/mqtt-client-dotnet).
126126

127127
## Related content
128128

129-
- [MQTT broker overview](../manage-mqtt-broker/overview-iot-mq.md)
130-
- [Develop with MQTT broker](edge-apps-overview.md)
129+
- [Publish and subscribe MQTT messages using MQTT broker](../manage-mqtt-broker/overview-iot-mq.md)
130+
- [Develop highly available distributed applications](edge-apps-overview.md)

0 commit comments

Comments
 (0)