Konteyner Orkestrasyon
TEKNİK REHBER KONTEYNER & EDGE balenaOS 2026

balenaOS —
Fleet Yönetimi.

Immutable OS, Supervisor ve Docker Compose tabanlı edge fleet yönetimi. balenaCloud'da multi-container uygulama, delta OTA güncelleme ve cihaz sağlık izleme. MQTT + InfluxDB + Grafana stack'i 10 cihaza deploy.

00 balenaOS mimarisi — immutable OS, Supervisor, Docker Compose

balenaOS, edge cihazlar için özel olarak tasarlanmış, immutable (değişmez) bir Linux dağıtımıdır. Uygulama katmanı Docker container'larında çalışır; OS katmanı OTA ile atomik olarak güncellenir.

Katmanlı mimari

  ┌──────────────────────────────────────────────────────┐
  │  Kullanıcı Uygulamaları (Docker Compose servisleri)  │
  │  sensor-collector  mqtt-broker  influxdb  grafana    │
  ├──────────────────────────────────────────────────────┤
  │  balena Supervisor (Go daemon)                       │
  │  · OTA uygulama güncellemesi                         │
  │  · Device state raporlama                            │
  │  · Sağlık kontrolü ve otomatik restart               │
  ├──────────────────────────────────────────────────────┤
  │  balenaEngine (Docker API uyumlu container runtime)  │
  ├──────────────────────────────────────────────────────┤
  │  balenaOS (Yocto tabanlı, immutable rootfs)          │
  │  · Read-only root partition                          │
  │  · A/B partition tabanlı OS güncelleme               │
  │  · Minimal attack surface                            │
  └──────────────────────────────────────────────────────┘
    
Immutable rootfsRoot dosya sistemi sadece okunabilir. Donanım arızası veya güç kesilmesinde bozulma yaşanmaz. Disk tutarsızlığı riski ortadan kalkar.
A/B partitionOS güncellemesi boştaki partition'a yazılır. Reboot sonrası yeni partition aktive edilir. Başarısız güncelleme otomatik rollback yapar.
balena SupervisorCihaz üzerinde çalışan Go daemon'u. balenaCloud ile WebSocket bağlantısı kurar, uygulama güncellemelerini çeker, sağlık metriklerini gönderir.
balenaEngineDocker Engine fork'u. Docker Compose v3 tam uyumluluğu. Mevcut Compose dosyaları değişiklik gerektirmez.
Desteklenen donanımRPi 3/4/5, CM3/CM4, balenaFin, Jetson Nano/TX2, Intel NUC, BeagleBone, NVIDIA Orin ve 100'den fazla donanım.

balena ekosistemi bileşenleri

BileşenGörev
balenaCloudFleet yönetim platformu — web dashboard, API, OTA orchestration
balenaOSYocto tabanlı immutable Linux OS
balena SupervisorCihaz üstü daemon; OTA, sağlık, state sync
balenaEngineDocker uyumlu container runtime
balena CLIGeliştirici araç seti: push, logs, ssh, local dev
openbalenaSelf-hosted balenaCloud alternatifi

Bu bölümde

  • balenaOS = immutable Yocto OS + A/B partition + balena Supervisor
  • Uygulama Docker Compose ile tanımlanır; Supervisor OTA ile günceller
  • RPi4, CM4, balenaFin dahil 100+ donanım resmi destek alır

01 balenaCloud hesap ve fleet oluşturma

balenaCloud'da fleet (cihaz grubu) oluşturma, OS image indirme ve cihazı kaydetme adımları.

Fleet oluşturma adımları

