Konteyner Orkestrasyon (Edge)
TEKNİK REHBER KONTEYNER EDGE CI/CD 2026

Edge CI/CD —
GitHub Actions Multi-Arch & ARM Runner.

ARM/RISC-V edge cihazlar için eksiksiz CI/CD boru hattı: Docker buildx ile çok mimari image derleme, QEMU emülasyonu, self-hosted ARM64 runner kurulumu, OCI registry push, Cosign imzalama ve OTA dağıtım iş akışı.

00 Edge CI/CD boru hattı mimarisi

Edge sistemler için CI/CD, klasik web uygulamalarından farklıdır: çoklu CPU mimarileri (AMD64, ARM64, ARMv7, RISC-V), kısıtlı bant genişliği, bağlantısız dönemler ve atomik güncelleme gereksinimleri söz konusudur.

Tam Edge CI/CD Boru Hattı
Geliştirici (git push)
       │
       ▼
GitHub Actions (CI)
  ├── Trivy secret scan
  ├── Unit / integration testleri
  ├── docker buildx (multi-arch: amd64, arm64, armv7)
  │     ├── QEMU emülasyon (hızlı prototip)
  │     └── Native ARM64 runner (üretim hızı)
  ├── Trivy image CVE tarama
  ├── Cosign image imzalama
  └── OCI registry push (GHCR / Harbor / ECR)
       │
       ▼
Registry (imzalı multi-arch manifest)
       │
       ▼
OTA Dağıtım (Moshi / RAUC / SWUpdate / Flux CD)
  ├── Edge fleet manager → hedef cihaz grupları
  ├── Kademeli yayın (canary → %5 → %25 → %100)
  ├── Sağlık kontrolü → başarısızsa rollback
  └── Dağıtım doğrulama (smoke test)

01 Docker buildx ile multi-arch build

Docker buildx, BuildKit üzerine inşa edilmiş ve çoklu mimari image derlemeyi destekleyen build aracıdır. Tek komutla amd64, arm64, armv7 image'ları üretir ve tek OCI manifest altında yayınlar.

buildx kurulum ve builder oluşturma

bash
## buildx versiyonunu kontrol et
docker buildx version
# github.com/docker/buildx v0.17.1

## Multi-platform builder oluştur
docker buildx create \
    --name multiarch-builder \
    --driver docker-container \
    --platform linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6 \
    --use

## Builder'ı başlat ve bootstrap et
docker buildx inspect --bootstrap multiarch-builder

## Desteklenen platformlar
docker buildx ls
# NAME/NODE              DRIVER/ENDPOINT  STATUS   PLATFORMS
# multiarch-builder *    docker-container running
#   multiarch-builder0   unix:///var/...  running  linux/amd64,
#                                                  linux/arm64,
#                                                  linux/arm/v7

Multi-arch image derleme ve push

bash — tek komutla çoklu mimari
## Tüm mimarileri derle ve registry'e push et
docker buildx build \
    --platform linux/amd64,linux/arm64,linux/arm/v7 \
    --tag ghcr.io/org/edge-app:v1.2.3 \
    --tag ghcr.io/org/edge-app:latest \
    --push \
    .

## Manifest listesini doğrula
docker buildx imagetools inspect ghcr.io/org/edge-app:v1.2.3
# Name: ghcr.io/org/edge-app:v1.2.3
# MediaType: application/vnd.oci.image.index.v1+json
# Digest: sha256:abc123...
#
# Manifests:
#   Name: ghcr.io/org/edge-app:v1.2.3@sha256:aaa...
#   MediaType: application/vnd.oci.image.manifest.v1+json
#   Platform: linux/amd64
#
#   Name: ghcr.io/org/edge-app:v1.2.3@sha256:bbb...
#   Platform: linux/arm64
#
#   Name: ghcr.io/org/edge-app:v1.2.3@sha256:ccc...
#   Platform: linux/arm/v7

Platform-aware Dockerfile

Dockerfile — TARGETPLATFORM kullanımı
## buildx otomatik TARGETPLATFORM, TARGETARCH, TARGETOS değişkenlerini sağlar
FROM --platform=$BUILDPLATFORM golang:1.22 AS builder
ARG TARGETPLATFORM
ARG TARGETOS
ARG TARGETARCH

