Skip to content
Stand with Ukraine flag

AKS Microservices Setup

This guide walks you through deploying ThingsBoard PE in microservices mode on Azure Kubernetes Service (AKS). We use Azure Database for PostgreSQL as the managed database.

Install kubectl and az CLI tools.

Log in to Azure:

Terminal window
az login

Verify that you can pull the images from Docker Hub:

Terminal window
docker pull thingsboard/tb-pe-node:4.3.1.1PE
docker pull thingsboard/tb-pe-web-report:4.3.1.1PE
docker pull thingsboard/tb-pe-web-ui:4.3.1.1PE
docker pull thingsboard/tb-pe-js-executor:4.3.1.1PE
docker pull thingsboard/tb-pe-http-transport:4.3.1.1PE
docker pull thingsboard/tb-pe-mqtt-transport:4.3.1.1PE
docker pull thingsboard/tb-pe-coap-transport:4.3.1.1PE
docker pull thingsboard/tb-pe-lwm2m-transport:4.3.1.1PE
docker pull thingsboard/tb-pe-snmp-transport:4.3.1.1PE

Step 1. Clone ThingsBoard PE K8S scripts repository

Section titled “Step 1. Clone ThingsBoard PE K8S scripts repository”
Terminal window
git clone -b release-4.3 https://github.com/thingsboard/thingsboard-pe-k8s.git --depth 1
cd thingsboard-pe-k8s/azure/microservices
Terminal window
export AKS_RESOURCE_GROUP=ThingsBoardResources
export AKS_LOCATION=eastus
export AKS_GATEWAY=tb-gateway
export TB_CLUSTER_NAME=tb-cluster
export TB_DATABASE_NAME=tb-db
export TB_REDIS_NAME=tb-redis
echo "Resource group: $AKS_RESOURCE_GROUP, location: $AKS_LOCATION, cluster: $TB_CLUSTER_NAME, database: $TB_DATABASE_NAME"
VariableDefaultDescription
AKS_RESOURCE_GROUPThingsBoardResourcesAzure Resource Group name
AKS_LOCATIONeastusAzure region. Run az account list-locations for options
AKS_GATEWAYtb-gatewayAzure Application Gateway name
TB_CLUSTER_NAMEtb-clusterAKS cluster name
TB_DATABASE_NAMEtb-dbPostgreSQL server name
TB_REDIS_NAMEtb-redisValkey/Redis cache name

Create the Azure Resource Group:

Terminal window
az group create --name $AKS_RESOURCE_GROUP --location $AKS_LOCATION

See az group for more info.

Create the AKS cluster with 3 nodes:

Terminal window
az aks create --resource-group $AKS_RESOURCE_GROUP \
--name $TB_CLUSTER_NAME \
--generate-ssh-keys \
--enable-addons ingress-appgw \
--appgw-name $AKS_GATEWAY \
--appgw-subnet-cidr "10.2.0.0/16" \
--node-vm-size Standard_DS3_v2 \
--node-count 3

Key parameters:

  • node-count — number of nodes per pool (default: 3)
  • node-vm-size — VM size (default: Standard_DS2_v2)
  • enable-addons — enables Application Gateway as a path-based load balancer
  • generate-ssh-keys — generates SSH keys if missing (stored in ~/.ssh)

See az aks create for the full parameter list. Alternatively, follow the portal-based cluster setup guide.

Terminal window
az aks get-credentials --resource-group $AKS_RESOURCE_GROUP --name $TB_CLUSTER_NAME

Verify the connection:

Terminal window
kubectl get nodes

You need to set up PostgreSQL on Azure. ThingsBoard uses it as the main database.

You may follow the Azure portal guide, keeping these requirements in mind:

  • PostgreSQL version 16.x
  • The instance must be accessible from the AKS cluster
  • Use thingsboard as the initial database name
  • High availability enabled is recommended for production

Alternatively, create using the CLI (replace POSTGRES_USER and POSTGRES_PASS with your credentials):

Terminal window
az postgres flexible-server create --location $AKS_LOCATION --resource-group $AKS_RESOURCE_GROUP \
--name $TB_DATABASE_NAME --admin-user POSTGRES_USER --admin-password POSTGRES_PASS \
--public-access 0.0.0.0 --storage-size 32 \
--version 16 -d thingsboard

