ΟΛΟΚΛΗΡΩΜΕΝΟΣ ΟΔΗΓΟΣ · ΟΚΤΩΒΡΙΟΣ 2026

Kubernetes & K3s Homelab
για Αρχάριους

Από το μηδέν στο δικό σου, production-style cluster στο σαλόνι σου: hardware, εγκατάσταση K3s, πρώτα deployments, ingress, storage, monitoring, TLS, GitOps και backups — όλα σε έναν αναλυτικό οδηγό βήμα-βήμα, με πραγματικές εντολές που δουλεύουν.

⏱️ ≈ 20 λεπτά ανάγνωσης 🎯 Επίπεδο: Αρχάριος 🛠️ Υλοποίηση: 1–2 ώρες 💸 Κόστος: από ~150€
homelab — kubectl
➜ kubectl get nodes
NAME          STATUS   ROLES           VERSION
k3s-server   Ready    control-plane   v1.30.4+k3s
k3s-agent-1  Ready    <none>          v1.30.4+k3s
k3s-agent-2  Ready    <none>          v1.30.4+k3s
➜ kubectl get pods -A
kube-system  coredns-77ccd578b-4xq2z   1/1  Running
kube-system  traefik-65bdc4c8d-k9m2f  1/1  Running
✔ Το δικό σου Kubernetes τρέχει στο σπίτι.
1Hardware→ 2OS & Δίκτυο→ 3K3s Install→ 41ο Deployment→ 5Ingress & TLS→ 6Storage→ 7Monitoring→ 8GitOps & Backups
ΕΝΟΤΗΤΑ 01

Τι είναι το Kubernetes (και γιατί να σε νοιάζει)

Το θεμέλιο: containers, orchestration και γιατί όλη η βιομηχανία «παίζει» σε αυτό.

Ας ξεκινήσουμε με τα βασικά. Μια εφαρμογή container (Docker) πακετάρει τον κώδικά σου μαζί με ό,τι χρειάζεται για να τρέξει: runtime, βιβλιοθήκες, ρυθμίσεις. Το αποτέλεσμα είναι «κουτιά» που τρέχουν όμοια παντού — στο laptop σου, σε ένα Raspberry Pi ή στο cloud. Δεν υπάρχει πια το κλασικό «αλλά σε μένα δούλευε!».

Όταν όμως έχεις πολλά containers — δεκάδες ή εκατοντάδες — εμφανίζονται σοβαρές ερωτήσεις: ποιος τα ξεκινά ξανά όταν κρασάρουν; πώς μοιράζεται η κίνηση μεταξύ τους; πώς κάνεις deploy νέα έκδοση χωρίς downtime; πώς κρύβεις τα secrets; Εδώ μπαίνει το Kubernetes (K8s): ένας orchestrator που διαχειρίζεται containers σε κλίμακα, σε οποιονδήποτε συνδυασμό μηχανών.

Φαντάσου το Kubernetes ως τον αρχισεφ μιας μεγάλης κουζίνας: εσύ του λες «θέλω 5 πιάτα μακαρονάδας» (desired state) και εκείνος φροντίζει να έχει 5 μάγειρες να τα φτιάχνουν, αντικαθιστά όποιον λιποθυμάει, μοιράζει τις παραγγελίες και κρατάει το ψυγείο γεμάτο. Εσύ απλά περιγράφεις τι θέλεις — όχι πώς θα γίνει.

💡 Λίγα ονόματα που θα δεις παντού

Pod = η μικρότερη μονάδα εκτέλεσης (1+ containers που μοιράζονται IP). Node = μία μηχανή (φυσική ή VM) που τρέχει pods. Control plane = ο «εγκέφαλος» που αποφασίζει. Deployment = περιγραφή «θέλω Ν αντίγραφα αυτού». Service = σταθερή «διεύθυνση» για pods που αλλάζουν IP συνέχεια. Ingress = η «πόρτα» από το δίκτυό σου προς τα pods.

Και γιατί να το τρέξω στο σπίτι;

Γιατί το homelab είναι από τους καλύτερους τρόπους να μάθεις πραγματικά Kubernetes — χωρίς cloud λογαριασμούς που τρέχουν «κατά λάθος» με 300€/μήνα. Στο σπίτι κάνεις τα λάθη σου δωρεάν: σπάς πράγματα, τα ξαναφτιάχνεις, και σε λίγους μήνες έχεις δεξιότητες που ζητούνται σχεδόν παντού: DevOps, SRE, backend, data engineering.

Ταυτόχρονα, ένα cluster στο σπίτι είναι και πρακτικό: τρέχει τα self-hosted apps σου (password manager, Nextcloud, Home Assistant, Pi-hole) με rolling updates, TLS, monitoring και auto-restart — σαν μικρογραφία ενός πραγματικού datacenter. Και ναι: το στυλ «κάνω restart το router και όλα ξανασηκώνονται μόνα τους» είναι από τις πιο ικανοποιητικές εμπειρίες του hobby.

ΕΝΟΤΗΤΑ 02

K3s: το Kubernetes που τρέχει και σε Raspberry Pi

Γιατί K3s και όχι «πλήρες» K8s — και τι κερδίζεις ή χάνεις πραγματικά.

