Skip to content
This repository was archived by the owner on Mar 24, 2024. It is now read-only.

Commit 859fd75

Browse files
committed
First commit
Signed-off-by: Patrik Cyvoct <[email protected]>
0 parents  commit 859fd75

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2853
-0
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
secret.enc.yaml diff=sopsdiffer
2+
cluster-secrets.yaml diff=sopsdiffer

.github/renovate.json5

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
{
2+
"enabled": true,
3+
"timezone": "Europe/Paris",
4+
"semanticCommits": "enabled",
5+
"dependencyDashboard": true,
6+
"dependencyDashboardTitle": "Renovate Dashboard",
7+
"commitBody": "Signed-off-by: Patrik Cyvoct <[email protected]>",
8+
// do not notify on closed unmerged PRs
9+
"suppressNotifications": ["prIgnoreNotification"],
10+
// only rebase PRs when there's a conflict
11+
"rebaseWhen": "conflicted",
12+
"kubernetes": {
13+
"fileMatch": ["cluster/.+\\.yaml$"],
14+
"ignorePaths": [
15+
"cluster/.+/base/",
16+
]
17+
},
18+
"helm-values": {
19+
"fileMatch": ["cluster/.+helm-release\\.yaml$"],
20+
},
21+
"regexManagers": [
22+
// regexManager to read and process HelmReleases and CRDs
23+
{
24+
"fileMatch": [
25+
"cluster/.+\\.yaml$",
26+
],
27+
"matchStrings": [
28+
// helm releases
29+
"registryUrl=(?<registryUrl>.*?)\n *chart: (?<depName>.*?)\n *version: (?<currentValue>.*)\n",
30+
// rook-ceph crd
31+
"registryUrl=(?<registryUrl>.*?) chart=(?<depName>.*?)\n *tag: (?<currentValue>.*)\n",
32+
// cert-manager crd
33+
"registryUrl=(?<registryUrl>.*?) chart=(?<depName>.*?)\n.*\\/(?<currentValue>.*?)\\/",
34+
],
35+
"datasourceTemplate": "helm",
36+
},
37+
],
38+
"packageRules": [
39+
// setup datasources
40+
{
41+
"matchDatasources": ["helm"],
42+
"separateMinorPatch": true,
43+
},
44+
// global docker datasource settings
45+
{
46+
"matchDatasources": ["docker"],
47+
"enabled": true,
48+
"commitMessageTopic": "container image {{depName}}",
49+
"commitMessageExtra": "to {{#if isSingleVersion}}v{{{newVersion}}}{{else}}{{{newValue}}}{{/if}}",
50+
"matchUpdateTypes": ["major", "minor", "patch"],
51+
"separateMinorPatch": true,
52+
},
53+
// add labels according to package and update types
54+
{
55+
"matchDatasources": ["docker"],
56+
"matchUpdateTypes": ["major"],
57+
"labels": ["renovate/image", "dep/major"],
58+
},
59+
{
60+
"matchDatasources": ["docker"],
61+
"matchUpdateTypes": ["minor"],
62+
"labels": ["renovate/image", "dep/minor"],
63+
},
64+
{
65+
"matchDatasources": ["docker"],
66+
"matchUpdateTypes": ["patch"],
67+
"labels": ["renovate/image", "dep/patch"],
68+
},
69+
{
70+
"matchDatasources": ["helm"],
71+
"matchUpdateTypes": ["major"],
72+
"labels": ["renovate/helm", "dep/major"],
73+
},
74+
{
75+
"matchDatasources": ["helm"],
76+
"matchUpdateTypes": ["minor"],
77+
"labels": ["renovate/helm", "dep/minor"],
78+
},
79+
{
80+
"matchDatasources": ["helm"],
81+
"matchUpdateTypes": ["patch"],
82+
"labels": ["renovate/helm", "dep/patch"],
83+
},
84+
// version strategies
85+
{
86+
"matchDatasources": ["docker"],
87+
"versioning": "loose",
88+
"matchPackageNames": [
89+
"docker.io/plexinc/pms-docker"
90+
],
91+
},
92+
// enable auto-merge
93+
{
94+
"matchDatasources": ["docker"],
95+
"automerge": true,
96+
"automergeType": "branch",
97+
"requiredStatusChecks": null,
98+
"matchUpdateTypes": ["minor", "patch"],
99+
"matchPackageNames": [
100+
"docker.io/linuxserver/jackett",
101+
"docker.io/linuxserver/sonarr",
102+
"docker.io/linuxserver/radarr",
103+
"docker.io/linuxserver/transmission",
104+
],
105+
},
106+
{
107+
"matchDatasources": ["helm", "docker"],
108+
"matchPackagePatterns": ["^rook.ceph"],
109+
"groupName": "rook-ceph-suite",
110+
"additionalBranchPrefix": "",
111+
"separateMinorPatch": true,
112+
},
113+
],
114+
}