Note the host value from the command output (e.g. tb-db.postgres.database.azure.com). Also note the username and password.

Edit tb-node-db-configmap.yml and replace YOUR_AZURE_POSTGRES_ENDPOINT_URL, YOUR_AZURE_POSTGRES_USER, and YOUR_AZURE_POSTGRES_PASSWORD with the correct values:

Terminal window
nano tb-node-db-configmap.yml

Using Cassandra is optional. We recommend it if you plan to insert more than 5K data points per second or want to optimize storage space.

Create 3 separate node pools with 1 node per zone. At least 4 vCPUs and 16 GB of RAM is recommended.

Terminal window
az aks nodepool add --resource-group $AKS_RESOURCE_GROUP --cluster-name $TB_CLUSTER_NAME --name tbcassandra1 --node-count 1 --zones 1 --labels role=cassandra
az aks nodepool add --resource-group $AKS_RESOURCE_GROUP --cluster-name $TB_CLUSTER_NAME --name tbcassandra2 --node-count 1 --zones 2 --labels role=cassandra
az aks nodepool add --resource-group $AKS_RESOURCE_GROUP --cluster-name $TB_CLUSTER_NAME --name tbcassandra3 --node-count 1 --zones 3 --labels role=cassandra
Terminal window
kubectl apply -f tb-namespace.yml
kubectl config set-context $(kubectl config current-context) --namespace=thingsboard
kubectl apply -f receipts/cassandra.yml
Terminal window
echo " DATABASE_TS_TYPE: cassandra" >> tb-node-db-configmap.yml
echo " CASSANDRA_URL: cassandra:9042" >> tb-node-db-configmap.yml
echo " CASSANDRA_LOCAL_DATACENTER: dc1" >> tb-node-db-configmap.yml
Terminal window
kubectl exec -it cassandra-0 -- bash -c "cqlsh -e \
\"CREATE KEYSPACE IF NOT EXISTS thingsboard \
WITH replication = { \
'class' : 'NetworkTopologyStrategy', \
'dc1' : '3' \
};\""

ThingsBoard uses cache to improve performance and avoid frequent DB reads. By default, the deployment already uses local Valkey cache. Azure does not provide a managed Valkey cluster. Instead of the default deployment, you can set up your own Valkey cluster according to the Azure documentation.

Edit the thirdparty.yml file, find the StatefulSet section named tb-valkey, and set the spec.replicas value to 0.

Once your Valkey cluster is ready, edit tb-cache-configmap.yml and replace REDIS_HOST with your Valkey endpoint. For cluster mode, use:

REDIS_CONNECTION_TYPE: cluster
REDIS_NODES: (Comma-separated list of "host:port" pairs)

We assume you have already chosen your subscription plan or decided to purchase a perpetual license. If not, navigate to the pricing page. See How to get pay-as-you-go subscription or How to get perpetual license for details.

Create a docker secret with your license key:

Terminal window
export TB_LICENSE_KEY=PUT_YOUR_LICENSE_KEY_HERE
kubectl create -n thingsboard secret generic tb-license --from-literal=license-key=$TB_LICENSE_KEY

Run the initial database setup:

Terminal window
./k8s-install-tb.sh --loadDemo

Where --loadDemo is an optional argument to load additional demo data.

After this command finishes you should see:

Installation finished successfully!

Deploy thirdparty components and main ThingsBoard microservices:

Terminal window
./k8s-deploy-resources.sh

After a few minutes, call kubectl get pods. If everything went fine, you should see tb-node-0 pod in the READY state.

Deploy the transport microservices you need. Omit protocols you don’t use to save resources:

Terminal window
# HTTP Transport (optional)
kubectl apply -f transports/tb-http-transport.yml
# MQTT Transport (optional)
kubectl apply -f transports/tb-mqtt-transport.yml
# CoAP Transport (optional)
kubectl apply -f transports/tb-coap-transport.yml
# LwM2M Transport (optional)
kubectl apply -f transports/tb-lwm2m-transport.yml
# SNMP Transport (optional)
kubectl apply -f transports/tb-snmp-transport.yml

You have 2 options:

  • HTTP — recommended for development. Simple configuration and minimum costs.
  • HTTPS — recommended for production. Requires an SSL certificate uploaded to Application Gateway.
Terminal window
kubectl apply -f receipts/http-load-balancer.yml

Check the status:

Terminal window
kubectl get ingress

Once provisioned, you should see output similar to:

NAME CLASS HOSTS ADDRESS PORTS AGE
tb-http-loadbalancer <none> * 34.111.24.134 80 7m25s

Use the address to access the web UI and connect devices via HTTP API.

Default credentials:

Upload your SSL certificate to Application Gateway:

Terminal window
az network application-gateway ssl-cert create \
--resource-group $(az aks show --name $TB_CLUSTER_NAME --resource-group $AKS_RESOURCE_GROUP --query nodeResourceGroup | tr -d '"') \
--gateway-name $AKS_GATEWAY \
--name ThingsBoardHTTPCert \
--cert-file YOUR_CERT \
--cert-password YOUR_CERT_PASS

Deploy the HTTPS load balancer:

Terminal window
kubectl apply -f receipts/https-load-balancer.yml

Check the status:

Terminal window
kubectl get ingress

10.2 Configure MQTT load balancer (optional)

Section titled “10.2 Configure MQTT load balancer (optional)”
Terminal window
kubectl apply -f receipts/mqtt-load-balancer.yml

The load balancer forwards all TCP traffic for ports 1883 and 8883.

For MQTT over SSL, follow the MQTT over SSL guide to configure transport/tb-mqtt-transport.yml.

10.3 Configure CoAP load balancer (optional)

Section titled “10.3 Configure CoAP load balancer (optional)”
Terminal window
kubectl apply -f receipts/coap-load-balancer.yml

The load balancer forwards UDP traffic for ports 5683 (CoAP non-secure) and 5684 (CoAP secure DTLS).

For CoAP over DTLS, follow the CoAP over DTLS guide to configure transport/tb-coap-transport.yml.

10.4 Configure LwM2M load balancer (optional)

Section titled “10.4 Configure LwM2M load balancer (optional)”
Terminal window
kubectl apply -f receipts/lwm2m-load-balancer.yml

The load balancer forwards UDP traffic for ports 5685–5688.

For LwM2M over DTLS, follow the LwM2M over DTLS guide to configure transport/tb-lwm2m-transport.yml.

10.5 Configure Edge load balancer (optional)

Section titled “10.5 Configure Edge load balancer (optional)”
Terminal window
kubectl apply -f receipts/edge-load-balancer.yml

The load balancer forwards all TCP traffic on port 7070.

Terminal window
docker pull thingsboard/trendz:1.15.1
docker pull thingsboard/trendz-python-executor:1.15.1

11.2 Create a Trendz database in the existing Azure Database

Section titled “11.2 Create a Trendz database in the existing Azure Database”

Edit trendz/trendz-secret.yml and replace YOUR_AZURE_POSTGRES_ENDPOINT_URL, YOUR_AZURE_POSTGRES_USER, and YOUR_AZURE_POSTGRES_PASSWORD, then apply:

Terminal window
kubectl apply -f ./trendz/trendz-secret.yml
kubectl apply -f ./trendz/trendz-create-db.yml

Check logs:

Terminal window
kubectl logs job/trendz-create-db -n thingsboard
Terminal window
./k8s-deploy-trendz.sh

After this command finishes you should see:

Trendz installed successfully!
Terminal window
kubectl get ingress
Terminal window
kubectl get service

Two load balancers are available:

  • tb-mqtt-loadbalancer — for TCP (MQTT) protocol
  • tb-udp-loadbalancer — for UDP (CoAP/LwM2M) protocol
Terminal window
kubectl logs -f tb-node-0

See the kubectl Cheat Sheet for more details.

Terminal window
./k8s-delete-resources.sh
./k8s-upgrade-tb.sh --fromVersion=[FROM_VERSION]
./k8s-deploy-resources.sh

Where FROM_VERSION is the starting version. See Upgrade Instructions for valid values. Upgrade versions one by one.

Upgrading to new Trendz version (optional)

Section titled “Upgrading to new Trendz version (optional)”
Terminal window
git pull origin master
./k8s-upgrade-trendz.sh

Delete ThingsBoard pods and load balancers:

Terminal window
./k8s-delete-resources.sh

Delete all data including database:

Terminal window
./k8s-delete-all.sh

Delete the AKS cluster:

Terminal window
az aks delete --resource-group $AKS_RESOURCE_GROUP --name $TB_CLUSTER_NAME