Το πρόβλημα του «κανονικού» Kubernetes για οικιακή χρήση: χρειάζεται αρκετή RAM, ξεχωριστό etcd, ingress controller, CNI plugin, storage provisioner… Πρακτικά 5–6 πράγματα να εγκαταστήσεις και να συντονίσεις πριν γράψεις το πρώτο σου pod. Το K3s, φτιαγμένο από την Rancher Labs (σήμερα SUSE), λύνει ακριβώς αυτό.

Συνοπτικά: είναι ένα single binary ~70MB που με μία εντολή σου δίνει πλήρες, πιστοποιημένο Kubernetes — ίδιο API, ίδια kubectl, ίδια manifests. Τα «βαρικά» εξαρτήματα έχουν αντικατασταθεί από ελαφριές εκδόσεις και ό,τι χρειάζεσαι έρχεται bundled.

ΧαρακτηριστικόΚλασικό KubernetesK3s
ΕγκατάστασηΠολλά components, kubeadm1 binary, 1 εντολή
Ελάχ. RAM~2GB+ ανά node (πρακτικά 4GB)~512MB
Datastoreetcd clusterSQLite ενσωματωμένο (ή etcd/pgsql για HA)
IngressΤο εγκαθιστάς μόνοςTraefik bundled
LoadBalancerMetallb ή cloud LBServiceLB bundled
StorageΧρειάζεσαι provisionerlocal-path-provisioner
Runtime / CNIcontainerd + Calico/Cilium…containerd + Flannel bundled
Πιστοποίηση CNCF✔✔ πλήρως conformant
Ιδανικό γιαDatacenter / cloudHomelab, edge, IoT, ARM
✅ Το σημαντικότερο σημείο του οδηγού

Το K3s είναι certified Kubernetes distribution. Ό,τι μαθαίνεις εδώ — kubectl, YAML, Deployments, Ingress — μεταφέρεται ακριβώς και σε EKS/AKS/GKE. Δεν μαθαίνεις «κάτι αντίστοιχο», μαθαίνεις το ίδιο πράγμα.

Το τίμημα; Κάποια bundled components είναι απλούστερα από τις «μεγάλες» εναλλακτικές (π.χ. το Flannel δεν κάνει NetworkPolicies από μόνο του). Όλα όμως αντικαθίστανται αργότερα — και στο homelab αυτό σπάνια χρειάζεται.

Single binary ~70MBSQLite datastore Traefik ingressARM64 + x64 1 έως 100+ nodescontainerdkubectl 100% συμβατό
ΕΝΟΤΗΤΑ 03

Το homelab σου: επιλογή hardware

Δεν χρειάζεσαι server rack. Χρειάζεσαι κάτι φθηνό, αθόρυβο και οικονομικό σε ρεύμα.

Ο χρυσός κανόνας για αρχή: ξεκίνα με ένα (1) δυνατό node και μεγάλωσε αργότερα. Με το K3s, το server node μπορεί να τρέχει και workloads — ένα cluster ενός node είναι πλήρως λειτουργικό. Προσθέτεις agents όποτε θες, με μηδενική ανακατασκευή.

ΕπιλογήΚόστοςRAMΡεύμαΑξιολόγηση
Mini PC x64 (Intel N100: Beelink, GMKtec)~150–200€8–16GB6–15W★★★★★ Η καλύτερη επιλογή — NVMe, αθόρυβο, γρήγορο
Μεταχειρισμένο SFF (Dell OptiPlex, Lenovo ThinkCentre)~100–180€16–32GB15–40W★★★★☆ Τεράστια αναβαθμισιμότητα, λίγο πιο θορυβώδες
Raspberry Pi 5 (8GB)~120€8GB5–10W★★★☆☆ Ωραίο για cluster 3×Pi, αλλά ARM images + αποθήκευση = περιπλοκές
Παλιό laptop0€8–16GB5–20W★★★☆☆ Δωρεάν + builtin «UPS» η μπαταρία, αλλά θόρυβος/ήδη παλιό
Μεταχειρισμένος rack server (R720, DL380)~200€+64GB+100–200W★☆☆☆☆ Αθόρυβο σαν τρακτέρ, λογαριασμός ρεύματος διπλασιάζεται
🎯 Η προτεινόμενη «συνταγή»

Ένα mini PC με Intel N100, 16GB RAM, 512GB NVMe (~180€). Τρέχει άνετα K3s, 15–20 pods, Prometheus, Grafana, Argo CD. Αργότερα προσθέτεις 2 Raspberry Pi ως agents (~80€) για να δεις replicas να μετακινούνται μεταξύ nodes — η «κανονική» cluster εμπειρία.

Λεπτομέρειες που μετράνε

  • Αποθήκευση: σε Raspberry Pi απόφυγε SD cards — χαλάουν σε μήνες υπό φόρτο. Πάρε USB-SSD. Σε x64, ένα NVMe 512GB είναι ιδανικό.
  • Δίκτυο: ενσύρματο ethernet, πάντα. WiFi σε cluster node είναι συνταγή για ακατανόητα timeouts. Κράτα σταθερή IP (DHCP reservation στον router είναι το πιο απλό).
  • Ρεύμα: 15W 24/7 ≈ ~11 kWh/μήνα ≈ 2–4€/μήνα. Ο λογαριασμός δεν θα σε πτοήσει.
  • Θερμοκρασία: καλή αερισμένη θέση, όχι σε κλειστό συρτάρι. Τα mini PCs σχεδιάζονται για 24/7 λειτουργία, αλλά ο θόρυβος των ανεμιστήρων ανεβαίνει με τη θερμότητα.