1. Hesap oluşturdashboard.balena.io adresinde hesap aç. Ücretsiz plan: 10 cihaz, unlimited fleet.
2. Fleet oluştur"Create fleet" → Donanım tipini seç (Raspberry Pi 4) → Fleet adı gir → Production veya Development mod seç.
3. OS Image indirFleet sayfasından "Add device" → balenaOS image indir. Development modda SSH ve local mode açık gelir. Production modda kapalıdır.
4. SD karta yazbalenaEtcher ile image'ı SD karta yaz. Cihazı başlat — internet bağlantısıyla otomatik olarak fleet'e kayıt olur.
5. Cihaz görünürDashboard'da cihaz "Online" olarak görünür. UUID, IP adresi, OS versiyonu ve uygulama durumu görüntülenir.
bash — balena CLI ile fleet yönetimi
# balena CLI kurulumu (npm)
npm install -g balena-cli

# veya binary indirme
curl -fsSL https://github.com/balena-io/balena-cli/releases/latest/download/balena-cli-v18.0.0-linux-x64-standalone.zip \
  | unzip - -d ~/.local/bin/

# balenaCloud hesabına giriş
balena login
# ? How would you like to login?
# > Web authorization (recommended)

# Fleet listele
balena fleets

# Fleet oluştur
balena fleet create sensor-platform \
  --type raspberrypi4-64

# Cihazları listele
balena devices --fleet sensor-platform

# Cihaz detayları
balena device <device-uuid>

Bu bölümde

  • Fleet oluştur → OS indir → balenaEtcher ile yaz → cihaz otomatik kaydolur
  • Development mod: SSH açık; Production mod: SSH kapalı, güvenli
  • balena CLI ile fleet ve cihaz yönetimi terminal üzerinden yapılır

02 balena CLI — push, logs, ssh

balena CLI'nin en çok kullanılan üç komutu: balena push (uygulama deploy), balena logs (container log izleme) ve balena ssh (uzak terminal).

balena push — uygulama deploy

bash — balena push ile fleet'e deploy
# Proje dizinine git
cd ~/projects/sensor-platform

# Tüm fleet'e push et
balena push sensor-platform

# balena push adımları:
# 1. docker-compose.yml dosyasını okur
# 2. Her servis için Dockerfile build eder (balena builder buluta yükler)
# 3. Multi-arch imaj oluşturur (ARM64 için aarch64 native)
# 4. Release oluşturur → fleet'teki tüm cihazlara deploy başlar

# Push çıktısı:
# [Build]   [main] Step 1/8 : FROM python:3.11-slim
# [Build]   [main] Successfully built abc123
# [Info]    Release: 1234567 (commit: abc123def)
# [Success] Deploy successful

# Belirli cihaza push et
balena push <device-uuid> --source .

# Draft release oluştur (production'a gitmeden test)
balena push sensor-platform --draft

balena logs

bash — container log izleme
# Tüm servislerin logunu izle
balena logs <device-uuid>

# Belirli servis logu
balena logs <device-uuid> --service sensor-collector

# Son 100 satır
balena logs <device-uuid> --tail 100

# Sistem logları (Supervisor dahil)
balena logs <device-uuid> --system

balena ssh

bash — uzak terminal erişimi
# Host OS'e SSH (development mod veya tunnel)
balena ssh <device-uuid>

# Belirli servis container'ına gir
balena ssh <device-uuid> --service sensor-collector

# Container içinde komut çalıştır
balena ssh <device-uuid> -s sensor-collector -- python3 -c "import sys; print(sys.version)"

# Lokal ağdaki cihaza direk SSH (local mode)
balena ssh <local-ip>
# root@<uuid>:~#

Bu bölümde

  • balena push: bulutta build → release oluştur → tüm fleet'e OTA deploy
  • balena logs: servis bazında log takibi, --system Supervisor loglarını kapsar
  • balena ssh: host OS veya belirli container'a uzak terminal erişimi

03 docker-compose.yml ile multi-container app

balenaOS uygulamaları Docker Compose v3 formatında tanımlanır. Her servis ayrı bir container olarak çalışır; Supervisor bu compose dosyasını yorumlar.

Örnek multi-container compose

docker-compose.yml — sensor platform stack
version: "2.4"

