AKS Microservices Setup
This guide walks you through deploying ThingsBoard in microservices mode on Azure Kubernetes Service (AKS). We use Azure Database for PostgreSQL as the managed database.
Prerequisites
Section titled “Prerequisites”Install and Configure Tools
Section titled “Install and Configure Tools”Install kubectl and az CLI tools.
Log in to Azure:
az loginPull ThingsBoard Images
Section titled “Pull ThingsBoard Images”Verify that you can pull the images from Docker Hub:
docker pull thingsboard/tb-node:4.4.0docker pull thingsboard/tb-web-report:4.4.0docker pull thingsboard/tb-web-ui:4.4.0docker pull thingsboard/tb-js-executor:4.4.0docker pull thingsboard/tb-http-transport:4.4.0docker pull thingsboard/tb-mqtt-transport:4.4.0docker pull thingsboard/tb-coap-transport:4.4.0docker pull thingsboard/tb-lwm2m-transport:4.4.0docker pull thingsboard/tb-snmp-transport:4.4.0docker pull thingsboard/tb-integration-executor:4.4.0Step 1. Clone ThingsBoard K8S Scripts Repository
Section titled “Step 1. Clone ThingsBoard K8S Scripts Repository”Clone the repository containing the Kubernetes deployment scripts:
git clone -b release-4.4.0 https://github.com/thingsboard/thingsboard-pe-k8s.git --depth 1cd thingsboard-pe-k8s/azure/microservicesStep 2. Define Environment Variables
Section titled “Step 2. Define Environment Variables”export AKS_RESOURCE_GROUP=ThingsBoardResourcesexport AKS_LOCATION=eastusexport AKS_GATEWAY=tb-gatewayexport TB_CLUSTER_NAME=tb-clusterexport TB_DATABASE_NAME=tb-dbexport TB_REDIS_NAME=tb-redisecho "Resource group: $AKS_RESOURCE_GROUP, location: $AKS_LOCATION, cluster: $TB_CLUSTER_NAME, database: $TB_DATABASE_NAME"| Variable | Default | Description |
|---|---|---|
AKS_RESOURCE_GROUP |
ThingsBoardResources |
Azure Resource Group name |
AKS_LOCATION |
eastus |
Azure region. Run az account list-locations for options |
AKS_GATEWAY |
tb-gateway |
Azure Application Gateway name |
TB_CLUSTER_NAME |
tb-cluster |
AKS cluster name |
TB_DATABASE_NAME |
tb-db |
PostgreSQL server name |
TB_REDIS_NAME |
tb-redis |
Valkey/Redis cache name |
Step 3. Configure and Create AKS Cluster
Section titled “Step 3. Configure and Create AKS Cluster”Create the Azure Resource Group:
az group create --name $AKS_RESOURCE_GROUP --location $AKS_LOCATIONSee az group for more info.
Create the AKS cluster with 3 nodes:
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 3Key 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.
Step 4. Update the Context of kubectl
Section titled “Step 4. Update the Context of kubectl”az aks get-credentials --resource-group $AKS_RESOURCE_GROUP --name $TB_CLUSTER_NAMEVerify the connection:
kubectl get nodesStep 5. Provision Databases
Section titled “Step 5. Provision Databases”5.1 Azure Database for PostgreSQL
Section titled “5.1 Azure Database for PostgreSQL”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
thingsboardas 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):
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 thingsboardNote 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:
nano tb-node-db-configmap.yml5.2 Cassandra (Optional)
Section titled “5.2 Cassandra (Optional)”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.
Provision Additional Node Pools
Section titled “Provision Additional Node Pools”Create 3 separate node pools with 1 node per zone. At least 4 vCPUs and 16 GB of RAM is recommended.
az aks nodepool add --resource-group $AKS_RESOURCE_GROUP --cluster-name $TB_CLUSTER_NAME --name tbcassandra1 --node-count 1 --zones 1 --labels role=cassandraaz aks nodepool add --resource-group $AKS_RESOURCE_GROUP --cluster-name $TB_CLUSTER_NAME --name tbcassandra2 --node-count 1 --zones 2 --labels role=cassandraaz aks nodepool add --resource-group $AKS_RESOURCE_GROUP --cluster-name $TB_CLUSTER_NAME --name tbcassandra3 --node-count 1 --zones 3 --labels role=cassandraDeploy Cassandra Stateful Set
Section titled “Deploy Cassandra Stateful Set”Create the namespace, then deploy Cassandra:
kubectl apply -f tb-namespace.ymlkubectl config set-context $(kubectl config current-context) --namespace=thingsboardkubectl apply -f receipts/cassandra.ymlUpdate DB Settings
Section titled “Update DB Settings”echo " DATABASE_TS_TYPE: cassandra" >> tb-node-db-configmap.ymlecho " CASSANDRA_URL: cassandra:9042" >> tb-node-db-configmap.ymlecho " CASSANDRA_LOCAL_DATACENTER: dc1" >> tb-node-db-configmap.ymlCreate Keyspace
Section titled “Create Keyspace”Create the ThingsBoard keyspace inside Cassandra:
kubectl exec -it cassandra-0 -- bash -c "cqlsh -e \ \"CREATE KEYSPACE IF NOT EXISTS thingsboard \ WITH replication = { \ 'class' : 'NetworkTopologyStrategy', \ 'dc1' : '3' \ };\""Step 6. Azure Cache for Valkey (Optional)
Section titled “Step 6. Azure Cache for Valkey (Optional)”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: clusterREDIS_NODES: (Comma-separated list of "host:port" pairs)Step 7. Obtain and Configure License Key
Section titled “Step 7. Obtain and Configure License Key”We assume you have already chosen your subscription plan or decided to purchase a perpetual license. If not, navigate to the pricing page.
Create a docker secret with your license key:
export TB_LICENSE_KEY=PUT_YOUR_LICENSE_KEY_HEREkubectl create -n thingsboard secret generic tb-license --from-literal=license-key=$TB_LICENSE_KEYStep 8. Installation
Section titled “Step 8. Installation”Run the initial database setup:
./k8s-install-tb.shAfter this command finishes you should see:
Installation finished successfully!Step 9. Starting
Section titled “Step 9. Starting”Deploy thirdparty components and main ThingsBoard microservices:
./k8s-deploy-resources.shAfter a few minutes, call kubectl get pods. If everything went fine, you should see tb-node-0 pod in the READY state.
Deploy Transport Microservices
Section titled “Deploy Transport Microservices”Deploy the transport microservices you need. Omit protocols you don’t use to save resources:
# 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.ymlStep 10. Configure Load Balancers
Section titled “Step 10. Configure Load Balancers”10.1 Configure HTTP(S) Load Balancer
Section titled “10.1 Configure HTTP(S) Load Balancer”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.
kubectl apply -f receipts/http-load-balancer.ymlCheck the status:
kubectl get ingressOnce provisioned, you should see output similar to:
NAME CLASS HOSTS ADDRESS PORTS AGEtb-http-loadbalancer <none> * 34.111.24.134 80 7m25sUse the address to access the web UI and connect devices via HTTP API.
Administrator account creation on first access is covered next, in Step 11. Create Your Administrator Account.
Upload your SSL certificate to Application Gateway:
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_PASSDeploy the HTTPS load balancer:
kubectl apply -f receipts/https-load-balancer.ymlCheck the status:
kubectl get ingress10.2 Configure MQTT Load Balancer (Optional)
Section titled “10.2 Configure MQTT Load Balancer (Optional)”kubectl apply -f receipts/mqtt-load-balancer.ymlThe 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)”kubectl apply -f receipts/coap-load-balancer.ymlThe 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)”kubectl apply -f receipts/lwm2m-load-balancer.ymlThe 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)”kubectl apply -f receipts/edge-load-balancer.ymlThe load balancer forwards all TCP traffic on port 7070.
Step 11. Create Your Administrator Account
Section titled “Step 11. Create Your Administrator Account”After launching ThingsBoard, open the web UI at the load balancer address. ThingsBoard prompts you to create your System Administrator account — the account that manages the platform itself (tenants, system settings, platform-wide resources).
- Enter Email, Password, and Confirm password.
- The Set up a demo tenant option is selected by default: it creates a ready-made tenant with dashboards, devices, and rule chains for exploring the platform before building your own solution. Clear it if you want to start with an empty platform.
- Click Create account. You are signed in as the system administrator.
Your ThingsBoard instance is now installed and running.
Validate the Setup
Section titled “Validate the Setup”Confirm that the load balancers created in Step 10 are provisioned and reachable, and note their addresses — you need them to open the web UI and to connect devices.
Validate Web UI Access
Section titled “Validate Web UI Access”Check the status of the ingress you created for the HTTP(S) load balancer:
kubectl get ingressOnce an external IP address is assigned, use it to open the ThingsBoard web interface in your browser.
Validate MQTT/CoAP Access
Section titled “Validate MQTT/CoAP Access”List the cluster services to find the external IP addresses assigned to the load balancers you configured:
kubectl get serviceTwo load balancers are available:
tb-mqtt-loadbalancer— for TCP (MQTT) protocoltb-udp-loadbalancer— for UDP (CoAP/LwM2M) protocol
Use the EXTERNAL-IP field of each load balancer to connect devices.
[Optional] Configure Trendz Analytics
Section titled “[Optional] Configure Trendz Analytics”Pull Trendz Images
Section titled “Pull Trendz Images”Pull the Trendz images from Docker Hub:
docker pull thingsboard/trendz:1.16.0docker pull thingsboard/trendz-python-executor:1.16.0Create a Trendz Database in the Existing Azure Database
Section titled “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:
kubectl apply -f ./trendz/trendz-secret.ymlkubectl apply -f ./trendz/trendz-create-db.ymlCheck logs:
kubectl logs job/trendz-create-db -n thingsboardDeploy Trendz
Section titled “Deploy Trendz”./k8s-deploy-trendz.shAfter this command finishes you should see:
Trendz installed successfully!Troubleshooting
Section titled “Troubleshooting”Stream the logs of the ThingsBoard node pod to diagnose startup or runtime issues:
kubectl logs -f tb-node-0See the kubectl Cheat Sheet for more details.
Cluster Deletion
Section titled “Cluster Deletion”Delete ThingsBoard pods and load balancers:
./k8s-delete-resources.shDelete all data including database:
./k8s-delete-all.shDelete the AKS cluster:
az aks delete --resource-group $AKS_RESOURCE_GROUP --name $TB_CLUSTER_NAMENext Steps
Section titled “Next Steps”With ThingsBoard running, these concept guides help you build your first solution:
- Getting Started — a guided walkthrough of the platform after installation.
- Multi-Tenancy & Hierarchy — how tenants, customers, and users are organized.
- Digital Twin Model — how devices and assets are modeled in the platform.
- Data Processing — how the Rule Engine transforms and routes incoming data.
- Alarms & Notifications — how to detect conditions and notify users.
- Data Visualization — how to build dashboards and widgets.
Was this helpful?