ΕΝΟΤΗΤΑ 04

Αρχιτεκτονική: πώς μοιάζει ένα K3s cluster

Μία εικόνα που αξίζει 1000 λέξεις — τι τρέχει σε κάθε node.

💻 Εσύ kubectl / browser HTTPS :6443 Server Node — Control Plane το «μυαλό» του cluster kube-apiserver scheduler controller-mgr Traefik ingress CoreDNS kubelet+containerd Pods (workloads) pod A pod B pod C SQLite datastore (κατάσταση cluster) /var/lib/rancher/k3s Agent Node 1 kubelet+containerd flannel (VXLAN) pod D pod E pod F STATUS: Ready Agent Node 2 kubelet+containerd flannel (VXLAN) pod G pod H pod I STATUS: Ready 8472 10250
Εικ. 1 — Το server κρατά την κατάσταση και αποφασίζει· οι agents απλά τρέχουν pods. Σε cluster 1 node, τα πάντα ζουν μαζί.
  • Server node: εκτελεί το control plane (apiserver, scheduler, controllers) και τη βάση SQLite. Δέχεται τις εντολές σου από το kubectl στο port 6443.
  • Agent nodes: δεν «σκέφτονται» — λαμβάνουν οδηγίες, τρέχουν pods και αναφέρουν πίσω. Αν πέσει ένας agent, το control plane επαναλαμβάνει τα pods του σε άλλους.
  • kubelet + containerd: σε κάθε node: ο τοπικός «μαître» που κατεβάζει images και σηκώνει containers.
  • Flannel/VXLAN: δημιουργεί ένα εικονικό δίκτυο, ώστε τα pods σε διαφορετικά nodes να «βλέπονται» σαν να είναι στο ίδιο LAN (port 8472/udp).
ℹ️ Πόσα nodes;

Για μάθηση: 1 node αρκεί. Για «πραγματική» εμπειρία (failover, μετακινήσεις): 1 server + 2 agents. Για HA του control plane (production pattern): 3 server nodes με embedded etcd — καλύτερα αργότερα, όχι στην πρώτη εβδομάδα.

ΕΝΟΤΗΤΑ 05

Προετοιμάζουμε το Ubuntu Server

Το «θεμέλιο» του node σου: OS, σταθερή IP, SSH. 15 λεπτά δουλειάς.

Προτείνω Ubuntu Server 24.04 LTS (ή Debian 12 — εξίσου άριστο). Χωρίς desktop environment: 512MB RAM λιγότερα, λιγότερες ενημερώσεις, λιγότερα unexpected popups. Κατέβασε το ISO και φτιάξε USB με το Balena Etcher ή Rufus (σε Raspberry Pi: Raspberry Pi Imager, επιλέγοντας «Ubuntu Server 24.04»).

Κατά την εγκατάσταση: δημιούργησε user (π.χ. lab), enable SSH, και όρισε να κάνει install τα openssh/openvpn δωρεάν extras. Μετά το reboot, συνδέσου από τον υπολογιστή σου:

terminal — στον υπολογιστή σου⧉Αντιγραφή
ssh [email protected]

# Πρώτα πράγματα μετά την πρώτη σύνδεση
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl jq htop git

# Όρισε ξεκάθαρο hostname — θα το βλέπεις παντού
sudo hostnamectl set-hostname k3s-server

Σταθερή IP με netplan

Το cluster σου πρέπει να «ξέρει» πού ζει το server. Αν το router σου κάνει DHCP reservation, τέλειο — τέλος. Διαφορετικά, βάλε στατική IP στο Ubuntu:

/etc/netplan/01-static.yaml — στο server⧉Αντιγραφή
network:
  ethernets:
    eth0:
      addresses: [192.168.1.100/24]
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses: [1.1.1.1, 9.9.9.9]
  version: 2
terminal⧉Αντιγραφή
sudo netplan apply
ip a show eth0   # επιβεβαίωσε την IP

# SSH keys — να μη γράφεις κωδικό συνέχεια
ssh-keygen -t ed25519
ssh-copy-id [email protected]
⚠️ Disable swap (σε x64)

Το kubelet δεν θέλει swap. Το Ubuntu Server το έχει off by default, αλλά έλεγξέ το — αν υπάρχει:

terminal⧉Αντιγραφή
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
free -h   # swap πρέπει να δείχνει 0B
ΕΝΟΤΗΤΑ 06

Εγκατάσταση K3s server — η φημισμένη μία εντολή

60 δευτερόλεπτα. Πραγματικά. Αυτό είναι το σημείο που θα χαμογελάσεις.

Στο server node, σαν απλός χρήστης με sudo:

terminal — server node⧉Αντιγραφή
curl -sfL https://get.k3s.io | sh -s - --write-kubeconfig-mode 644
#        └── installer   └─ flags: kubeconfig με mode 644
# (η 644 είναι ok για homelab· σε shared υπολογιστή κράτα το default 600)

Τι μόλις έγινε; Κατέβηκε το binary k3s (μέσα σε λίγα δευτερόλεπτα), δημιουργήθηκε systemd service k3s.service, ξεκίνησε το control plane με SQLite datastore, και «φύτευτηκαν» αυτόματα: Traefik, CoreDNS, ServiceLB, local-path storage. Χωρίς κανένα extra βήμα.