volumes:
  influxdb-data:
  grafana-data:
  mosquitto-data:

services:

  mqtt-broker:
    build: ./mqtt-broker
    restart: always
    ports:
      - "1883:1883"
      - "9001:9001"
    volumes:
      - mosquitto-data:/mosquitto/data
      - ./mqtt-broker/config:/mosquitto/config:ro
    labels:
      io.balena.features.supervisor-api: "1"

  sensor-collector:
    build: ./sensor-collector
    restart: always
    privileged: true
    devices:
      - "/dev/i2c-1:/dev/i2c-1"
      - "/dev/gpiomem:/dev/gpiomem"
    environment:
      MQTT_HOST: mqtt-broker
      MQTT_PORT: "1883"
      POLL_INTERVAL: "10"
    depends_on:
      - mqtt-broker
    labels:
      io.balena.features.balena-socket: "1"

  influxdb:
    image: influxdb:2.7-alpine
    restart: always
    ports:
      - "8086:8086"
    volumes:
      - influxdb-data:/var/lib/influxdb2
    environment:
      DOCKER_INFLUXDB_INIT_MODE: setup
      DOCKER_INFLUXDB_INIT_USERNAME: admin

  grafana:
    image: grafana/grafana:10.2.0
    restart: always
    ports:
      - "3000:3000"
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning:ro
    depends_on:
      - influxdb
io.balena.features.supervisor-apiServis, Supervisor API'sine erişebilir. Cihaz yeniden başlatma, uygulama güncelleme gibi işlemler programatik yapılabilir.
io.balena.features.balena-socketbalenaEngine Docker socket'ine erişim. Dinamik container yönetimi gerektiğinde kullanılır.
privileged: trueGPIO ve I2C erişimi için gerekli. Üretimde mümkün olduğunca --device ile sınırlı erişim tercih edilmeli.

Bu bölümde

  • Docker Compose v2.4 formatı kullanılır (v3 özelliklerinin bir kısmı desteklenmez)
  • io.balena.features.* label'ları ile Supervisor özellikleri etkinleştirilir
  • GPIO/I2C için devices veya privileged; üretimde devices tercih edilmeli

04 Environment variable ve secret yönetimi

balenaCloud'da ortam değişkenleri fleet seviyesinde veya tekil cihaz seviyesinde tanımlanabilir. Hassas değerler için "balena Secret" özelliği kullanılır.

Fleet ve cihaz seviyesi değişkenler

bash — balena CLI ile env var yönetimi
# Fleet seviyesi değişken ekle (tüm cihazlara uygulanır)
balena env add MQTT_BROKER_URL \
  mqtt://mqtt-broker:1883 \
  --fleet sensor-platform

# Birden fazla servis için (belirli servise)
balena env add POLL_INTERVAL 30 \
  --fleet sensor-platform \
  --service sensor-collector

# Cihaz seviyesi değişken (yalnızca bu cihaz için)
balena env add DEVICE_LOCATION \
  "factory-floor-A" \
  --device <device-uuid>

# Tüm değişkenleri listele
balena envs --fleet sensor-platform

# Değişken güncelle
balena env rename <var-id> NEW_VALUE

# Değişken sil
balena env rm <var-id>

balena Secret (gizli değerler)

bash — secret yönetimi
# Secret oluştur — dashboard'da değer şifreli saklanır
balena env add INFLUXDB_PASSWORD \
  "s3cr3tP@ssw0rd" \
  --fleet sensor-platform \
  --secret

# API token secret'ı
balena env add GRAFANA_ADMIN_PASSWORD \
  "gr4f4n4P4ss" \
  --fleet sensor-platform \
  --secret

# Secret değerler CLI çıktısında maskelenir
# balena envs → INFLUXDB_PASSWORD: ***

compose'da env var kullanımı

