❯ infra · Running

Un NAS x86 à 6W rejoint le cluster Pi — partie 1 : build & monitoring unifié A 6W x86 NAS Joins the Pi Cluster — Part 1: Build & Unified Monitoring

Montage d'un NAS silencieux ASRock N100M dans un Jonsbo N4 — et intégration dans la stack d'observabilité du cluster : node_exporter, agent Portainer, et monitoring SMART des disques via smartctl_exporter (avec un piège d'image ARM64). Building a silent ASRock N100M NAS in a Jonsbo N4 — and wiring it into the cluster's observability stack: node_exporter, a Portainer agent, and SMART disk monitoring via smartctl_exporter (including an ARM64 image pitfall).

· 9 min de lecture 9 min read ·
k3s-clusternashardwaremonitoringdockersmartctlportainern100infra
🇫🇷 Lire cet article en français

The K3s cluster has a rack neighbour: a NAS hosting the media stack and Nextcloud, outside the cluster, on Docker Compose. The incumbent — an i5-4690 from 2014, 84W of TDP — is running out of breath. Its replacement is called gbnas: a silent build around an ASRock N100M board, designed for three roles — NAS, backup target for the cluster, and workstation for the agent that drives the infrastructure.

This part 1 covers the build and the first integration: bringing an x86 machine into the monitoring ecosystem of an ARM cluster. The migration of the media stack is covered in part 2.

The build

ComponentChoiceWhy
MotherboardASRock N100M (mATX)Integrated Intel N100, 4 cores, 6 W TDP, QuickSync iGPU
CaseJonsbo N46× 3.5” bays + 2× 2.5” — 3 free bays to grow into
PSUbe quiet! SFX Power 3 450WSilent, very generous headroom
DisksWD Red Plus 6 TB (CMR)mdadm RAID1 mirror (~5.5 TiB usable), free bays to grow into
SSD256 GB NVMe (OS) + 500 GB SATA (Docker apps)Separate OS / appdata / data
Network2.5GbE PCIe cardlink verified at 2500 Mb/s
CoolingNoctua NF-A12x25 + NF-A6x15inaudible
SATA controllerStarTech PCIe x1the N100M only has 2 native SATA ports

Two quirks of the N100M worth knowing: a single DDR4 SO-DIMM slot (16 GB max), and only 2 SATA ports — hence the PCIe controller. Both PCIe slots are therefore taken (network + SATA), leaving only the M.2.

Compared with the outgoing machine: equivalent Passmark (~5500 vs ~5100) for 14× less TDP (6 W vs 84 W), plus a modern QuickSync that decodes AV1 — Jellyfin transcoding will happen in hardware.

OS: Ubuntu Server, without agonising over it

I weighed TrueNAS Scale (native ZFS, but ~1 GB of RAM per TB, and a 16 GB ceiling here), Proxmox (overkill for a single-purpose NAS) and Unraid (licence). Ubuntu Server won on pragmatism: the current stack is pure Docker Compose — the migration will be an rsync plus a docker compose up, not a conceptual reinstall.

Setup as built: static IP 10.0.0.30, Docker + Compose, and the 2.5GbE link validated with iperf3 at a steady 2.37 Gbit/s towards the PC. The internet speedtest tops out around 1 Gbit/s symmetrical — that is the subscription talking, not the machine.

The monitoring integration: just another scrape target

The reflex to avoid: installing a monitoring stack on the NAS (a second Grafana, a local Netdata…). The NAS is not in the cluster, but it has no reason to own its observability either: vmagent scrapes whatever it is told to scrape, inside the cluster or outside it.

node_exporter — 10 lines

One container on the NAS, one static job on the vmagent side:

# monitoring/vm/vmagent-values.yaml
- job_name: nas-gbnas
  static_configs:
  - targets: ['10.0.0.30:9100']
    labels:
      instance: gbnas
      role: nas

Immediate result: gbnas shows up in the “Benchmarks — all machines” dashboard alongside the 6 Pis. CPU, RAM, disk, network, temperatures — same panels, same alerts available. During a network audit the week before, the NAS was literally invisible in the measurements; that hole is plugged.

Portainer — the agent, not a second Portainer

For the NAS containers (the future media stack), Portainer — which runs in the cluster — already knows how to manage several environments. One agent on the NAS:

services:
  portainer_agent:
    image: portainer/agent:2.42.0
    restart: always
    ports: ["9001:9001"]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes

A topology subtlety: standard agent, not Edge Agent. The standard agent gets contacted by Portainer (pod → 10.0.0.30:9001) — trivial on the same LAN. The Edge Agent reverses the direction (NAS → Portainer tunnel), which would mean exposing a port through Cloudflare. On a LAN: standard, and port 9001 stays strictly internal (it exposes the Docker socket — never through the tunnel).

smartctl_exporter — and the ARM64 trap

Mechanical disks that will spin 24/7 deserve better than a quarterly manual smartctl -a. smartctl_exporter exposes temperature, power-on hours, reallocated sectors and SMART status — on the NAS and on the SSDs of the cluster nodes (privileged DaemonSet, /dev access).

The trap that cost an evening: since v0.7.0, the officially published image is amd64-only. On the Pis: exec format error, on repeat. The fix — pin by digest the last multi-arch image:

# The "latest" tag lies about its architectures. The digest never does.
# (digest truncated below for readability)
image: quay.io/prometheuscommunity/smartctl-exporter@sha256:b71402…

It is the same reflex as digest pinning in CI, applied for a different reason: not reproducibility, but architectural truth. On a mixed ARM/x86 fleet, a floating tag can change the architectures it supports under your feet.

The alerts that come with it

Wiring the NAS into monitoring is not just cosmetic — it inherits the cluster’s alerting pipeline. Next up, rules dedicated to the disks:

- alert: NasDiskTemperature   # smartctl_device_temperature > 50°C
- alert: NasDiskUnhealthy     # smartctl_device_smart_status != 1
- alert: NasDiskAlmostFull    # the RAID1 mirror > 85%

What comes next (part 2)

The migration has happened — and the plan did not survive contact with reality intact (spoiler: RAIDZ1 lost against an mdadm mirror). The full media stack, Nextcloud and two surprise guests now run on gbnas: part 2 — the media stack moves in.

After that come the projects where the NAS actually serves the cluster: Longhorn backups offloaded from worker-2’s precious SSD, an out-of-cluster backup CronJob, an NFS StorageClass.

k3s-clusternashardwaremonitoringdockersmartctlportainern100infra