terminal — επιβεβαίωση⧉Αντιγραφή
sudo kubectl get nodes
NAME        STATUS   ROLES           VERSION
k3s-server  Ready    control-plane   v1.30.4+k3s

kubectl get pods -A
NAMESPACE     NAME                    READY  STATUS
kube-system   coredns-77ccd...4xq2z   1/1    Running
kube-system   traefik-65bdc...k9m2f   1/1    Running
kube-system   local-path-provisioner  1/1    Running

Βλέπεις Ready; Έχεις Kubernetes. Τόσο απλά. Το kubeconfig ζει στο /etc/rancher/k3s/k3s.yaml — για να δουλεύει το kubectl χωρίς sudo:

terminal⧉Αντιγραφή
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER ~/.kube/config
export KUBECONFIG=~/.kube/config   # βάλ' το και στο ~/.bashrc

Σημαντικό: το node token

Θα το χρειαστείς για να «καλέσεις» agents στο cluster (κράτα το μυστικό — είναι ο admin κλειδί)

terminal⧉Αντιγραφή
sudo cat /var/lib/rancher/k3s/server/node-token
# K10...HASH...::server:LONG-STRING-HERE   ← copy αυτό
⚙️ Χρήσιμα flags (προαιρετικά)

--tls-san=192.168.1.100 (αν θες kubectl από άλλο PC), --disable=traefik (αν προτιμάς ingress-nginx), --node-ip=192.168.1.100. Σύνταξη: curl -sfL https://get.k3s.io | sh -s - --tls-san=192.168.1.100. Πλήρης λίστα: k3s server --help.

ΕΝΟΤΗΤΑ 07

Προσθέτουμε agents — το cluster μεγαλώνει

Δεύτερο/τρίτο Raspberry Pi ή PC; Εντάξου: μία εντολή.

Σε κάθε επιπλέον μηχανή (πρόσεξε: πρέπει να «βλέπει» το server στο δίκτυο και να έχει την ίδια αρχιτεκτονική ή συμβατά images):

terminal — στον agent⧉Αντιγραφή
curl -sfL https://get.k3s.io | \
  K3S_URL=https://192.168.1.100:6443 \
  K3S_TOKEN=K10xxxx... \
  sh -

Πίσω στο server, σε λίγα δευτερόλεπτα:

terminal — server⧉Αντιγραφή
kubectl get nodes
NAME         STATUS   ROLES           VERSION
k3s-server   Ready    control-plane   v1.30.4+k3s
k3s-agent-1  Ready    <none>          v1.30.4+k3s
k3s-agent-2  Ready    <none>          v1.30.4+k3s
🔌 Firewall: αυτά τα ports πρέπει να είναι ανοιχτά

Αν έχεις ufw/firewalld ενεργό, δώσε στα agents πρόσβαση στο server: 6443/tcp (API), 8472/udp (Flannel VXLAN), 10250/tcp (kubelet). Αν κάποιος agent κολλάει στο NotReady, το 90% των φορών φταίει δίκτυο/firewall.

ΕΝΟΤΗΤΑ 08

kubectl: τα πρώτα σου παιχνίδια

Τα 8 commands που θα πληκτρολογείς 100 φορές την εβδομάδα.

Το kubectl είναι το «τηλεκοντρόλ» του cluster. Δουλεύει με pattern kubectl <ρήμα> <αντικείμενο>. Δοκίμασε τα παρακάω με τη σειρά — δεν σπάς τίποτα:

terminal⧉Αντιγραφή
kubectl get nodes -o wide        # nodes + IPs + versions
kubectl get pods -A              # όλα τα pods, όλα τα namespaces
kubectl get pods -A -w           # live παρακολούθηση (Ctrl+C για έξοδο)
kubectl get ns                   # namespaces
kubectl top nodes                # CPU/RAM ανά node (με metrics-server)
kubectl describe pod <name>      # το «ιατρικό φάκελο» ενός pod
kubectl logs -f <pod>             # logs του pod, -f = follow
kubectl api-resources | head     # τι είδους objects υπάρχουν
🗂️ Namespaces σε μία πρόταση

Είναι «φακέλοι» που οργανώνουν resources. Π.χ. kube-system = τα system pods, monitoring = Prometheus/Grafana, media = Jellyfin. Το flag -n <ns> στοχεύει συγκεκριμένο namespace· το -A σημαίνει «όλους».

ΕΝΟΤΗΤΑ 09

Το πρώτο σου deployment (YAML 101)

Το κείμενο που θα γράφεις χιλιάδες φορές: 3 αντικείμενα σε ένα αρχείο.

Στο Kubernetes όλα είναι YAML: περιγράφεις την επιθυμητή κατάσταση και το cluster την πραγματοποιεί — και τη διατηρεί για πάντα. Φτιάξε τον φάκελο σου και το πρώτο σου αρχείο:

my-first-app.yaml⧉Αντιγραφή
apiVersion: v1
kind: ConfigMap
metadata:
  name: web-html
data:
  index.html: |
    <h1>Γεια σου από το δικό μου Kubernetes! 🚀</h1>
    <p>Αυτό το pod τρέχει σε {{NODE_NAME}} με IP {{POD_IP}}</p>
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-web
  labels: {app: my-web}
spec:
  replicas: 2
  selector: {matchLabels: {app: my-web}}
  template:
    metadata: {labels: {app: my-web}}
    spec:
      containers:
        - name: web
          image: nginx:1.27-alpine
          ports: [{containerPort: 80}]
          volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
      volumes:
        - name: html
          configMap: {name: web-html}
