K8s Cluster Analyze — investigační log

Záznam průzkumu osobního k8s clusteru. Pro každou oblast: použitý příkaz, klíčový výstup a okamžité pozorování.


1. Setup a verze

Příkazy

ls -la ~/.kube/
which kubectl
kubectl version --client
kubectl get nodes

Nález

  • Kubeconfig na nestandardním místě: ~/.kube/kube.yml (ne ~/.kube/config).
  • kubectl v1.35.4 (klient).
  • Cluster přístupný, vrací 3 nody Ready.

Důsledky

  • kubectl funguje (přes KUBECONFIG, alias nebo symlink).
  • Klient o ~9 minor verzí napřed před serverem — funguje díky tomu, že kubectl je obvykle backwards-compatible v širokém rozpětí, ale přesnější skew tolerance je ±1 minor; můžou se objevit drobné nekompatibility u nových API.

2. Cluster status

Příkazy

kubectl get nodes -o wide
kubectl get componentstatuses
kubectl cluster-info
kubectl top nodes

Nález

  • 3 nody (k8s-master, k8s-1, k8s-2), všechny Ready, k8s v1.26.0, Ubuntu 20.04.6, kernel 6.12.79, containerd 1.7.27.
  • Uptime nodů ~4 roky 191 dní.
  • Control plane endpoint: https://172.16.16.1:6443 (≠ InternalIP masteru 172.19.9.10) — to je WireGuard interface.
  • etcd, controller-manager: Healthy.
  • scheduler: hlášený jako Unhealthy, ale jen kvůli starému health endpoint check (port 10251 vs 10259).
  • kubectl top nodes: Metrics API not available (metrics-server nenainstalovaný).

Důsledky

  • k8s 1.26 je EOL (oficiální podpora skončila únor 2024). Žádné security patche.
  • API server schovaný za WireGuard = dobrá bezpečnostní praxe.
  • Bez metrics-server nefunguje HPA, kubectl top, sledování zátěže.
  • componentstatuses warning na schedulera je deprecated check, ne reálný problém.

3. Ingress

Příkazy

kubectl get ingressclass
kubectl get pods -A | grep -iE 'ingress|traefik|nginx|haproxy'
kubectl get ingress -A
kubectl -n ingress-nginx get svc
kubectl get ingress -A -o jsonpath='{...class-annotation...ingressClassName...}'

Nález

  • Žádný IngressClass resource neexistuje (No resources found).
  • 1× ingress-nginx-controller pod (1/1 Ready, 50 restartů za 230 dní).
  • 20 ingressů napříč 9 namespacy, všechny:
    • apiVersion: networking.k8s.io/v1 (modern)
    • kubernetes.io/ingress.class: nginx anotace (deprecated od 1.18)
    • spec.ingressClassName prázdný
  • Service ingress-nginx-controller: LoadBalancer, externí IP 37.205.11.119 (přidělená MetalLB), porty 80/443.

Důsledky

  • Funguje, protože ingress-nginx pořád respektuje deprecated anotaci jako fallback.
  • Při budoucím upgrade ingress-nginx (verze, která tu anotaci přestane podporovat) hrozí výpadek všech ingressů najednou.
  • Stačí vytvořit jeden IngressClass resource — existující ingressy budou fungovat dál.

4. Storage

Příkazy

kubectl get storageclass
kubectl get pv
kubectl get pvc -A
kubectl get pv nfs-pv -o yaml
kubectl get pods -A -o jsonpath='{...volumes...hostPath.path...nfs.server...}'

Nález

  • 1× StorageClass: example-nfs (provisioner vpsfree.cz, Reclaim Delete, AllowVolumeExpansion: false).
  • 1× PV: nfs-pv (200Mi, RWX, NFS 172.16.129.146:/nas/4721/shared).
  • 1× PVC: default/example-nfs — používaný jen testovacím podem nfs-nginx.
  • Všechny ostatní stateful workloady mají hostPath:
    • krcmar/web → /k8s/cityhry
    • nextcloud → /k8s/nextcloud
    • sellapp/uvasinu-test → /k8s/sellapp/uvasinu-test
    • openldap → /k8s/ldap/{conf,data}
    • pgadmin → /k8s/kubernetes-pgadmin
    • postgres → /k8s/kubernetes-postgresql
    • wireguard → /etc/wireguard, /var/lib/wgui

Důsledky

  • Data jsou přilepená na konkrétní node (kde je adresář). Bez nodeSelectoru hrozí, že se pod přeplánuje a data nenajde.
  • Žádné k8s-řízené zálohy. Vše musí být zálohováno na úrovni filesystému.
  • Postgres a OpenLDAP na hostPath = single point of failure pro kritická data.
  • Existující NFS infrastruktura (1 SC) je nedostatečně využívaná.

5. Síť

Příkazy

kubectl get nodes -o jsonpath='{...PodCIDR...}'
kubectl -n kube-system get pods -l app=flannel -o wide
kubectl -n kube-system get cm kube-flannel-cfg -o jsonpath='{.data.net-conf\.json}'
kubectl -n kube-system get cm kubeadm-config
kubectl -n kube-system get cm kube-proxy
kubectl -n metallb-system get cm config
kubectl get networkpolicy -A
kubectl exec ... ip route
kubectl exec ... ping ...
kubectl exec ... ip -d link show flannel.1
kubectl exec ... bridge fdb show dev flannel.1

Nález

  • CNI: Flannel, backend vxlan (VNI 1, UDP port 8472), MTU 1450.
  • Pod CIDR: 10.244.0.0/16 (per-node /24).
  • Service CIDR: 10.243.0.0/16.
  • DNS: cluster.local, kube-dns na 10.243.0.10.
  • kube-proxy: mode "" = iptables (default).
  • MetalLB: Layer2, advertizuje 37.205.11.119/32. Konfigurace přes starý ConfigMap (před v0.13 CRD-based).
  • NetworkPolicies: žádné.
  • Underlay: nody na venet0 (LXC/OpenVZ interface), segment 172.19.9.10-12.
  • Routy na masteru:
    • default přes venet0
    • 10.244.{1,2}.0/24 přes flannel.1 (VXLAN tunel)
    • 172.16.16.0/24, 192.168.0.0/24, 192.168.1.0/24 přes wg0 (WireGuard)
    • tap0/tap1 (OpenVPN)
    • docker0 (linkdown, leftover)
  • Latence:
    • master → 10.244.1.1 (pod gateway): 0.23 ms
    • master → 10.244.2.1: 0.22 ms
    • master → 172.19.9.11 (underlay): 0.15 ms
  • VXLAN FDB má korektní MAC→IP mappingy pro všechny peery.

Důsledky

  • Síť je funkční a low-latency, VXLAN overhead ~70-100 µs (zanedbatelné).
  • VXLAN je v LXC prostředí jediná rozumná volba (host-gw nelze, není kontrola nad routováním na hostu).
  • Bez NetworkPolicies = jakýkoli pod si může povídat s jakýmkoli jiným. Pro osobní cluster ok, ale citlivé namespacy (postgres, openldap) by mohly mít aspoň základní izolaci.
  • MetalLB v ConfigMap konfiguraci = velmi stará verze (před v0.13). Funguje, ale neaktualizovaná. Při upgrade k8s je třeba migrace na CRD-based config.
  • MetalLB Layer2 = single point of forwarding pro public IP (vždy přes node, který IP zrovna ARP-uje). Failover ~10s. Pro tento scale ok.