Skip to content
This repository has been archived by the owner on May 5, 2023. It is now read-only.

Latest commit

 

History

History
147 lines (84 loc) · 9.2 KB

README.md

File metadata and controls

147 lines (84 loc) · 9.2 KB

My home lab repository :octocat:

... managed with Flux, Renovate and GitHub Actions 🤖


k3s pre-commit GitHub Workflow Status Lines of code


📖 Overview

This is my home cluster, built on k3s, backed by FluxCD, Terraform, Ansible, and GitOps/DevOps principles. This is a place for me to learn, and share everything I've learned along the way. Feel free to ask questions, submit improvements, and learn from all the hard work I've put into this!

If you want to read about my adventures, I try to post about all my learning experiences on my blog. Come git gud with me!


⛵ Kubernetes

There's an excellent template over at k8s-at-home/template-cluster-k3 that I based my cluster on if you feel like following along :)

Installation

My cluster is k3s provisioned overtop bare-metal Ubuntu 20.04 using the Ansible galaxy role ansible-role-k3s. This is a semi hyper-converged cluster, workloads and block storage are sharing the same available resources on my nodes while I have a separate server for (NFS) file storage.

🔸 Click here to see my Ansible playbooks and roles.

Core Components

GitOps

Flux watches my cluster folder (see Directories below) and makes the changes to my cluster based on the YAML manifests.

Renovate watches my entire repository looking for dependency updates, when they are found a PR is automatically created. When some PRs are merged Flux applies the changes to my cluster.

Directories

The Git repository contains the following directories under cluster and are ordered below by how Flux will apply them.

  • base: directory is the entrypoint to Flux.
  • crds: directory contains custom resource definitions (CRDs) that need to exist globally in your cluster before anything else exists.
  • core: directory (depends on crds) are important infrastructure applications (grouped by namespace) that should never be pruned by Flux.
  • apps: directory (depends on core) is where your common applications (grouped by namespace) could be placed, Flux will prune resources here if they are not tracked by Git anymore.

Networking

Name CIDR
Kubernetes Nodes 10.1.0.0/24
Kubernetes external services (Calico w/ BGP) 10.117.0.0/24
Kubernetes pods 10.69.0.0/16
Kubernetes services 10.96.0.0/16

Persistent Volume Data Backup and Recovery

Currently, I use nfs-subdir-external-provisioner to provision PVs on my NAS over NFS. This way, at least for the time being, my PVs are backed up along with the NAS in Google Workspace (Google Drive). This isn't the most resilient or appropriate way to do it, but I'm not quite ready to set up block storage yet :)


🌐 DNS

Ingress Controller

Over WAN, I have port forwarded ports 80 and 443 to the load balancer IP of my ingress controller that's running in my Kubernetes cluster.

Cloudflare works as a proxy to hide my homes WAN IP and also as a firewall. When not on my home network, all the traffic coming into my ingress controller on port 80 and 443 comes from Cloudflare.

🔸 Cloudflare is also configured to GeoIP block all countries except a few I have whitelisted

Internal DNS

For now, this is just handled by my Mikrotik RB4011 router (soon to upgrade to an RB5009!)

I will, at some point in the future, do something a little more exciting with this!

External DNS

external-dns is deployed in my cluster and configure to sync DNS records to Cloudflare. The only ingresses external-dns looks at to gather DNS records to put in Cloudflare are ones that I explicitly set an annotation of external-dns/is-public: "true"

🔸 Click here to see how else I manage Cloudflare.

Dynamic DNS

My home IP can change at any given time and in order to keep my WAN IP address up to date on Cloudflare I have deployed a CronJob in my cluster. This periodically checks and updates the A record ipv4.domain.tld. I followed the example of onedr0p/home-ops as well as docs online. I'll probably write a blog post about it! external-dns is pure magic!


⚡ Network Attached Storage

Right now, I'm running my NAS off an old Dell PowerEdge R510 12 bay server. It's a little power hungry! I run TrueNAS, and have a RAIDz10 setup.

Currently, my raw storage capacity is about 56TB. However, I only get about half that since I'm doing RAIDz10. I have a striped set of 6 mirrored pairs. Effectively I can lose up to half my drives, but if I lose both drives in any pair, I'm having a bad day.

To offset this, I back up the NAS once a week to Google Drive (Google Workspaces), where I pay for an Enterprise account, which gets me a large amount of storage with the caveat of only being able to upload about 750GB a day. Since I completed a main backup of my NAS a long time ago, I only do incremental backups now.

I'm slowly replacing all the 2TB drives, which came with my NAS, as they fail or I catch a sale on nicer WD Easy Store drives that I shuck. These are usually white label WD Red drives, or sometimes even better, HGST drives. My plan is to slowly upgrade everything to 12TB drives.

My NAS can be accessed via NFS over my home network.


🔧 Hardware

Device Count OS Disk Size Data Disk Size Ram Operating System Purpose
Poweredge R720 1 500GB SATA N/A 128GB Ubuntu 20.04 Kubernetes (k3s) Node
Intel NUC8i7HVK1 1 256GB NVMe N/A 16GB Ubuntu 20.04 Kubernetes (k3s) Node
UCS C220 M3 1 2x500GB SAS N/A 96GB Ubuntu 20.04 Kubernetes (k3s) Node
PowerEdge R510 1 32GB Flash Drive 2x12TB, 2x8TB, 8x2TB RAIDz10 16GB TrueNAS 12.0 Network Attached Storage (NAS)

🤝 Graditude and Thanks

Thanks to all the people who donate their time to the Kubernetes @Home community. A lot of inspiration for my cluster came from the people that have shared their clusters over at awesome-home-kubernetes.


📜 Changelog

See commit history


🔏 License

See LICENSE