WORKDIR /app
COPY . .
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH \
    CGO_ENABLED=0 \
    go build -ldflags="-s -w" -o /edge-app ./cmd/

FROM gcr.io/distroless/static:nonroot
COPY --from=builder /edge-app /edge-app
ENTRYPOINT ["/edge-app"]

02 QEMU emülasyonu — ARM64/ARMv7 x86'da derleme

QEMU user-space emülasyonu, x86 runner üzerinde ARM binary'lerini çalıştırır. Yerel derlemeye göre 5–20× yavaştır; yalnızca hızlı prototipleme veya küçük image'lar için uygundur.

QEMU kurulum ve test

bash
## QEMU statik binary'lerini Docker daemon'a kaydet
docker run --privileged --rm \
    tonistiigi/binfmt --install all

## Kayıtlı emülatörler
ls /proc/sys/fs/binfmt_misc/ | grep qemu
# qemu-aarch64
# qemu-arm
# qemu-riscv64

## ARM64 image'ı doğrudan çalıştır (x86 makine)
docker run --platform linux/arm64 --rm \
    arm64v8/alpine:3.20 uname -m
# aarch64   ← QEMU sayesinde x86'da ARM64 çalıştı

## Derleme hızı karşılaştırması (basit Go projesi)
# QEMU (x86 → arm64):    ~45 saniye
# Native ARM64 runner:    ~8 saniye
# Çapraz derleme (CGO=0): ~6 saniye

CGO ile çapraz derleme (QEMU gerektirmez)

Dockerfile — çapraz derleme (hızlı)
## CGO_ENABLED=0: QEMU emülasyonu gerektirmez
FROM --platform=linux/amd64 golang:1.22 AS builder
ARG TARGETARCH
RUN apt-get update && apt-get install -y \
    gcc-aarch64-linux-gnu  # CGO kullanan paketler için

ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=$TARGETARCH

WORKDIR /app
COPY . .
RUN go build -o /app/edge-app ./cmd/

FROM --platform=$TARGETPLATFORM gcr.io/distroless/static:nonroot
COPY --from=builder /app/edge-app /edge-app
ENTRYPOINT ["/edge-app"]

03 Self-hosted ARM64 runner kurulumu

Yerel ARM64 runner, QEMU emülasyonuna kıyasla 5–10× daha hızlı derleme sağlar. Raspberry Pi 5, Jetson Orin veya AWS Graviton instance kullanılabilir.

GitHub Actions runner kurulumu

bash — Raspberry Pi 5 (ARM64)
## GitHub → Repository → Settings → Actions → Runners → New self-hosted runner

## Runner indirme (ARM64)
mkdir -p ~/actions-runner && cd ~/actions-runner

curl -o actions-runner-linux-arm64-2.319.1.tar.gz -L \
  https://github.com/actions/runner/releases/download/v2.319.1/\
actions-runner-linux-arm64-2.319.1.tar.gz

tar xzf actions-runner-linux-arm64-2.319.1.tar.gz

## Yapılandırma (GitHub'dan token al)
./config.sh \
    --url https://github.com/org/repo \
    --token AABBC1234XXXXX \
    --name "rpi5-arm64-runner" \
    --labels "self-hosted,linux,ARM64,edge" \
    --work "_work"

## Servis olarak kur (systemd)
sudo ./svc.sh install
sudo ./svc.sh start
sudo systemctl status actions.runner.org-repo.rpi5-arm64-runner

Runner önbellekleme optimizasyonu

bash — Docker layer cache
## Self-hosted runner'da BuildKit cache mount
docker buildx create \
    --name arm64-builder \
    --driver docker-container \
    --driver-opt image=moby/buildkit:latest \
    --use

## Cache mount ile Dockerfile
# RUN --mount=type=cache,target=/root/.cache/go-build \
#     go build ./...

## GitHub Actions cache backend
docker buildx build \
    --cache-from type=gha \
    --cache-to type=gha,mode=max \
    --platform linux/arm64 \
    -t ghcr.io/org/app:latest \
    --push \
    .

