Super K3S internet test setup

Cluster-A ๐ŸŒ in cloud (Hetzner control plane) + workers across 3+ home sites ๐Ÿก๐Ÿš๐Ÿ  over VPN

  • Cluster-B ๐Ÿงฑ local cluster at your main home
  • Dynamic DNS via Joker.com ๐ŸŒ to keep each home site reachable
  • CloudNativePG ๐Ÿƒ with:
    • Primary DB at your home site (Cluster-A)
    • Async replicas at Site-2 & Site-3
  • Topology-aware reads ๐Ÿ“ (local reads)
  • Write routing to primary โœ๏ธ
  • Local services per home site ๐Ÿงฉ

๐ŸŒ High-Level Architecture

        Hetzner Cloud โ˜๏ธ
    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
    โ”‚ k3s control-plane ๐Ÿง    โ”‚
    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
            โ”‚ Tailscale/WG VPN ๐Ÿ”
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
        Multi-Site WAN Mesh

๐Ÿก Home Site (Primary DB)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ k3s worker nodes          โ”‚
โ”‚ Longhorn storage ๐Ÿ’พ       โ”‚
โ”‚ CNPG primary ๐Ÿ˜           โ”‚
โ”‚ DDNS updater โ†ป            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿš Site-2
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ k3s worker nodes          โ”‚
โ”‚ CNPG async replica ๐Ÿ“–     โ”‚
โ”‚ DDNS updater โ†ป            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ  Site-3
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ k3s worker nodes          โ”‚
โ”‚ CNPG async replica ๐Ÿ“–     โ”‚
โ”‚ DDNS updater โ†ป            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿก Local-only Cluster-B
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ k3s server + workers      โ”‚
โ”‚ Local apps only ๐Ÿšช        โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

โœ… Core Principles

FeatureDesign
Cluster-ADistributed across sites via VPN
Cluster-BLocal to main home
NetworkingTailscale or WireGuard
DNSJoker.com Dynamic DNS
DBCNPG primary @ home + async replicas at other sites
StorageLonghorn per site only (no cross-WAN replication)
RoutingWrites โ†’ primary; Reads โ†’ local

๐Ÿ—๏ธ Step-by-Step Setup


1๏ธโƒฃ VPN Everywhere (Tailscale recommended)

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --auth-key <KEY> --hostname <NODE_NAME>
ip -br a | grep tailscale0

Use the Tailscale IP (100.x.x.x) for all k3s --node-ip values.


2๏ธโƒฃ Joker.com Dynamic DNS ๐ŸŒ

For each site create DNS entries like:

  • home.example.com
  • site2.example.com
  • site3.example.com

Enable Dynamic DNS in Joker control panel (per host).

๐Ÿ” Site updater (ddclient method)

sudo apt install -y ddclient

/etc/ddclient.conf per site:

daemon=300
use=web, web=svc.joker.com/nic/checkip
protocol=dyndns2
server=svc.joker.com/nic/update?
ssl=yes

login=YOUR_DDNS_USER
password=YOUR_DDNS_PASS
host=home.example.com

Enable:

sudo systemctl enable --now ddclient

3๏ธโƒฃ Cluster-A: Cloud control plane โ˜๏ธ

On the Hetzner VM:

TS_IP_CP=<tailscale ip>

curl -sfL https://get.k3s.io | \
INSTALL_K3S_EXEC="--node-ip ${TS_IP_CP} --disable servicelb --disable local-storage" \
sh -

kubectl taint nodes $(hostname) node-role.kubernetes.io/control-plane=true:NoSchedule

4๏ธโƒฃ Join Worker Nodes at Each Site ๐Ÿก๐Ÿš๐Ÿ 

On each worker:

TS_IP_NODE=<tailscale-ip>
K3S_URL=https://<tailscale-ip-hetzner>:6443
K3S_TOKEN=$(ssh root@<hetzner> "sudo cat /var/lib/rancher/k3s/server/node-token")

curl -sfL https://get.k3s.io | \
K3S_URL=$K3S_URL K3S_TOKEN=$K3S_TOKEN \
INSTALL_K3S_EXEC="--node-ip ${TS_IP_NODE}" sh -

Label nodes:

kubectl label node node-home-1 site=home topology.kubernetes.io/zone=home
kubectl label node node-site2-1 site=site2 topology.kubernetes.io/zone=site2
kubectl label node node-site3-1 site=site3 topology.kubernetes.io/zone=site3

5๏ธโƒฃ Install MetalLB at Each Site ๐ŸŽฏ

Give each site its own LAN range.

Example:

# home LAN LB range
addresses: ["192.168.10.240-192.168.10.250"]

Repeat for site2/site3.


6๏ธโƒฃ Install Longhorn ๐Ÿ„ (per site)

kubectl create ns longhorn-system
kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.6.2/deploy/longhorn.yaml

Set replicas only within that site via UI or StorageClass override.


7๏ธโƒฃ CloudNativePG Setup ๐Ÿ˜

๐Ÿก Primary at Home Site

Apply primary manifest (truncated):

spec:
  instances: 2
  storage: { size: 200Gi, storageClass: longhorn }
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: site
                operator: In
                values: ["home"]

๐Ÿš & ๐Ÿ  Replica Clusters (async)

Each replica points to home RW service and stays pinned locally.


8๏ธโƒฃ Topology-Aware Reads ๐Ÿ“

Patch read-only services:

kubectl -n data annotate svc appdb-home-ro  service.kubernetes.io/topology-mode=auto
kubectl -n data annotate svc appdb-site2-ro service.kubernetes.io/topology-mode=auto
kubectl -n data annotate svc appdb-site3-ro service.kubernetes.io/topology-mode=auto

9๏ธโƒฃ App DSNs ๐ŸŽฏ

Environment variables:

WRITE_DSN=postgres://...@appdb-home-rw...
READ_DSN=postgres://...@appdb-siteX-ro...

Your application router decides read vs write.


๐Ÿ”Ÿ Local-Only Cluster-B at Home ๐Ÿงฑ

Install k3s normally.
Optional: run your own CNPG here too.


๐ŸŽ‰ At This Point You Have:

โœ… Global multi-site k3s mesh
โœ… Local-only cluster for homelab apps
โœ… Joker DDNS for site discovery
โœ… VPN-backed private cluster network
โœ… CNPG primary + async replicas
โœ… Local read affinity
โœ… Cloud ingress + local per-site ingress


๐Ÿ’ก Tips

NeedSolution
Local-only site servicesMetalLB w/ site pools
Public HTTPSTraefik + cert-manager
Zero trustTailscale ACLs
DRPromote CNPG replica
GitOpsFlux across clusters

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.