docker-compose.yml — env var referansı
  influxdb:
    image: influxdb:2.7-alpine
    environment:
      DOCKER_INFLUXDB_INIT_PASSWORD: ${INFLUXDB_PASSWORD}
      DOCKER_INFLUXDB_INIT_ORG: ${INFLUXDB_ORG:-myorg}
      DOCKER_INFLUXDB_INIT_BUCKET: ${INFLUXDB_BUCKET:-sensors}

Bu bölümde

  • Fleet seviyesi değişkenler tüm cihazlara, cihaz seviyesi değişkenler tekil cihaza uygulanır
  • --secret flag'i ile değer dashboard'da maskelenir, log'a düşmez
  • compose'da ${VAR:-default} sözdizimi ile varsayılan değer tanımlanır

05 OTA güncelleme akışı — delta update

balenaCloud'un delta update sistemi, yalnızca değişen dosya bloklarını iletir. 100 MB imaj için sadece 2-5 MB veri aktarılabilir; düşük bant genişliği ve ölçülü veri planı olan edge cihazlar için kritiktir.

OTA güncelleme akışı

  Geliştirici
  balena push sensor-platform
         │
         ▼
  balena Builder (bulut)
  · Dockerfile build (aarch64 native)
  · Multi-layer imaj oluştur
  · Delta hesapla (mevcut sürümle fark)
         │
         ▼
  balenaCloud Release (commit hash)
         │
         ▼ (SuperVisor polling veya push event)
  Cihazlar (10x RPi4)
  · Delta parçaları indir (~MB, tam imaj değil ~100MB)
  · containerd imaj katmanlarını güncelle
  · Graceful restart: eski container dur → yeni başlar
  · Başarısızsa: otomatik rollback
    
bash — release yönetimi
# Güncel release listele
balena releases sensor-platform

# Belirli release'i pinle (otomatik güncelleme durdur)
balena fleet pin sensor-platform <release-commit>

# Tekil cihaza release pinle
balena device pin <device-uuid> <release-commit>

# Pin kaldır (tekrar otomatik güncellemeye geç)
balena fleet track-latest sensor-platform

# Draft release'i final yap (staged rollout)
balena release finalize <release-commit>

# Cihaz güncelleme durumunu izle
balena devices --fleet sensor-platform \
  --fields id,uuid,status,is_online,os_version,supervisor_version

Supervisor API ile programatik güncelleme

bash — Supervisor API üzerinden güncelleme tetikleme
# Container içinden (io.balena.features.supervisor-api aktif)
# Uygulamayı güncelle
curl -X POST \
  "http://$(BALENA_SUPERVISOR_ADDRESS)/v1/update" \
  -H "Authorization: Bearer $BALENA_SUPERVISOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"force": true}'

# Cihazı yeniden başlat
curl -X POST \
  "http://$(BALENA_SUPERVISOR_ADDRESS)/v1/reboot" \
  -H "Authorization: Bearer $BALENA_SUPERVISOR_API_KEY"

Bu bölümde

  • Delta update: değişen bloklar iletilir; bant genişliği %90+ tasarruf
  • Release pin ile belirli sürüm dondurulur; staged rollout desteklenir
  • Supervisor API ile container içinden güncelleme ve reboot tetiklenir

06 Device health monitoring — dashboard ve metrikler

balenaCloud dashboard'u, cihaz sağlığını anlık izleme, CPU/RAM/disk metrikleri ve bağlantı durumu görünürlüğü sağlar.

Dashboard metrikleri

CPU kullanımıOrtalama ve anlık CPU yükü (%). Yüksek değerler uygulama performans sorununa işaret eder.
Bellek kullanımıKullanılan / toplam RAM (MB). Bellek sızıntısı tespitinde zaman serisi grafiği kullanılır.
DepolamaData partition kullanımı (%). Log birikimi ve data büyümesi disk dolmasına yol açabilir.
Ağ bağlantısıOnline/offline durumu, son görülme zamanı, VPN bağlantı durumu.
OS ve Supervisor versiyonuFleet'teki tüm cihazlarda versiyon dağılımı. Eski versiyondaki cihazlar tespit edilir.

