Restore test fixes: site facts, self-restore, CNPG archive generations, dependency graph #1296
+18
-12
@@ -6,18 +6,24 @@ below (like `wp-pg`) keeps `bootstrap.recovery` in git: a cold rebuild restores
|
||||
each from its backup with no manual step. This document covers the
|
||||
precondition, watching and verifying that restore, and the reasoning behind it.
|
||||
|
||||
| Cluster | Namespace | ObjectStore | barman path (`destinationPath`) | app DB / owner |
|
||||
|-----------|----------------|-----------------|--------------------------------------|---------------------------------|
|
||||
| `ak-pg` | authentik | `ak-pg-store` | `s3://renner-uno-k8s-cnpg/ak-pg` | `authentik`/`authentik` |
|
||||
| `im-pg` | immich | `im-pg-store` | `s3://renner-uno-k8s-cnpg/im-pg` | `immich`/`immich` |
|
||||
| `pprl-pg` | paperless | `pprl-pg-store` | `s3://renner-uno-k8s-cnpg/pprl-pg` | `paperless`/`paperless` |
|
||||
| `ha-pg` | home-assistant | `ha-pg-store` | `s3://renner-uno-k8s-cnpg/ha-pg` | `homeassistant`/`homeassistant` |
|
||||
| `mx-pg` | matrix | `mx-pg-store` | `s3://renner-uno-k8s-cnpg/mx-pg` | `synapse`/`synapse` |
|
||||
| `tr-pg` | trmnl | `tr-pg-store` | `s3://renner-uno-k8s-cnpg/tr-pg` | `terminus`/`terminus` |
|
||||
| Cluster | Namespace | app DB / owner |
|
||||
|-----------|----------------|---------------------------------|
|
||||
| `ak-pg` | authentik | `authentik`/`authentik` |
|
||||
| `im-pg` | immich | `immich`/`immich` |
|
||||
| `pprl-pg` | paperless | `paperless`/`paperless` |
|
||||
| `ha-pg` | home-assistant | `homeassistant`/`homeassistant` |
|
||||
| `mx-pg` | matrix | `synapse`/`synapse` |
|
||||
| `tr-pg` | trmnl | `terminus`/`terminus` |
|
||||
| `wp-pg` | woodpecker | `woodpecker`/`woodpecker` |
|
||||
|
||||
The barman **`serverName`** is the last path segment of `destinationPath`, i.e.
|
||||
it equals the cluster name. `gf-pg` (monitoring) has no ObjectStore and stays
|
||||
on `initdb`.
|
||||
Each cluster `<x>` has two ObjectStores in `kubernetes/cnpg-object-stores/`:
|
||||
`<x>-store`, where it archives WAL and takes base backups, and
|
||||
`<x>-store-source`, which `bootstrap.recovery` reads. Their paths come from the
|
||||
`flux-system/cnpg-paths` ConfigMap, which `bootstrap.sh` writes once per
|
||||
cluster incarnation: the source is the prefix in `s3://renner-uno-k8s-cnpg`
|
||||
whose `<x>/base/` holds the newest base backup, the archive a new prefix
|
||||
`<x>-g<timestamp>`. The barman **`serverName`** is the cluster name in both.
|
||||
`gf-pg` (monitoring) has no ObjectStore and stays on `initdb`.
|
||||
|
||||
---
|
||||
|
||||
@@ -129,7 +135,7 @@ cluster in the *same* namespace (so it can reference the existing namespaced
|
||||
restore, but never archiving, so it only ever *reads* the backup path.
|
||||
|
||||
```sh
|
||||
NS=authentik ; SRC=ak-pg ; STORE=ak-pg-store ; DB=authentik
|
||||
NS=authentik ; SRC=ak-pg ; STORE=ak-pg-store-source ; DB=authentik
|
||||
kubectl apply -f - <<EOF
|
||||
apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
|
||||
@@ -131,7 +131,7 @@ data:
|
||||
state: absent
|
||||
|
||||
# shelly-manager.home.renner.uno is gated by authentik-gate-sync
|
||||
# (kubernetes/apps/home-assistant/shelly-manager-ingress.yaml), which
|
||||
# (kubernetes/apps/home-assistant-iot/shelly-manager-ingress.yaml), which
|
||||
# admits this group. Members are managed in Authentik.
|
||||
- model: authentik_core.group
|
||||
identifiers:
|
||||
|
||||
@@ -47,7 +47,7 @@ spec:
|
||||
plugin:
|
||||
name: barman-cloud.cloudnative-pg.io
|
||||
parameters:
|
||||
barmanObjectName: ak-pg-store
|
||||
barmanObjectName: ak-pg-store-source
|
||||
serverName: ak-pg
|
||||
postgresql:
|
||||
parameters:
|
||||
|
||||
@@ -152,10 +152,11 @@ spec:
|
||||
targetCPUUtilizationPercentage: 70
|
||||
metrics:
|
||||
enabled: true
|
||||
# The chart renders it without checking for monitoring.coreos.com, so
|
||||
# the install would wait on monitoring. Declared in
|
||||
# monitoring-rules/authentik-servicemonitor.yaml instead.
|
||||
serviceMonitor:
|
||||
enabled: true
|
||||
labels:
|
||||
release: kube-prometheus-stack
|
||||
enabled: false
|
||||
ingress:
|
||||
enabled: true
|
||||
ingressClassName: traefik
|
||||
|
||||
@@ -15,6 +15,5 @@ resources:
|
||||
# infrastructure-cnpg-barman dep + CNPG Cluster healthCheckExprs (see
|
||||
# clusters/homelab/authentik.yaml).
|
||||
- cluster.yaml
|
||||
- objectstore.yaml
|
||||
- scheduled-backup.yaml
|
||||
- hetzner-creds-externalsecret.yaml
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: ak-pg-store
|
||||
namespace: authentik
|
||||
annotations:
|
||||
# Prune-disabled — a standing guard kept from the seed->authentik-KS handoff (backup target).
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
configuration:
|
||||
# Offsite Hetzner Object Storage (fsn1) — replaces Garage on nas-1.
|
||||
# No SSE: Hetzner supports only SSE-C, unusable by barman-cloud
|
||||
# (plugin #646), so at-rest encryption is unavailable; transit is TLS.
|
||||
destinationPath: s3://renner-uno-k8s-cnpg/ak-pg
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
# Region is required (REGION=fsn1) — without it boto3's HeadBucket
|
||||
# (barman-cloud-check-wal-archive during bootstrap.recovery) 400s.
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
@@ -10,10 +10,8 @@
|
||||
# - Name, namespace, accessModes, storageClassName and volumeMode must match
|
||||
# the live claim exactly: they are immutable, a mismatch fails the whole
|
||||
# gitea Kustomization (no change to the live claim).
|
||||
# - volumeName must stay: kustomize-controller has owned spec.volumeName
|
||||
# since the namespace move pre-created this claim (eb23d3ac, #878).
|
||||
# Without it, server-side apply tries to clear the field and the API server
|
||||
# rejects the whole claim as an immutable-spec change.
|
||||
# - No volumeName: the gitea Kustomization ignores /spec/volumeName on this
|
||||
# claim, so the bound volume is kept and a fresh cluster binds a new one.
|
||||
# - Grow only. A smaller value is rejected by the API server.
|
||||
# - prune: disabled, so removing this file from git never deletes the claim
|
||||
# and its data. To hand ownership back, delete the file; the claim stays.
|
||||
@@ -33,7 +31,6 @@ spec:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
storageClassName: ceph-block
|
||||
volumeMode: Filesystem
|
||||
volumeName: pvc-e7c56db2-481d-40cb-b94a-b264b7b4b5be
|
||||
resources:
|
||||
requests:
|
||||
storage: 60Gi
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# The home-assistant workloads attached to the IoT VLAN (v30iot). Separate from
|
||||
# ../home-assistant so that HA and what depends on it do not wait on a VLAN
|
||||
# the node may not have; the pods run only where it does
|
||||
# (net.renner.uno/iot-vlan).
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- shelly-manager-pvc.yaml
|
||||
- shelly-manager-network-attachment.yaml
|
||||
- shelly-manager-firmware-rbac.yaml
|
||||
- shelly-ble-proxy-key-externalsecret.yaml
|
||||
# shelly-manager-auth comes from ../home-assistant: mqtt-account-controller
|
||||
# mounts it too, and that Kustomization comes first.
|
||||
- shelly-manager-llat-externalsecret.yaml
|
||||
- shelly-manager-deployment.yaml
|
||||
- shelly-manager-service.yaml
|
||||
- shelly-manager-ingress.yaml
|
||||
# mDNS relay — carries IoT-VLAN announcements into HA's zeroconf listener as
|
||||
# unicast, which is the only direction the CNI will move them. Without it HA
|
||||
# never learns that a device's DHCP lease moved. See the header comment in
|
||||
# mdns-relay-deployment.yaml.
|
||||
- mdns-relay-network-attachment.yaml
|
||||
- mdns-relay-service.yaml
|
||||
- mdns-relay-deployment.yaml
|
||||
configMapGenerator:
|
||||
# shelly-manager api-proxy sidecar config (REN-935). Hash suffix disabled
|
||||
# (name stays stable), so editing shelly-manager-api-proxy.conf does not
|
||||
# auto-roll the pod — restart manually with
|
||||
# `kubectl rollout restart deploy/shelly-manager -n home-assistant`.
|
||||
- name: shelly-manager-api-proxy
|
||||
namespace: home-assistant
|
||||
files:
|
||||
- api.conf.template=shelly-manager-api-proxy.conf
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
+3
@@ -47,6 +47,9 @@ spec:
|
||||
homelab.renner.uno/restarted-for: "2026-10-06 cni-plugins v1.9.1 attach check"
|
||||
k8s.v1.cni.cncf.io/networks: mdns-relay-iot
|
||||
spec:
|
||||
# Runs where the node patch declares the IoT VLAN (ens19).
|
||||
nodeSelector:
|
||||
net.renner.uno/iot-vlan: "true"
|
||||
enableServiceLinks: false
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
+4
-4
@@ -47,10 +47,10 @@ spec:
|
||||
spec:
|
||||
# eth0 (Cilium-managed pod network) is still the primary — it
|
||||
# carries the ingress, mosquitto LB return path, etc. The macvlan
|
||||
# above is additive. No explicit edge exclusion is needed: the
|
||||
# `workload-class=pinned:NoSchedule` taint on k8s-edge already
|
||||
# keeps this pod off there (we never tolerate it), and the NAD's
|
||||
# `master: ens19` (stable predictable name for the v30iot NIC) is present on every k8s-{1,2,3} worker.
|
||||
# above is additive.
|
||||
# Runs where the node patch declares the IoT VLAN (ens19).
|
||||
nodeSelector:
|
||||
net.renner.uno/iot-vlan: "true"
|
||||
enableServiceLinks: false
|
||||
# Grants shelly-manager the in-cluster identity used by the firmware
|
||||
# pipeline to create esphome flash Jobs and stream their logs. RBAC is
|
||||
@@ -116,7 +116,7 @@ spec:
|
||||
plugin:
|
||||
name: barman-cloud.cloudnative-pg.io
|
||||
parameters:
|
||||
barmanObjectName: ha-pg-store
|
||||
barmanObjectName: ha-pg-store-source
|
||||
serverName: ha-pg
|
||||
postgresql:
|
||||
parameters:
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
# Barman object store for ha-pg: base backups + continuous WAL archiving to
|
||||
# Hetzner Object Storage, same target bucket as the other CNPG clusters.
|
||||
#
|
||||
# Its own prefix. Two clusters archiving WAL to one destinationPath interleave
|
||||
# their streams and corrupt both — see the note in
|
||||
# kubernetes/apps/woodpecker/objectstore.yaml, which learned that the hard way.
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: ha-pg-store
|
||||
namespace: home-assistant
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: s3://renner-uno-k8s-cnpg/ha-pg
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
# Matches the 30d retention the other CNPG clusters use and the
|
||||
# renner-uno-k8s-cnpg bucket's noncurrent-version expiry in
|
||||
# opentofu/object_storage.tf, so old S3 versions don't outlive the backups
|
||||
# that superseded them.
|
||||
retentionPolicy: "30d"
|
||||
@@ -21,26 +21,11 @@ resources:
|
||||
- mosquitto-iot-service.yaml
|
||||
- mosquitto-deployment.yaml
|
||||
- mosquitto-evcc-credentials-externalsecret.yaml
|
||||
- shelly-manager-pvc.yaml
|
||||
- shelly-manager-network-attachment.yaml
|
||||
- shelly-manager-firmware-rbac.yaml
|
||||
- shelly-ble-proxy-key-externalsecret.yaml
|
||||
- shelly-manager-auth-externalsecret.yaml
|
||||
- shelly-manager-llat-externalsecret.yaml
|
||||
- shelly-manager-deployment.yaml
|
||||
- shelly-manager-service.yaml
|
||||
- shelly-manager-ingress.yaml
|
||||
# shelly-manager and the mDNS relay sit on the IoT VLAN: ../home-assistant-iot.
|
||||
- esphome-pvc.yaml
|
||||
- esphome-deployment.yaml
|
||||
- esphome-service.yaml
|
||||
- esphome-ingress.yaml
|
||||
# mDNS relay — carries IoT-VLAN announcements into HA's zeroconf listener as
|
||||
# unicast, which is the only direction the CNI will move them. Without it HA
|
||||
# never learns that a device's DHCP lease moved. See the header comment in
|
||||
# mdns-relay-deployment.yaml.
|
||||
- mdns-relay-network-attachment.yaml
|
||||
- mdns-relay-service.yaml
|
||||
- mdns-relay-deployment.yaml
|
||||
# Zigbee2MQTT — ZHA replacement bridge. Ships scaled to 0; the cutover
|
||||
# runbook (zigbee2mqtt-migration-runbook.md) scales it up. The MQTT
|
||||
# `zigbee2mqtt` broker user is provisioned by mosquitto-bootstrap.yaml
|
||||
@@ -57,7 +42,6 @@ resources:
|
||||
# Live: recorder.db_url in the homeassistant repo points here, and the
|
||||
# long-term statistics carry their full history from 2024.
|
||||
- ha-pg-hetzner-creds-externalsecret.yaml
|
||||
- ha-pg-objectstore.yaml
|
||||
- ha-pg-cluster.yaml
|
||||
- ha-pg-scheduled-backup.yaml
|
||||
# MQTT credential management (REN-802): the account controller manages the
|
||||
@@ -66,6 +50,8 @@ resources:
|
||||
# Register: mqtt-accounts.yaml (configMapGenerator).
|
||||
- mosquitto-dynsec-test.yaml
|
||||
- mqtt-account-controller.yaml
|
||||
# Also mounted by shelly-manager (../home-assistant-iot), which runs after this.
|
||||
- shelly-manager-auth-externalsecret.yaml
|
||||
configMapGenerator:
|
||||
# nginx config for the reverse-proxy sidecar. Hash suffix disabled so
|
||||
# the cm name stays stable; editing proxy.conf does not auto-roll the
|
||||
@@ -116,13 +102,5 @@ configMapGenerator:
|
||||
namespace: home-assistant
|
||||
files:
|
||||
- mqtt-accounts.yaml
|
||||
# shelly-manager api-proxy sidecar config (REN-935). Hash suffix disabled
|
||||
# (name stays stable), so editing shelly-manager-api-proxy.conf does not
|
||||
# auto-roll the pod — restart manually with
|
||||
# `kubectl rollout restart deploy/shelly-manager -n home-assistant`.
|
||||
- name: shelly-manager-api-proxy
|
||||
namespace: home-assistant
|
||||
files:
|
||||
- api.conf.template=shelly-manager-api-proxy.conf
|
||||
generatorOptions:
|
||||
disableNameSuffixHash: true
|
||||
|
||||
@@ -305,10 +305,13 @@ spec:
|
||||
- key: api-key
|
||||
path: api-key
|
||||
# Client certificate HA gets (cert-manager renews it in place; not a
|
||||
# subPath mount, so the next loop sees the new file).
|
||||
# subPath mount, so the next loop sees the new file). Optional: this
|
||||
# controller creates its Certificate, so on a new cluster the Secret
|
||||
# appears only after the controller has started.
|
||||
- name: ha-mqtt-tls
|
||||
secret:
|
||||
secretName: mqtt-home-assistant-tls
|
||||
optional: true
|
||||
# HA long-lived token of the service user `MQTT Cert Sync`
|
||||
# (system-admin; config flows need admin). REN-1268.
|
||||
- name: ha-token
|
||||
|
||||
@@ -43,7 +43,7 @@ spec:
|
||||
plugin:
|
||||
name: barman-cloud.cloudnative-pg.io
|
||||
parameters:
|
||||
barmanObjectName: im-pg-store
|
||||
barmanObjectName: im-pg-store-source
|
||||
serverName: im-pg
|
||||
postgresql:
|
||||
# vchord only. The image also ships pgvecto.rs (vectors.so), but its
|
||||
|
||||
@@ -11,7 +11,6 @@ resources:
|
||||
# a teardown). This KS gains the infrastructure-cnpg-barman dep + CNPG Cluster
|
||||
# healthCheckExprs (see clusters/homelab/immich.yaml).
|
||||
- cluster.yaml
|
||||
- objectstore.yaml
|
||||
- scheduled-backup.yaml
|
||||
- hetzner-creds-externalsecret.yaml
|
||||
- pvcs.yaml
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: im-pg-store
|
||||
namespace: immich
|
||||
annotations:
|
||||
# Prune-disabled — a standing guard kept from the seed->immich-KS handoff (backup target).
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
configuration:
|
||||
# Offsite Hetzner Object Storage (fsn1) — replaces Garage on nas-1.
|
||||
# No SSE: Hetzner supports only SSE-C, unusable by barman-cloud
|
||||
# (plugin #646), so at-rest encryption is unavailable; transit is TLS.
|
||||
destinationPath: s3://renner-uno-k8s-cnpg/im-pg
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
# Region is required (REGION=fsn1) — without it boto3's HeadBucket
|
||||
# (barman-cloud-check-wal-archive during bootstrap.recovery) 400s.
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
@@ -44,6 +44,9 @@ spec:
|
||||
labels:
|
||||
app.kubernetes.io/name: llama-server
|
||||
spec:
|
||||
# Runs only where the node patch declares the Intel iGPU.
|
||||
nodeSelector:
|
||||
hardware.renner.uno/intel-gpu: "true"
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
|
||||
@@ -34,6 +34,9 @@ spec:
|
||||
labels:
|
||||
app.kubernetes.io/name: llama-embed
|
||||
spec:
|
||||
# Runs only where the node patch declares the Intel iGPU.
|
||||
nodeSelector:
|
||||
hardware.renner.uno/intel-gpu: "true"
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
|
||||
@@ -23,6 +23,9 @@ spec:
|
||||
labels:
|
||||
app.kubernetes.io/name: wiki-embed
|
||||
spec:
|
||||
# Runs only where the node patch declares the Intel iGPU.
|
||||
nodeSelector:
|
||||
hardware.renner.uno/intel-gpu: "true"
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
|
||||
@@ -31,7 +31,7 @@ spec:
|
||||
plugin:
|
||||
name: barman-cloud.cloudnative-pg.io
|
||||
parameters:
|
||||
barmanObjectName: mx-pg-store
|
||||
barmanObjectName: mx-pg-store-source
|
||||
serverName: mx-pg
|
||||
postgresql:
|
||||
parameters:
|
||||
|
||||
@@ -9,6 +9,5 @@ resources:
|
||||
# mx-pg CNPG Postgres + offsite Barman backup. The media store and signing
|
||||
# key are on synapse-data, backed up by Velero (matrix-daily).
|
||||
- cluster.yaml
|
||||
- objectstore.yaml
|
||||
- scheduled-backup.yaml
|
||||
- hetzner-creds-externalsecret.yaml
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: mx-pg-store
|
||||
namespace: matrix
|
||||
spec:
|
||||
configuration:
|
||||
# Offsite Hetzner Object Storage (fsn1), same bucket as the other CNPG
|
||||
# clusters. No SSE: Hetzner supports only SSE-C, unusable by barman-cloud
|
||||
# (plugin #646), so at-rest encryption is unavailable; transit is TLS.
|
||||
destinationPath: s3://renner-uno-k8s-cnpg/mx-pg
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
# Region is required (REGION=fsn1) — without it boto3's HeadBucket
|
||||
# (barman-cloud-check-wal-archive during bootstrap.recovery) 400s.
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
@@ -32,11 +32,9 @@ spec:
|
||||
# OTBR via OTBR's ClusterIP Service). The macvlan attachment
|
||||
# above is additive, not a replacement.
|
||||
#
|
||||
# No nodeSelector/toleration: this pod only needs v30iot (present
|
||||
# on all nodes), not the edge USB devices. Dropping the
|
||||
# workload-class=pinned toleration lets the edge taint keep it off
|
||||
# the (tiny) edge box, reserving that node for the USB-bound
|
||||
# home-assistant + zwave-js pods.
|
||||
# Runs where the node patch declares the IoT VLAN (ens19).
|
||||
nodeSelector:
|
||||
net.renner.uno/iot-vlan: "true"
|
||||
containers:
|
||||
- name: matter-server
|
||||
# Use the HAOS-published image from `ghcr.io/matter-js/...`,
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
# Only radius needs a hand-written ServiceMonitor. The goauthentik.io operator
|
||||
# creates one per outpost and Prometheus discovers those directly, because
|
||||
# serviceMonitorSelector here is empty (see monitoring/helmrelease-prometheus.yaml).
|
||||
# Standalone copies for ldap and paperless-gate used to live here as well; they
|
||||
# duplicated the operator's and were removed.
|
||||
#
|
||||
# Radius requires extra plumbing. The radius binary listens on :9300 just
|
||||
# like ldap/proxy (hardcoded in authentik/lib/default.yml), but authentik's
|
||||
# Python operator (`providers/radius/controllers/kubernetes.py`) omits the
|
||||
# `DeploymentPort(9300, "http-metrics", "tcp", 9300)` entry from its
|
||||
# `deployment_ports` list — that's an upstream bug; the ldap controller has
|
||||
# it, radius does not. Result: the operator-managed `ak-outpost-local-radius`
|
||||
# Service exposes only UDP 1812. Add a sibling Service here that selects the
|
||||
# same pod labels and exposes 9300/TCP, then a ServiceMonitor for it.
|
||||
#
|
||||
# The operator's own `ak-outpost-local-radius` ServiceMonitor cannot cover
|
||||
# this: it selects on `app.kubernetes.io/managed-by: goauthentik.io` together
|
||||
# with `goauthentik.io/service-type: metrics`, and no Service carries both —
|
||||
# the operator's has the first, the one below has the second.
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ak-outpost-local-radius-metrics
|
||||
namespace: authentik
|
||||
labels:
|
||||
app.kubernetes.io/managed-by: homelab
|
||||
goauthentik.io/outpost-name: local-radius
|
||||
goauthentik.io/outpost-type: radius
|
||||
spec:
|
||||
type: ClusterIP
|
||||
clusterIP: None
|
||||
selector:
|
||||
goauthentik.io/outpost-name: local-radius
|
||||
goauthentik.io/outpost-type: radius
|
||||
ports:
|
||||
- name: http-metrics
|
||||
port: 9300
|
||||
targetPort: 9300
|
||||
protocol: TCP
|
||||
---
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: authentik-outpost-radius
|
||||
namespace: authentik
|
||||
labels:
|
||||
release: kube-prometheus-stack
|
||||
spec:
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- authentik
|
||||
selector:
|
||||
# Pinned to the Service above. Without managed-by this would also match the
|
||||
# operator's Service and scrape the same endpoint twice.
|
||||
matchLabels:
|
||||
app.kubernetes.io/managed-by: homelab
|
||||
goauthentik.io/outpost-name: local-radius
|
||||
goauthentik.io/outpost-type: radius
|
||||
endpoints:
|
||||
- port: http-metrics
|
||||
path: /metrics
|
||||
interval: 30s
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
# authentik server metrics. The chart's metrics Service stays; only its
|
||||
# ServiceMonitor is declared here (see apps/authentik/helmrelease.yaml).
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: authentik-server-metrics
|
||||
namespace: authentik
|
||||
labels:
|
||||
release: kube-prometheus-stack
|
||||
spec:
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- authentik
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/name: authentik
|
||||
app.kubernetes.io/instance: authentik
|
||||
app.kubernetes.io/component: server-metrics
|
||||
endpoints:
|
||||
- port: metrics
|
||||
path: /metrics
|
||||
interval: 30s
|
||||
scrapeTimeout: 3s
|
||||
@@ -49,7 +49,7 @@ resources:
|
||||
# cannot live beside the Velero HelmRelease.
|
||||
- velero-podmonitor.yaml
|
||||
- velero-servicemonitor.yaml
|
||||
- authentik-outpost-servicemonitors.yaml
|
||||
- authentik-servicemonitor.yaml
|
||||
# Rook's exporter/mgr monitors: the operator aborts its node-daemon reconcile
|
||||
# when it cannot create these, which held the CephCluster in Progressing and
|
||||
# deadlocked the whole apps layer. See the file for the cycle.
|
||||
|
||||
@@ -269,9 +269,9 @@ spec:
|
||||
# per the app's own test (shelly-manager repo,
|
||||
# AuthenticationTests.Health_IsUnauthenticated); it is also the pod's
|
||||
# kubelet liveness/readiness path
|
||||
# (../home-assistant/shelly-manager-deployment.yaml). AllowedHosts is
|
||||
# (../home-assistant-iot/shelly-manager-deployment.yaml). AllowedHosts is
|
||||
# "*", so the cluster-local Host header is accepted. Service :80 ->
|
||||
# container :8080 (../home-assistant/shelly-manager-service.yaml).
|
||||
# container :8080 (../home-assistant-iot/shelly-manager-service.yaml).
|
||||
#
|
||||
# NO CiliumNetworkPolicy change: the home-assistant default-deny
|
||||
# admits the whole monitoring namespace on every port
|
||||
|
||||
@@ -25,6 +25,8 @@ spec:
|
||||
- key: node-role.kubernetes.io/control-plane
|
||||
operator: Exists
|
||||
effect: NoSchedule
|
||||
nodeSelector:
|
||||
hardware.renner.uno/intel-gpu: "true"
|
||||
securityContext:
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
@@ -33,12 +33,9 @@ spec:
|
||||
k8s.v1.cni.cncf.io/networks: music-assistant-iot
|
||||
spec:
|
||||
enableServiceLinks: false
|
||||
# No nodeSelector/toleration: MA only needs a node on v30iot (all
|
||||
# of them) for audio-sync L2, not the edge USB devices. It's the
|
||||
# heaviest of the formerly edge-pinned pods (2Gi limit), so
|
||||
# dropping the workload-class=pinned toleration — which lets the
|
||||
# edge taint keep it off the tiny edge box — is the main capacity
|
||||
# win for this step.
|
||||
# Runs where the node patch declares the IoT VLAN (ens19).
|
||||
nodeSelector:
|
||||
net.renner.uno/iot-vlan: "true"
|
||||
initContainers:
|
||||
# MA advertises a stored publish_ip to players (Sendspin / Snapcast /
|
||||
# SlimProto) and binds its stream + Sendspin servers to a stored
|
||||
|
||||
@@ -30,11 +30,10 @@ spec:
|
||||
# the IoT VLAN for mDNS/SRP advertisements and RA listening.
|
||||
k8s.v1.cni.cncf.io/networks: otbr-iot
|
||||
spec:
|
||||
# No nodeSelector/toleration: OTBR only needs v30iot L2 presence
|
||||
# (macvlan master: ens19, present on every node), not the edge USB
|
||||
# devices, and its Thread RCP is reached over the network
|
||||
# (slzb-thread.renner.uno). Dropping the workload-class=pinned
|
||||
# toleration lets the edge taint keep it off the tiny edge box.
|
||||
# Runs where the node patch declares the IoT VLAN (ens19). Its Thread
|
||||
# RCP is reached over the network (slzb-thread.renner.uno).
|
||||
nodeSelector:
|
||||
net.renner.uno/iot-vlan: "true"
|
||||
containers:
|
||||
# The Thread RCP is a network-attached radio (Serial-over-IP), so the
|
||||
# spinel transport needs a TCP-to-PTY bridge. Two obvious approaches
|
||||
|
||||
@@ -39,7 +39,7 @@ spec:
|
||||
plugin:
|
||||
name: barman-cloud.cloudnative-pg.io
|
||||
parameters:
|
||||
barmanObjectName: pprl-pg-store
|
||||
barmanObjectName: pprl-pg-store-source
|
||||
serverName: pprl-pg
|
||||
postgresql:
|
||||
parameters:
|
||||
|
||||
@@ -17,7 +17,6 @@ resources:
|
||||
# transferred without a teardown). This KS gains the infrastructure-cnpg-barman
|
||||
# dep + CNPG Cluster healthCheckExprs (see clusters/homelab/paperless.yaml).
|
||||
- cluster.yaml
|
||||
- objectstore.yaml
|
||||
- scheduled-backup.yaml
|
||||
- hetzner-creds-externalsecret.yaml
|
||||
- pvcs.yaml
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: pprl-pg-store
|
||||
namespace: paperless
|
||||
annotations:
|
||||
# Prune-disabled — a standing guard kept from the seed->paperless-KS handoff (backup target).
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
configuration:
|
||||
# Offsite Hetzner Object Storage (fsn1) — replaces local Garage on
|
||||
# nas-1 so paperless backups survive nas-1 being powered off. barman
|
||||
# uses boto3 default (auto) addressing; Hetzner (Ceph RGW) accepts it.
|
||||
destinationPath: s3://renner-uno-k8s-cnpg/pprl-pg
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
# No `encryption: AES256` (SSE-S3): Hetzner Object Storage supports
|
||||
# only SSE-C, which the barman-cloud plugin can't use (cnpg
|
||||
# plugin-barman-cloud #646). At-rest encryption is therefore not
|
||||
# available here; transit is TLS and the bucket is private.
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
@@ -36,7 +36,7 @@ spec:
|
||||
plugin:
|
||||
name: barman-cloud.cloudnative-pg.io
|
||||
parameters:
|
||||
barmanObjectName: tr-pg-store
|
||||
barmanObjectName: tr-pg-store-source
|
||||
serverName: tr-pg
|
||||
postgresql:
|
||||
parameters:
|
||||
|
||||
@@ -18,6 +18,5 @@ resources:
|
||||
# tr-pg CNPG Postgres + offsite Barman backup. Note this cluster runs
|
||||
# PostgreSQL 18, not the repo-standard 16 — see the comment in cluster.yaml.
|
||||
- cluster.yaml
|
||||
- objectstore.yaml
|
||||
- scheduled-backup.yaml
|
||||
- hetzner-creds-externalsecret.yaml
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: tr-pg-store
|
||||
namespace: trmnl
|
||||
spec:
|
||||
configuration:
|
||||
# Offsite Hetzner Object Storage (fsn1), same bucket as the other CNPG
|
||||
# clusters. No SSE: Hetzner supports only SSE-C, unusable by barman-cloud
|
||||
# (plugin #646), so at-rest encryption is unavailable; transit is TLS.
|
||||
destinationPath: s3://renner-uno-k8s-cnpg/tr-pg
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
# Region is required (REGION=fsn1) — without it boto3's HeadBucket
|
||||
# (barman-cloud-check-wal-archive during bootstrap.recovery) 400s.
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
@@ -39,6 +39,10 @@ spec:
|
||||
labels:
|
||||
app.kubernetes.io/name: wiki
|
||||
spec:
|
||||
# Its embedding backend (wiki-embed) needs the Intel iGPU; without it
|
||||
# the wiki has nothing to serve, so it runs where the iGPU is declared.
|
||||
nodeSelector:
|
||||
hardware.renner.uno/intel-gpu: "true"
|
||||
automountServiceAccountToken: false
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
|
||||
@@ -34,6 +34,5 @@ resources:
|
||||
# This KS depends on infrastructure-cnpg-barman for the barman plugin behind
|
||||
# the ObjectStore and ScheduledBackup.
|
||||
- hetzner-creds-externalsecret.yaml
|
||||
- objectstore.yaml
|
||||
- cluster.yaml
|
||||
- scheduled-backup.yaml
|
||||
|
||||
+703
-94
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,7 @@ spec:
|
||||
# woodpecker migrated) — secrets come from OpenBao via ESO
|
||||
# (MIGRATION-sops-openbao.md).
|
||||
dependsOn:
|
||||
- name: restore-apps
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
- name: infrastructure-ceph-cluster
|
||||
@@ -22,6 +22,7 @@ spec:
|
||||
secretRef:
|
||||
name: sops-age
|
||||
dependsOn:
|
||||
- name: restore-audiobookshelf
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
|
||||
@@ -20,10 +20,12 @@ spec:
|
||||
# from OpenBao via ESO (MIGRATION-sops-openbao.md). This was the LAST
|
||||
# sops consumer; phase 4 (age-key retirement) may proceed after soak.
|
||||
dependsOn:
|
||||
- name: restore-authentik
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
- name: infrastructure-cnpg-barman
|
||||
- name: cnpg-object-stores # the ObjectStores its Cluster names
|
||||
- name: gitea # server, LDAP outpost and gate-sync images are in Gitea's registry
|
||||
healthCheckExprs:
|
||||
- apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# The CNPG ObjectStores. Their paths come from the cnpg-paths ConfigMap, which
|
||||
# bootstrap.sh writes once per cluster incarnation and never replaces:
|
||||
# CNPG_<X>_SOURCE the bucket prefix holding <x>'s newest base backup
|
||||
# CNPG_<X>_ARCHIVE a new, empty prefix <x>-g<timestamp>
|
||||
# Not optional: without it every path renders empty.
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: cnpg-object-stores
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
retryInterval: 1m
|
||||
timeout: 5m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/cnpg-object-stores
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: infrastructure
|
||||
- name: infrastructure-cnpg-barman
|
||||
postBuild:
|
||||
substituteFrom:
|
||||
- kind: ConfigMap
|
||||
name: cnpg-paths
|
||||
@@ -19,3 +19,5 @@ spec:
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
# mqtt-account-controller there delivers mqtt-evcc-client-tls; mosquitto is the broker.
|
||||
- name: home-assistant
|
||||
|
||||
@@ -16,3 +16,4 @@ spec:
|
||||
dependsOn:
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: gitea # serves Gitea's API
|
||||
|
||||
@@ -14,7 +14,14 @@ spec:
|
||||
path: ./kubernetes/apps/gitea
|
||||
prune: true
|
||||
wait: true
|
||||
# The claim's bound volume differs per cluster (apps/gitea/pvc.yaml).
|
||||
ignore:
|
||||
- paths: ["/spec/volumeName"]
|
||||
target:
|
||||
kind: PersistentVolumeClaim
|
||||
name: data-gitea-0
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
|
||||
@@ -4,43 +4,28 @@ metadata:
|
||||
name: home-assistant
|
||||
namespace: flux-system
|
||||
spec:
|
||||
# Seed Job collapsed into the HA pod's `seed` initContainer so the
|
||||
# backup tarball + .HA_RESTORE manifest staging happens in the same
|
||||
# pod as HA Core (no Multi-Attach race against the RWO Ceph-RBD
|
||||
# PVC if production grows to multiple edge nodes). HA Core still
|
||||
# does the actual restore from the staged manifest on its boot.
|
||||
# Timeout has to absorb the worst-case 3h wait for the HAOS backup
|
||||
# to appear in Garage plus the in-pod download + HA's native restore.
|
||||
# The slowest part on a cold start is ha-pg recovering from barman (base
|
||||
# backup ~1.7 GiB compressed, then WAL replay); the config PVC is restored
|
||||
# beforehand by restore-home-assistant.
|
||||
interval: 10m
|
||||
retryInterval: 1m
|
||||
timeout: 4h
|
||||
timeout: 30m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/apps/home-assistant
|
||||
prune: true
|
||||
# Same TBD-USB caveat for the stromzaehler hostPath. Manifests apply;
|
||||
# HA pod may CrashLoop until the USB is present — acceptable during canary.
|
||||
wait: false
|
||||
wait: true
|
||||
# decryption block dropped 2026-07-13: path is sops-free — secrets come
|
||||
# from OpenBao via ESO (MIGRATION-sops-openbao.md).
|
||||
dependsOn:
|
||||
- name: restore-home-assistant
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
# ha-pg-objectstore.yaml declares an ObjectStore, whose CRD comes from the
|
||||
# CNPG Barman plugin in infrastructure-cnpg-barman. Without this edge the
|
||||
# kind is unknown when this path is first applied, and a server-side
|
||||
# dry-run rejects the ENTIRE set over the one object it cannot recognise:
|
||||
#
|
||||
# ObjectStore/home-assistant/ha-pg-store dry-run failed:
|
||||
# no matches for kind "ObjectStore" in version ...
|
||||
#
|
||||
# Every other ObjectStore user — authentik, immich, paperless, trmnl,
|
||||
# woodpecker — already declares it. This was the only one that did not, and
|
||||
# it took speech-to-phrase, zone-configurator and matter-server down with
|
||||
# it, since all three wait on home-assistant.
|
||||
- name: infrastructure-cnpg-barman
|
||||
- name: cnpg-object-stores # the ObjectStores its Cluster names
|
||||
- name: gitea # mqtt-account-controller's image is in Gitea's registry
|
||||
- name: influxdb # HA's InfluxDB integration writes there
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
@@ -58,10 +43,35 @@ spec:
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-home-assistant
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
---
|
||||
# shelly-manager and the mDNS relay: home-assistant's IoT-VLAN workloads.
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: home-assistant-iot
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
retryInterval: 1m
|
||||
timeout: 10m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/apps/home-assistant-iot
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-home-assistant # shelly-manager's PVC
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
- name: gitea # shelly-manager's image is in Gitea's registry
|
||||
- name: home-assistant # both serve HA: its API, its zeroconf listener
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
@@ -76,10 +86,13 @@ spec:
|
||||
name: flux-system
|
||||
path: ./kubernetes/apps/otbr
|
||||
prune: true
|
||||
wait: false
|
||||
# Not in use.
|
||||
suspend: true
|
||||
wait: true
|
||||
# decryption block dropped 2026-07-13: path is sops-free — secrets come
|
||||
# from OpenBao via ESO (MIGRATION-sops-openbao.md).
|
||||
dependsOn:
|
||||
- name: restore-home-assistant
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
---
|
||||
@@ -120,6 +133,7 @@ spec:
|
||||
# First boot downloads the Whisper model (a few hundred MB) — give it room.
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-home-assistant
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
|
||||
@@ -20,10 +20,11 @@ spec:
|
||||
# decryption block dropped 2026-07-13: path is sops-free — secrets come
|
||||
# from OpenBao via ESO (MIGRATION-sops-openbao.md).
|
||||
dependsOn:
|
||||
- name: restore-immich
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
- name: infrastructure-cnpg-barman
|
||||
- name: cnpg-object-stores # the ObjectStores its Cluster names
|
||||
healthCheckExprs:
|
||||
- apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
|
||||
@@ -25,6 +25,7 @@ spec:
|
||||
# boilerplate from the monolithic seed KS — InfluxDB has no CNPG cluster, only
|
||||
# a chart-provisioned ceph-block PVC, so ceph is the only storage dep needed.
|
||||
dependsOn:
|
||||
- name: restore-influxdb
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: infrastructure-inhouse
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
retryInterval: 2m
|
||||
timeout: 10m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/infrastructure-inhouse
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: gitea # its images are in Gitea's registry
|
||||
@@ -0,0 +1,98 @@
|
||||
# Infrastructure services that consume Secrets from OpenBao. Each carries its
|
||||
# ExternalSecrets and depends on infrastructure-crds, where the openbao
|
||||
# ClusterSecretStore turns Ready only once OpenBao is unsealed, so the
|
||||
# HelmRelease never installs before its Secret exists. One Kustomization each:
|
||||
# a broken service holds back nothing but itself (velero: the restore chain).
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: crowdsec
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
retryInterval: 1m
|
||||
timeout: 10m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/infrastructure/crowdsec
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: external-dns-unifi
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
retryInterval: 1m
|
||||
timeout: 5m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/infrastructure/external-dns-unifi
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: netbird-ingress
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
retryInterval: 1m
|
||||
timeout: 5m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/infrastructure/netbird-ingress
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: velero
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
retryInterval: 1m
|
||||
timeout: 15m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/infrastructure/velero
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: velero-schedules
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
retryInterval: 1m
|
||||
timeout: 5m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/infrastructure/velero-schedules
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: velero # the velero.io CRDs
|
||||
@@ -40,6 +40,13 @@ spec:
|
||||
kind: HelmRelease
|
||||
name: openbao # the ESO backend ExternalSecrets resolve against
|
||||
namespace: openbao
|
||||
# Ready only when every replica is unsealed (readiness probe: bao status).
|
||||
# The HelmRelease is Ready as soon as the chart is installed; the
|
||||
# ClusterSecretStore in infrastructure-crds must not come up before.
|
||||
- apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
name: openbao
|
||||
namespace: openbao
|
||||
- apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
name: rook-ceph-operator # storage — apps mount PVCs
|
||||
|
||||
@@ -17,10 +17,11 @@ spec:
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-matrix
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
- name: infrastructure-cnpg-barman
|
||||
- name: cnpg-object-stores # the ObjectStores its Cluster names
|
||||
healthCheckExprs:
|
||||
- apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
|
||||
@@ -46,6 +46,7 @@ spec:
|
||||
# from OpenBao via ESO (MIGRATION-sops-openbao.md).
|
||||
dependsOn:
|
||||
- name: grafana-db
|
||||
- name: influxdb # its Job writes the grafana-influxdb-token Secret Grafana mounts
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
|
||||
@@ -22,6 +22,7 @@ spec:
|
||||
secretRef:
|
||||
name: sops-age
|
||||
dependsOn:
|
||||
- name: restore-music-assistant
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
|
||||
@@ -14,6 +14,7 @@ spec:
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-navidrome
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
|
||||
@@ -20,10 +20,12 @@ spec:
|
||||
# decryption block dropped 2026-07-13: path is sops-free — secrets come
|
||||
# from OpenBao via ESO (MIGRATION-sops-openbao.md).
|
||||
dependsOn:
|
||||
- name: restore-paperless
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
- name: infrastructure-cnpg-barman
|
||||
- name: cnpg-object-stores # the ObjectStores its Cluster names
|
||||
- name: gitea # ftp-scanner (vsftpd) image is in Gitea's registry
|
||||
healthCheckExprs:
|
||||
- apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
|
||||
@@ -35,3 +35,4 @@ spec:
|
||||
# The `openbao` ClusterSecretStore, including the `renovate` entry in its
|
||||
# conditions.namespaces allowlist.
|
||||
- name: infrastructure-crds
|
||||
- name: gitea # the platform it runs against (git.renner.uno)
|
||||
|
||||
@@ -0,0 +1,396 @@
|
||||
# Ready once Velero has completed a sync of the backups in the bucket. A
|
||||
# Restore created before that finds no backup and fails for good.
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: velero-backups-synced
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 30m
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/gate
|
||||
prune: true
|
||||
dependsOn:
|
||||
- name: velero # the BackupStorageLocation and its credentials
|
||||
healthChecks:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: BackupStorageLocation
|
||||
name: default
|
||||
namespace: velero
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: BackupStorageLocation
|
||||
current: has(status.lastSyncedTime)
|
||||
---
|
||||
# One Kustomization per Velero Schedule (infrastructure/velero-schedules/schedules.yaml),
|
||||
# each restoring that schedule's newest backup. An app depends on its own, so
|
||||
# it waits for its data and for nothing else. Gitea's data goes first: it is
|
||||
# the registry for the in-house images; the others depend on restore-gitea.
|
||||
# openbao-daily has none: bootstrap.sh restores OpenBao from its raft snapshot.
|
||||
# Every one carries the same health check: a schedule without any backup has
|
||||
# nothing to restore (FailedValidation "No backups found for schedule").
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-gitea
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/gitea
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-apps
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/apps
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-audiobookshelf
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 3h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/audiobookshelf
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-authentik
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/authentik
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-home-assistant
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/home-assistant
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-immich
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 6h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/immich
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-influxdb
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/influxdb
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-matrix
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/matrix
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-music-assistant
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/music-assistant
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-navidrome
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/navidrome
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-paperless
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/paperless
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-trmnl
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/trmnl
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: restore-wordpress
|
||||
namespace: flux-system
|
||||
spec:
|
||||
interval: 10m
|
||||
timeout: 1h
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: flux-system
|
||||
path: ./kubernetes/restore/wordpress
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-gitea
|
||||
- name: velero-backups-synced
|
||||
- name: infrastructure-ceph-cluster
|
||||
healthCheckExprs:
|
||||
- apiVersion: velero.io/v1
|
||||
kind: Restore
|
||||
failed: >-
|
||||
has(status.phase) && (status.phase in ['Failed', 'PartiallyFailed'] ||
|
||||
(status.phase == 'FailedValidation' && !(has(status.validationErrors) &&
|
||||
status.validationErrors.exists(e, e.startsWith('No backups found for schedule')))))
|
||||
current: >-
|
||||
has(status.phase) && (status.phase == 'Completed' || status.phase == 'FailedValidation')
|
||||
@@ -16,3 +16,4 @@ spec:
|
||||
dependsOn:
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: gitea # its image is in Gitea's registry
|
||||
|
||||
@@ -17,10 +17,12 @@ spec:
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-trmnl
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
- name: infrastructure-cnpg-barman
|
||||
- name: cnpg-object-stores # the ObjectStores its Cluster names
|
||||
- name: home-assistant # the renderer reads HA's API
|
||||
healthCheckExprs:
|
||||
- apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
|
||||
@@ -20,3 +20,4 @@ spec:
|
||||
- name: infrastructure-ceph-cluster
|
||||
# wiki-embed (the embedding backend) lives in the llama-server app.
|
||||
- name: llama-server
|
||||
- name: gitea # its image is in Gitea's registry
|
||||
|
||||
@@ -24,7 +24,8 @@ spec:
|
||||
- name: infrastructure
|
||||
- name: infrastructure-crds
|
||||
- name: infrastructure-ceph-cluster
|
||||
- name: infrastructure-cnpg-barman
|
||||
- name: cnpg-object-stores # the ObjectStores its Cluster names
|
||||
- name: gitea # its forge and login provider
|
||||
healthCheckExprs:
|
||||
- apiVersion: postgresql.cnpg.io/v1
|
||||
kind: Cluster
|
||||
|
||||
@@ -12,7 +12,9 @@ spec:
|
||||
name: flux-system
|
||||
path: ./kubernetes/apps/wordpress
|
||||
prune: true
|
||||
wait: true
|
||||
dependsOn:
|
||||
- name: restore-wordpress
|
||||
# infrastructure gates on the mariadb-operator HelmRelease being Ready,
|
||||
# so the MariaDB CRD exists and has a controller before this applies.
|
||||
- name: infrastructure
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: ak-pg-store
|
||||
namespace: authentik
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_AK_PG_ARCHIVE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: ak-pg-store-source
|
||||
namespace: authentik
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
cnpg.renner.uno/server-name: ak-pg
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_AK_PG_SOURCE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: ha-pg-store
|
||||
namespace: home-assistant
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_HA_PG_ARCHIVE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: ha-pg-store-source
|
||||
namespace: home-assistant
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
cnpg.renner.uno/server-name: ha-pg
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_HA_PG_SOURCE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: im-pg-store
|
||||
namespace: immich
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_IM_PG_ARCHIVE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: im-pg-store-source
|
||||
namespace: immich
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
cnpg.renner.uno/server-name: im-pg
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_IM_PG_SOURCE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
@@ -0,0 +1,24 @@
|
||||
# Every CNPG cluster's two ObjectStores: <x>-store, where it archives WAL and
|
||||
# takes base backups, and <x>-store-source, which its bootstrap.recovery reads.
|
||||
#
|
||||
# Their destinationPaths are Flux variables from the cnpg-paths ConfigMap
|
||||
# (clusters/homelab/cnpg-object-stores.yaml). Nothing else may live in this
|
||||
# directory: postBuild substitution blanks every ${...} it renders.
|
||||
#
|
||||
# The source store carries cnpg.renner.uno/server-name, the cluster whose
|
||||
# backups bootstrap.sh looks for, and optionally
|
||||
# cnpg.renner.uno/source-prefixes, bucket prefixes outside the <name> and
|
||||
# <name>-g<timestamp> pattern that may still hold them.
|
||||
#
|
||||
# No SSE: Hetzner supports only SSE-C, unusable by barman-cloud (plugin #646),
|
||||
# so at-rest encryption is unavailable; transit is TLS.
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ak-pg.yaml
|
||||
- ha-pg.yaml
|
||||
- im-pg.yaml
|
||||
- mx-pg.yaml
|
||||
- pprl-pg.yaml
|
||||
- tr-pg.yaml
|
||||
- wp-pg.yaml
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: mx-pg-store
|
||||
namespace: matrix
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_MX_PG_ARCHIVE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: mx-pg-store-source
|
||||
namespace: matrix
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
cnpg.renner.uno/server-name: mx-pg
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_MX_PG_SOURCE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: pprl-pg-store
|
||||
namespace: paperless
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_PPRL_PG_ARCHIVE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: pprl-pg-store-source
|
||||
namespace: paperless
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
cnpg.renner.uno/server-name: pprl-pg
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_PPRL_PG_SOURCE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: tr-pg-store
|
||||
namespace: trmnl
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_TR_PG_ARCHIVE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: tr-pg-store-source
|
||||
namespace: trmnl
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
cnpg.renner.uno/server-name: tr-pg
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_TR_PG_SOURCE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
+32
-35
@@ -1,46 +1,14 @@
|
||||
---
|
||||
# RECOVERY SOURCE — read-only. The prefix wp-pg archives to (wp-pg-store below).
|
||||
#
|
||||
# serverName on the consuming externalCluster must be `wp-pg`, the name of the
|
||||
# cluster that produced these backups.
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: wp-pg-store-source
|
||||
namespace: woodpecker
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: s3://renner-uno-k8s-cnpg/wp-pg-woodpecker
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
# No retentionPolicy: wp-pg-store owns the lifecycle of this prefix.
|
||||
---
|
||||
# ARCHIVING TARGET.
|
||||
#
|
||||
# Not s3://renner-uno-k8s-cnpg/wp-pg: the retired `apps/wp-pg` archived there,
|
||||
# and two clusters archiving WAL to one destinationPath interleave their streams
|
||||
# and corrupt both.
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: wp-pg-store
|
||||
namespace: woodpecker
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: s3://renner-uno-k8s-cnpg/wp-pg-woodpecker
|
||||
destinationPath: ${CNPG_WP_PG_ARCHIVE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
@@ -57,3 +25,32 @@ spec:
|
||||
data:
|
||||
compression: gzip
|
||||
retentionPolicy: "30d"
|
||||
---
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: wp-pg-store-source
|
||||
namespace: woodpecker
|
||||
annotations:
|
||||
kustomize.toolkit.fluxcd.io/prune: disabled
|
||||
cnpg.renner.uno/server-name: wp-pg
|
||||
# wp-pg's archive since its move out of `apps`.
|
||||
cnpg.renner.uno/source-prefixes: wp-pg-woodpecker
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: ${CNPG_WP_PG_SOURCE}
|
||||
endpointURL: https://fsn1.your-objectstorage.com
|
||||
s3Credentials:
|
||||
accessKeyId:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_KEY_ID
|
||||
secretAccessKey:
|
||||
name: hetzner-s3-creds
|
||||
key: ACCESS_SECRET_KEY
|
||||
region:
|
||||
name: hetzner-s3-creds
|
||||
key: REGION
|
||||
wal:
|
||||
compression: gzip
|
||||
data:
|
||||
compression: gzip
|
||||
+4
@@ -51,6 +51,10 @@ spec:
|
||||
# Owns table 47, where all pod traffic is routed. Without it the table
|
||||
# stays empty and the rules fall through to main, unseparated.
|
||||
priorityClassName: system-node-critical
|
||||
# Table 47 exists only where the site patch routes pod traffic into it
|
||||
# (RoutingRuleConfig); the same patch labels those nodes.
|
||||
nodeSelector:
|
||||
net.renner.uno/pod-table: "47"
|
||||
# Writes host routes and peers on host addresses.
|
||||
hostNetwork: true
|
||||
serviceAccountName: bird
|
||||
@@ -0,0 +1,7 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
# Infrastructure that runs images from Gitea's registry with no copy on
|
||||
# ghcr.io, so it cannot start before Gitea serves them.
|
||||
resources:
|
||||
- bird/
|
||||
- netbird-service-sync/
|
||||
@@ -0,0 +1,79 @@
|
||||
apiVersion: source.toolkit.fluxcd.io/v1
|
||||
kind: HelmRepository
|
||||
metadata:
|
||||
name: ceph-csi-operator
|
||||
namespace: rook-ceph
|
||||
spec:
|
||||
interval: 24h
|
||||
url: https://ceph.github.io/ceph-csi-operator
|
||||
---
|
||||
# The CSI Driver and OperatorConfig resources Rook requires
|
||||
# (rook/Documentation/Helm-Charts/csi-drivers-chart.md). Values are Rook's
|
||||
# recommended ones (rook/deploy/charts/ceph-csi-drivers/values.yaml) plus the
|
||||
# shape this cluster runs with.
|
||||
apiVersion: helm.toolkit.fluxcd.io/v2
|
||||
kind: HelmRelease
|
||||
metadata:
|
||||
name: ceph-csi-drivers
|
||||
namespace: rook-ceph
|
||||
spec:
|
||||
interval: 30m
|
||||
dependsOn:
|
||||
- name: rook-ceph-operator
|
||||
chart:
|
||||
spec:
|
||||
chart: ceph-csi-drivers
|
||||
sourceRef:
|
||||
kind: HelmRepository
|
||||
name: ceph-csi-operator
|
||||
namespace: rook-ceph
|
||||
install:
|
||||
remediation:
|
||||
retries: 3
|
||||
upgrade:
|
||||
remediation:
|
||||
retries: 3
|
||||
values:
|
||||
operatorConfig:
|
||||
namespace: rook-ceph
|
||||
driverSpecDefaults:
|
||||
imageSet:
|
||||
name: rook-csi-operator-image-set-configmap
|
||||
nodePlugin:
|
||||
priorityClassName: system-node-critical
|
||||
controllerPlugin:
|
||||
priorityClassName: system-cluster-critical
|
||||
drivers:
|
||||
rbd:
|
||||
enabled: true
|
||||
name: rook-ceph.rbd.csi.ceph.com
|
||||
# Velero snapshots ceph-block claims through CSI.
|
||||
snapshotPolicy: volumeSnapshot
|
||||
nodePlugin:
|
||||
tolerations:
|
||||
- key: workload-class
|
||||
operator: Equal
|
||||
value: pinned
|
||||
effect: NoSchedule
|
||||
controllerPlugin:
|
||||
replicas: 2
|
||||
deploymentStrategy:
|
||||
type: Recreate
|
||||
cephfs:
|
||||
enabled: true
|
||||
name: rook-ceph.cephfs.csi.ceph.com
|
||||
snapshotPolicy: volumeGroupSnapshot
|
||||
nodePlugin:
|
||||
tolerations:
|
||||
- key: workload-class
|
||||
operator: Equal
|
||||
value: pinned
|
||||
effect: NoSchedule
|
||||
controllerPlugin:
|
||||
replicas: 2
|
||||
deploymentStrategy:
|
||||
type: Recreate
|
||||
nfs:
|
||||
enabled: false
|
||||
nvmeof:
|
||||
enabled: false
|
||||
@@ -1,5 +1,6 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- helmrelease.yaml
|
||||
- serviceaccounts.yaml
|
||||
- rbac.yaml
|
||||
|
||||
@@ -184,26 +184,13 @@ spec:
|
||||
# Cilium's, the sessions re-establish.
|
||||
bgpControlPlane:
|
||||
enabled: true
|
||||
# Masquerading exception, not a routing statement: pod traffic to these
|
||||
# ranges leaves unmasqueraded, so LAN services see real pod IPs. That only
|
||||
# works because BGP advertises the pod CIDRs, which is what gives the UDM a
|
||||
# route back. The two settings are one decision and have to move together.
|
||||
#
|
||||
# Pod CIDRs are 10.244.0.0/16 and fd10:244::/48 (talos/patches/cluster.yaml);
|
||||
# the supernets here cover the LAN as well, which is the point.
|
||||
ipv4NativeRoutingCIDR: 10.0.0.0/8
|
||||
ipv6NativeRoutingCIDR: fd00::/8
|
||||
# Pod east-west leaves the node on pod0 (VLAN 48) rather than the
|
||||
# management VLAN. Native routing hands forwarding to the kernel;
|
||||
# autoDirectNodeRoutes installs the remote PodCIDR routes, which is
|
||||
# allowed because all three nodes share pod0's L2 segment.
|
||||
#
|
||||
# directRoutingDevice is explicit on purpose: with several addressed
|
||||
# devices Cilium falls back to the one carrying the Kubernetes InternalIP,
|
||||
# which is mgmt0.
|
||||
#
|
||||
# Encapsulation is gone, so the datapath MTU goes 1450 -> 1500.
|
||||
routingMode: native
|
||||
autoDirectNodeRoutes: true
|
||||
nodePort:
|
||||
directRoutingDevice: pod0
|
||||
# What the site's network can carry decides how pod traffic crosses between
|
||||
# nodes and which destinations see real pod IPs: routingMode,
|
||||
# autoDirectNodeRoutes, the direct-routing device and the native-routing
|
||||
# (masquerade-exempt) CIDRs come from the cilium-site ConfigMap that each
|
||||
# Talos site patch carries (talos/patches/site-*.yaml). They must not be set
|
||||
# in values above, which would override it.
|
||||
valuesFrom:
|
||||
- kind: ConfigMap
|
||||
name: cilium-site
|
||||
valuesKey: values.yaml
|
||||
|
||||
@@ -3,3 +3,5 @@ kind: Kustomization
|
||||
resources:
|
||||
- lapi-ingress.yaml
|
||||
- helmrelease.yaml
|
||||
- crowdsec-bouncer-key-externalsecret.yaml
|
||||
- crowdsec-edge-bouncer-key-externalsecret.yaml
|
||||
|
||||
@@ -2,3 +2,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- helmrelease.yaml
|
||||
- externalsecret.yaml
|
||||
|
||||
@@ -119,3 +119,4 @@ spec:
|
||||
type: DirectoryOrCreate
|
||||
nodeSelector:
|
||||
kubernetes.io/arch: amd64
|
||||
hardware.renner.uno/intel-gpu: "true"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user