04 GitHub Actions workflow — multi-arch build

Eksiksiz bir multi-arch build ve deploy workflow'u: QEMU emülasyonu, native ARM64 runner, Trivy tarama ve Cosign imzalamayı tek pipeline'da birleştirme.

.github/workflows/edge-build.yml
name: Edge Multi-Arch Build

on:
  push:
    branches: [main]
    tags: ["v*"]
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Secret tarama
      uses: trufflesecurity/trufflehog@main
      with:
        path: ./

  build-and-push:
    needs: security-scan
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write   # Cosign keyless için

    steps:
    - uses: actions/checkout@v4

    - name: Docker meta (tag hesapla)
      id: meta
      uses: docker/metadata-action@v5
      with:
        images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
        tags: |
          type=semver,pattern={{version}}
          type=semver,pattern={{major}}.{{minor}}
          type=sha,prefix=git-
          type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}

    - name: QEMU kurulum
      uses: docker/setup-qemu-action@v3
      with:
        platforms: arm64,arm

    - name: Docker Buildx kurulum
      uses: docker/setup-buildx-action@v3
      with:
        driver-opts: image=moby/buildkit:latest

    - name: GHCR login
      uses: docker/login-action@v3
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Multi-arch build ve push
      id: build
      uses: docker/build-push-action@v6
      with:
        context: .
        platforms: linux/amd64,linux/arm64,linux/arm/v7
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}
        push: ${{ github.event_name != 'pull_request' }}
        cache-from: type=gha
        cache-to: type=gha,mode=max
        sbom: true     # SBOM oluştur
        provenance: true  # SLSA provenance

    - name: Trivy CVE tarama
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
        severity: CRITICAL,HIGH
        exit-code: 1
        ignore-unfixed: true

    - name: Cosign kurulum
      uses: sigstore/cosign-installer@v3

    - name: Cosign keyless imzalama
      if: github.event_name != 'pull_request'
      run: |
        cosign sign --yes \
          ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}

05 OCI registry push ve image tagging stratejisi

Doğru image tagging stratejisi, hangi sürümün nerede çalıştığını izlemeyi ve güvenli rollback'i kolaylaştırır. Semantik sürümleme + git SHA kombinasyonu önerilir.

Tagging stratejisi

Tag Stratejisi
Tag türü         Örnek                     Kullanım
─────────────────────────────────────────────────────────────────
SemVer           :v1.2.3                   Üretim release
SemVer major     :v1                       Major stable
SemVer minor     :v1.2                     Minor stable
Git SHA          :git-a1b2c3d              Debug, izlenebilirlik
Branch           :main, :develop           CI test sürümü
latest           :latest                   Son main build
edge             :edge                     Geliştirme kanalı

Harbor registry ile imzalı image yönetimi

bash — Harbor + Cosign
## Harbor'a imzalı image push
docker login harbor.edge.company.com
docker buildx build \
    --platform linux/amd64,linux/arm64 \
    -t harbor.edge.company.com/edge/app:v1.2.3 \
    --push .

## Cosign imzala
cosign sign --key cosign.key \
    harbor.edge.company.com/edge/app:v1.2.3

## Harbor'da content trust doğrula
cosign verify --key cosign.pub \
    harbor.edge.company.com/edge/app:v1.2.3

## Image silme politikası — 30 günden eski :git-* tag'lerini temizle
harbor garbage-collect --delete-untagged

06 Cosign imzalama ile güvenli pipeline

Cosign'ı CI/CD pipeline'ına entegre ederek her imzalı build için doğrulanabilir kriptografik kanıt oluşturulur. SLSA provenance ve SBOM attestation ile yazılım tedarik zinciri güvence altına alınır.

SBOM ve Provenance attestation

bash — SBOM üretme ve imzalama
## Syft ile SBOM üret
syft ghcr.io/org/edge-app:v1.2.3 \
    -o spdx-json > sbom.spdx.json

## SBOM'u Cosign attestation olarak imzala
cosign attest --key cosign.key \
    --predicate sbom.spdx.json \
    --type spdxjson \
    ghcr.io/org/edge-app:v1.2.3

