diff --git a/.gitignore b/.gitignore index 80ff8df..e31aa6c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ talos/clusterconfig/ # SOPS / age (clés privées — jamais dans git) *.age keys.txt +.config/sops/ # Claude Code (settings locaux à la machine) .claude/settings.local.json diff --git a/.sops.yaml b/.sops.yaml new file mode 100644 index 0000000..bdbac27 --- /dev/null +++ b/.sops.yaml @@ -0,0 +1,3 @@ +creation_rules: + - path_regex: \.sops\.yaml$ + age: age16rg9hnvnu89rll5schg8d2q5sccxlp7cxms9jmflguxapmtjp3lq0j4393 diff --git a/admin/talos.md b/admin/talos.md new file mode 100644 index 0000000..4910a1d --- /dev/null +++ b/admin/talos.md @@ -0,0 +1,239 @@ +# Talos Linux — Installation et administration du cluster + +Cluster Kubernetes **funk** sur 3 ThinkCentre (AMD A10-9700E) via Talos Linux. + +--- + +## Architecture + +| Nœud | IP | Rôle | Disque | RAM | +|---|---|---|---|---| +| compute-01 | 192.168.10.11 | control-plane | NVMe 256 GB (PNY/Samsung) | 16 GB | +| compute-02 | 192.168.10.12 | worker | NVMe 256 GB (PNY) | 8 GB | +| compute-03 | 192.168.10.13 | worker | NVMe 256 GB (PNY) | 8 GB | + +- **OS** : Talos Linux v1.13.0 +- **Kubernetes** : v1.33.1 +- **CNI** : Flannel (pods `10.42.0.0/16`, services `10.43.0.0/16`) +- **Single control-plane** : si compute-01 tombe, `kubectl` ne fonctionne plus mais les workloads continuent + +--- + +## Outils requis (poste perso + storage-01) + +```bash +# talhelper +curl -sL https://github.com/budimanjojo/talhelper/releases/latest/download/talhelper_linux_amd64.tar.gz | sudo tar xz -C /usr/local/bin talhelper + +# age +AGE_VERSION=$(curl -s https://api.github.com/repos/FiloSottile/age/releases/latest | grep tag_name | cut -d'"' -f4) +curl -sL "https://github.com/FiloSottile/age/releases/download/${AGE_VERSION}/age-${AGE_VERSION}-linux-amd64.tar.gz" | sudo tar xz -C /tmp && sudo mv /tmp/age/age /usr/local/bin/ && sudo mv /tmp/age/age-keygen /usr/local/bin/ + +# sops +sudo curl -sL "https://github.com/getsops/sops/releases/download/v3.9.4/sops-v3.9.4.linux.amd64" -o /usr/local/bin/sops && sudo chmod +x /usr/local/bin/sops + +# talosctl +curl -sL https://talos.dev/install | sh + +# kubectl +curl -sL "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" -o /tmp/kubectl && sudo install /tmp/kubectl /usr/local/bin/kubectl +``` + +--- + +## Structure du repo + +``` +talos/ +├── talconfig.yaml # config déclarative — source de vérité +├── talsecret.sops.yaml # secrets chiffrés (SOPS/age) — commitable +├── patches/ +│ ├── all.yaml # NTP + DNS → storage-01 +│ └── workers.yaml # kubelet reserved resources (8 GB RAM) +└── clusterconfig/ # généré par talhelper — NE PAS committer + ├── funk-compute-01.yaml + ├── funk-compute-02.yaml + ├── funk-compute-03.yaml + └── talosconfig +``` + +--- + +## Clé age (SOPS) + +```bash +# Générer une fois par poste admin +mkdir -p ~/.config/sops/age +age-keygen -o ~/.config/sops/age/keys.txt +# → noter la clé publique et l'ajouter dans .sops.yaml +``` + +> La clé privée (`~/.config/sops/age/keys.txt`) ne doit JAMAIS être committée. + +--- + +## Procédure d'installation (premier déploiement) + +### 1. Préparer la clé USB + +```bash +# Flasher l'ISO Talos directement (pas Ventoy) +sudo dd if=/mnt/data/talos/1.13/metal-amd64.iso of=/dev/sdX bs=4M status=progress conv=fsync +``` + +> Utiliser le metal ISO directement (pas Ventoy) — Talos doit être le seul bootable sur la clé. + +### 2. Générer les configs + +```bash +cd talos/ + +# Générer les secrets (une seule fois) +talhelper gensecret | sops --filename-override talsecret.sops.yaml --encrypt /dev/stdin > talsecret.sops.yaml + +# Générer les configs nœuds +talhelper genconfig +``` + +### 3. Booter chaque nœud en maintenance mode + +1. Brancher la clé USB sur le nœud, allumer +2. Le nœud prend une IP DHCP dans `192.168.10.50-99` (dnsmasq sur storage-01) +3. Vérifier les disques **avant** d'appliquer la config : + +```bash +export TALOSCONFIG=talos/clusterconfig/talosconfig +talosctl get disks --insecure --nodes +``` + +> ⚠️ Les ThinkCentre ont un NVMe (`nvme0n1`), pas un SATA. Vérifier que `installDisk: /dev/nvme0n1` dans `talconfig.yaml`. + +### 4. Appliquer la config + +```bash +# compute-01 +talosctl apply-config --insecure --nodes --file talos/clusterconfig/funk-compute-01.yaml + +# compute-02 +talosctl apply-config --insecure --nodes --file talos/clusterconfig/funk-compute-02.yaml + +# compute-03 +talosctl apply-config --insecure --nodes --file talos/clusterconfig/funk-compute-03.yaml +``` + +Talos installe sur nvme0n1 et reboot automatiquement → nœud disponible sur son IP statique. + +> Si le nœud reboot sur un ancien OS (EFI entries) : lancer `talosctl upgrade --image ghcr.io/siderolabs/installer:v1.13.0 --nodes ` puis retirer la clé USB pendant le reboot. + +### 5. Bootstrap etcd (une seule fois sur compute-01) + +```bash +talosctl bootstrap --nodes 192.168.10.11 +``` + +> ⚠️ Ne lancer qu'une seule fois — relancer sur un cluster existant casse etcd. + +### 6. Récupérer le kubeconfig + +```bash +talosctl kubeconfig --nodes 192.168.10.11 ~/.kube/config +kubectl get nodes +``` + +### 7. Déployer Flannel (CNI) + +```bash +kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml +``` + +Les nœuds passent `NotReady` → `Ready` en ~1 minute. + +--- + +## Administration quotidienne + +### État du cluster + +```bash +kubectl get nodes -o wide +kubectl get pods -A +talosctl --nodes 192.168.10.11,192.168.10.12,192.168.10.13 service +``` + +### Logs et diagnostics + +```bash +# Logs d'un service Talos +talosctl --nodes 192.168.10.11 dmesg | tail -30 +talosctl --nodes 192.168.10.11 service etcd + +# Logs d'un pod k8s +kubectl logs -n + +# Events k8s +kubectl get events -A --sort-by='.lastTimestamp' +``` + +### Reboot / shutdown d'un nœud + +```bash +# Reboot propre +talosctl --nodes 192.168.10.12 reboot + +# Shutdown +talosctl --nodes 192.168.10.12 shutdown + +# Tous les workers +talosctl --nodes 192.168.10.12,192.168.10.13 reboot +``` + +### Mise à jour de la config d'un nœud + +```bash +cd talos/ +# 1. Modifier talconfig.yaml +# 2. Régénérer +talhelper genconfig +# 3. Appliquer (sans --insecure cette fois) +talosctl --nodes 192.168.10.11 apply-config --file clusterconfig/funk-compute-01.yaml +``` + +### Backup etcd (critique — single control-plane) + +```bash +talosctl --nodes 192.168.10.11 etcd snapshot /tmp/etcd-backup-$(date +%Y%m%d).db +# Copier vers storage-01 RAID5 +scp /tmp/etcd-*.db storage-01:/srv/data/backups/etcd/ +``` + +> À planifier en cron hebdomadaire au minimum. + +### Variables d'environnement utiles + +```bash +export TALOSCONFIG=~/Projets/lab/talos/clusterconfig/talosconfig +export KUBECONFIG=~/.kube/config +``` + +--- + +## MACs des nœuds (baux DHCP statiques) + +| Nœud | MAC | IP fixe | +|---|---|---| +| compute-01 | `6c:4b:90:82:8e:47` | 192.168.10.11 | +| compute-02 | `6c:4b:90:cf:7f:c5` | 192.168.10.12 | +| compute-03 | `6c:4b:90:b6:49:20` | 192.168.10.13 | + +--- + +## Points d'attention + +| Sujet | Détail | +|---|---| +| installDisk | Toujours `nvme0n1` sur ces ThinkCentre — ne pas mettre `/dev/sda` (clé USB) | +| USB ISO | Flasher le metal ISO directement avec `dd`, pas Ventoy | +| Bootstrap | Une seule fois sur compute-01, jamais relancer | +| etcd backup | Critique sur single control-plane — planifier en cron | +| RAM workers | 8 GB sur compute-02/03 — toujours définir `resources.requests/limits` | +| VIP | Ne pas configurer de VIP = même IP que le nœud — inutile et cassant | diff --git a/ansible/roles/dnsmasq/defaults/main.yml b/ansible/roles/dnsmasq/defaults/main.yml index 482b92f..bc3a55c 100644 --- a/ansible/roles/dnsmasq/defaults/main.yml +++ b/ansible/roles/dnsmasq/defaults/main.yml @@ -1,7 +1,22 @@ --- dns_upstream: - - 8.8.8.8 - - 8.8.4.4 + - 1.1.1.1 + - 9.9.9.9 + +dhcp_range_start: 192.168.10.50 +dhcp_range_end: 192.168.10.99 +dhcp_lease_time: 12h + +dhcp_static_hosts: + - mac: "6c:4b:90:82:8e:47" + name: compute-01 + ip: 192.168.10.11 + - mac: "6c:4b:90:cf:7f:c5" + name: compute-02 + ip: 192.168.10.12 + - mac: "6c:4b:90:b6:49:20" + name: compute-03 + ip: 192.168.10.13 dns_cluster_hosts: - name: storage-01 diff --git a/ansible/roles/dnsmasq/templates/dnsmasq.conf.j2 b/ansible/roles/dnsmasq/templates/dnsmasq.conf.j2 index 0ed7019..19dcbb0 100644 --- a/ansible/roles/dnsmasq/templates/dnsmasq.conf.j2 +++ b/ansible/roles/dnsmasq/templates/dnsmasq.conf.j2 @@ -23,6 +23,16 @@ address=/{{ host.name }}.{{ dns_domain }}/{{ host.ip }} address=/{{ host.name }}/{{ host.ip }} {% endfor %} +# DHCP — plage dynamique pour le LAN cluster +dhcp-range={{ dhcp_range_start }},{{ dhcp_range_end }},{{ dhcp_lease_time }} +dhcp-option=option:dns-server,{{ lan_ip }} +dhcp-option=option:router,{{ lan_ip }} + +# Baux statiques (MAC → IP fixe, ajoutés après récupération des MACs) +{% for host in dhcp_static_hosts %} +dhcp-host={{ host.mac }},{{ host.name }},{{ host.ip }} +{% endfor %} + # Cache cache-size=1000 diff --git a/ansible/roles/gateway/templates/nftables.conf.j2 b/ansible/roles/gateway/templates/nftables.conf.j2 index 60091e0..465f497 100644 --- a/ansible/roles/gateway/templates/nftables.conf.j2 +++ b/ansible/roles/gateway/templates/nftables.conf.j2 @@ -20,9 +20,10 @@ table inet filter { # SSH depuis le LAN domestique et le LAN cluster tcp dport 22 ip saddr { 192.168.1.0/24, 192.168.10.0/24 } accept - # DNS (dnsmasq) + # DNS + DHCP (dnsmasq) udp dport 53 ip saddr 192.168.10.0/24 accept tcp dport 53 ip saddr 192.168.10.0/24 accept + udp dport 67 iif {{ lan_interface }} accept # NFS tcp dport { 111, 2049 } ip saddr 192.168.10.0/24 accept diff --git a/talos/patches/all.yaml b/talos/patches/all.yaml new file mode 100644 index 0000000..442b085 --- /dev/null +++ b/talos/patches/all.yaml @@ -0,0 +1,8 @@ +machine: + time: + servers: + - 192.168.10.1 + - time.cloudflare.com + network: + nameservers: + - 192.168.10.1 diff --git a/talos/patches/workers.yaml b/talos/patches/workers.yaml new file mode 100644 index 0000000..4fdaeb9 --- /dev/null +++ b/talos/patches/workers.yaml @@ -0,0 +1,5 @@ +machine: + kubelet: + extraArgs: + system-reserved: cpu=500m,memory=1Gi + kube-reserved: cpu=500m,memory=1Gi diff --git a/talos/talconfig.yaml b/talos/talconfig.yaml new file mode 100644 index 0000000..9200664 --- /dev/null +++ b/talos/talconfig.yaml @@ -0,0 +1,64 @@ +clusterName: funk +talosVersion: v1.13.0 +kubernetesVersion: v1.33.1 +endpoint: https://192.168.10.11:6443 +domain: cluster.local +allowSchedulingOnControlPlanes: false + +clusterPodNets: + - 10.42.0.0/16 +clusterSvcNets: + - 10.43.0.0/16 + +cniConfig: + name: flannel + +patches: + - "@./patches/all.yaml" + +nodes: + - hostname: compute-01 + ipAddress: 192.168.10.11 + installDisk: /dev/nvme0n1 + controlPlane: true + networkInterfaces: + - deviceSelector: + driver: r8169 + dhcp: false + addresses: + - 192.168.10.11/24 + routes: + - network: 0.0.0.0/0 + gateway: 192.168.10.1 + + - hostname: compute-02 + ipAddress: 192.168.10.12 + installDisk: /dev/nvme0n1 + controlPlane: false + patches: + - "@./patches/workers.yaml" + networkInterfaces: + - deviceSelector: + driver: r8169 + dhcp: false + addresses: + - 192.168.10.12/24 + routes: + - network: 0.0.0.0/0 + gateway: 192.168.10.1 + + - hostname: compute-03 + ipAddress: 192.168.10.13 + installDisk: /dev/nvme0n1 + controlPlane: false + patches: + - "@./patches/workers.yaml" + networkInterfaces: + - deviceSelector: + driver: r8169 + dhcp: false + addresses: + - 192.168.10.13/24 + routes: + - network: 0.0.0.0/0 + gateway: 192.168.10.1 diff --git a/talos/talsecret.sops.yaml b/talos/talsecret.sops.yaml new file mode 100644 index 0000000..f38aea1 --- /dev/null +++ b/talos/talsecret.sops.yaml @@ -0,0 +1,43 @@ +cluster: + id: ENC[AES256_GCM,data:KEq52diis3aWgN/vuCIdY/KEzBGxixGOoySwtMc/wsZKLpBmwETJEVLA3EI=,iv:jsN0iQ/sQ5F6xCncQlun41WDNtpGn4tSi13HKIClfko=,tag:RHEssptlASf/3lNCB/k/jQ==,type:str] + secret: ENC[AES256_GCM,data:chXnz1q2vehtww77iRRXLac79AqigLcAEhr9W8vSwUFtqI/qQl6LPnjpJ9U=,iv:Y+aElq9ISgZY7EpWkTlcy62ju21n8iE3OkYmPzt4Fz4=,tag:F8cepGMpLtP8u/vovbxsGQ==,type:str] +secrets: + bootstraptoken: ENC[AES256_GCM,data:hmOMJikfG1L6q4KGn7yLlaQYqm6SLyc=,iv:GcV2kZzyJQEMoUZRC3aOAfQpIvV/c/K55Lxmxw2pyNQ=,tag:J0La4SKvEXOyubGIOx7gpw==,type:str] + secretboxencryptionsecret: ENC[AES256_GCM,data:bUbpgqjA6UTl6loEjPLf0q7TEJht5sDgdmuNtRlIol5GeTlY+xPGsC+53RU=,iv:tC8PdBU9106BjAkzzCgghsrac0+fWkGjNYxAqlqJcs4=,tag:pcNScFslsEtCDL9LLkVoVA==,type:str] +trustdinfo: + token: ENC[AES256_GCM,data:WbXgkyRGKMMfoYKiTHSnultHO3urqZY=,iv:Axp5p4R6g7Ko3d7TT/lQN4MnerHRlF3CQ4jxkXXgsiw=,tag:AtHkrgXqdtlYguj3EU9w+g==,type:str] +certs: + etcd: + crt: ENC[AES256_GCM,data:umCSD38OP8/vakXZPDtKmQBlUMtkXdOR28FWk4chQwhm/oFlYEhfVZxQoabe53CcQ5WwL+I727Ydp1xCYICCmEWLRnWf0TvmBiE407DRKhOdsXrJ9whPP7M1TKayO94SZqxqRaniJj65hP3/brh3p65K3Mff1DlCRKf52U5v7Mkm6iz25JiGYCM9Kpxi4sjcfiqi6AK8xHVhfx9sjTuxOD1vIDUvk7K2HAYRUhcyQl8e08ldePpke6vV9y0Qe9QhvmAvnkYNxBpwLOp0+TAng/nueMoFZC/jC0E1KFAO6Osk039om4VqTY4tzefpLIgepS+p6cR3OYnQiw6ngvAF+tQ8mFJ4XOTBBEDEtmRiZPGk7lfs7lZvUL4DjjSCKT+1M73I5LW+8+JtM85enTU6DdjCl87EI7MoslO/Dg00JUp3DKiUi4XHqoNiQm8v5Q8NHHKuRZ3q0f3Bht4taABmBom2OFajLxyH1b48bLtEqOwmw8X9CBSyDkPchDxgO3/IlBbNuh0f14Gsxw92Z/UWcaA/sWB2cVnndFtgKvgjFtiW+xNgTk36W539GK/j0enyvwEicwxmKtwJooXXRokfJvcFFALBG9+f9Zlnh1EEVinEhhhrBh4iBH0N6EsFEaANeiiRm/zz7hYWILjHAOAAIbZBKjoTTOg+RBFZW9HGHbjLIbDIDOc6tN2NWDnwd3r+6H5PHqOcqhKN5F4CG7kXSugHORARIlm3YnsLN1BoqItRmEpcPx5TO1NMLBa5UylahYcJizQ+ubfNmyelPvcE1dQOcE0nJTd0E1zduNlwjU2MSUJQmlSaQMPgTYlDABNGoxbpOtuyDTjLvT6gLQwStByfczvNVfcqdg15BjU02xtGS28JgJWIACyS4qyIIdFdmpHRlLcQCr89KWwJ8UXoup13oRdJS8lIzwKhgPFhZFuvhIliGebSaUP5FDL2rS6Q9IrF/X+D6qO063JgTOV5y9s3wjI3dN72hMbttDamzBhlr+lH/uBN6dcEzYBXnYax8+8KJQ==,iv:CmXCedbhA7aO4FlCwlLdum3rW7ac/udwwuoXeeQO8+s=,tag:Y4hlkBO5CbBWPVedhHH0tg==,type:str] + key: ENC[AES256_GCM,data:58POYWDhZ4a0LamqoxyF2yJkoHLIKPzA0Q4DiZwlJKIyPf+2wrK5fsLI3qp4qVTDBj78H1uai5GYvtiJwG4+0xbMlIBkzHeIyURQFssuyrlKOO+qBjzPks4zLFLTi2H3ETT3KfVvR72JksP9Ky7VJzayeX+B3RHn9mI31ajjajVaOutxunm3/vx63+SHANsfGDWkCIMsDSWYmUbf+EnlRiRjAXyPddntRbRyAysurfWmDlSfe2Uv6nTI8vatF1dzZ+jW2/o5wcEEzM/Tw3LWuw55AunFoFIcB9mIFiMMWZlB21Z8Ap6SO0JxjrLloMM4WEfPy4qmQ9FcToalxHIjH+u9rVfgl/5xGSzlOQzV7mLklKigDNs70cV+06+zO0p9k5GwRcjCBA67vPjurEJSqA==,iv:QqRPX8Fb5XUjavgj/eagLaHiE3XlLZ9gWlwU1UxVvxk=,tag:mxmklGAUgEKZbQXnhwtCMw==,type:str] + k8s: + crt: ENC[AES256_GCM,data:30pK5IFhrs9I+WIaivpwFfQpzYzfJrPWrIrnsUkentLVuJuNmMenZuuW7QZV8wIX+ibWY18UDfXoNX/Yxj3mnJSYtG0ghZjOpiAMQFPv2QdOwxhsnct6WRqILTWdA6mpQ1vVNvJNhe1JwHTMBOmM7AwsXoMrIUjzJ+BKfErIeW5Tei8Pyo/XDIN4UtPG15vcanYpYL2cz5FjbHvFR37Rpqk/X4Zzr2PsEvsCWzEu53IOnevVQ0vnIzO20nJkxbEazhx0EXRpk5sFzjThoLdWisdOnxsk/HNehd18xFk1HFZAwHVANijEEdTtdQWIeuegv1VfU6kXVQy+g2IN2pWIwicxBCRjG/kTqBiJoBbta5kxSTTmQksuuInxmJX/7dvGra8SAoRqB31VRq6m+c5GPoqNf4jiij9nZKbnw8jzQt2Sa9m2m5B6YHO4n3zKbEaYW8LAtyzlvABFiFFD65LPupSbgR9YT3owf1e3Xz6SIS7ihIQ7ynCNUSodUtZVifKVGk3mf+/ktIP02UjEESv8ALI6pD3fljap4VVsm4iSH/nxsSAqPaCurs5msdhCRzXbnqPhGu2LvwR8Qpr3poFI8xnoy3YQHCbZQz2Jb0mcBTCpsvCaELyQoms9BEd04/5765wao3Vtxu8ivT/yuAnPYBi1DYjZckRUfxJjfIs9cP8z7Z1nVTj46ZMX4DtVLFYQcIXLrhzdgPZGuf62tcqZoG9M+0k2+hFTcY4RB97gN8eTw/DZL5pK2LUgm/AYPjsVlaOlpal4LR4gsDUU+IsSzrjHMOYU+7VRAHiOV8ybmE5JILogQyAammPejKzEoFa+CFJ2yqNR0QA/BKpErcsvA6kplXYay1uiqEeVehCTuGOuqn15nom2lkzFt0IS0E5EmHu0REckXFa/lsOyp7CO5CL+ZjawcJCd9nEQ5WeIhfYytxfvnFcL7xmaLQDWiSfs2XtH4l6YwdKo1Mcc9xsvQ2ZSkOqakPwbTMAfRhjh0oILdZJdEjNWkZSCTrS6ETDxcmX9yZLZSz/Y6vCyhJpNd+iua2FTkziDMiKLvg==,iv:sk99hmBPuFx5aEq8NkVMIM2hDiUh/ZkfLbegwQTRVXI=,tag:jPlbInONzj0KiNMTnbDWqw==,type:str] + key: ENC[AES256_GCM,data:xhGmleYsEt64tV7iufPmdOihyOrrgLVeKktjP0kgq5zZE1Rbx/zi7uZYIHE+dFsoE8Db5KigYiKDYdPIox2MW4KEBZkyPWWS09LRTOmAfCvNDOVXinH+cK7sSO94ahrKeVDToIVE2ALqN1DD42v5gBYUA2GveETx4ymV0HaOX0CuPJ+j0hMRr6mBkRrUbYNxrUS6zse9B57ArgjzDrcF5Y0+5jhMAEbBb1o9tjPv5INm4hZK8naAKIKFTyYtupEcouo1PAq7yK6VmNGi0UBygGE0b0j6GXcWbc8C0VTLgrZEj5GAzSn+HJ/bjwqc2q5KhLivSiwBETt1zyUwxQT/oQN/x5k5uatek84P6nq+UMKvavFnA+rs2OtaDeLWG4FXY9JAUVp6hyz3sShBzWwc2w==,iv:5Weecm0lMGyRCvsoRI/Gr80DvmYKmtpsGIlWbND8wDk=,tag:kri3oSHEzMb7sXELWPQl8g==,type:str] + k8saggregator: + crt: ENC[AES256_GCM,data:Fh0nbE7Pv/GVrFq9Z9oN9lSd+nXw9hG+cyWCEcOIgKOLAT+xWfZQ6SY53Pdib/esVcompMcJNnDRgHbvRIcPGzGOB+Gul6RO7NThSrVRYIE1LvhksDSWiMaAAhUBl2t5NPZ1CyLa5dwwK2oOYKfJ/iUAydADHKG61D+Tv4ZEa+8FYIUqyKs/sYfb/hliA5pgRZjO6oPwfQuvXpoLQvP4KqbRNaETVXPwyapV18XwehJubdk/3jXCZ8lrdU5ekT8hep49BkD68/LGC9ufrHDai8oq4SLGPwqig+gNypJP/rsaJ5LSMyw+AcvXX4/whRZrqmJ9qe/vLfo64McGTlvphwFgnxh/guBJ2CeebozEurhjCoQ4JyyF9WjqhN4pC08ORUEEZZbYvTnsiJSHg/9ewdbtoHpROmdlghXoL0N/le6oyEl7eF7vkZxCHv85xJV0vFyyh08WsnII8QVycGN5YJksmNIxmkoq7pEYICSKWvpxccJsAX/EcjMnz4c0BvqLhQ3U+VQLoRBzifLL0XbI7X+8eo9ziEogHypLFP7YpFru9UZh0afGCSJmdQD0T6Nwp3RlCA0cLple7ZkPMq84YbgV7gTH3CrUO0CDqZly4Wkiz/Bgo0Qjmj/n/cb11PNsUHWderMdfhOGtW4ZtNqb3HR4jb2RypuK7JJ4MN9EefPkbeZibq8RvNZ+dEDkeW5d5F4hH++Vyl5C6dypFetkPsXqd0O22wONRjuJLq3H1iRoXOkDVOxKHHEMduMbgKzxqRbUHBnhIfTKcfdwOPzhHo3LM3duYqw72/Net9lnEAiTYh6Bq63UrecIWqsKjhc/eOk7fp+Bm9FT6fhVuWHvi17qTUmaDTU404v4pdM8naFs0YaZaWN/qNmfJnT6Ek9NMTU9q3vxQBPGDtLvfZda7740aaF0aYnOsuevvazVZvCKGnhITRaeNQ==,iv:BLz5/ma1vXlCj8gu0gyRjeMmd/qMHE6b2sd49O+Lg7g=,tag:z6HNNRALG6j5fiJrdfSYWA==,type:str] + key: ENC[AES256_GCM,data:5iDFW1cZb8kQMZY4sOQJoB/Tr2EAm+9dQSuHbxId+T8gptPeqe+PUBBhmACh17yXPQKVsthn7RgHqHstuHAz88kWm5AZ96l0NgngLUZMQ4UD+nPDiHY9aG5V8fkFkNa3akF2KBdcemhdczrSl9JV0LIoL8yMdWTtNMGiGO6KmG1m7axJ8Kr+v8i5JPGPlR0sFgoVjzDIZszqZnqs/ydsRf34bHqibpxvS1S6YHVnbRt63JmW8h0KtijNN1qe5M4sT0zNAUKwDsH7OgH+++yRzlH2KjyYARNXPOjG10haOXxHetccZ3w6gb3oSXxw5eFa0/hcXs0sSThnVQi0BAF0jxG0nLB4itFbLa/RMv3YlfbvDEr8+VvZthgR+OfmQXqpLKVhUHE3d9jLwWZagNX4aQ==,iv:M31FaRrIhd/Hbe7RHUD9R8AXbFw4ZWWpq1DTzBUgdkY=,tag:8+etTIyQ7eZkgq2TuwqjFg==,type:str] + k8sserviceaccount: + key: ENC[AES256_GCM,data:OaUycm2nJKdNVaMtRxhlxgXHt3rtZvfm2tM6nyve/Pl8jYsKqwV+YHBhA1b8r5To/CULr1A1kEeX7Kdc3p8FLd3xIh8C29oOqpw2rr8lka5hX/eKnYRSvIqY74tqRFA9wYNPQHTu53Z2vCwx+JOr45DqlQiH11x+qR9kbIRoW+2rPg6mPxKUN6xtX0ms1AONjtV1/QH6dQI0DByCyAKPldYrLBhvSyesYuOB7b6Plip3bas++scxaPLO23bn6NAu3SgIspuOsSh+GK2jdP5jyLFzAZXmr+xPw2OvchinJ0ZJFhDpjIXN6/qq1WL8n8Uo+ftwm3VYimkIwQyJ9qeaKsYh54shCNaA6vwv4uLVm1AIdhQQmAEDm49op9oeMp30d2zXQMJH7GYzDsqFw1YOsTIvIrEQ9CHFaKU7eIkgg1HrDh1cEAFiGONl54PEy2gWs4D4W2CyJ+rUz70rD5N0py1G35JMb5EjYh50tMXz/ivtA9g/X0mOIdK+wcNp+p+Io9i5X8GGAiMyVPBpQ3eYM6mp4kiUjoDJAA1O10exHDg1CRsF035oEZDdk7RJOtLYUd68HMqL9hShpfZkZLgo8jYsDB7SnPLn2Cmm8Rlwn0vGQFd+lCVO3pbnxfCCVZWnMNW2eQ/A2gtRJhDTE8ZTCZwT4KVPdzJb4L8LPm3C3sHUjXEmIBf0PoxBg0MzKcfcw+dHC/4nkcd5k+Uee3NPleeSwdwdN1MoRmtpCz3J+T0RgcX9Xrrjew8A2DYk9R6ejDLhDulRNiga+1CHbV8nx0NvBFjhx149M0O8+vKQgu8HkwXsv5Mz9P9EXFXX42E/DL1Zaq/IhTSDI/00TFzGVY3fyKZRllotgel5Wql0yuPIIlQQtGpafcTh2dZ/4ugfUjZ43yoUG9ThKgNiPeQ62ItZ33ft3ejSW70/yyVmlNCh2N8iLIZVfDjTS6c4TS8CdTnTH5r31qCdeZqGG0siIHzPyZq41Bnvu+ghh0qqG1K07bvZnzkK9KL3gI2ZttmXvlbLGub2fnIzZe4NguKPRPqHQ1KUmt+wkH+DWeg6VMnhRbCCPh70isE8NvRZ6PUlsddTdZ49ewqPjs1oI9B1UH7SudfTHw7eGeROF0okXERfIh8S31rvEVS3z62pO2vtAe6MQLaOQBhDiVmtcXWx55DNYfo7hhqz4MuqncIjnmbkjnbKKcu/ASd4L759qlnPpEJdx43TyrUnhzPxZEjJylLPL/1NdAzZFajUzyIL/XhEPlpcI+tQcuHEYTPiYsCKXKpe9xPloZgpnhBL5OR8p0pVY3GeL+iz2bC6elDzfMrIzbhgjxl2JQI+raf/9qGAXBwd5DjIypLUc++h6zwNHeOVc+iETIKjMTTE0l2UV6u352xaFaIYDnuPE09obI1suv2HiJgOFzBj0rMdNHtF8/ez1tixpG1j9FttkpXAGkJwgUf55xGShh4DZzSXZ3t4hnnGwNe5cKV7R90NTNnt87HlLwK+nx1VuI2XAf73YeePb1nVyhMbE7ubFWe71yFgh+5wPNHL2mlMZ1zVG20uEFIqMHCDYZrRCBEZjRNLeUB7UjxIebaQCepUW4BrbvDNL11lxqFTtTF3obEb6AIiYUujTu7OpL++ZDsEFFxDWy6mKcuQi0tMtrkgQvQu438tbnvMzz4Yx4N6xG3WyETCAbpXWw35bumDSs4JqjT/Ge7qCnPX8ENJLuhtfjnRGp+wwa4ki4rvDR84vJJ0Jp7hp14A6PaYEthHhH+Ew2IRrs3skv/8KKDWGceGYuIsO4hjsRPc/sPxYYZlo20OfjqPDt4p3Uchw60VSA9qlAPjTY2gsh3B5oHy6HWz3EAJyl3ffqt72+W4LJLthXgdFzBBpvJgMTUJ6rvOoyI2R8Y4yudecoTKXoc13DXfZy//6LosYij/VlfuYKbEe5ZQLAi/ah7bywgVr1eDLEL6AdIjMtKIRFxfe7YqmcvwvhHosiwRIxnA38/wmq3ae9PgRP4hzRTgnEjS+jtUK0taSB5HzRLkE9SqFEBdVA2nXuOe4/o8XKUnR6Be1ddqlBW/UPsqFDmHSJIIPiO9SOnNEhymLt9mFqHmWDXO7YHQ6YCu4yAsy6sncZPqgFMECJkF8/RrTXiQn1pT8InB+uJnDx7230BccQTGJtor7+1ywPKuRxNHtpze9jJjxYSurNdu9wCd+wMduRiwjOD5bjC6UfZGa+OJTPw6zMJVZ39YIru7RV4VdrURC/29qWqyKgvHK3Cri3jLE+FLAnK7PznHI/w8UyI6DXkqCC1rODLkJwQl1CC5ND4GwkiA61A1CcWqnj24+dfmbgl5KK9xXA75JCfNGaQiCYXwOo1s5CUuYw01UeraAR1HxDG+4xSjv/BA4lh0OAdbEAe0hjX7zharBjomk1LJDIuVUVRVMfzgv06mGfFBovSR2j5wxVgwcht2MqZPAaiJI90rcX14jZISnqbPSsrN5T1mXLl1kuf0D904hGhsCXU0VW5R+97sn2pj5xqIkxGxpBd8Paupogs099lkW5ptXAXPyA/9tQX0D8gxLLlDDj4f/nQuAO6MUb+DeluNYp6sQL8GjQMxYqSnQUpn4rBlFQIAC2As+pdyQeTNXdnkw06Nu11Pvf7dACCXBB2tfg6JBWzOtEFe0UiiyfFhaxfTwFFnaIlwsEeYLg9CzxcJ2+exYmOScm1X54AQVcxuxwxZ6MoMEQ9IfwLrLkFOdWwEpSfEZDkN5QTA3TnYe7u8EIaM1C9ue2gD/MhZHUZmOUA022WTv1E2Ugmw1wuVZIy0KhHuD8Bimvh8wSwGTxplm7AuZ+8LEn/kmpUsja0OUBu8cEZJ40SncJCy6LW6RjUymvUbEC/HCLONxePkIax4/vTocN3JsEoPGFgK0Z/xRqjghnwgXnURWVLH3F2O0PDJTlieXv5UzF4qUMKIOtfTaQiLt7Iz9Fa/uNqgYm9arw9uXn1C18KcbcO9c+8oj3fLc3Nzq1Jv6LbxddQQ+B6CvZwJRMWgdY5FH/wssPE4ClyvPEJK/HV7AkUnput/cAyCSW2tTsc/etpfbZaR/4IlaPVnBEN/28099cLCOJB19siadB5VhznJW82lwbXc0ACskk3XnKhuw+ya0raL/fuSCURnyFSuXH935dvCwz83vt+SS0v8UZzGNhIMVrEeqfE3nbyBTL3UnOrJ22RFD3hIfGSAugzncMRIjmp8dOM0ZUhKD/27SHx9jkEzm7PRgSh/OjhVaAKH/bYQWVqUTIc4IcWQm1pDiGa7aPsOK6U5i9UjHuqCmZg/Fpcolv3nAVAj6DP3km1ee6fMncvh1hX4keTXsF/fawkNY1vI1V+4LGhVh63bLKOEtV0BE2kK//ccXLOQ3ERDEMAYfYLN3MD9Omn7I6IiXxA7pD4fp24pU2rMQbqgYUHZ0RQUrFKkY7lmFidS7jy/ltaC1FUGDRiZM4rKGAc8KGw+tzPbh/vYSZ5bACGkBcUEPu4rf5bTc6xlWBJZmMUYK6C7iDWSbBzU65aUt1SYUM0DGq4Z4eumf7/BIymhv0Lt6TTHRlMvI+Syq34B+x4fqmOg20O9qAgt1A+wnLjweNR9fdkHhjYuuQa+ANZl9hIFOk4uJ/VNut8p5Nxkxfv77qRFBW0mqge0pYgJOwLMTCj1JS8bu+TpjzGYi65oRmYQlWHuzNAxpUN4DSha16TEwIdO6ZtjRgm9VZvSGLhA7IuwpgWPbZkGi77jKDLf+n4WKCkzRJpmqHmGkKjdMFW+WrDF05EQdb71sXBRSggL7DtlQcOyGANlzqCK6Z8qz9ky7FCeKGGGPppjf16VHt8x3dQ0YaTWWqibgcETvJCkZ7SWEIG/Ha8uKagQ5mBVptRZ3Q0El9CuBThBLiyv01A8XjcWH/Z3K8KBeHe+ac6grUI+I58Bhmp4IsHdxMRJ9yDpNF/uPi1SNXhhlu5jMMEkbNY2hJMROscX4cI2Cw9s560c97JF+Cdk9S7O6eoYgrqzzzyN3GXlG2SlYzhDAtbJi6MsDc/7XMflsG58LT2J/sPmmTt8rsIw36ohtERq9QvGKjIZiP4V+vy1kjmILK3GSstgeGMMPrWnceoBV1cmfFPTo5Y2F+uJ0lncTFULl3xQtgc5paxuFzGrBysP+FL8Bc4Wh8H9Shfczc6ux3zGlKTiBPwd0Y1nxnIBUu24xKsDi/nkdjYz0x+LXBT65bSfmRBEbgIA3gEOyZWbZc7JX3VjYp037aYHCpo7WGKFYV49fM1W/schvf5suXlnLB4kicYmnn8SbCPWTD3GREw2zACfae5VTEGqnP4izMMM8YLBIe3YVnU0XYRFQPm1UJkJAj7mMzIR/DZGVNWxB5y4GMyfCC6yiuw5CzeL7mhFIjFkyqRen9+sa+5o+wKtm9bnzr0RlAmPdNvXxYaUdaMikrtNVYIaV7njFs8jqCYkpXeL5x8+1W6/1Ip/cQoT7qm8bDOw8vtkokUuzhNB+Sgp1Mt5digzs72PFBWwElw/EWxADvqKTENUknlQsbCyJU/i3bx1DxUieW4IbtObz9QBFcmD3PU50Or0bMLlFqYrYIHL1jgEN2bCdBJ9YIunBLdqLaQcDc2IQ4ke/ShjbZyW7cKFbA1iaSFbMxC+aLkIiPeRo6cfCApY4HpVnBktWZWCcaoPfZq34PrWg8oiMwRE1+TdB1MqoP1YkEt9I3kWXwIhKvqoo51HjxPkNkyKB9fesTqEf+RIyT9ouQLtSlT4d6GPnyMRJ8WFNS190Q9SC7mPiGoHV1OU8QSyf8VbxlTdfUAMoTyYcM5I+8lPkvXvNGisS5brk2B9fJgAngzovMnHnJjj95ucXSWjmDPa+Xp9JDtXLbZnl3pfV1YMx+8gU/7MlOM7pQnutGsXYitan+9em8ogYpR9S4Gm2THBlp4qVcd6oGzEplBsfaUdCCwORKFE7wCi5SVh4uzpqA9b6gNeQX+wB1QvDqJ6Wwza1AXD42e5wLaLKP0hWVrBnvECWQaAz0e3QHg1Fk8X6I9qcDx/MtkPowpt/gOkv62NR3CY56zZsFwcxdEow4yhOJJaueRFkVhF92T/pyAFocdeczmDn3v8VeggJJ/mOwhQ6BryPJkB669LtDaLiDuRn4EkSBoTf8xXp9FOcxCBn4bmi/lXo9pzeaFaOl3C9r5EA6ORhJV1lGQJ+wAkPKkXtRcN0GEkVIqJ9/g1oO8QfS/oUUNjRxeG2zSQOmIo/I2L0BPe0n/70/KJheUD2w0bQWii9Qcq2DWk//Sdcy92RPnOAxBenuO8X1V97abNSA32cMxIEGBjExQneqRoFBCzhSgU7PwamnVYvHvR1iXIG7pV5oOfbPJf6hBXrw7FRH6qw8s/bBqACRMEOn0tPIIho+v5S3NqMoaKQpWPXRNR0G775Uozn3hkfaWgQlyFADrNwIaH5a2+cc+EZKxHtBAG03GEAZPQiOZN1mjlLpVRD6tjnDe5PmyVfQtuDKisqslTgcWsbmbOfhce0uGYvcUbcKSb5oziGDZSI9Up/1KDOfxHQFAfN15t7t6GrZxiDmDP2CJTAdQE8amf2Q5WUbg4ogF9WBKREFMkIOW7EJJwiMF88N9CFwudp6i6d8ZNAE+DV5K5imMhCuBHvl2yVcNr5WEj6WxIzQZhRn8ArrV7MUTj2AYBsph6dk9FO0sjpPgn20pvjm3s5tjLxSd0v3xtB0R8DXlwsSpoyvzTk+zSnBnXqMo0nQz6eQH7Xd/p8IkHqfwdYe3F4rBCCfZhChX5Vw==,iv:RXNV2EPCIK+GzJGZWlSOULK8Ttb5aHWhBEw9ERf1ucI=,tag:S3PVVYwCCdhB5AVKSBsPjA==,type:str] + os: + crt: ENC[AES256_GCM,data:oOe7Vc1LENade70jxsZzp6F0epjrw9AUQ3MMoNqm/EN5F5rt6A8HVH9nDJoEb82zVIr914VA9okl4lXZ8+FgPhl3fHMfnpYkrulFjORupuPDXFwRsrZm6h4r/Baq3s0gne5t8sj3kMRlNZpymA/y9YbTyfwdIosrUU2bIVNIogkwe/QmqkFl7KXq5GUZK3EZd0RL5prdBo6TswaFs/pDer9Nvow7n0MaluMaHlq/uMubkRZHlgjoXu8R+M/wnfKgEF9rlFUXh7swRcgSaszRnDl3bAfndUaMBM5Zr4I/Gy4j+z2w8FxEop5cZxxuZmMMYvUG1F5M+3B5PWB8r3A1vCB4YHg7ceNYWUYYz1RmSXuirlO8WT4ZNTx6pMi3g1MH7FYhrHbUN0kvo8jXrlGmlKzS2DFSrIL0T2fQ9yc1yFK1CPb7lF0wFTuKpvhJaeMOCRdrR0Nny20RACeQJ8yyl/cCqbdE5QrXp+7LZ7WwRweWgYKDH4+fr4A4nL98KNiLcxYErNuk7Bj5tPBMkn4oUfwZ63nJ5GxWy20MchprX1PIpPeyn4tsL3/VYCASg7IT0KKJQsIvXE0f+qqGM/fYOd57AXFgu2QyzkaRWKjyIYy81Sh4HMihseJmaOVm7IesOYKV4lFg5/B69c47QX35K+KwlnnnBk7Qu7OU8tc3Cv4JnObdCwzK7KjJCX4Oegc+KEpk/q2STgsuPClvYxDAKvTgPj6l0vJp0JPz+2u5o9OsXQBG6EhzvNRATuqIhLVzbFpgNOptG+HDtK6GrNXBOu6fAwsaGVGYpsiXYz+Uq60Z99mQ2P5RYeN+Bd6zItjzoK7Zz+em8fSjkDVHxn4OvPkfZcH5jnF1LiJquomRg90ZKYO+,iv:dzXInb/7GVmV7ojRMnVUAkVz35zgjJojU+eZo00F1yY=,tag:F0CYNYs+brlq+UJLO/BCSw==,type:str] + key: ENC[AES256_GCM,data:0k3xMx/k1y8cOUnpFFvekNwo7xfLE9eWj3N3Cnm2NjuXCXTCPz3CD7L+Aown7rJd3jTfY1pQ+YxWB7UTncNv4HgObCSYtjI/CL5FZEjCcQe+cjirunWkGEvY13BIUAIU+8vbc5GT4viWva/Mpv7qGjI7D5CGo5rw12O8qbTgYco5/kTAELZ6K1o0tihOZ758IfaS/y7/+GMH4+8/67vFQQU2hHri0PmgGw40Pqn2FnNx1Efk,iv:0EqgG95EbvdMR1ei2xmd2vIqfbgov1IHdkpNtskJwds=,tag:YR1a1Ylstjxrn3KwFAxwIw==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age16rg9hnvnu89rll5schg8d2q5sccxlp7cxms9jmflguxapmtjp3lq0j4393 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTaXRiRU9xZms5TXJZaXdX + NGEyQXdlbFNzOTdteHo5SHdqZ0lDdFNnM21RCk84TXpOZWVEZHBwVEJKSGcvM21Y + RWlrdTRPS1J0RVR6QWxNYWJNK2YwYWsKLS0tIFFzT3RtNjlCV2N1MXZhYlVhZ05J + MDRYZWc4SGhnYjI1R2UzdHdLVDRNdW8KGUQhKjxdK6CM+KUe6AgnbOXJmgD3pDjK + vBZ9WmfZFsd1sVksQTofTX9z4b1Ofc6HMc3FAvTj8o86aJfvSNmGfg== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-05-12T18:46:03Z" + mac: ENC[AES256_GCM,data:tJ0rCfSdJoSh0Nc29S/5/VspZW8QjNyvnoEZZSn8nNx/XxyyvuYOv27jpy45jktZWTKDzoHObGqkDdnEMEmd59vLoGD7GK/mmU2biM/MNjcKf7Xbxz2DcxTtx7+bPH+FJxM9ECxoezJ1k3dLGeHdvBNEgLExaR6d038eiDrfVjg=,iv:5FEZqTxrMjpPUHDptBm69+RLNB1wiJLTRxVyBICV4Z8=,tag:aG963eiS5FKg1PR7Fhg98Q==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.9.4