TemPy: IoT com Raspberry Pi, Skupper e Grafana
Tabela de conteúdos
Descrição
Este projeto é uma prova de conceito de uma arquitetura IoT com Raspberry Pi e um sensor de temperatura que expõe os dados por uma API REST. Junto com a API, há integração com qualquer provedor de nuvem usando Skupper, para visualizar os dados em um dashboard Grafana.
Clone o repositório e siga as instruções para rodar o projeto. https://github.com/rafaelvzago/skupper-tempy
git clone https://github.com/rafaelvzago/skupper-tempy.git
Sumário
- Hardware
- Configuração do Raspberry
- Captura de temperatura
- Papel do Skupper
- Conexão com o cluster via Skupper e armazenamento no Prometheus
- Prometheus
- Grafana
- Repositório
Arquitetura
A arquitetura do projeto se divide nestas partes:
Hardware
Componentes físicos usados no projeto: Raspberry Pi e sensor de temperatura.
- Raspberry Pi 3 Model B+ Raspberry Pi 3 Model B+
- DS18B20 Temperature Sensor DS18B20 Temperature Sensor
- 4.7kΩ Resistor 4.7kΩ Resistor
- Breadboard Breadboard
- Jumper Wires Jumper Wires
Configuração do Raspberry
Setup e configuração do Raspberry Pi, incluindo software e bibliotecas necessárias.
- Ubuntu 23.04 server for Raspberry Pi Ubuntu Installation
- GoLang 1.18+ GoLang Installation
- Skupper Main Skupper Installation
- Podman > 4.3 Podman Installation
Captura de temperatura
Aqui o sensor é ligado ao Raspberry Pi e o código de captura das leituras é implementado.
Configuração:
- Pinos GPIO do Raspberry Pi:
- Pin 1 (3.3V) conectado ao pino VDD do DS18B20.
- Pin 7 (GPIO 4) conectado ao pino DQ do DS18B20.
- Pin 9 (GND) conectado ao pino GND do DS18B20.
- DS18B20:
- O pino VDD é alimentado com 3.3V do Raspberry Pi.
- O pino DQ vai para o GPIO 4 com um resistor pull-up.
- O pino GND fica aterrado no Raspberry Pi.
Conexões:
- Um resistor pull-up de 4.7kΩ (R1) fica entre as linhas VDD e DQ.
- A linha VDD do DS18B20 usa um fio vermelho representando 3.3V do Raspberry Pi.
- A linha DQ usa um fio branco (dados) ligado ao GPIO 4 do Raspberry Pi.
- A linha GND usa um fio preto (terra) do Raspberry Pi.
Funcionamento:
- O sensor DS18B20 reporta temperatura pela interface 1-Wire, que precisa de apenas uma linha de dados (e terra) para falar com o Raspberry Pi.
- O resistor pull-up é necessário para o protocolo 1-Wire do DS18B20 funcionar corretamente.
API REST:
- Para expor a temperatura, a API REST é implementada em GoLang. Ela captura os dados e os disponibiliza para o provedor de nuvem.
go build tempy/tempy.go
- Encontre um jeito de rodar o binário tempy no Raspberry Pi; neste exemplo uso um
nohupsimples para deixar o processo em background.
nohup ./tempy &
- A API REST fica na porta 5000/temperature. Dá para acessar assim:
curl localhost:5000/temperature
Papel do Skupper
Usamos Skupper para estabelecer a comunicação entre o Raspberry Pi e o provedor de nuvem, e para expor a temperatura na nuvem. Esta parte cobre o setup e a configuração do Skupper.
Skupper é um service interconnect de camada 7 que permite comunicação segura entre clusters Kubernetes, cobrindo protocolos de rede e de aplicação. Foi pensado para conectar serviços em infraestruturas diferentes e se baseia na ideia de um service bus. Skupper
Neste exemplo usamos skupper gateway para expor a temperatura na nuvem. É preciso ter um site Skupper rodando na nuvem e um skupper gateway no Raspberry Pi. O skupper gateway permite expor serviços que não estão em Kubernetes na rede Skupper; aqui ele expõe a temperatura para a nuvem.
Site Skupper:
- Um namespace rodando Skupper. Neste exemplo aproveitamos o serviço Prometheus para guardar a temperatura, então inicializamos o Skupper no cluster com:
skupper init --site-name site1 --enable-console --enable-flow-collector
Gateway Skupper no Raspberry Pi:
- Para expor a temperatura na nuvem, usamos um skupper gateway com o comando:
skupper gateway expose tempy localhost 5000 --type podman
Conexão com o cluster via Skupper e armazenamento no Prometheus
Os dados capturados pelo Raspberry Pi são armazenados na nuvem com o provedor escolhido. Esta parte explica como os dados são guardados e gerenciados.
Neste exemplo fazemos o deploy de um Prometheus para armazenar a temperatura e de um prometheus-adapter para fazer scrape da API REST e gravar no Prometheus. Para facilitar, configuramos o service discovery do Prometheus para coletar de qualquer serviço rotulado como app=metric. Assim dá para acrescentar mais sensores e o Prometheus passa a coletar sozinho.
O serviço fica com o label app=metric, e o prometheus-adapter adiciona a temperatura ao serviço para o Prometheus fazer o scrape.
apiVersion: v1
kind: Service
metadata:
name: tempy-prometheus-adapter-service
spec:
type: ClusterIP
selector:
app: metrics
Prometheus Adapter:
- Build da imagem TemPy prometheus-adapter:
podman build -t quay.io/YOUR-USER/tempy-prometheus-adapter:0.1 -f prometheus-adapter/Dockerfile-TempyPrometheusAdapter .
- Push da imagem para o registry quay.io:
podman push quay.io/YOUR-USER/tempy-prometheus-adapter:0.1
- Deploy do prometheus-adapter:
kubectl apply -f prometheus-adapter/TempyPrometheusAdapter-deployment.yaml
- Expor o prometheus-adapter:
kubectl apply -f prometheus-adapter/TempyPrometheusAdapter-service.yaml
- Verificar se o prometheus-adapter está rodando:
kubectl run -i --tty --rm curl-pod --image=curlimages/curl -- sh
curl tempy-prometheus-adapter:9090/metrics
...
# TYPE temperature_celsius gauge
temperature_celsius 19.81
# HELP temperature_fahrenheit Current temperature in Fahrenheit
# TYPE temperature_fahrenheit gauge
temperature_fahrenheit 67.66
- Conferir o service do prometheus-adapter e se os labels estão sendo aplicados:
kubectl get svc tempy-prometheus-adapter-service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
tempy-prometheus-adapter-service ClusterIP 10.43.154.250 <none> 9090/TCP 11h app=metrics
Prometheus
A temperatura fica armazenada em um serviço Prometheus. Esta parte cobre o setup e a configuração. Precisamos persistir os dados, então usamos um PVC; no meu caso uso a storage class longhorn, mas você pode usar qualquer uma disponível no cluster.
Este trecho da configuração do Prometheus faz scrape de qualquer serviço com label app=metrics, então o Prometheus coleta do prometheus-adapter. Note que a config só olha serviços no namespace skupper-pi; se usar outro namespace, ajuste o arquivo.
...
- job_name: 'metrics-targets'
scrape_interval: 5s
kubernetes_sd_configs:
- role: service
namespaces:
names: ['skupper-pi']
relabel_configs:
- source_labels: [__meta_kubernetes_service_label_app]
regex: metrics
action: keep
...
- Criar o PVC do Prometheus:
kubectl apply -f prometheus/prometheus-pvc.yaml
- Criar o deployment do Prometheus:
kubectl apply -f prometheus/prometheus-deployment.yaml
- Configurar o service discovery para scrape de serviços com
app=metrics:
kubectl apply -f prometheus/prometheus-cm.yaml
- Deploy do Prometheus:
kubectl apply -f prometheus/prometheus-deployment.yaml
- Criar o service do Prometheus:
kubectl apply -f prometheus/prometheus-service.yaml
- Verificar se o Prometheus está rodando. A partir daqui ele deve estar coletando do prometheus-adapter ou de qualquer serviço com
app=metrics. Vamos consultar os serviços descobertos:
kubectl run -i --tty --rm curl-pod --image=curlimages/curl -- sh -c 'curl -G --data-urlencode "query=up" http://prometheus:9090/api/v1/query' | jq .
If you don't see a command prompt, try pressing enter.
warning: couldn't attach to pod/curl-pod, falling back to streaming logs: Internal error occurred: error attaching to container: container is in CONTAINER_EXITED state
{
"status": "success",
"data": {
"resultType": "vector",
"result": [
{
"metric": {
"__name__": "up",
"instance": "localhost:9090",
"job": "prometheus"
},
"value": [
1708523706.121,
"1"
]
},
{
"metric": {
"__name__": "up",
"instance": "promock.skupper-pi.svc:80",
"job": "metrics-targets"
},
"value": [
1708523706.121,
"1"
]
},
{
"metric": {
"__name__": "up",
"instance": "tempy-prometheus-adapter-service.skupper-pi.svc:9090",
"job": "metrics-targets"
},
"value": [
1708523706.121,
"1"
]
}
]
}
}
...
Grafana
Os dados de temperatura são visualizados em um dashboard Grafana. Esta parte cobre o setup e a configuração do dashboard.
Para visualizar a temperatura, usamos um dashboard Grafana configurado para puxar dados do Prometheus e mostrar em gráfico. O deploy do Grafana é feito com os comandos abaixo.
Para persistência, usamos um PVC. No meu cluster tenho longhorn instalado e uso ele; você pode usar qualquer outra storage class disponível.
- Criar o PVC do Grafana:
kubectl apply -f grafana/grafana-pvc.yaml
- Criar o deployment do Grafana:
kubectl apply -f grafana/grafana-deployment.yaml
- Criar o service do Grafana:
kubectl apply -f grafana/grafana-service.yaml
Importante: meu cluster usa ingress controller, então preciso criar um ingress para expor o Grafana. Se o seu não tiver ingress, exponha com nodeport ou loadbalancer.
- Criar uma conexão de data source no Grafana apontando para o Prometheus:
http://skupper-prometheus:9090
- Importar o dashboard:
grafana/dashboard.json
- Por fim, você deve conseguir visualizar a temperatura no dashboard Grafana.
Repositório
O código completo do projeto está neste repositório no GitHub: TemPy