---
apiVersion: v1
kind: Service
metadata:
  name: my-web-svc
spec:
  type: ClusterIP
  selector: {app: my-web}
  ports: [{port: 80, targetPort: 80}]

Δες τι περιέχει: ένα ConfigMap (το static HTML), ένα Deployment (2 replicas nginx που κάνουν mount το HTML) κι ένα Service (η «διεύθυνση» που σταθερά δείχνει στα 2 pods, όσο κι αν αυτά αναδημιουργούνται). Το --- χωρίζει αντικείμενα στο ίδιο αρχείο.

terminal⧉Αντιγραφή
kubectl apply -f my-first-app.yaml
configmap/web-html created
deployment.apps/my-web created
service/my-web-svc created

kubectl get pods -l app=my-web
NAME                    READY   STATUS    RESTARTS
my-web-7f8b9c6d5-abcde   1/1     Running   0
my-web-7f8b9c6d5-fghij   1/1     Running   0

# Δοκιμή από το εσωτερικό του cluster
kubectl run tmp --rm -it --image=curlimages/curl -- \
  curl -s http://my-web-svc
Γεια σου από το δικό μου Kubernetes! 🚀

Μαγικά πειράματα (κάνε τα!)

terminal⧉Αντιγραφή
# 1) Scale σε 5 replicas — σε 2 δευτερόλεπτα
kubectl scale deployment my-web --replicas=5

# 2) Σκότωσε ένα pod — δες το να ξανασηκώνεται μόνο του
kubectl delete pod my-web-7f8b9c6d5-abcde
kubectl get pods -w

# 3) Rolling update σε νέα έκδοση image, μηδέν downtime
kubectl set image deployment/my-web web=nginx:1.28-alpine
kubectl rollout status deployment/my-web

# 4) Αν κάτι πήγε στραβά: γύρνα πίσω
kubectl rollout undo deployment/my-web
🧠 Η «αχα» στιγμή

Το #2 είναι η ουσία του Kubernetes: σκότωσες» ένα pod και δεν έγινε τίποτα — ένα άλλο εμφανίστηκε στη θέση του αυτόματα, και το Service συνέχισε να δείχνει σωστά. Αυτή η αυτό-ίαση (self-healing) είναι όλο το «μάγκικο» — και την έχεις ήδη δουλέψει.

ΕΝΟΤΗΤΑ 10

Ingress: πραγματικά ονόματα και TLS

Από το http://192.168.1.100:31234 στο https://myweb.homelab.local — με κλειδαριά.

Μέχρι τώρα «χτυπούσες» τις εφαρμογές σου με IP και πόρτα. Ο Ingress αλλάζει το παιχνίδι: ένας κανόνας λέει στον Traefik (που ήδη τρέχει από το K3s) «ό,τι φτάνει με hostname myweb.homelab.local → πήγαινέ το στο service my-web-svc». Δεκάδες εφαρμογές, όλες στις πόρτες 80/443, με καθαρά ονόματα — μία μόνο «πόρτα» προς τα έξω.

Βήμα 1 — DNS: δώσε ονόματα στις εφαρμογές

  • Σε 10 δευτερόλεπτα: πρόσθεσε στο /etc/hosts του PC σου (Windows: C:\Windows\System32\drivers\etc\hosts) τη γραμμή 192.168.1.100 myweb.homelab.local — δουλεύει μόνο για εκείνη τη συσκευή.
  • Για όλο το σπίτι: με Pi-hole ή AdGuard Home φτιάχνεις DNS record *.homelab.local → 192.168.1.100. Κάθε συσκευή, κάθε app, αυτόματα.
  • Για αληθινό TLS από το internet: πάρε δωρεάν domain στο duckdns.org (π.χ. mylab.duckdns.org) — μόνο με δημόσιο domain βγάζεις πιστοποιητικά Let's Encrypt.

Βήμα 2 — το πρώτο σου Ingress

my-web-ingress.yaml⧉Αντιγραφή
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-web
spec:
  ingressClassName: traefik
  rules:
    - host: myweb.homelab.local
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-web-svc
                port: {number: 80}
terminal⧉Αντιγραφή
kubectl apply -f my-web-ingress.yaml
# Άνοιξε στον browser: http://myweb.homelab.local  ✔

Βήμα 3 — TLS με cert-manager + Let's Encrypt

terminal⧉Αντιγραφή
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/latest/download/cert-manager.yaml
kubectl -n cert-manager get pods   # περίμενε να δεις 3/3 Running
issuer.yaml⧉Αντιγραφή
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: [email protected]
    privateKeySecretRef: {name: letsencrypt-key}
    solvers:
      - http01:
          ingress: {ingressClassName: traefik}

Τέλος, στο Ingress πρόσθεσε annotation και ενότητα tls (και άλλαξε το host στο δημόσιο domain σου):

προσθήκες στο ingress⧉Αντιγραφή
metadata:
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt
spec:
  tls:
    - hosts: [myweb.mylab.duckdns.org]
      secretName: my-web-tls
ℹ️ Πότε δουλεύει το http01

