feat: taskfile -> just + rework talos config gen

This commit is contained in:
Peter Ahinko 2025-12-25 23:20:09 +01:00
parent e4be384103
commit 187ad31ec2
No known key found for this signature in database
GPG key ID: A49FDC84B6AD510B
22 changed files with 462 additions and 584 deletions

27
.justfile Normal file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env -S just --justfile
set quiet := true
set shell := ['bash', '-euo', 'pipefail', '-c']
mod k8s "kubernetes"
mod talos "kubernetes/talos"
[private]
default:
just -l
[private]
log lvl msg *args:
gum log -t rfc3339 -s -l "{{ lvl }}" "{{ msg }}" {{ args }}
[private]
template file *args:
minijinja-cli --config-file "{{ justfile_dir() }}/.minijinja.toml" "{{ file }}" {{ args }} | op inject
[doc('Install Homebrew packages from Brewfile')]
brew:
brew bundle --file "{{ justfile_dir() }}/Brewfile"
[doc('Install kubectl krew plugins')]
krew:
kubectl krew install cnpg rook-ceph browse-pvc view-secret node-shell

View file

@ -1,28 +1,6 @@
{
$schema: "https://docs.renovatebot.com/renovate-schema.json",
customManagers: [
{
customType: "regex",
description: "Process Kubernetes versions",
fileMatch: ["kubernetes/talos/talconfig.yaml"],
matchStrings: ["kubernetesVersion: (?<currentValue>.*)"],
depNameTemplate: "ghcr.io/siderolabs/kubelet",
datasourceTemplate: "docker",
},
{
customType: "regex",
description: "Process Talos versions",
fileMatch: [
"kubernetes/talos/talconfig.yaml",
".taskfiles/talos/taskfile.yaml",
],
matchStrings: [
"talosVersion: (?<currentValue>.*)",
"factory.talos.dev/image/[a-z0-9]*/(?<currentValue>.*)/metal",
],
depNameTemplate: "ghcr.io/siderolabs/installer",
datasourceTemplate: "docker",
},
{
customType: "regex",
description: "Process raw GitHub URLs",

View file

@ -129,15 +129,6 @@
commitMessageTopic: "{{{groupName}}} group",
},
},
{
description: "Silence Operator Group",
groupName: "Silence Operator",
matchDatasources: ["docker", "github-releases"],
matchPackageNames: ["/silence-operator/"],
group: {
commitMessageTopic: "{{{groupName}}} group",
},
},
{
description: "AliasVault Group",
groupName: "AliasVault",

18
.renovate/overrides.json5 Normal file
View file

@ -0,0 +1,18 @@
{
$schema: "https://docs.renovatebot.com/renovate-schema.json",
packageRules:
[
{
description: "Override Helmfile Dependency Name",
matchDatasources: ["docker"],
matchManagers: ["helmfile"],
overrideDepName: "{{packageName}}",
},
{
description: "Override Talos Installer Package Name",
matchDatasources: ["docker"],
matchPackageNames: ["/factory\\.talos\\.dev/"],
overridePackageName: "ghcr.io/siderolabs/installer",
},
],
}

View file

@ -1,34 +0,0 @@
---
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: "3"
tasks:
hr:
desc: List all Helm Releases
silent: true
cmds:
- flux get hr -A
hs:
desc: List all Helm sources
silent: true
cmds:
- flux get sources helm -A
hc:
desc: List all Helm charts
silent: true
cmds:
- flux get sources chart -A
k:
desc: List all Kustomizations
silent: true
cmds:
- flux get kustomizations -A
wk:
desc: List reconciling or failed kustomizations
silent: true
cmds:
- viddy --disable_auto_save 'flux get kustomizations -A | grep -v Applied'

View file

@ -1,41 +0,0 @@
---
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: 3
tasks:
delete-pods:
desc: Cleanse pods with a Failed/Pending/Succeeded phase
cmds:
- for:
matrix:
PHASE: [Failed, Succeeded]
cmd: kubectl delete pods --all-namespaces --field-selector status.phase={{.ITEM.PHASE}} --ignore-not-found=true
preconditions:
- which kubectl
list-not-running-pods:
desc: Lists pods that are not running
cmds:
- viddy --disable_auto_save 'kubectl get pods --field-selector status.phase!=Running -A'
node-shell:
desc: Open a shell to a node [NODE=required]
interactive: true
cmd: kubectl node-shell -n kube-system -x {{.NODE}}
requires:
vars: [NODE]
preconditions:
- kubectl get nodes {{.NODE}}
- kubectl node-shell --version
- which kubectl
upgrade-arc:
desc: Upgrade the ARC
cmds:
- helm -n actions-runner-system uninstall arc-homelab
- helm -n actions-runner-system uninstall actions-runner-controller
- sleep 30
- flux -n actions-runner-system reconcile hr actions-runner-controller
- flux -n actions-runner-system reconcile hr arc-homelab
preconditions:
- which flux helm

View file

@ -1,93 +0,0 @@
---
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: "3"
vars:
CONTROLLER:
sh: talosctl config info --output json | jq --raw-output '.endpoints[]' | shuf -n 1
tasks:
wait_for_health:
internal: True
desc: Wait for services in cluster to be healthy
cmds:
# Ensure CephCluster is healthy
- kubectl -n rook-ceph wait --for jsonpath='{.status.ceph.health}'='HEALTH_OK' --timeout {{ .TIMEOUT | default "30s" }} cephcluster rook-ceph
# Ensure CloudNative-PG cluster has 3 ready instances
- kubectl -n databases wait --for jsonpath='{.status.readyInstances}'='3' --timeout {{ .TIMEOUT | default "30s" }} cluster postgres18
talosconfig:
desc: Get an updated version of talosconfig
cmds:
- cp {{ .TALOS_DIR }}/clusterconfig/talosconfig {{ .TALOSCONFIG }}
generate:
desc: Generate Talos machine configurations
dir: "{{.TALOS_DIR}}"
cmds:
- op run --env-file="./talsecret.env" -- talhelper genconfig
sources:
- talconfig.yaml
- talsecret.yaml
generates:
- clusterconfig/*.yaml
- clusterconfig/talosconfig
apply:
desc: Apply Talos config on a node, NODE=required
requires:
vars:
- NODE
dir: "{{.TALOS_DIR}}"
cmds:
- task: generate
- task: wait_for_health
vars: { TIMEOUT: 30s }
- talhelper gencommand apply -n {{.NODE}} | bash
upgrade:
desc: Upgrade Talos on a node, NODE=required
requires:
vars:
- NODE
dir: "{{.TALOS_DIR}}"
cmds:
- task: generate
- task: wait_for_health
vars: { TIMEOUT: 30s }
- talhelper gencommand upgrade -n {{.NODE}} --extra-flags=--stage | bash
preconditions:
- talosctl --nodes {{.NODE}} get machineconfig
- which talosctl yq
upgrade:k8s:
desc: Upgrade Kubernetes
dir: "{{.TALOS_DIR}}"
cmds:
- task: generate
- task: wait_for_health
vars: { TIMEOUT: 30s }
- talosctl -n {{.CONTROLLER}} etcd snapshot etcd.backup
- talhelper gencommand upgrade-k8s | bash
write-to-usb:
desc: Write Talos image to USB drive, use configuration to determine architecture and schematic, NODE=required
dir: "{{.TALOS_DIR}}"
requires:
vars:
- NODE
vars:
IMAGE_URL:
sh: talhelper genurl image -n {{.NODE}} -c {{.TALOS_DIR}}/talconfig.yaml
cmds:
- echo "Downloading image from {{.IMAGE_URL}}"
- curl -L -o {{.ROOT_DIR}}/talos-{{.NODE}}.raw.xz {{.IMAGE_URL}} && xz -d {{.ROOT_DIR}}/talos-{{.NODE}}.raw.xz
- "diskutil list"
- |
echo "Path to USB drive:"
read path;
diskutil unmount ${path} || true
diskutil unmountDisk ${path} || true
echo "Writing image to: ${path}";
sudo dd if={{.ROOT_DIR}}/talos-{{.NODE}}.raw of=${path} conv=fsync bs=4M
- "rm {{.ROOT_DIR}}/talos-{{.NODE}}.raw"

View file

@ -1,25 +0,0 @@
# yaml-language-server: $schema=https://taskfile.dev/schema.json
---
version: 3
env:
WORKSTATION_RESOURCES_DIR: "{{.ROOT_DIR}}/.taskfiles/workstation/resources"
tasks:
brew:
desc: Set up Homebrew tools
cmd: brew bundle --file {{.WORKSTATION_RESOURCES_DIR}}/Brewfile
generates:
- "{{.WORKSTATION_RESOURCES_DIR}}/Brewfile.lock.json"
preconditions:
- command -v brew
- test -f {{.WORKSTATION_RESOURCES_DIR}}/Brewfile
krew:
desc: Install/update all required dependencies
silent: true
cmds:
- kubectl krew install cnpg rook-ceph browse-pvc view-secret node-shell
preconditions:
- kubectl krew version
- which kubectl

View file

@ -3,6 +3,7 @@
"*.json5": "json5",
"**/ansible/**/*.yaml": "ansible",
"**/**/inventory/**/*.yaml": "yaml",
"mod.just": "just",
},
"material-icon-theme.folders.associations": {
"*.gotmpl": "smarty",

View file

@ -1,6 +1,5 @@
# Tap
tap "fluxcd/tap"
tap "go-task/tap"
tap "siderolabs/tap"
# Terminal
@ -15,7 +14,6 @@ cask "claude-code"
# Command line tools
brew "bash"
brew "ansible"
brew "go-task/tap/go-task"
brew "just"
brew "git"
brew "nano"

View file

@ -1,31 +0,0 @@
---
# yaml-language-server: $schema=https://taskfile.dev/schema.json
version: "3"
set:
- pipefail
shopt:
- globstar
vars:
K8S_DIR: "{{.ROOT_DIR}}/kubernetes"
MINIJINJA_CONFIG_FILE: "{{.ROOT_DIR}}/.minijinja.toml"
TALOS_DIR: "{{.K8S_DIR}}/talos"
env:
KUBECONFIG: "~/.kube/configs/mainframe"
MINIJINJA_CONFIG_FILE: "{{.ROOT_DIR}}/.minijinja.toml"
TALOSCONFIG: "~/.talos/config"
includes:
bootstrap: .taskfiles/bootstrap/taskfile.yaml
flux: .taskfiles/flux/taskfile.yaml
k8s: .taskfiles/kubernetes/taskfile.yaml
talos: .taskfiles/talos/taskfile.yaml
workstation: .taskfiles/workstation/taskfile.yaml
tasks:
default:
silent: true
cmds:
- task --list

81
kubernetes/mod.just Normal file
View file

@ -0,0 +1,81 @@
set quiet := true
set shell := ['bash', '-euo', 'pipefail', '-c']
kubernetes_dir := justfile_dir() + '/kubernetes'
[private]
default:
just -l k8s
[doc('Watch reconciling and failed kustomizations')]
watch-ks:
viddy --disable_auto_save 'flux get kustomizations -A | grep -v Applied'
[doc('Browse a PVC')]
browse-pvc namespace claim:
kubectl browse-pvc -n {{ namespace }} -i mirror.gcr.io/alpine:latest {{ claim }}
[doc('Open a shell on a node')]
node-shell node:
kubectl debug node/{{ node }} -n default -it --image='mirror.gcr.io/alpine:latest' --profile sysadmin
kubectl delete pod -n default -l app.kubernetes.io/managed-by=kubectl-debug
[doc('Prune pods in Failed, Pending, or Succeeded state')]
prune-pods:
for phase in Failed Pending Succeeded; do \
kubectl delete pods -A --field-selector status.phase="$phase" --ignore-not-found=true; \
done
[doc('Apply local Flux Kustomization')]
apply-ks ns ks:
just k8s render-local-ks "{{ ns }}" "{{ ks }}" \
| kubectl apply --server-side --force-conflicts --field-manager=kustomize-controller -f /dev/stdin
[doc('Delete local Flux Kustomization')]
delete-ks ns ks:
just k8s render-local-ks "{{ ns }}" "{{ ks }}" \
| kubectl delete -f /dev/stdin
[doc('Sync single Flux HelmRelease')]
sync-hr ns name:
kubectl -n "{{ ns }}" annotate --field-manager flux-client-side-apply --overwrite hr "{{ name }}" reconcile.fluxcd.io/requestedAt="$(date +%s)" reconcile.fluxcd.io/forceAt="$(date +%s)"; \
[doc('Sync single Flux Kustomizations')]
sync-ks ns name:
kubectl -n "{{ ns }}" annotate --field-manager flux-client-side-apply --overwrite ks "{{ name }}" reconcile.fluxcd.io/requestedAt="$(date +%s)"; \
[doc('Sync single ExternalSecret')]
sync-es ns name:
kubectl -n "{{ ns }}" annotate --field-manager flux-client-side-apply --overwrite es "{{ name }}" force-sync="$(date +%s)"; \
[doc('Sync all Flux HelmReleases')]
sync-all-hr:
kubectl get hr --no-headers -A | while read -r ns name _; do \
just k8s sync-hr "$ns" "$name"; \
done
[doc('Sync all Flux Kustomizations')]
sync-all-ks:
kubectl get ks --no-headers -A | while read -r ns name _; do \
just k8s sync-ks "$ns" "$name"; \
done
[doc('Sync all ExternalSecrets')]
sync-all-es:
kubectl get es --no-headers -A | while read -r ns name _; do \
just k8s sync-es "$ns" "$name"; \
done
[doc('Snapshot all VolSync ReplicationSource')]
snapshot ns name:
kubectl -n "{{ ns }}" patch replicationsources "{{ name }}" --type merge -p '{"spec":{"trigger":{"manual":"$(date +%s)"}}}'; \
[doc('Snapshot all VolSync ReplicationSources')]
snapshot-all:
kubectl get replicationsources --no-headers -A | while read -r ns name _; do \
just k8s snapshot "$ns" "$name"; \
done
[private]
render-local-ks ns ks:
flux-local build ks --namespace "{{ ns }}" --path "{{ kubernetes_dir }}/flux/cluster" "{{ ks }}"

View file

@ -0,0 +1,168 @@
---
# yaml-language-server: $schema=https://raw.githubusercontent.com/siderolabs/talos/refs/heads/release-1.12/website/content/v1.12/schemas/config.schema.json
version: v1alpha1
machine:
ca:
crt: op://Homelab/talos/TALOS_CERTS_OS_CRT
{% if ENV.IS_CONTROLPLANE %}
key: op://Homelab/talos/TALOS_CERTS_OS_KEY
{% endif %}
features:
apidCheckExtKeyUsage: true
diskQuotaSupport: true
hostDNS:
enabled: true
forwardKubeDNSToHost: true # Requires Cilium socketLB features
resolveMemberNames: true
kubePrism:
enabled: true
port: 7445
{% if ENV.IS_CONTROLPLANE %}
kubernetesTalosAPIAccess:
allowedKubernetesNamespaces:
- actions-runner-system
- kube-system
allowedRoles:
- os:admin
enabled: true
{% endif %}
rbac: true
files:
- op: create
path: /etc/cri/conf.d/20-customization.part
content: |
[plugins."io.containerd.cri.v1.images"]
discard_unpacked_layers = false
[plugins."io.containerd.cri.v1.runtime"]
cdi_spec_dirs = ["/var/cdi/static", "/var/cdi/dynamic"]
device_ownership_from_security_context = true
install:
image: factory.talos.dev/metal-installer/07fc545562cc6c5d76cf282c30a95d10b86286cd345bac2fa963c786397475cd:v1.11.5
wipe: false
kubelet:
defaultRuntimeSeccompProfileEnabled: true
disableManifestsDirectory: true
extraConfig:
serializeImagePulls: false
image: ghcr.io/siderolabs/kubelet:v1.35.0
nodeIP:
validSubnets:
- 192.168.20.0/24
nodeLabels:
topology.kubernetes.io/region: mainframe
sysctls:
fs.inotify.max_user_instances: "8192"
fs.inotify.max_user_watches: "1048576"
net.core.rmem_max: "67108864"
net.core.wmem_max: "67108864"
net.ipv4.neigh.default.gc_thresh1: "4096"
net.ipv4.neigh.default.gc_thresh2: "8192"
net.ipv4.neigh.default.gc_thresh3: "16384"
net.ipv4.tcp_fastopen: "3"
user.max_user_namespaces: "11255"
token: op://Homelab/talos/TALOS_TRUSTD_INFO_TOKEN
cluster:
{% if ENV.IS_CONTROLPLANE %}
aggregatorCA:
crt: op://Homelab/talos/TALOS_CERTS_K8SAGGREGATOR_CRT
key: op://Homelab/talos/TALOS_CERTS_K8SAGGREGATOR_KEY
allowSchedulingOnControlPlanes: true
apiServer:
image: registry.k8s.io/kube-apiserver:v1.35.0
extraArgs:
enable-aggregator-routing: "true"
feature-gates: MutatingAdmissionPolicy=true
runtime-config: admissionregistration.k8s.io/v1beta1=true
certSANs:
- 127.0.0.1 # KubePrism
- 192.168.20.30
disablePodSecurityPolicy: true
controllerManager:
image: registry.k8s.io/kube-controller-manager:v1.35.0
coreDNS:
disabled: true
etcd:
ca:
crt: op://Homelab/talos/TALOS_CERTS_ETCD_CRT
key: op://Homelab/talos/TALOS_CERTS_ETCD_KEY
extraArgs:
listen-metrics-urls: http://0.0.0.0:2381
proxy:
disabled: true
image: registry.k8s.io/kube-proxy:v1.35.0
scheduler:
config:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- pluginConfig:
- args:
defaultConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
defaultingType: List
name: PodTopologySpread
plugins:
score:
disabled:
- name: ImageLocality
schedulerName: default-scheduler
extraArgs:
bind-address: 0.0.0.0
image: registry.k8s.io/kube-scheduler:v1.35.0
secretboxEncryptionSecret: op://Homelab/talos/TALOS_SECRETS_SECRETBOX_ENCRYPTION_SECRET
serviceAccount:
key: op://Homelab/talos/TALOS_CERTS_K8SSERVICEACCOUNT_KEY
{% endif %}
ca:
crt: op://Homelab/talos/TALOS_CERTS_K8S_CRT
{% if ENV.IS_CONTROLPLANE %}
key: op://Homelab/talos/TALOS_CERTS_K8S_KEY
{% endif %}
controlPlane:
endpoint: https://192.168.20.30:6443
clusterName: mainframe
discovery:
enabled: true
registries:
kubernetes: { disabled: true }
service: { disabled: false }
id: op://Homelab/talos/TALOS_CLUSTER_ID
network:
cni:
name: none
dnsDomain: cluster.local
podSubnets:
- 10.244.0.0/16
serviceSubnets:
- 10.96.0.0/12
secret: op://Homelab/talos/TALOS_CLUSTER_SECRET
token: op://Homelab/talos/TALOS_SECRETS_BOOTSTRAP_TOKEN
---
apiVersion: v1alpha1
kind: DHCPv4Config
name: net0
---
apiVersion: v1alpha1
kind: WatchdogTimerConfig
device: /dev/watchdog0
timeout: 5m
---
apiVersion: v1alpha1
kind: VolumeConfig
name: EPHEMERAL
provisioning:
diskSelector:
match: system_disk
grow: false
minSize: 100GiB
maxSize: 100GiB
---
apiVersion: v1alpha1
kind: UserVolumeConfig
name: local-hostpath
provisioning:
diskSelector:
match: system_disk
minSize: 350GiB

66
kubernetes/talos/mod.just Normal file
View file

@ -0,0 +1,66 @@
set quiet := true
set shell := ['bash', '-euo', 'pipefail', '-c']
kubernetes_dir := justfile_dir() + '/kubernetes'
talos_dir := kubernetes_dir + '/talos'
controller := `talosctl config info --output json | jq --raw-output '.endpoints[]' | shuf -n 1`
nodes := `talosctl config info -o yaml | yq -e '.nodes | join (",")'`
[private]
default:
just -l talos
[doc('Apply Talos config to a node')]
apply-node node *args:
just talos render-config "{{ node }}" | talosctl -n "{{ node }}" apply-config -f /dev/stdin {{ args }}
[doc('Reboot a node')]
reboot-node node:
gum confirm "Reboot node {{ node }}?" --default="No" && \
talosctl -n {{ node }} reboot -m powercycle || exit 0
[doc('Reset a node')]
reset-node node *args:
gum confirm "Reset node {{ node }}?" --default="No" && \
talosctl -n "{{ node }}" reset --system-labels-to-wipe STATE --system-labels-to-wipe EPHEMERAL --system-labels-to-wipe u-local-hostpath --graceful=false {{ args }} || exit 0
[doc('Shutdown a node')]
shutdown-node node *args:
gum confirm "Shutdown node {{ node }}?" --default="No" && \
talosctl -n "{{ node }}" shutdown --force {{ args }} || exit 0
[doc('Upgrade Kubernetes version on the cluster')]
upgrade-k8s version:
talosctl -n "{{ controller }}" upgrade-k8s --to {{ version }}
[doc('Upgrade Talos version on a node')]
upgrade-node node *args:
talosctl -n "{{ node }}" upgrade -i "$(just talos machine-image)" -m powercycle --timeout=10m {{ args }}
[private]
machine-controller node:
just template "{{ talos_dir }}/nodes/{{ node }}.yaml.j2" | yq -e 'select(.machine) | (.machine.type == "controlplane") // ""'
[doc('Get the machine image for a given node')]
[private]
machine-image node:
talosctl --nodes {{ node }} get machineconfig --output=jsonpath='{.spec}' | yq -e 'select(.machine) | .machine.install.image'
[doc('Generate schematic ID from Talos schematic')]
gen-schematic-id node:
export HAS_ZFS="$(just template "{{ talos_dir }}/nodes/{{ node }}.yaml.j2" | yq -e '.machine.kernel.modules[] | select(.name == "zfs")' > /dev/null 2>&1 && echo true || echo false)"; \
curl -sX POST --data-binary @<(just template "{{ talos_dir }}/schematic.yaml.j2") "https://factory.talos.dev/schematics" | jq -r '.id'
[doc('Render Talos config for a node')]
render-config node:
export IS_CONTROLPLANE="$(just talos machine-controller {{ node }})"; \
talosctl machineconfig patch <(just template "{{ talos_dir }}/machineconfig.yaml.j2") \
-p @<(just template "{{ talos_dir }}/nodes/{{ node }}.yaml.j2")
[doc('Download Talos machine image')]
download-image version schematic:
gum spin --title "Downloading Talos {{ version }} ..." -- \
curl -sfL --remove-on-error --retry 5 --retry-delay 5 --retry-all-errors \
-o "{{ talos_dir }}/talos-{{ version }}-{{ replace_regex(schematic, '^(.{8}).*', '$1') }}.iso" \
"https://factory.talos.dev/image/{{ schematic }}/{{ version }}/metal-amd64.iso"
just log info "Downloaded Talos" version "{{ version }}" schematic "{{ schematic }}"

View file

@ -0,0 +1,18 @@
---
machine:
install:
disk: /dev/sda
type: controlplane
nodeLabels:
node.kubernetes.io/gpu: "true"
node.kubernetes.io/gpu.arc: "true"
---
apiVersion: v1alpha1
kind: HostnameConfig
hostname: n01
---
apiVersion: v1alpha1
kind: LinkAliasConfig
name: net0
selector:
match: mac(link.permanent_addr) == "88:ae:dd:65:a5:49"

View file

@ -0,0 +1,18 @@
---
machine:
install:
disk: /dev/sda
type: controlplane
nodeLabels:
node.kubernetes.io/gpu: "true"
node.kubernetes.io/gpu.arc: "true"
---
apiVersion: v1alpha1
kind: HostnameConfig
hostname: n02
---
apiVersion: v1alpha1
kind: LinkAliasConfig
name: net0
selector:
match: mac(link.permanent_addr) == "88:ae:dd:68:a1:b6"

View file

@ -0,0 +1,18 @@
---
machine:
install:
disk: /dev/sda
type: controlplane
nodeLabels:
node.kubernetes.io/gpu: "true"
node.kubernetes.io/gpu.arc: "true"
---
apiVersion: v1alpha1
kind: HostnameConfig
hostname: n03
---
apiVersion: v1alpha1
kind: LinkAliasConfig
name: net0
selector:
match: mac(link.permanent_addr) == "88:ae:dd:68:a3:43"

View file

@ -0,0 +1,22 @@
---
machine:
type: worker
install:
diskSelector:
serial: "S4EVNM0R816141L"
image: factory.talos.dev/metal-installer/4dc3f9e65093d1c47a15fa5ab9bdae7121036139f08b9709df1f0bbe3aead6d5:v1.12.0
kernel:
modules:
- name: zfs
nodeLabels:
node.kubernetes.io/gpu: "true"
---
apiVersion: v1alpha1
kind: HostnameConfig
hostname: s01
---
apiVersion: v1alpha1
kind: LinkAliasConfig
name: net0
selector:
match: mac(link.permanent_addr) == "ec:e7:a7:17:ff:4c"

View file

@ -0,0 +1,25 @@
---
customization:
extraKernelArgs:
- -selinux
- -init_on_alloc
- -init_on_free
- apparmor=0
- i915.enable_guc=3
- init_on_alloc=0
- init_on_free=0
- intel_iommu=on
- iommu=pt
- mitigations=off
- security=none
- sysctl.kernel.kexec_load_disabled=1
- talos.auditd.disabled=1
- net.ifnames=1 # Enable predictable NIC naming
systemExtensions:
officialExtensions:
- siderolabs/i915 # Intel iGPU
- siderolabs/intel-ucode # Intel iGPU
- siderolabs/mei # Intel iGPU
{% if ENV.HAS_ZFS == "true" %}
- siderolabs/zfs
{% endif %}

View file

@ -1,290 +0,0 @@
---
clusterName: mainframe
endpoint: https://192.168.20.30:6443
talosVersion: v1.12.0
kubernetesVersion: v1.34.3
additionalApiServerCertSans:
- 127.0.0.1 # KubePrism
additionalMachineCertSans:
- 192.168.20.30
- 127.0.0.1 # KubePrism
cniConfig:
name: none
nodes:
- hostname: n01
ipAddress: 192.168.20.21
controlPlane: true
installDisk: /dev/sda
networkInterfaces:
- deviceSelector:
hardwareAddr: 88:ae:dd:65:a5:49
addresses:
- 192.168.20.21/24
dhcp: true
machineSpec: &machine-spec
mode: metal
arch: amd64
bootMethod: disk-image
imageSuffix: raw.xz
schematic: &schematic
customization:
extraKernelArgs:
- -init_on_alloc # Less security, faster puter
- -init_on_free # Less security, faster puter
- -selinux # Less security, faster puter
- apparmor=0 # Less security, faster puter
- i915.enable_guc=3 # Meteor Lake CPU / iGPU
- init_on_alloc=0 # Less security, faster puter
- init_on_free=0 # Less security, faster puter
- intel_iommu=on # PCI Passthrough
- iommu=pt # PCI Passthrough
- mitigations=off # Less security, faster puter
- security=none # Less security, faster puter
- sysctl.kernel.kexec_load_disabled=1 # Meteor Lake CPU / iGPU
- talos.auditd.disabled=1 # Less security, faster puter
systemExtensions:
officialExtensions:
- siderolabs/i915
- siderolabs/intel-ucode
- siderolabs/mei
patches: &patches
- |-
apiVersion: v1alpha1
kind: VolumeConfig
name: EPHEMERAL
provisioning:
diskSelector:
match: system_disk
grow: false
minSize: 100GiB
maxSize: 100GiB
- |-
apiVersion: v1alpha1
kind: UserVolumeConfig
name: local-hostpath
provisioning:
diskSelector:
match: system_disk
minSize: 350GiB
- hostname: n02
ipAddress: 192.168.20.22
controlPlane: true
installDisk: /dev/sda
networkInterfaces:
- deviceSelector:
hardwareAddr: 88:ae:dd:68:a1:b6
addresses:
- 192.168.20.22/24
dhcp: true
machineSpec: *machine-spec
schematic: *schematic
patches: *patches
- hostname: n03
ipAddress: 192.168.20.23
controlPlane: true
installDisk: /dev/sda
networkInterfaces:
- deviceSelector:
hardwareAddr: 88:ae:dd:68:a3:43
addresses:
- 192.168.20.23/24
dhcp: true
machineSpec: *machine-spec
schematic: *schematic
patches: *patches
- hostname: s01
ipAddress: 192.168.20.24
controlPlane: false
installDiskSelector:
serial: "S4EVNM0R816141L"
networkInterfaces:
- deviceSelector:
hardwareAddr: ec:e7:a7:17:ff:4c
addresses:
- 192.168.20.24/24
dhcp: true
nodeLabels:
openebs.io/nodeid: s01
machineSpec: *machine-spec
kernelModules:
- name: zfs
schematic:
customization:
extraKernelArgs:
- -selinux # Less security, faster puter
- -init_on_alloc # Less security, faster puter
- -init_on_free # Less security, faster puter
- apparmor=0 # Less security, faster puter
- init_on_alloc=0 # Less security, faster puter
- init_on_free=0 # Less security, faster puter
- intel_iommu=on # PCI Passthrough
- iommu=pt # PCI Passthrough
- mitigations=off # Less security, faster puter
- security=none # Less security, faster puter
- talos.auditd.disabled=1 # Less security, faster puter
- net.ifnames=1 # Enable predictable NIC naming
systemExtensions:
officialExtensions:
- siderolabs/i915
- siderolabs/intel-ucode
- siderolabs/zfs
patches: *patches
controlPlane:
patches:
# Disable search domain everywhere
- &disableSearchDomainPatch |-
machine:
network:
disableSearchDomain: true
# Force nameserver
- &nameServersPatch |-
machine:
network:
nameservers:
- 192.168.20.1
# Configure NTP
- &timeServersPatch |-
machine:
time:
disabled: false
servers:
- gbg2.ntp.se
- sth1.ntp.se
# Enable K8s Talos API Access
- |-
machine:
features:
kubernetesTalosAPIAccess:
enabled: true
allowedRoles:
- os:admin
allowedKubernetesNamespaces:
- kube-system
- actions-runner-system
# Enable MutatingAdmissionPolicy
- |-
cluster:
apiServer:
extraArgs:
enable-aggregator-routing: "true"
runtime-config: admissionregistration.k8s.io/v1beta1=true
# Cluster configuration
- |-
cluster:
allowSchedulingOnControlPlanes: true
coreDNS:
disabled: true
proxy:
disabled: true
scheduler:
config:
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
plugins:
score:
disabled:
- name: ImageLocality
pluginConfig:
- name: PodTopologySpread
args:
defaultingType: List
defaultConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
# Use discovery-service.
# The previous Kubernetes discovery service is deprecated due to security changes in Kubernetes.
# https://www.talos.dev/v1.10/talos-guides/discovery/#registries
# https://github.com/siderolabs/talos/issues/9980
- &clusterDiscovery |-
cluster:
discovery:
enabled: true
registries:
kubernetes:
disabled: true
service:
disabled: false
- &hostDns |-
machine:
features:
hostDNS:
enabled: true
forwardKubeDNSToHost: true
resolveMemberNames: true
# Disable default API server admission plugins.
- |-
- op: remove
path: /cluster/apiServer/admissionControl
# Kubelet configuration
- &kubeletPatch |-
machine:
kubelet:
extraArgs:
image-gc-high-threshold: 70
image-gc-low-threshold: 65
extraConfig:
maxParallelImagePulls: 10
maxPods: 200
serializeImagePulls: false
nodeIP:
validSubnets:
- 192.168.20.0/24
# Custom sysctls
- &sysctlsPatch |-
machine:
sysctls:
fs.inotify.max_user_instances: "8192" # Watchdog
fs.inotify.max_user_watches: "1048576" # Watchdog
net.core.rmem_max: "67108864" # Cloudflared / QUIC
net.core.wmem_max: "67108864" # Cloudflared / QUIC
net.ipv4.neigh.default.gc_thresh1: "4096" # Prevent ARP cache overflows
net.ipv4.neigh.default.gc_thresh2: "8192" # Prevent ARP cache overflows
net.ipv4.neigh.default.gc_thresh3: "16384" # Prevent ARP cache overflows
net.ipv4.tcp_fastopen: "3" # Send and accept data in the opening SYN packet
user.max_user_namespaces: "11255" # User namespaces
# Configure containerd
- &containerdPatch |-
machine:
files:
- op: create
path: /etc/cri/conf.d/20-customization.part
content: |
[plugins]
[plugins."io.containerd.cri.v1.images"]
discard_unpacked_layers = false
[plugins."io.containerd.cri.v1.runtime"]
device_ownership_from_security_context = true
worker:
patches:
- *disableSearchDomainPatch
- *nameServersPatch
- *timeServersPatch
- *clusterDiscovery
- *hostDns
- *kubeletPatch
- *sysctlsPatch
- *containerdPatch

View file

@ -1,14 +0,0 @@
TALOS_CLUSTER_ID="op://Homelab/talos/TALOS_CLUSTER_ID"
TALOS_CLUSTER_SECRET="op://Homelab/talos/TALOS_CLUSTER_SECRET"
TALOS_SECRETS_BOOTSTRAP_TOKEN="op://Homelab/talos/TALOS_SECRETS_BOOTSTRAP_TOKEN"
TALOS_SECRETS_SECRETBOX_ENCRYPTION_SECRET="op://Homelab/talos/TALOS_SECRETS_SECRETBOX_ENCRYPTION_SECRET"
TALOS_TRUSTD_INFO_TOKEN="op://Homelab/talos/TALOS_TRUSTD_INFO_TOKEN"
TALOS_CERTS_ETCD_CRT="op://Homelab/talos/TALOS_CERTS_ETCD_CRT"
TALOS_CERTS_ETCD_KEY="op://Homelab/talos/TALOS_CERTS_ETCD_KEY"
TALOS_CERTS_K8S_CRT="op://Homelab/talos/TALOS_CERTS_K8S_CRT"
TALOS_CERTS_K8S_KEY="op://Homelab/talos/TALOS_CERTS_K8S_KEY"
TALOS_CERTS_K8SAGGREGATOR_CRT="op://Homelab/talos/TALOS_CERTS_K8SAGGREGATOR_CRT"
TALOS_CERTS_K8SAGGREGATOR_KEY="op://Homelab/talos/TALOS_CERTS_K8SAGGREGATOR_KEY"
TALOS_CERTS_K8SSERVICEACCOUNT_KEY="op://Homelab/talos/TALOS_CERTS_K8SSERVICEACCOUNT_KEY"
TALOS_CERTS_OS_CRT="op://Homelab/talos/TALOS_CERTS_OS_CRT"
TALOS_CERTS_OS_KEY="op://Homelab/talos/TALOS_CERTS_OS_KEY"

View file

@ -1,23 +0,0 @@
cluster:
id: ${TALOS_CLUSTER_ID}
secret: ${TALOS_CLUSTER_SECRET}
secrets:
bootstraptoken: ${TALOS_SECRETS_BOOTSTRAP_TOKEN}
secretboxencryptionsecret: ${TALOS_SECRETS_SECRETBOX_ENCRYPTION_SECRET}
trustdinfo:
token: ${TALOS_TRUSTD_INFO_TOKEN}
certs:
etcd:
crt: ${TALOS_CERTS_ETCD_CRT}
key: ${TALOS_CERTS_ETCD_KEY}
k8s:
crt: ${TALOS_CERTS_K8S_CRT}
key: ${TALOS_CERTS_K8S_KEY}
k8saggregator:
crt: ${TALOS_CERTS_K8SAGGREGATOR_CRT}
key: ${TALOS_CERTS_K8SAGGREGATOR_KEY}
k8sserviceaccount:
key: ${TALOS_CERTS_K8SSERVICEACCOUNT_KEY}
os:
crt: ${TALOS_CERTS_OS_CRT}
key: ${TALOS_CERTS_OS_KEY}