.github/yamllint.config.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
ignore: |
2+
.github/
3+
ansible/
4+
integrations/
5+
*-crds.yaml
6+
extends: default
7+
rules:
8+
truthy:
9+
allowed-values: ['true', 'false', 'on', 'yes']
10+
comments:
11+
min-spaces-from-content: 1
12+
line-length: disable
13+
braces:
14+
min-spaces-inside: 0
15+
max-spaces-inside: 1
16+
brackets:
17+
min-spaces-inside: 0
18+
max-spaces-inside: 0
19+
indentation:
20+
spaces: 2
21+
indent-sequences: consistent

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ansible/inventory/*.yaml
2+
!ansible/inventory/*.enc.yaml

.pre-commit-config.yaml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
fail_fast: false
2+
repos:
3+
- repo: https://github.com/adrienverge/yamllint
4+
rev: v1.26.1
5+
hooks:
6+
- args:
7+
- -c
8+
- .github/yamllint.config.yaml
9+
id: yamllint
10+
- repo: https://github.com/pre-commit/pre-commit-hooks
11+
rev: v3.4.0
12+
hooks:
13+
- id: trailing-whitespace
14+
- id: end-of-file-fixer
15+
- id: mixed-line-ending
16+
- repo: https://github.com/Lucas-C/pre-commit-hooks
17+
rev: v1.1.10
18+
hooks:
19+
- id: remove-crlf
20+
- id: remove-tabs
21+
- repo: https://github.com/sirosen/fix-smartquotes
22+
rev: 0.2.0
23+
hooks:
24+
- id: fix-smartquotes
25+
- repo: https://github.com/k8s-at-home/sops-pre-commit
26+
rev: v2.0.3
27+
hooks:
28+
- id: forbid-secrets

.sops.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
creation_rules:
3+
- encrypted_regex: '^(data|stringData)$'
4+
pgp: 2C3E86E982BBE36AD0FBB0270B323237B39B6B5B

LICENSE

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
This is free and unencumbered software released into the public domain.
2+
3+
Anyone is free to copy, modify, publish, use, compile, sell, or
4+
distribute this software, either in source code form or as a compiled
5+
binary, for any purpose, commercial or non-commercial, and by any
6+
means.
7+
8+
In jurisdictions that recognize copyright laws, the author or authors
9+
of this software dedicate any and all copyright interest in the
10+
software to the public domain. We make this dedication for the benefit
11+
of the public at large and to the detriment of our heirs and
12+
successors. We intend this dedication to be an overt act of
13+
relinquishment in perpetuity of all present and future rights to this
14+
software under copyright law.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19+
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20+
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21+
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22+
OTHER DEALINGS IN THE SOFTWARE.
23+
24+
For more information, please refer to <https://unlicense.org>

README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<div align="center">
2+
3+
### My ~home~ cloud Kubernetes cluster
4+
5+
</div>
6+
7+
<div align="center">
8+
9+
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=for-the-badge)](https://github.com/pre-commit/pre-commit)
10+
[![renovate](https://img.shields.io/badge/renovate-enabled-green?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjUgNSAzNzAgMzcwIj48Y2lyY2xlIGN4PSIxODkiIGN5PSIxOTAiIHI9IjE4NCIgZmlsbD0iI2ZlMiIvPjxwYXRoIGZpbGw9IiM4YmIiIGQ9Ik0yNTEgMjU2bC0zOC0zOGExNyAxNyAwIDAxMC0yNGw1Ni01NmMyLTIgMi02IDAtN2wtMjAtMjFhNSA1IDAgMDAtNyAwbC0xMyAxMi05LTggMTMtMTNhMTcgMTcgMCAwMTI0IDBsMjEgMjFjNyA3IDcgMTcgMCAyNGwtNTYgNTdhNSA1IDAgMDAwIDdsMzggMzh6Ii8+PHBhdGggZmlsbD0iI2Q1MSIgZD0iTTMwMCAyODhsLTggOGMtNCA0LTExIDQtMTYgMGwtNDYtNDZjLTUtNS01LTEyIDAtMTZsOC04YzQtNCAxMS00IDE1IDBsNDcgNDdjNCA0IDQgMTEgMCAxNXoiLz48cGF0aCBmaWxsPSIjYjMwIiBkPSJNMjg1IDI1OGw3IDdjNCA0IDQgMTEgMCAxNWwtOCA4Yy00IDQtMTEgNC0xNiAwbC02LTdjNCA1IDExIDUgMTUgMGw4LTdjNC01IDQtMTIgMC0xNnoiLz48cGF0aCBmaWxsPSIjYTMwIiBkPSJNMjkxIDI2NGw4IDhjNCA0IDQgMTEgMCAxNmwtOCA3Yy00IDUtMTEgNS0xNSAwbC05LThjNSA1IDEyIDUgMTYgMGw4LThjNC00IDQtMTEgMC0xNXoiLz48cGF0aCBmaWxsPSIjZTYyIiBkPSJNMjYwIDIzM2wtNC00Yy02LTYtMTctNi0yMyAwLTcgNy03IDE3IDAgMjRsNCA0Yy00LTUtNC0xMSAwLTE2bDgtOGM0LTQgMTEtNCAxNSAweiIvPjxwYXRoIGZpbGw9IiNiNDAiIGQ9Ik0yODQgMzA0Yy00IDAtOC0xLTExLTRsLTQ3LTQ3Yy02LTYtNi0xNiAwLTIybDgtOGM2LTYgMTYtNiAyMiAwbDQ3IDQ2YzYgNyA2IDE3IDAgMjNsLTggOGMtMyAzLTcgNC0xMSA0em0tMzktNzZjLTEgMC0zIDAtNCAybC04IDdjLTIgMy0yIDcgMCA5bDQ3IDQ3YTYgNiAwIDAwOSAwbDctOGMzLTIgMy02IDAtOWwtNDYtNDZjLTItMi0zLTItNS0yeiIvPjxwYXRoIGZpbGw9IiMxY2MiIGQ9Ik0xNTIgMTEzbDE4LTE4IDE4IDE4LTE4IDE4em0xLTM1bDE4LTE4IDE4IDE4LTE4IDE4em0tOTAgODlsMTgtMTggMTggMTgtMTggMTh6bTM1LTM2bDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMxZGQiIGQ9Ik0xMzQgMTMxbDE4LTE4IDE4IDE4LTE4IDE4em0tMzUgMzZsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzJiYiIgZD0iTTExNiAxNDlsMTgtMTggMTggMTgtMTggMTh6bTU0LTU0bDE4LTE4IDE4IDE4LTE4IDE4em0tODkgOTBsMTgtMTggMTggMTgtMTggMTh6bTEzOS04NWwyMyAyM2M0IDQgNCAxMSAwIDE2TDE0MiAyNDBjLTQgNC0xMSA0LTE1IDBsLTI0LTI0Yy00LTQtNC0xMSAwLTE1bDEwMS0xMDFjNS01IDEyLTUgMTYgMHoiLz48cGF0aCBmaWxsPSIjM2VlIiBkPSJNMTM0IDk1bDE4LTE4IDE4IDE4LTE4IDE4em0tNTQgMThsMTgtMTcgMTggMTctMTggMTh6bTU1LTUzbDE4LTE4IDE4IDE4LTE4IDE4em05MyA0OGwtOC04Yy00LTUtMTEtNS0xNiAwTDEwMyAyMDFjLTQgNC00IDExIDAgMTVsOCA4Yy00LTQtNC0xMSAwLTE1bDEwMS0xMDFjNS00IDEyLTQgMTYgMHoiLz48cGF0aCBmaWxsPSIjOWVlIiBkPSJNMjcgMTMxbDE4LTE4IDE4IDE4LTE4IDE4em01NC01M2wxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjMGFhIiBkPSJNMjMwIDExMGwxMyAxM2M0IDQgNCAxMSAwIDE2TDE0MiAyNDBjLTQgNC0xMSA0LTE1IDBsLTEzLTEzYzQgNCAxMSA0IDE1IDBsMTAxLTEwMWM1LTUgNS0xMSAwLTE2eiIvPjxwYXRoIGZpbGw9IiMxYWIiIGQ9Ik0xMzQgMjQ4Yy00IDAtOC0yLTExLTVsLTIzLTIzYTE2IDE2IDAgMDEwLTIzTDIwMSA5NmExNiAxNiAwIDAxMjIgMGwyNCAyNGM2IDYgNiAxNiAwIDIyTDE0NiAyNDNjLTMgMy03IDUtMTIgNXptNzgtMTQ3bC00IDItMTAxIDEwMWE2IDYgMCAwMDAgOWwyMyAyM2E2IDYgMCAwMDkgMGwxMDEtMTAxYTYgNiAwIDAwMC05bC0yNC0yMy00LTJ6Ii8+PC9zdmc+)](https://github.com/renovatebot/renovate)
11+
12+
</div>
13+
14+
<br/>
15+
16+
## History
17+
18+
Once upon a time, I had one server, hosted on [Kimsufi](https://www.kimsufi.com). It was full of ugly docker-compose files, nothing was automated, it was just plain ol' `ssh` and that was it.
19+
20+
In 2017, while studying in Poland, I discovered [Scaleway](https://www.scaleway.com), and more generally the cloud. So I ending up migrating everything on some VC1S servers, still using `ssh`.
21+
22+
2 years later, I started working at [Scaleway](https://www.scaleway.com/en/) on [Kapsule](https://www.scaleway.com/en/kubernetes-kapsule/), their managed Kubernetes solution. Since then, I've always thought of migrating everything to Kubernetes, but was always too lazy to set it up :sweat_smile:. I still managed to migrate from the VC1S to some [Dedibox](https://www.scaleway.com/en/dedibox/) servers, but again, still using `ssh` and `docker-compose`. Nothing was automated, it was a real mess!
23+
24+
Though at work, I was trying to automate everything, my personal setup was not part of it!
25+
26+
So 2021, new year and all that, it was THE year to finally automate everyhting. Disclaimer: even though I'd like a home cluster, I've got no place to host it in my flat yet!
27+
28+
After some reflection, and testing, I ended up choosing [baremetal Hetzner servers](https://www.hetzner.com/). Hence the following part, describing my setup.
29+
30+
## Setup
31+
32+
I've chosen to use three servers, acting as worker and control plane.
33+
They are linked with a [vSwitch](https://docs.hetzner.com/robot/dedicated-server/network/vswitch/), everything binding to the private IP, except SSH.
34+
35+
I've written sone basic [Ansible](https://www.ansible.com/) [roles](./ansible/roles), in order to set up the Kubernetes cluster. Well not so basic, it supports a Kubernetes version rolling upgrade :smile:!
36+
37+
I'm using [Tailscale](https://tailscale.com/) in order to have acces to the Kubernetes API server. For public access, I'm using [MetalLB](https://metallb.universe.tf/) with a public subnet routed directly in the vSwitch. With the help of [Cilium](https://cilium.io/) and [Direct Server Return (DSR)](https://docs.cilium.io/en/v1.9/gettingstarted/kubeproxy-free/#dsr-mode) I'm able to get the real client IP directly into my pods (very useful for the mail server).
38+
39+
For the storage, I'm using [Rook](https://rook.io/), with direct access the drives (yeah I just dropped the RAID!), wich allows me to get Block, and Filesystems storage for my pods.
40+
41+
I'm then using [cert-manager](https://cert-manager.io/docs/) and [ExternalDNS](https://github.com/kubernetes-sigs/external-dns), both using my [Cloudflare](https://www.cloudflare.com/) account to manage TLS certificate, and DNS.
42+
43+
Regarding the monitoring, I still have a free student [Datadog](https://www.datadoghq.com/) account, so why not use it! (If someone at Datadog reads this, please don't drop that :smile:, if you do, I'll switch to a classic [Prometheus](https://prometheus.io/), [Grafana](https://grafana.com/) and [Loki](https://grafana.com/oss/loki/) setup!)
44+
45+
As for the ingress, I've chosen [Contour](https://projectcontour.io/) since I've grown kind of fond of [Envoy](https://www.envoyproxy.io/)!
46+
47+
I'm also using a (still) local fork of the [Hetzner cloud controller manager](https://github.com/identw/hetzner-cloud-controller-manager), to get both the ExternalIP and (vSwitch) InternalIP of my nodes.
48+
49+
I was using the [Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets), but I switched to [sops](https://github.com/mozilla/sops/) before writing this.
50+
51+
Finally, for the automation, I was using [Flux](https://fluxcd.io/) with a private git repo. Now this will still be with Flux, but in public repo, and a lot of automation taken from here and there!
52+
53+
## Credits & Thanks
54+
55+
Most of the git automation here is taken from the awsome [@onedr0p](https://github.com/onedr0p) and his [home-cluster](https://github.com/onedr0p/home-cluster/) repo and the more widely [k8s-at-home](https://github.com/k8s-at-home) community. Kudos to him and the community :tada:!

ansible/.sops.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
creation_rules:
3+
- encrypted_regex: '^(ansible_host|subnet|gateway)$'
4+
pgp: 2C3E86E982BBE36AD0FBB0270B323237B39B6B5B

ansible/ansible.cfg

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[defaults]
2+
host_key_checking = False
3+
gathering = smart
4+
fact_caching = jsonfile
5+
fact_caching_connection = /tmp
6+
callback_whitelist = profile_tasks
7+
deprecation_warnings = False
8+
retry_files_enabled = False
9+
interpreter_python = /usr/bin/python3

0 commit comments

Comments
 (0)