Ο έλεγχος http01 απαιτεί ο Let's Encrypt να «χτυπήσει» το http://mylab.duckdns.org/.well-known/acme-challenge/… — δηλαδή ο router σου πρέπει να κάνει port-forward της 80 (και της 443) στο 192.168.1.100. Αν δεν θες καθόλου port-forward, χρησιμοποίησε DNS-01 με DuckDNS token: φτιάξε solver dns01: {providers: [{duckdns: {token: ...}}]} και βγάλε wildcard certificate *.mylab.duckdns.org για όλες τις εφαρμογές με ένα πιστοποιητικό.

Δώσε kubectl apply ξανά και σε 30–60 δευτερόλεπτα ο cert-manager έχει βγάλει πιστοποιητικό — δωρεάν, αυτόματο, ανανεούμενο για πάντα. Το lockaki στον browser σου από hardcoded IP:port γίνεται πράγμα.

ΕΝΟΤΗΤΑ 11

Storage: όταν τα δεδομένα θέλουν να μείνουν

Pods έρχονται και φεύγουν. Τα αρχεία σου όχι — αν τα ζητήσεις σωστά.

Προεπιλογή στο Kubernetes: ό,τι γράψει ένα container στο filesystem του χάνεται όταν το pod ξαναδημιουργηθεί. Λογικό για stateless apps, καταστροφικό για βάσεις δεδομένων. Η λύση: PersistentVolumeClaim (PVC) — «ζητάω 2GB αποθήκευσης» — και το K3s, χάρη στον bundled local-path-provisioner, την ικανοποιεί αμέσως φτιάχνοντας φάκελο στο δίσκο του node.

Pod volumeMount: /data stateful app (π.χ. DB) claim PVC storage: 2Gi class: local-path bind PersistentVolume φτιάχνεται αυτόματα από local-path-provisioner 💾 Node /var/lib/ rancher/k3s/ storage/
Εικ. 2 — Το pod «δανείζεται» χώρο μέσω PVC· τα δεδομένα ζουν στον δίσκο του node, εκτός κύκλου ζωής του pod.

Το δοκιμάζουμε

data-pvc.yaml⧉Αντιγραφή
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-pvc
spec:
  accessModes: [ReadWriteOnce]
  storageClassName: local-path
  resources:
    requests: {storage: 2Gi}
σε κάθε deployment που θέλει δεδομένα⧉Αντιγραφή
# μέσα στο spec.template.spec:
      containers:
        - name: app
          volumeMounts:
            - name: data
              mountPath: /data
      volumes:
        - name: data
          persistentVolumeClaim: {claimName: data-pvc}
terminal — η απόδειξη⧉Αντιγραφή
kubectl apply -f data-pvc.yaml
kubectl get pvc
NAME      STATUS   VOLUME  CAPACITY  STORAGECLASS
data-pvc  Bound    pvc-x   2Gi       local-path

# Γράψε ένα αρχείο μέσα
kubectl exec deploy/my-web -- sh -c 'echo "ζω!" > /data/test.txt'

# Σκότωσε το pod — και δες το αρχείο να επιβιώνει
kubectl delete pod -l app=my-web
kubectl exec deploy/my-web -- cat /data/test.txt
ζω!
⚠️ Το όριο του local-path

Ο όγκος «δένεται» με τον συγκεκριμένο node που τον δημιούργησε. Αν το pod μετακινηθεί σε άλλο node (multi-node cluster), δεν θα βρει τα δεδομένα του. Για πραγματική πολυ-νομική αποθήκευση με replication και snapshots, το επόμενο βήμα είναι το Longhorn (ένα Helm install — άφησέ το για όταν νιώσεις άνετα με τα βασικά).

ΕΝΟΤΗΤΑ 12

Monitoring: Prometheus + Grafana σε 5 λεπτά

Γράφητα CPU/RAM, alerts, και το «γιατί είναι αργό το Pi μου;» — με απαντήσεις.

Καλή είδηση πρώτα: το K3s φέρνει bundled το metrics-server, οπότε το kubectl top nodes και kubectl top pods δουλεύουν ήδη. Για πλήρη εικόνα (ιστορικά, γραφήματα, dashboards) το standard είναι ο συνδυασμός Prometheus + Grafana — και εγκαθίστανται με Helm, τον package manager του Kubernetes, σε μία εντολή.

terminal⧉Αντιγραφή
# 1) Helm — αν δεν το έχεις ήδη
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# 2) Το "kube-prometheus-stack": Prometheus + Grafana + Alertmanager
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack \
  -n monitoring --create-namespace \
  --set grafana.adminPassword='admin123' \
  --set grafana.persistence.size=2Gi
terminal — άνοιγμα του Grafana⧉Αντιγραφή
kubectl -n monitoring port-forward svc/monitoring-grafana 3000:80
# Browser: http://localhost:3000 — user: admin / admin123

Μέσα θα βρεις έτοιμα dashboards (π.χ. Kubernetes / Compute Resources / Nodes) που δείχνουν τα πάντα: CPU, RAM, δίσκο, πόσα pods τρέχουν, ακόμα και πότε το node «πνίγηκε». Δοκίμασε να αφήσεις ένα kubectl top pods -A δίπλα σε ένα Grafana dashboard — ξαφνικά το cluster σου παύει να είναι μαύρο κουτί.

📉 Πόσο «τρώει» το monitoring;

Το kube-prometheus-stack θέλει άνετα ~1GB RAM συνολικά. Σε mini PC 16GB: μηδέν πρόβλημα. Σε Pi 4GB με πολλά apps: προτίμησε το ελαφρύ PathFinder/uptime scripts ή άφησέ το Monitoring να μπει αργότερα — το cluster δεν «κρυώνει» χωρίς αυτό.