Supervisor API ile metrik okuma

bash — Supervisor API metrik endpointleri
# Cihaz durumu (container içinden)
curl "http://$BALENA_SUPERVISOR_ADDRESS/v2/device/name" \
  -H "Authorization: Bearer $BALENA_SUPERVISOR_API_KEY"
# {"status":"success","deviceName":"floral-dew"}

# Çalışan servisler
curl "http://$BALENA_SUPERVISOR_ADDRESS/v2/containerId" \
  -H "Authorization: Bearer $BALENA_SUPERVISOR_API_KEY"

# Uygulama state
curl "http://$BALENA_SUPERVISOR_ADDRESS/v2/applications/state" \
  -H "Authorization: Bearer $BALENA_SUPERVISOR_API_KEY"

# Host OS metrik
curl "http://$BALENA_SUPERVISOR_ADDRESS/v1/device" \
  -H "Authorization: Bearer $BALENA_SUPERVISOR_API_KEY"
# {"api_port":48484,"ip_address":"192.168.1.50","mac_address":"dc:a6:32:xx:xx:xx",
#  "memory_usage":412,"memory_total":3904,"storage_usage":2048,"storage_total":29000,
#  "cpu_usage":12,"cpu_temp":47}
Prometheus entegrasyonu

Supervisor metriklerini kendi Prometheus/Grafana stack'inize aktarmak için BALENA_SUPERVISOR_ADDRESS ve BALENA_SUPERVISOR_API_KEY ortam değişkenlerini kullanan bir exporter servisi yazabilirsiniz. Bu metrikleri Fleet'teki tüm cihazlardan merkezde toplamak için Prometheus remote_write kullanın.

Bu bölümde

  • Dashboard: CPU, RAM, disk, ağ durumu, OS/Supervisor versiyonu
  • Supervisor API /v1/device ile programatik metrik okuma
  • Metrikler kendi Prometheus/Grafana stack'ine aktarılabilir

07 balena local mode — yerel geliştirme

Local mode, balenaCloud'a push etmeden aynı ağdaki cihaza doğrudan kod deploy etmeyi sağlar. Geliştirme döngüsünü saniyeye indirir.

Local mode aktifleştirme

bash — local mode etkinleştirme ve kullanım
# Dashboard'dan veya CLI ile local mode aç
balena device local-mode enable <device-uuid>

# Aynı ağdaki cihazları tara
balena scan
# - 192.168.1.50   floral-dew.local
# - 192.168.1.51   crimson-leaf.local

# Lokal cihaza push et (bulut build olmadan)
balena push floral-dew.local

# veya IP ile
balena push 192.168.1.50

# Lokal SSH
balena ssh floral-dew.local

# Servis container'ına gir
balena ssh floral-dew.local -s sensor-collector

Live update (sıcak kod güncellemesi)

bash — live update ile anında kod değişikliği
# Live update: dosya değişikliği algılanır, container yeniden başlatılmadan güncellenir
balena push floral-dew.local --live

# Çıktı:
# [Live] Watching for file changes...
# [Live] File changed: src/sensor.py
# [Live] Syncing to sensor-collector...
# [Live] Sync complete in 1.2s

# .balenaignore ile gereksiz dosyaları hariç tut
cat .balenaignore
# __pycache__/
# *.pyc
# .git/
# node_modules/
# tests/

Bu bölümde

  • Local mode: buluta push gerekmez, aynı ağdaki cihaza doğrudan deploy
  • balena scan ile ağdaki balenaOS cihazları keşfedilir
  • --live flag'i ile dosya değişikliği anında cihaza sync edilir

08 Pratik — MQTT + InfluxDB + Grafana 10 cihaza deploy

