Docker Deployment
Step 1: Create Docker Image
The Docker image for the Balena Prometheus Exporter is built from a Python base image. The Dockerfile is structured as follows:
FROM python:3.10-alpine
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY main.py .
USER nobody
CMD [ "python", "./main.py" ]
Step 2: Build the Docker Image
To build the Docker image, run the following command in the terminal:
$ docker build -t balena-exporter .
Step 3: Run the Docker Container
When running the container, you need to provide the BALENA_TOKEN
environment variable. This token is used to authenticate access to the Balena API.
$ docker run -d \
--name balena-exporter \
-p 8000:8000 \
-e BALENA_TOKEN=YOUR_BRELA_TOKEN_HERE \
balena-exporter
Step 4: Optional Configuration
You can also set the optional CRAWL_INTERVAL
environment variable to adjust how frequently the exporter pulls metrics. The default is set to 60 seconds:
$ docker run -d \
--name balena-exporter \
-p 8000:8000 \
-e BALENA_TOKEN=YOUR_BALENA_TOKEN_HERE \
-e CRAWL_INTERVAL=30 \
balena-exporter
Step 5: Verification
After the container is running, verify that the exporter is functioning correctly by sending a request to the exposed port:
$ curl http://localhost:8000
You should see the Prometheus formatted metrics.
Code Insights
Main Application Logic
The main logic of the exporter is encapsulated in main.py
. The functionality begins by checking for the BALENA_TOKEN
:
def main():
if not BALENA_TOKEN:
print("Please set the BALENA_TOKEN environment variable")
sys.exit(1)
start_http_server(8000)
REGISTRY.register(BalenaCollector())
while True:
time.sleep(int(CRAWL_INTERVAL))
main()
Collecting Metrics
The BalenaCollector
class handles the process of fetching metrics from the Balena API. For example, the method to fetch fleet metrics is implemented as:
def get_fleet_metrics(self, fleet_id):
headers = {
"Authorization": f"Bearer {BALENA_TOKEN}",
"Content-Type": "application/json",
}
response = requests.get(
f"https://api.balena-cloud.com/v6/application({fleet_id})?$expand=owns__device/$count($filter=is_online eq true)",
headers=headers,
)
if not response.ok:
print("Error: {}".format(response.text))
sys.exit(1)
device_online_count = response.json()["d"][0]["owns__device"]
fleet_name = response.json()["d"][0]["app_name"]
return fleet_name, device_online_count
Testing the Exporter
Unit tests for the exporter can be structured using unittest
. Below is a simple test to check the fleet collection:
def test_get_balena_fleets(self):
with mock.patch("main.requests.get") as mock_get:
mock_get.return_value.ok = True
mock_get.return_value.json.return_value = {"d": [{"id": "fleet1"}, {"id": "fleet2"}]}
result = list(self.collector.get_balena_fleets())
expected = ["fleet1", "fleet2"]
self.assertEqual(result, expected)
Final Notes
Ensure to replace YOUR_BRELA_TOKEN_HERE
with the actual token for production deployment. It is crucial to monitor the deployed service to ensure reliability and performance. Consider using a dedicated monitoring stack for proactive alerting and insights.