From e5e8efbb0c71ea7aa8de25d95bc3f73d5c2f0d81 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sat, 5 Jul 2025 21:21:36 +0300 Subject: more on this --- ...RAFT-f3s-kubernetes-with-freebsd-part-6.gmi.tpl | 247 +++++++++++++++++++-- 1 file changed, 232 insertions(+), 15 deletions(-) diff --git a/gemfeed/DRAFT-f3s-kubernetes-with-freebsd-part-6.gmi.tpl b/gemfeed/DRAFT-f3s-kubernetes-with-freebsd-part-6.gmi.tpl index 55ba2bff..e667195f 100644 --- a/gemfeed/DRAFT-f3s-kubernetes-with-freebsd-part-6.gmi.tpl +++ b/gemfeed/DRAFT-f3s-kubernetes-with-freebsd-part-6.gmi.tpl @@ -12,14 +12,40 @@ This is the sixth blog post about the f3s series for self-hosting demands in a h ## Introduction -In this blog post, we are going to extend the Beelinks with some additional storage. +In the previous posts, we set up a FreeBSD-based Kubernetes cluster using k3s. While the base system works well, Kubernetes workloads often require persistent storage for databases, configuration files, and application data. Local storage on each node has significant limitations: -Some photos here, describe why there are 2 different models of SSD drives (replication etc) +- **No data sharing**: Pods on different nodes can't access the same data +- **Pod mobility**: If a pod moves to another node, it loses access to its data +- **No redundancy**: Hardware failure means data loss +- **Limited capacity**: Individual nodes have finite storage + +This post implements a robust storage solution using: +- **ZFS**: For data integrity, encryption, and efficient snapshots +- **CARP**: For high availability with automatic IP failover +- **NFS over stunnel**: For secure, encrypted network storage +- **zrepl**: For continuous replication between nodes + +The end result is a highly available, encrypted storage system that survives node failures while providing shared storage to all Kubernetes pods. We're using two different SSD models (Samsung 870 EVO and Crucial BX500) to avoid simultaneous failures from the same manufacturing batch. ## ZFS encryption keys +ZFS native encryption requires encryption keys to unlock datasets. We need a secure method to store these keys that balances security with operational needs: + +- **Security**: Keys must not be stored on the same disks they encrypt +- **Availability**: Keys must be available at boot for automatic mounting +- **Portability**: Keys should be easily moved between systems for recovery + +Using USB flash drives as hardware key storage provides an elegant solution. The encrypted data is unreadable without physical access to the USB key, protecting against disk theft or improper disposal. In production environments, you might use enterprise key management systems, but for a home lab, USB keys offer good security with minimal complexity. + ### UFS on USB keys +We'll format the USB drives with UFS (Unix File System) rather than ZFS for several reasons: + +- **Simplicity**: UFS has less overhead for small, removable media +- **Reliability**: No ZFS pool import/export issues with removable devices +- **Compatibility**: UFS is universally supported across BSD systems +- **Fast mounting**: No pool discovery or feature flag checking + ``` paul@f0:/ % doas camcontrol devlist <512GB SSD D910R170> at scbus0 target 0 lun 0 (pass0,ada0) @@ -150,19 +176,48 @@ zroot/bhyve/rocky encryptionroot zroot/bhyve - zroot/bhyve/rocky keystatus available - ``` -## CARP +## CARP (Common Address Redundancy Protocol) + +High availability is crucial for storage systems. If the NFS server goes down, all pods lose access to their persistent data. CARP provides a solution by creating a virtual IP address that automatically moves between servers during failures. + +### How CARP Works + +CARP allows multiple hosts to share a virtual IP address (VIP). The hosts communicate using multicast to elect a MASTER, while others remain as BACKUP. When the MASTER fails, a BACKUP automatically promotes itself, and the VIP moves to the new MASTER. This happens within seconds, minimizing downtime. + +Key benefits for our storage system: +- **Automatic failover**: No manual intervention required for basic failures +- **Transparent to clients**: Pods continue using the same IP address +- **Works with stunnel**: The VIP ensures encrypted connections follow the active server +- **Simple configuration**: Just a single line in rc.conf -adding to /etc/rc.conf on f0 and f1: +### Configuring CARP + +First, add the CARP configuration to `/etc/rc.conf` on both f0 and f1: + +```sh +# The virtual IP 192.168.1.138 will float between f0 and f1 ifconfig_re0_alias0="inet vhid 1 pass testpass alias 192.168.1.138/32" +``` + +Parameters explained: +- `vhid 1`: Virtual Host ID - must match on all CARP members +- `pass testpass`: Password for CARP authentication (use a stronger password in production) +- `alias 192.168.1.138/32`: The virtual IP address with a /32 netmask -adding to /etc/hosts (on n0, n1, n2, r0, r1, r2): +Next, update `/etc/hosts` on all nodes (n0, n1, n2, r0, r1, r2) to resolve the VIP hostname: ``` 192.168.1.138 f3s-storage-ha f3s-storage-ha.lan f3s-storage-ha.lan.buetow.org 192.168.2.138 f3s-storage-ha f3s-storage-ha.wg0 f3s-storage-ha.wg0.wan.buetow.org ``` -Adding on f0 and f1: +This allows clients to connect to `f3s-storage-ha` regardless of which physical server is currently the MASTER. + +### CARP State Change Notifications + +To properly manage services during failover, we need to detect CARP state changes. FreeBSD's devd system can notify us when CARP transitions between MASTER and BACKUP states. + +Add this to `/etc/devd.conf` on both f0 and f1: paul@f0:~ % cat < ../ Back to the main site +- **High Availability**: CARP ensures the storage VIP moves automatically during failures +- **Data Protection**: ZFS encryption protects data at rest, stunnel protects data in transit +- **Continuous Replication**: 1-minute RPO for critical data, automated via zrepl +- **Secure Access**: Client certificate authentication prevents unauthorized access +- **Kubernetes Integration**: Shared storage accessible from all cluster nodes + +### Architecture Benefits -https://forums.freebsd.org/threads/hast-and-zfs-with-carp-failover.29639/ +This design prioritizes **data integrity** over pure availability: +- Manual failover prevents split-brain scenarios +- Certificate-based authentication provides strong security +- Encrypted replication protects data even over untrusted networks +- ZFS snapshots enable point-in-time recovery +### Lessons Learned + +1. **Stunnel vs Native NFS/TLS**: While native encryption would be ideal, stunnel provides better cross-platform compatibility +2. **Manual vs Automatic Failover**: For storage systems, controlled failover often prevents more problems than it causes +3. **Replication Frequency**: Balance between data protection (RPO) and system load +4. **Client Compatibility**: Different NFS implementations behave differently - test thoroughly + +### Next Steps + +With reliable storage in place, we can now: +- Deploy stateful applications on Kubernetes +- Set up databases with persistent volumes +- Create shared configuration stores +- Implement backup strategies using ZFS snapshots + +The storage layer is the foundation for any serious Kubernetes deployment. By building it on FreeBSD with ZFS, CARP, and stunnel, we get enterprise-grade features on commodity hardware. + +### References + +- FreeBSD CARP documentation: https://docs.freebsd.org/en/books/handbook/advanced-networking/#carp +- ZFS encryption guide: https://docs.freebsd.org/en/books/handbook/zfs/#zfs-encryption +- Stunnel documentation: https://www.stunnel.org/docs.html +- zrepl documentation: https://zrepl.github.io/ + +Other *BSD-related posts: + +<< template::inline::rindex bsd E-Mail your comments to `paul@nospam.buetow.org` -- cgit v1.2.3