10 adet Raspberry Pi 4'ten oluşan bir sensör izleme fleet'ine balenaCloud üzerinden MQTT + InfluxDB + Grafana stack'i deploy ediyoruz.

Proje yapısı

  sensor-platform/
  ├── docker-compose.yml
  ├── mqtt-broker/
  │   ├── Dockerfile
  │   └── config/mosquitto.conf
  ├── sensor-collector/
  │   ├── Dockerfile
  │   ├── requirements.txt
  │   └── src/collector.py
  ├── influxdb/
  │   └── setup.sh
  └── grafana/
      └── provisioning/
          ├── datasources/influxdb.yaml
          └── dashboards/sensors.json
    

sensor-collector Dockerfile

sensor-collector/Dockerfile
FROM balenalib/raspberrypi4-64-python:3.11-bookworm-run
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY src/ ./src/
CMD ["python3", "src/collector.py"]
sensor-collector/src/collector.py — MQTT sensör toplayıcı
import os, time, json, smbus2
import paho.mqtt.client as mqtt

MQTT_HOST    = os.environ.get("MQTT_HOST", "mqtt-broker")
MQTT_PORT    = int(os.environ.get("MQTT_PORT", 1883))
DEVICE_UUID  = os.environ.get("BALENA_DEVICE_UUID", "unknown")
POLL_INTERVAL = int(os.environ.get("POLL_INTERVAL", 10))

client = mqtt.Client(client_id=f"collector-{DEVICE_UUID}")
client.connect(MQTT_HOST, MQTT_PORT)
client.loop_start()

def read_sensor():
    # BME280 I2C sensör okuma (gerçek uygulamada)
    import random
    return {
        "device_uuid": DEVICE_UUID,
        "temperature": 23.0 + random.uniform(-1, 1),
        "humidity":    55.0 + random.uniform(-5, 5),
        "pressure":    1013.0 + random.uniform(-2, 2),
        "timestamp":   time.time()
    }

while True:
    data = read_sensor()
    topic = f"sensors/{DEVICE_UUID}/environment"
    client.publish(topic, json.dumps(data), qos=1)
    print(f"Published: {data}")
    time.sleep(POLL_INTERVAL)

Fleet deploy ve izleme

bash — fleet deploy ve cihaz izleme
# Fleet değişkenlerini ayarla
balena env add INFLUXDB_ORG myorg --fleet sensor-platform
balena env add INFLUXDB_BUCKET sensors --fleet sensor-platform
balena env add INFLUXDB_PASSWORD "s3cr3t" --fleet sensor-platform --secret
balena env add GRAFANA_ADMIN_PASSWORD "gr4f4n4" --fleet sensor-platform --secret

# Tüm fleet'e push et
balena push sensor-platform

# 10 cihazın güncelleme durumunu izle
watch -n 5 "balena devices --fleet sensor-platform | grep -E 'UUID|STATUS'"

# MQTT mesajlarını test cihazından izle
balena ssh <device-uuid> -s mqtt-broker -- \
  mosquitto_sub -h localhost -t "sensors/#" -v

# InfluxDB'de veri kontrolü
balena ssh <device-uuid> -s influxdb -- \
  influx query 'from(bucket:"sensors") |> range(start: -1h) |> limit(n:5)'
Ölçeklendirme notu

10 cihaz için balenaCloud ücretsiz planı yeterlidir. Daha büyük fleet'lerde (100+ cihaz) openbalena self-hosted kurulumu maliyet optimizasyonu sağlar. openbalena, tam balenaCloud stack'ini kendi altyapınızda çalıştırmanıza olanak verir.

Bu bölümde

  • MQTT → InfluxDB → Grafana stack balenaOS üzerinde Compose ile çalışır
  • BALENA_DEVICE_UUID env değişkeni her cihazda unique topic oluşturmak için kullanıldı
  • balena push ile tüm 10 cihaza delta OTA güncelleme tek komutla yapılır