Skip to content
Stand with Ukraine flag

AWS EKS Monolith Setup

This guide walks you through deploying ThingsBoard PE in monolith mode on AWS EKS. We use Amazon RDS for managed PostgreSQL.

Install kubectl, eksctl, and AWS CLI.

Configure your AWS credentials. To get Access and Secret keys, follow this guide. The default region should be the ID of the region where you want to deploy the cluster.

Terminal window
aws configure

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

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/aws/monolith

In the cluster.yml file you can find the suggested cluster configuration. Key fields you can change:

FieldDefaultDescription
regionus-east-1AWS region for the cluster
availabilityZones[us-east-1a, us-east-1b, us-east-1c]Region availability zones
instanceTypem5.xlargeEC2 instance type for nodes

Create the cluster:

Terminal window
eksctl create cluster -f cluster.yml

Step 3. Create AWS load-balancer controller

Section titled “Step 3. Create AWS load-balancer controller”

Once the cluster is ready, create the AWS load-balancer controller by following this guide.

The cluster provisioning scripts create several load balancers:

Load BalancerTypePurpose
tb-http-loadbalancerALBWeb UI, REST API, HTTP transport
tb-mqtt-loadbalancerNLBMQTT transport
tb-coap-loadbalancerNLBCoAP transport
tb-edge-loadbalancerNLBEdge instances connectivity

Set up PostgreSQL on Amazon RDS. ThingsBoard uses it as the main database for devices, dashboards, rule chains, and device telemetry. Follow this guide, but take into account the following requirements:

  • Keep your PostgreSQL password in a safe place. We will refer to it later as YOUR_RDS_PASSWORD.
  • Make sure your PostgreSQL version is latest 16.x.
  • Make sure your PostgreSQL RDS instance is accessible from the ThingsBoard cluster. The easiest way is to deploy the RDS instance in the same VPC and use the eksctl-thingsboard-cluster-ClusterSharedNodeSecurityGroup-* security group.
  • Make sure you use “thingsboard” as the initial database name. If you do not specify a database name, Amazon RDS does not create one.

Recommendations:

  • Use Production template for high availability.
  • Use Provisioned IOPS for better performance.
  • Consider creating a custom parameters group for your RDS instance.
  • Consider deploying the RDS instance into private subnets.

Once the database switches to the Available state, navigate to Connectivity and Security and copy the endpoint value. We will refer to it as YOUR_RDS_ENDPOINT_URL.

Edit tb-node-db-configmap.yml and replace YOUR_RDS_ENDPOINT_URL and YOUR_RDS_PASSWORD.

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 groups to host Cassandra instances. At least 4 vCPUs and 16 GB of RAM is recommended.

Create 3 separate node pools with 1 node per zone. Since we use EBS disks, we don’t want K8S to launch a pod in a zone where the corresponding disk is unavailable.

Terminal window
eksctl create nodegroup --config-file=<path> --include='cassandra-*'
Terminal window
kubectl apply -f tb-namespace.yml
kubectl config set-context $(kubectl config current-context) --namespace=thingsboard

Deploy Cassandra:

Terminal window
kubectl apply -f receipts/cassandra.yml

The startup may take a few minutes. Monitor the process:

Terminal window
kubectl get pods

Edit the ThingsBoard DB settings file and add Cassandra settings. Don’t forget to replace YOUR_AWS_REGION with the name of your AWS region.

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: YOUR_AWS_REGION" >> tb-node-db-configmap.yml

Verify:

Terminal window
cat tb-node-db-configmap.yml | grep DATABASE_TS_TYPE

Expected output: DATABASE_TS_TYPE: cassandra

Terminal window
kubectl exec -it cassandra-0 -- bash -c "cqlsh -e \
\"CREATE KEYSPACE IF NOT EXISTS thingsboard \
WITH replication = { \
'class' : 'NetworkTopologyStrategy', \
'us-east' : '3' \
};\""

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

Execute the following command to run the initial setup of the database. This command launches a short-living ThingsBoard pod to provision necessary DB tables, indexes, etc:

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!

Execute the following command to deploy resources:

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.

You have 2 options:

  • HTTP — recommended for development. Simple configuration and minimum costs.
  • HTTPS — recommended for production. Acts as an SSL termination point with automatic redirect from HTTP to HTTPS.
Terminal window
kubectl apply -f receipts/http-load-balancer.yml

Check the status:

Terminal window
kubectl get ingress

Once provisioned, you should see:

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

Use the address to access the HTTP web UI (port 80) and connect devices via HTTP API.

Default credentials:

Use AWS Certificate Manager to create or import an SSL certificate. Note your certificate ARN.