## SLSA provenance (GitHub Actions ile otomatik)
# docker/build-push-action provenance=true ayarıyla SLSA Level 2

## Attestation doğrula
cosign verify-attestation \
    --key cosign.pub \
    --type spdxjson \
    ghcr.io/org/edge-app:v1.2.3 \
    | jq '.payload | @base64d | fromjson | .predicate.packages | length'

GitHub Actions imzalama adımı

workflow kısmı
    - name: Cosign keyless + SBOM attestation
      if: startsWith(github.ref, 'refs/tags/v')
      env:
        DIGEST: ${{ steps.build.outputs.digest }}
      run: |
        IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}"

        # Image imzala
        cosign sign --yes "${IMAGE}@${DIGEST}"

        # SBOM üret ve attest
        syft "${IMAGE}@${DIGEST}" -o spdx-json > sbom.json
        cosign attest --yes \
            --predicate sbom.json \
            --type spdxjson \
            "${IMAGE}@${DIGEST}"

        echo "Image: ${IMAGE}@${DIGEST}" >> $GITHUB_STEP_SUMMARY
        echo "Cosign imzalandı" >> $GITHUB_STEP_SUMMARY

07 OTA (Over-the-Air) dağıtım iş akışı

Edge cihazlara güvenli ve güvenilir OTA dağıtım, A/B bölümleme veya konteyner güncelleme yöneticileriyle sağlanır. Fleet yönetimi için kademeli yayın (progressive rollout) kritiktir.

Flux CD ile GitOps tabanlı OTA

flux — edge fleet deployment
## Flux CD kurulum (edge cluster — k3s)
flux bootstrap github \
    --owner=org \
    --repository=edge-fleet-config \
    --branch=main \
    --path=clusters/edge-site-01

## HelmRelease ile kademeli güncelleme
cat > edge-app-helmrelease.yaml <<'EOF'
apiVersion: helm.toolkit.fluxcd.io/v2beta2
kind: HelmRelease
metadata:
  name: edge-app
  namespace: default
spec:
  interval: 1m
  chart:
    spec:
      chart: edge-app
      version: "1.2.*"
      sourceRef:
        kind: HelmRepository
        name: edge-charts
  values:
    image:
      repository: ghcr.io/org/edge-app
      tag: v1.2.3
    replicas: 1
  upgrade:
    remediation:
      retries: 3
  rollback:
    timeout: 5m
    cleanupOnFail: true
EOF
kubectl apply -f edge-app-helmrelease.yaml

Balena Cloud (konteyner tabanlı OTA)

