IaC Worker Node - Naina #17
Labels
No labels
blocked
bug
duplicate
effort
high
effort
low
effort
medium
effort
minimal
enhancement
help wanted
invalid
pr
feedback
pr
reviewing
question
status
backlog
status
document
status
done
status
implement
status
pending
status
planning
status
reviewing
waiting
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
tepichord/milner#17
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Naina:
Overview
Add a
worker/Terraform root that provisions the naina worker-large VM (20 GB RAM / 6 vCPU1 / 40 GiB disk, per ARCHITECTURE.md §1 — §1 sizes RAM/vCPU only and specifies no disk; the 40 GiB is control-plane parity2) attached to the existingcp-bridgeNAT network3, and joins it to the live cluster as a Talos worker using the control-plane root's machine secrets. The shell-based provisioning (worker/vm-setup/) is superseded and removed; the control-plane graph gains two sensitive outputs plus a DHCP reservation for the worker.Technical Approach
control-plane/main.tf— expose cluster identity to the worker root45worker/main.tf— provider block + secrets read from the CP statelibvirt_domain.worker— join the CP-owned network/pool by name678Docs + harness updates (root
tests/test_terraform.pyrunsterraform testin both roots11;tests/test_static.pyfmt/shellchecklists extended toworker/12;README.md+worker/README.mdrunbook mirroringcontrol-plane/;AGENTS.mdrepo-map and "How Changes Ship" updated;worker/cleanup.sh= confirm-gatedterraform destroyof worker resources only — no pool sweep, the pool is CP-owned).Delete superseded files:
worker/vm-setup/create-worker-vm.sh,worker/tests/test_create_worker_vm.bats,worker/patches/worker-patch-1.yaml(placeholders are now inlineconfig_patches).131415Implementation Details
Files to create:
worker/main.tf— remote-state read, worker volumes/domain, worker talos config + apply (conventions mirrorcontrol-plane/main.tf)worker/terraform.tfvars— repo-default knobs (mirrors CP file style)worker/.gitignore—.terraform/,*.tfstate*,*.auto.tfvarsworker/tests/plan.tftest.hcl+worker/tests/fixtures/cp.tfstateworker/cleanup.sh,worker/README.mdFiles to modify:
control-plane/main.tf— append 6 outputs +worker_dhcp_hostsvariable +hosts = concat(...)inlibvirt_network16control-plane/terraform.tfvars— addworker_dhcp_hostsentry1718control-plane/tests/plan.tftest.hcl— add run asserting the worker reservation and the new outputstests/test_terraform.py,tests/test_static.py,README.md,AGENTS.mdFiles to delete:
worker/vm-setup/create-worker-vm.sh,worker/tests/test_create_worker_vm.bats,worker/patches/worker-patch-1.yaml, plus the now-emptyworker/vm-setup/dir. The bats pytest intests/test_shell.pyis removed with the bats dir.19Dependencies: none new — provider pins (
talos ~> 0.11,libvirt ~> 0.9,time ~> 0.14) identical to the control-plane root20;worker/.terraform.lock.hclgenerated byterraform init.Constraints:
control-plane-net/talos-imagesby name string only21.talos_machine_configuration_applyhas nomachine_typeand no join-token input — role + join material come from themachine_type = "worker"data source and the shared machine secrets.2223worker_ip/worker_macinworker/must match the CPworker_dhcp_hostsreservation; comments cross-reference both sides and tests lock the values.talosctl healthafterwards.node-role: workerviamachine.nodeLabelsis outside NodeRestriction's restricted prefixes (NodeRestriction forbids onlynode-role.kubernetes.io/*and otherkubernetes.io/k8s.io-domain labels), but is empirically unverified on this cluster — confirm withkubectl get node --show-labelsafter join.2425Out-of-scope notes:
worker-simnode and any further workers (Phase 4 stays 🚧 until 3+ nodes; per-node DHCP reservations would need the same pattern).worker/is built standalone and can be folded in later.~> 0.11; post-0.11 ephemeral-secrets features and the v1.14KubeNodeConfignodeLabels refactor are future work).Acceptance Criteria
terraform -chdir=control-plane plan(withworker_dhcp_hostsset) shows only the additive DHCP host + outputs; existing control-planeterraform testsuite still passes with the new reservation/output runsterraform -chdir=worker planagainst the real CP state creates exactly the worker disk/ISO volumes,milner-worker-1domain, andtalos_machine_configuration_apply.worker— no network, pool, bootstrap, or kubeconfig resourcesmemory_unit = "MiB"), 6 vCPU, 40 GiB qcow2 disk, MAC52:54:00:10:00:04on networkcontrol-plane-net,installer_isotoggle with hd/cdrom boot + SCSI cdrom, serial console, noprevent_destroykubectl get nodesshowsmilner-worker-1Readywithnode-role=workerlabel; a secondterraform -chdir=worker applyis a no-oppytest tests/,terraform testin both roots, fmt/shellcheckoverworker/worker/README.mdrunbook, rootREADME.md/AGENTS.md,PLAN.mdPhase 4 notes the worker-large node is now Terraform-managedTesting Plan
control-plane/tests/plan.tftest.hcl) — mock-provider plan assertions thatdhcp.hostslength =control_plane_count + 1withhosts[1] == { mac = "52:54:00:10:00:04", ip = "10.5.0.20" }, and that themachine_secrets/client_configurationoutputs are non-null and sensitive.worker/tests/plan.tftest.hcl) — mock-provider plan assertions (fixture CP state): domain shape (memory/unit/vcpu, boot order hd→cdrom, qcow2 driver, virtio-scsi controller, AAVMF os block, serial console, autostart/running), interface MAC/network-name/wait_for_ip, disk 40 GiB qcow2, ISO volume present only wheninstaller_iso = true(and ejected-run variant withinstaller_iso = false),machine_type == "worker"+nodeLabelspatch, apply count 1,time_sleepdependency chain.terraform testboth roots,terraform fmt -check -recursive,shellcheckon bothcleanup.shscripts, all offline.terraform -chdir=worker apply; verifytalosctl healthandkubectl get nodes -o wide+--show-labels. Recovery check:terraform -chdir=worker apply -replace='libvirt_domain.worker're-joins the node while the CP stays up.Related Issues/PRs
Research Findings
machine_type = "worker"on thetalos_machine_configurationdata source; the apply resource has nomachine_typeor join-token input — the generated config carries the join material, so every node must derive from the sametalos_machine_secretsor the new node cannot join. (talos provider docs, Talos scaling-up guide)control-plane-net, not bridgecp-bridge); network/pool stay owned by the control-plane root to avoid one real object under two states. (provider data-source tree at v0.9.8)talos_machine_secretsimport from a secrets file orterraform_remote_state(local backend); the plan adopts remote state, noting it exposes the whole CP state snapshot to the worker root. (machine_secrets import, remote-state data)machine.nodeLabels; NodeRestriction forbids kubelet self-assignment ofnode-role.kubernetes.io/*, but the plainnode-role: workerkey used by ARCHITECTURE.md affinity is outside restricted prefixes (still worth empirical confirmation). (node labels guide)Pre-Mortem
terraform_remote_stateand requires the CP root to have been re-applied first to publish the secrets outputs and the DHCP reservation; if the roots are applied out of order or the CP tfstate path/lock is stale, the workerplan/applyerrors out or the VM never receives its reserved lease andwait_for_iptimes out. This dependency is only documented, never enforced, so it is the easiest step to get wrong on the live host.talos_machine_configuration_applyfails or the node stays NotReady when the secrets pulled from remote state do not match the live cluster's CA (sensitive-output handling quirks) or when the installer-ISOtalos_versiondrifts from the running cluster version. The failure surfaces only in the manual smoke step, so hermetic tests stay green while the node never appears inkubectl get nodes.libvirt_networkDHCP (dnsmasq restart), and if the MAC/IP pair drifts between the two tfvars files, the network update can disturb the running CP node or leave the worker IP-less, while the "second apply is a no-op" andnode-role: workerlabel assumptions remain empirically unverified until the live-cluster smoke test.