ΕΝΟΤΗΤΑ 13

GitOps με Argo CD: το Git γίνεται το αφεντικό

Σταματάς να «τρέχεις» deployments με το χέρι — τα βγάζεις από ένα repository.

Η ιδέα του GitOps είναι απλή αλλά αλλάζει τα πάντα: όλα τα YAML σου ζουν σε ένα Git repository (π.χ. GitHub, Gitea στο σπίτι σου). Μία εφαρμογή — εδώ το Argo CD — παρακολουθεί το repo και κάνει το cluster να «ταιριάζει» με ό,τι γράφεις εκεί. Κάνεις git push, το deploy γίνεται μόνο του. Σβήνεις ένα YAML, η εφαρμογή φεύγει. Ολόκληρο ιστορικό αλλαγών, undo = git revert.

terminal — εγκατάσταση Argo CD⧉Αντιγραφή
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
kubectl -n argocd get pods   # περίμενε Running

# Πρόσβαση στο UI
kubectl -n argocd port-forward svc/argocd-server 8080:443
# Browser: https://localhost:8080

# Ο αρχικός κωδικός admin
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d; echo

Στο UI (user: admin + τον κωδικό που βγήκε) κάνεις New App, δίνεις το repo σου (π.χ. https://github.com/<user>/homelab), path ., destination default namespace, και επιλέγεις Auto-Sync. Από εδώ και πέρα: κάθε git push που αλλάζει τα YAML σου εμφανίζεται στο cluster μέσα σε δευτερόλεπτα, και το Argo CD δείχνει με χρώματα τι ταιριάζει και τι όχι.

🚀 Πρώτο βήμα اليوم

Ανέβασε τα my-first-app.yaml και my-web-ingress.yaml σε ένα private GitHub repo και συνάρτησέ τα με το Argo CD. Από εκεί και πέρα, το homelab σου έχει «source of truth» — και το rebuild σε νέα μηχανή γίνεται: install K3s + Argo CD + «sync». Πέντε λεπτά, ολόκληρο σύστημα.

ΕΝΟΤΗΤΑ 14

Backups: γιατί «θα το κοιτάξω αύριο» είναι λάθος

Τρία επίπεδα προστασίας, από το απλό στο επαγγελματικό.

Σε ένα cluster, τα «τιμημένα» σου είναι δύο: τα manifests (πώς είναι φτιαγμένο το σύστημα) και τα δεδομένα (PVCs, βάσεις). Οι τακτικές:

  • Επίπεδο 1 — Git: όλα τα manifests σε repo (κάνεις το GitOps της προηγούμενης ενότητας και το έχεις ήδη). Με GitOps, ο κόπος rebuild ενός cluster είναι 15 λεπτά.
  • Επίπεδο 2 — Snapshot της κατάστασης: το K3s κρατά την κατάσταση του cluster στο /var/lib/rancher/k3s/server/db — ένα νυχτερινό backup αυτού του φακέλου (και του storage/ για τα PVC) σε εξωτερικό δίσκο/NAS σε καλύπτει πλήρως.
  • Επίπεδο 3 — Velero / Longhorn: εργαλεία για backup όλου του cluster + volumes (σε S3/MinIO, με snapshots). Φέρνοντάς τα όταν το homelab γίνει «σοβαρό» infrastructure.
backup-k3s.sh — cron script⧉Αντιγραφή
#!/bin/bash
# Νυχτερινό backup σε NAS/εξωτερικό δίσκο (mount ως /mnt/backup)
BACKUP=/mnt/backup
sudo tar czf $BACKUP/k3s-$(date +%F).tgz \
  /var/lib/rancher/k3s/server/db \
  /var/lib/rancher/k3s/storage

# Κράτα 14 μέρες — σβήνε τα παλιά
find $BACKUP -name 'k3s-*.tgz' -mtime +14 -delete
terminal — προγραμματισμός⧉Αντιγραφή
chmod +x backup-k3s.sh
crontab -e
# πρόσθεσε τη γραμμή (κάθε βράδυ 03:00):
# 0 3 * * * /home/lab/backup-k3s.sh
🧨 Ο χρυσός κανόνας των backups

Backup που δεν έχεις δοκιμάσει να επαναφέρεις δεν είναι backup — είναι ελπίδα. Μία φορά τον μήνα: σβήσε επίτηδες κάτι (π.χ. ένα ConfigMap), κάνε restore, επιβεβαίωσε. Αν θες να παίξεις «από το μηδέν» σε νέα μηχανή: fresh K3s + kubectl apply από το Git σου — καλύτερο test από όλα.

ΕΝΟΤΗΤΑ 15

Troubleshooting: τα 6 λάθη που WILL κάνεις

Καμία παγίδα δεν σε περιμένει — μαθαίνεις να τις αναγνωρίζεις σε 5 δευτερόλεπτα.

ΣύμπτωμαΤι συνήθως σημαίνειΗ εντολή-κλειδί
ImagePullBackOffΛάθος όνομα image, χωρίς internet, ή x64 image σε ARM nodekubectl describe pod
CrashLoopBackOffΗ εφαρμογή μέσα κρασάρει (missing env, λάθος config)kubectl logs --previous
PendingΔεν χωράει στον node, ή PVC που δεν γίνεται Boundkubectl describe pod ( Events)
Node NotReadyK3s service κάτω, ή μπλοκαρισμένα ports firewall (8472/udp)journalctl -u k3s -f στον node
Ingress → 404Λάθος service name/port στο ingress, ή λάθος host στο DNSkubectl get ingress
kubectl → connection refusedΛάθος IP στο kubeconfig, ή σβηστό k3s serversudo systemctl status k3s

Η γενική μέθοδος πάντα ίδια: kubectl get pods -A → βρες τον «άρρωστο» → kubectl describe (διάβασε τα Events στο τέλος — εκεί γράφεται σχεδόν πάντα η απάντηση) → kubectl logs. Και μην ξεχνάς τα logs του ίδιου του K3s: journalctl -u k3s -f --lines=50.

🩺 Bonus: k9s

Το k9s είναι ένα terminal UI για kubectl — βλέπεις pods/services/logs σε πραγματικό χρόνο, χωρίς να γράφεις εντολές. Εγκατάσταση ενός binary, ανοίγεις και γράφεις : + όνομα resource. Από τα εργαλεία που μόλις το δοκιμάσεις, δεν γυρνάς πίσω.

ΕΝΟΤΗΤΑ 16

Cheat Sheet: οι εντολές της καθημερινότητας

Αποθήκευσε αυτή την ενότητα — θα την ανοίγεις συνέχεια.

🖥️ Nodes
kubectl get nodes -o wideόλα τα nodes με IPs
kubectl top nodesCPU / RAM ανά node
kubectl drain <node> --ignore-daemonsetsαδειάζω node για service
📦 Pods
kubectl get pods -A -wόλα, live ενημέρωση
kubectl get pods -n monitoringσε συγκεκριμένο namespace
kubectl delete pod <name>σκότωσέ το — θα ξαναρθεί
🔬 Debug
kubectl describe pod <name>ιατρικός φάκελος — δες Events
kubectl logs -f <pod>logs σε πραγματικό χρόνο
kubectl exec -it <pod> -- shμπαίνω μέσα στο pod
🚀 Rollouts
kubectl rollout status deploy/<d>παρακολούθηση deploy
kubectl rollout undo deploy/<d>γύρνα πίσω την έκδοση
kubectl scale deploy <d> --replicas=5άμεσο scale
💾 Storage & Secrets
kubectl get pvc,pvόγκοι: claims και volumes
kubectl get secretsτα (κρυφά) δεδομένα
kubectl describe ingressοι κανόνες routing
🧹 Καθάρισμα
kubectl delete -f app.yamlσβήνω ό,τι έφτιαξα
kubectl delete ns testingσβήνω ολόκληρο namespace
journalctl -u k3s -flogs του ίδιου του k3s
ΕΝΟΤΗΤΑ 17

Επόμενα βήματα: το homelab μεγαλώνει

Έχεις ζωντανό cluster, ingress, TLS, monitoring και GitOps. Πού πας από εδώ;

  1. Self-hosted apps: πέρνα πραγματικά apps — Vaultwarden (passwords), Pi-hole/AdGuard (DNS για όλο το σπίτι), Home Assistant, Nextcloud, Jellyfin. Κάθε ένα = ένα YAML + ένα ingress.
  2. Longhorn: κατανεμημένο storage με replication — τα PVC σου επιβιώνουν και σε πτώση node.
  3. MetallB: αν θες «πραγματικές» LoadBalancer IPs στο LAN σου αντί για port-forwards.
  4. Flux CD: η εναλλακτική του Argo CD — πιο «engineer-y», με Kustomize/Helm native.
  5. Renovate / pinning: αυτόματες PRs όταν βγαίνουν νέες εκδόσεις images — giữει τα apps σου φρέσκα.
  6. 3ος node + HA: τρία server nodes με embedded etcd — το control plane επιβιώνει και από πτώση μηχανής.
  7. Πειραματίσου ανεμελιά: το ωραίο του homelab είναι ότι τίποτα δεν είναι production. Σπάσε το, ξαναφτιάξ' το, μάθε.
🏁 Το κοντινότερο « missions» σου

1) Ανέβασε το repo σου στο GitHub και συνάρτησε το Argo CD. 2) Βγάλε wildcard TLS για το *.homelab.local ή DuckDNS σου. 3) Φτιάξε ένα dashboard (Grafana ή Homepage) που δείχνει όλα τα apps σου. Μετά από αυτά, δεν είσαι πια «αρχάριος» — είσαι homelabber με προσωπικό cluster. 🎉

FAQ

Συχνές ερωτήσεις

Οι απαντήσεις που ψάχνουν όλοι πριν στήσουν K3s.

Τι hardware χρειάζομαι για K3s homelab;

Ένα Raspberry Pi αρκεί για αρχή. Για σοβαρό cluster, x86 mini PC ή παλιό laptop με 8GB+ RAM.

K3s ή κανονικό Kubernetes;

K3s: ελαφρύ single-binary Kubernetes, ιδανικό για homelab και edge. Το κανονικό Kubernetes θέλει περισσότερους πόρους και συντήρηση.

Πώς παίρνω backup στο K3s;

Velero για cluster resources, snapshots για volumes (Longhorn), και GitOps repo ως source of truth για όλα τα manifests.

Πώς βρίσκω τι φταίει όταν πέφτει pod;

kubectl logs/describe για άμεση εικόνα, Prometheus/Grafana για τάσεις και alerts.