docker-compose.yml — balena fleet
version: "2"
services:
  edge-app:
    image: ghcr.io/org/edge-app:v1.2.3
    restart: always
    privileged: false
    security_opt:
      - no-new-privileges:true
    environment:
      - NODE_ENV=production
    ports:
      - "8080:8080"
    volumes:
      - data:/var/lib/app
    healthcheck:
      test: ["CMD", "/edge-app", "--health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s

volumes:
  data:
GitHub Actions — Balena OTA push
    - name: Balena push (OTA)
      if: startsWith(github.ref, 'refs/tags/v')
      env:
        BALENA_API_KEY: ${{ secrets.BALENA_API_KEY }}
      run: |
        npm install -g balena-cli
        balena login --token "$BALENA_API_KEY"
        balena push edge-production-fleet

08 Dağıtım doğrulama ve rollback

Başarılı dağıtım, image'ın çekilmesi değil, uygulamanın istenen durumda çalışmasıdır. Smoke test, health check ve otomatik rollback pipeline'ın son katmanıdır.

Kubernetes rollout ve smoke test

bash — rollout takibi
## Güncellemeyi izle
kubectl set image deployment/edge-app \
    edge-app=ghcr.io/org/edge-app:v1.2.3

kubectl rollout status deployment/edge-app --timeout=5m
# Waiting for deployment "edge-app" rollout to finish:
# 1 out of 3 new replicas have been updated...
# deployment "edge-app" successfully rolled out

## Pod sağlık durumu
kubectl get pods -l app=edge-app -w

## Smoke test
kubectl run smoke-test --rm -it --image=curlimages/curl \
    --restart=Never -- \
    curl -f http://edge-app:8080/healthz
# {"status":"ok","version":"v1.2.3"}

Otomatik rollback — GitHub Actions

workflow — deploy ve rollback
  deploy-and-verify:
    needs: [build-and-push]
    runs-on: ubuntu-latest
    steps:
    - name: Deploy
      run: |
        kubectl set image deployment/edge-app \
            edge-app=ghcr.io/org/edge-app:${{ github.sha }}
        kubectl rollout status deployment/edge-app --timeout=5m

    - name: Smoke test
      run: |
        ENDPOINT=$(kubectl get svc edge-app \
            -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
        curl -f --retry 5 --retry-delay 3 \
            http://${ENDPOINT}:8080/healthz

    - name: Rollback on failure
      if: failure()
      run: |
        echo "Dağıtım başarısız — rollback yapılıyor"
        kubectl rollout undo deployment/edge-app
        kubectl rollout status deployment/edge-app
        exit 1

Kademeli yayın — Argo Rollouts

argo-rollout.yaml
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: edge-app
spec:
  replicas: 10
  strategy:
    canary:
      steps:
      - setWeight: 10     # %10 canary
      - pause: {duration: 5m}
      - analysis:
          templates:
          - templateName: edge-app-health
      - setWeight: 50
      - pause: {duration: 5m}
      - setWeight: 100
  selector:
    matchLabels:
      app: edge-app
  template:
    spec:
      containers:
      - name: edge-app
        image: ghcr.io/org/edge-app:v1.2.3

09 Maliyet optimizasyonu ve paralel build stratejileri

Multi-arch build'ler GitHub Actions dakika tüketimini artırabilir. Akıllı paralelleştirme ve cache stratejileri hem süreyi hem maliyeti düşürür.

Build süresi karşılaştırması

Süre Tablosu — Node.js Uygulaması (100MB image)
Tablo
Yöntem                           amd64  arm64  armv7  Toplam
──────────────────────────────────────────────────────────────
QEMU emülasyon (seri)            2 dk   18 dk  22 dk   42 dk
QEMU emülasyon (paralel matrix)  2 dk   18 dk  22 dk   22 dk
Native ARM64 runner              2 dk    3 dk   —       5 dk
Çapraz derleme (CGO=0)          2 dk    2 dk   2 dk    4 dk
Cache ile çapraz derleme         30sn   30sn   30sn    90sn

Matrix strategy ile paralel build

workflow — matrix paralel build
  build-matrix:
    strategy:
      matrix:
        platform:
          - linux/amd64
          - linux/arm64
          - linux/arm/v7
      fail-fast: false
    runs-on: ${{ matrix.platform == 'linux/arm64' && 'self-hosted' || 'ubuntu-latest' }}

    steps:
    - uses: actions/checkout@v4

    - name: Build platform image
      uses: docker/build-push-action@v6
      with:
        context: .
        platforms: ${{ matrix.platform }}
        outputs: type=image,name=ghcr.io/org/app,push-by-digest=true,push=true
        cache-from: type=gha,scope=${{ matrix.platform }}
        cache-to: type=gha,mode=max,scope=${{ matrix.platform }}

  merge-manifest:
    needs: build-matrix
    runs-on: ubuntu-latest
    steps:
    - name: Manifest birleştir
      run: |
        docker buildx imagetools create \
            -t ghcr.io/org/app:${{ github.sha }} \
            $(docker buildx imagetools inspect ghcr.io/org/app \
              --format '{{.Manifest.Digest}}')

Optimizasyon özeti

GitHub Actions cache
type=gha cache backend ile tekrarlayan build'lerde layer yeniden kullanımı. İlk build sonrası 5–10× hızlanma.
CGO=0 çapraz derleme
Go, Rust, Zig gibi diller için CGO kapatıp standart çapraz derleme kullanın. QEMU'ya gerek kalmaz.
Self-hosted ARM64 runner
Raspberry Pi 5 veya AWS Graviton3 runner ile arm64 build'leri yerelde yapın. Dakika ücreti sıfır.
Conditional build
PR'larda sadece amd64 derle, main/tag'lerde çoklu mimari. Geliştirme döngüsünü hızlandırır.