205 lines
10 KiB
YAML
205 lines
10 KiB
YAML
---
|
|
# Shared config for the whole k3s_cluster group (both k3s_control_plane and
|
|
# k3s_workers) — see roles/k3s_node and playbooks/k3s.yml.
|
|
|
|
# Used as the kubeconfig context/cluster name and as the Vault path suffix
|
|
# below, so the cluster has one name in every place it shows up.
|
|
k3s_cluster_name: homelab-utils
|
|
|
|
# Pinned, not "latest" — a rebuild months from now should produce the same
|
|
# cluster it does today, same reasoning as pinning an app's image tag in
|
|
# common/vars.yml. Bump deliberately; check the current stable release at
|
|
# https://github.com/k3s-io/k3s/releases first.
|
|
k3s_version: v1.31.4+k3s1
|
|
|
|
# One Vault path for the whole cluster, same "one path per stack" convention
|
|
# as everything under homelab/<app> — see docs/vault-secrets.md.
|
|
k3s_vault_path: "homelab/k3s-{{ k3s_cluster_name }}"
|
|
|
|
# The SSH key this group is reached with. A different path from k3s_vault_path
|
|
# above because it's a different kind of secret: that one is cluster identity
|
|
# (the join token), this one is access to the hosts, and it lives alongside
|
|
# the Unraid key under homelab/ci/ rather than with the cluster's own data.
|
|
# Fetched by playbooks/k3s_ssh_key.yml, which both k3s playbooks import.
|
|
k3s_ssh_key_vault_path: homelab/ci/ssh-k3s
|
|
|
|
# Where that play writes it, and what every play here then connects with — so
|
|
# a manual run needs Vault credentials in the environment and nothing else,
|
|
# rather than the key pre-loaded into ssh-agent. Override on the command line
|
|
# (-e ansible_ssh_private_key_file=~/.ssh/k3s_ansible) to use a local copy
|
|
# instead, e.g. if Vault itself is down.
|
|
#
|
|
# Under local/, which .gitignore already excludes — same as the kubeconfig
|
|
# below, and for the same reason: generated credential, never committed. Built
|
|
# from playbook_dir rather than repo_root, unlike k3s_kubeconfig_local_path:
|
|
# repo_root is a *play* var set in k3s.yml, so it only resolves inside the two
|
|
# plays that set it, whereas this is a connection var and has to resolve in
|
|
# every play in the file.
|
|
k3s_ssh_key_local_path: "{{ playbook_dir }}/../../../../local/k3s/{{ k3s_cluster_name }}.key"
|
|
ansible_ssh_private_key_file: "{{ k3s_ssh_key_local_path }}"
|
|
|
|
# Extra INSTALL_K3S_EXEC args appended on every node, both roles. Empty by
|
|
# default. Only flags valid on *both* `k3s server` and `k3s agent` belong
|
|
# here — see k3s_server_extra_args below for server-only flags like
|
|
# `--disable`, which `k3s agent` doesn't understand and will fail to start
|
|
# with.
|
|
k3s_extra_args: []
|
|
|
|
# Extra INSTALL_K3S_EXEC args appended on the control-plane node only.
|
|
# --disable=servicelb turns off k3s's bundled LoadBalancer controller
|
|
# (Klipper) in favour of roles/k3s_metallb — the two would otherwise both
|
|
# try to satisfy the same LoadBalancer Services. Add e.g. '--disable=traefik'
|
|
# here too if homelab-utils apps end up wanting their own ingress instead.
|
|
#
|
|
# Changing this (or k3s_extra_args) on an already-installed cluster is picked
|
|
# up on the next `ansible-playbook playbooks/k3s.yml` run — roles/k3s_node
|
|
# tracks the exec line it last installed with and reinstalls (restarting the
|
|
# k3s/k3s-agent service, not the node) whenever it drifts from what's
|
|
# configured here. See tasks/server.yml and tasks/agent.yml.
|
|
k3s_server_extra_args:
|
|
- "--disable=servicelb"
|
|
|
|
# MetalLB's LoadBalancer IP pool — see roles/k3s_metallb. Must be addresses
|
|
# on the LAN (192.168.50.0/24 — see inventory/hosts.yml) that nothing else,
|
|
# DHCP included, will ever hand out. Adjust to a range your DHCP scope
|
|
# doesn't cover before the first run.
|
|
k3s_metallb_address_range: "192.168.50.80-192.168.50.99"
|
|
|
|
# The LAN address the shared Postgres primary answers on — see
|
|
# roles/k3s_postgres, which declares a LoadBalancer Service for it alongside
|
|
# CNPG's built-in ClusterIP ones. Pinned rather than auto-assigned because
|
|
# the address gets written down elsewhere (an app's vars.yml, a connection
|
|
# string in Vault) instead of only being looked up at runtime, so it mustn't
|
|
# move when the Service is recreated.
|
|
#
|
|
# Must be inside the pool above — MetalLB only assigns from its own pools,
|
|
# and a request for an address outside them leaves the Service pending
|
|
# forever rather than failing loudly. The caveat of pinning out of the same
|
|
# pool MetalLB auto-assigns from: it hands unpinned Services the lowest free
|
|
# address, so if some other LoadBalancer Service is created before this one
|
|
# and takes .80, this Service is the one left pending. Nothing else here
|
|
# requests an IP today. If that changes, the fix is a second
|
|
# IPAddressPool with autoAssign: false in roles/k3s_metallb reserved for
|
|
# pinned addresses, not a different number here.
|
|
k3s_postgres_loadbalancer_ip: "192.168.50.81"
|
|
|
|
# Where playbooks/k3s.yml fetches the kubeconfig to, on the Ansible
|
|
# controller. Under local/, which .gitignore already excludes — it's a
|
|
# generated credential, never committed.
|
|
k3s_kubeconfig_local_path: "{{ repo_root }}/local/k3s/{{ k3s_cluster_name }}.kubeconfig"
|
|
|
|
# --- cert-manager (roles/k3s_cert_manager) ----------------------------------
|
|
#
|
|
# TLS for anything this cluster serves over Traefik. See that role's
|
|
# defaults/main.yml for why DNS-01 rather than HTTP-01, and what each of
|
|
# these does.
|
|
|
|
# Where Let's Encrypt sends expiry warnings. An ACME account is registered
|
|
# against it.
|
|
k3s_cert_manager_acme_email: russell.seymour@turtlesystems.co.uk
|
|
|
|
# >>> SET BEFORE THE FIRST RUN <<<
|
|
#
|
|
# How cert-manager proves control of the domain, rendered into the
|
|
# ClusterIssuer's solvers list as-is. Left empty deliberately — it depends on
|
|
# who runs DNS for turtlesystems.uk, which this repo has no way to know.
|
|
# roles/k3s_cert_manager fails fast while it's empty, rather than creating an
|
|
# issuer that can never satisfy an order.
|
|
#
|
|
# Cloudflare, as the most common case — the token needs Zone:DNS:Edit on the
|
|
# zone, and is stored in Vault (see k3s_cert_manager_vault_path below and
|
|
# docs/vault-secrets.md) rather than written here:
|
|
#
|
|
# k3s_cert_manager_solver:
|
|
# dns01:
|
|
# cloudflare:
|
|
# apiTokenSecretRef:
|
|
# name: cert-manager-dns-credentials
|
|
# key: CLOUDFLARE_API_TOKEN
|
|
# selector:
|
|
# dnsZones:
|
|
# - turtlesystems.uk
|
|
#
|
|
# For another provider, take the stanza from
|
|
# https://cert-manager.io/docs/configuration/acme/dns01/ and point its secret
|
|
# ref at whichever key you stored at that Vault path.
|
|
#
|
|
# Use the Let's Encrypt staging directory while working this out — override
|
|
# k3s_cert_manager_acme_server. Production allows 5 failed validations per
|
|
# hostname per hour, and exhausting it means waiting, not retrying.
|
|
k3s_cert_manager_solver:
|
|
dns01:
|
|
cloudflare:
|
|
apiTokenSecretRef:
|
|
name: cert-manager-dns-credentials
|
|
key: CLOUDFLARE_API_TOKEN
|
|
selector:
|
|
dnsZones:
|
|
- turtlesystems.uk
|
|
|
|
# --- Traefik (roles/k3s_traefik) --------------------------------------------
|
|
#
|
|
# The ingress controller k3s installs for itself; that role installs nothing,
|
|
# it only adjusts what's already there. Its defaults are enough for the
|
|
# dashboard over `kubectl port-forward` — see that role's defaults/main.yml
|
|
# and README.md → "Dashboard (Traefik)".
|
|
|
|
# >>> SET WHEN AUTHENTIK IS READY TO PROTECT IT <<<
|
|
#
|
|
# Uncomment to publish the dashboard on this hostname, behind the forward-auth
|
|
# middleware below. Until then the port-forward is the only way in, which is
|
|
# the safe default rather than a limitation. Needs a DNS record pointing at
|
|
# Traefik's MetalLB address (`kubectl -n kube-system get svc traefik`).
|
|
#
|
|
# Before uncommenting, in Authentik: create a Proxy Provider in **forward auth
|
|
# (domain level)** mode covering turtlesystems.uk, assign it to an
|
|
# application, and add that application to the embedded outpost. Domain level
|
|
# rather than single-application for a Kubernetes-specific reason — see
|
|
# roles/k3s_traefik/defaults/main.yml.
|
|
#
|
|
# k3s_traefik_dashboard_host: traefik.turtlesystems.uk
|
|
|
|
# Authentik's embedded outpost, by in-cluster DNS — the `authentik-server`
|
|
# Service in the `authentik` namespace, i.e. the chart's own service, not a
|
|
# separately deployed outpost. Unused while the host above is commented out;
|
|
# set here anyway so enabling the dashboard is one line rather than two.
|
|
# roles/k3s_traefik refuses to run if the host is set and this isn't.
|
|
k3s_traefik_dashboard_auth_address: "http://authentik-server.authentik.svc.cluster.local/outpost.goauthentik.io/auth/traefik"
|
|
|
|
# --- Apps on the cluster (roles/k3s_app) ------------------------------------
|
|
#
|
|
# The k3s equivalent of `stacks:` in host_vars/nas01.yml and `apps:` in a
|
|
# Proxmox guest's host_vars — the list of *applications* on this cluster, as
|
|
# opposed to the k3s_* cluster services above, which are the cluster's own
|
|
# infrastructure.
|
|
#
|
|
# In group_vars rather than host_vars because an app is deployed to the
|
|
# cluster, not to a node: playbooks/k3s.yml runs roles/k3s_app against
|
|
# k3s_control_plane only (that's where the manifests directory is), but
|
|
# nothing about an app belongs to that Pi specifically.
|
|
#
|
|
# Same entry shape as the other two platforms — name, src, vault_path, an
|
|
# optional `db:`, and an optional `state:`. And the same removal rule as
|
|
# Unraid: set `state: absent` to tear an app down and leave the entry here as
|
|
# a tombstone; deleting the entry removes nothing, it just stops Ansible
|
|
# visiting it. See roles/k3s_app/tasks/remove.yml.
|
|
k3s_apps:
|
|
- name: authentik
|
|
src: authentik
|
|
vault_path: homelab/authentik
|
|
db:
|
|
name: authentik
|
|
user: authentik
|
|
# The key at homelab/authentik holding this role's password. Named for
|
|
# the environment variable Authentik itself reads, because
|
|
# roles/k3s_app passes Vault keys through to the app's Secret verbatim
|
|
# — so one value serves both the provisioning step and the running app.
|
|
password_vault_key: AUTHENTIK_POSTGRESQL__PASSWORD
|
|
admin_vault_path: homelab/shared/postgres
|
|
# The CNPG LoadBalancer, not the in-cluster -rw Service: these tasks
|
|
# run on the Ansible controller (delegate_to: localhost), which is off
|
|
# the cluster and can't resolve or route to a ClusterIP. Authentik
|
|
# itself uses the ClusterIP — see
|
|
# src/authentik/ansible/kubernetes/vars.yml.
|
|
provision_host: "{{ k3s_postgres_loadbalancer_ip }}"
|
|
provision_port: "5432"
|