Edit the load balancer configuration and replace YOUR_HTTPS_CERTIFICATE_ARN with your certificate ARN:

Terminal window
nano receipts/https-load-balancer.yml

Deploy the HTTPS load balancer:

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

8.2 Configure MQTT load balancer (optional)

Section titled “8.2 Configure MQTT load balancer (optional)”

Configure MQTT load balancer if you plan to use MQTT protocol to connect devices.

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

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

The simplest way to configure MQTTS is to make the AWS NLB act as a TLS termination point. Traffic between devices and the load balancer is encrypted, while traffic between the load balancer and MQTT Transport is not encrypted. There should be no security issues since the NLB runs in your VPC.

Use AWS Certificate Manager to create or import an SSL certificate. Edit the load balancer configuration:

Terminal window
nano receipts/mqtts-load-balancer.yml

Replace YOUR_MQTTS_CERTIFICATE_ARN with your certificate ARN, then deploy:

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

Follow the MQTT over SSL guide to create a .pem file. Store it as server.pem in the working directory.

Create a config-map with your PEM file:

Terminal window
kubectl create configmap tb-mqtts-config \
--from-file=server.pem=YOUR_PEM_FILENAME \
--from-file=mqttserver_key.pem=YOUR_PEM_KEY_FILENAME \
-o yaml --dry-run=client | kubectl apply -f -

Uncomment all sections in the tb-node.yml file marked with “Uncomment the following lines to enable two-way MQTTS”, then apply:

Terminal window
kubectl apply -f tb-node.yml

Deploy the “transparent” load balancer:

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

8.3 Configure UDP load balancer (optional)

Section titled “8.3 Configure UDP load balancer (optional)”

Configure UDP load balancer if you plan to use CoAP or LwM2M protocol.

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

The load balancer forwards all UDP traffic for ports:

PortProtocol
5683CoAP non-secure
5684CoAP secure DTLS
5685LwM2M non-secure
5686LwM2M secure DTLS
5687LwM2M bootstrap DTLS
5688LwM2M bootstrap secure DTLS

For CoAP over DTLS, follow the CoAP over DTLS guide. For LwM2M over DTLS, follow the LwM2M over DTLS guide.

8.4 Configure Edge load balancer (optional)

Section titled “8.4 Configure Edge load balancer (optional)”

Configure the Edge load balancer if you plan to connect Edge instances to your ThingsBoard server.

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

The load balancer forwards all TCP traffic on port 7070.

To get the external IP address:

Terminal window
kubectl get services | grep "EXTERNAL-IP\|tb-edge-loadbalancer"

Use the external IP address as CLOUD_RPC_HOST in Edge connection parameters.

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

9.2 Create a Trendz database in the existing RDS instance

Section titled “9.2 Create a Trendz database in the existing RDS instance”

Edit trendz/trendz-secret.yml and replace YOUR_RDS_ENDPOINT_URL and YOUR_RDS_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!

Get the DNS name of the HTTP load balancer:

Terminal window
kubectl get ingress

Use the address to open the ThingsBoard web interface in your browser.

Default credentials:

Get the load balancer services:

Terminal window
kubectl get service

Two load balancers are available:

  • tb-mqtt-loadbalancer-external — for MQTT protocol
  • tb-coap-loadbalancer-external — for CoAP protocol

Use the EXTERNAL-IP field of the load balancers to connect to the cluster.

To examine ThingsBoard node logs:

Terminal window
kubectl logs -f tb-node-0

Other useful commands:

  • kubectl get pods — see the state of all pods
  • kubectl get services — see the state of all services
  • kubectl get deployments — see the state of all deployments

See the kubectl Cheat Sheet for more details.

Merge your local changes with the latest release branch from the repo you cloned in Step 1.

If a database upgrade is needed:

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

Where FROM_VERSION is the starting version. See Upgrade Instructions for valid fromVersion values. You must upgrade versions one by one (e.g., 3.6.1 → 3.6.2 → 3.6.3).

Once completed, re-deploy resources:

Terminal window
./k8s-deploy-resources.sh

Upgrading to new Trendz version (optional)

Section titled “Upgrading to new Trendz version (optional)”

Pull the latest changes:

Terminal window
git pull origin master

Then execute:

Terminal window
./k8s-upgrade-trendz.sh

Delete all ThingsBoard pods:

Terminal window
./k8s-delete-resources.sh

Delete all ThingsBoard pods and configmaps:

Terminal window
./k8s-delete-all.sh

Delete the EKS cluster (change cluster name and region as needed):

Terminal window
eksctl delete cluster -r us-east-1 -n thingsboard -w