[{"data":1,"prerenderedAt":2922},["ShallowReactive",2],{"post:\u002F2026\u002F07\u002F08\u002Fkubernetes-running-talos-alongside-a-legacy-hyper-v-estate\u002F":3},{"post":4,"newer":2873,"older":2885,"related":2895,"series":2920},{"id":5,"title":6,"body":7,"canonical":2853,"categories":2854,"date":2856,"description":2857,"extension":2858,"featured":2859,"hero":2860,"image":2860,"meta":2861,"navigation":130,"path":2862,"readingTime":159,"seo":2863,"series":2860,"seriesOrder":2860,"sites":2864,"source":2860,"stem":2865,"tags":2866,"updated":2870,"url":2871,"__hash__":2872},"blog\u002Fblog\u002F2026\u002F07\u002F08\u002Fkubernetes-running-talos-alongside-a-legacy-hyper-v-estate.md","Kubernetes: Running Talos Alongside a Legacy Hyper-V Estate",{"type":8,"value":9,"toc":2846},"minimark",[10,14,17,22,25,37,92,187,194,197,240,243,1865,1868,1876,1879,1941,1950,1954,1957,1964,2158,2169,2172,2694,2701,2704,2708,2715,2719,2736,2740,2842],[11,12,13],"p",{},"Most of the Kubernetes-on-Hyper-V advice I've read assumes you're starting from a clean slate or migrating everything to a new hypervisor. Neither describes reality when you're supporting a Windows estate that has years of Hyper-V clusters, System Center tooling, and operational habits built around VMM and Failover Clustering. Ripping that out to make room for Kubernetes was never on the table. What worked was treating Talos Linux as just another guest OS on the existing Hyper-V hosts, and being deliberate about where the two worlds have to touch.",[11,15,16],{},"Everything here is written against Talos 1.14. Hyper-V is on Talos' list of supported virtualized platforms, and there's a Hyper-V page in the Talos docs, but it's a lab walkthrough built on a community PowerShell module. What follows is how I turned that into something that fits a managed estate.",[18,19,21],"h2",{"id":20},"talos-as-a-guest-not-a-replacement","Talos as a guest, not a replacement",[11,23,24],{},"Talos ships as an ISO from the Image Factory, and as far as Talos is concerned Hyper-V is an ordinary hypervisor: the VM boots into maintenance mode, gets a machine config applied over the network, and comes up as an immutable, API-managed node with no SSH and no package manager to drift. The settings that took adjustment were on the Hyper-V side, and once they were captured in a script, a new node became a five-minute task instead of a bespoke one.",[11,26,27,28,32,33,36],{},"First, the image. I build a schematic that adds the official ",[29,30,31],"code",{},"hyperv-guest-agent"," system extension, which provides the Hyper-V KVP daemon (it reports the guest's IP, hostname and OS to the host, so ",[29,34,35],{},"Get-VMNetworkAdapter"," shows the address) and the VSS daemon:",[38,39,44],"pre",{"className":40,"code":41,"language":42,"meta":43,"style":43},"language-yaml shiki shiki-themes github-dark","# schematic.yaml\ncustomization:\n  systemExtensions:\n    officialExtensions:\n      - siderolabs\u002Fhyperv-guest-agent\n","yaml","",[29,45,46,55,66,74,82],{"__ignoreMap":43},[47,48,51],"span",{"class":49,"line":50},"line",1,[47,52,54],{"class":53},"sAwPA","# schematic.yaml\n",[47,56,58,62],{"class":49,"line":57},2,[47,59,61],{"class":60},"s4JwU","customization",[47,63,65],{"class":64},"s95oV",":\n",[47,67,69,72],{"class":49,"line":68},3,[47,70,71],{"class":60},"  systemExtensions",[47,73,65],{"class":64},[47,75,77,80],{"class":49,"line":76},4,[47,78,79],{"class":60},"    officialExtensions",[47,81,65],{"class":64},[47,83,85,88],{"class":49,"line":84},5,[47,86,87],{"class":64},"      - ",[47,89,91],{"class":90},"sU2Wk","siderolabs\u002Fhyperv-guest-agent\n",[38,93,97],{"className":94,"code":95,"language":96,"meta":43,"style":43},"language-bash shiki shiki-themes github-dark","curl -X POST --data-binary @schematic.yaml https:\u002F\u002Ffactory.talos.dev\u002Fschematics\n# {\"id\":\"\u003Cschematic-id>\",\"schematic\":\"customization:\\n    systemExtensions: ...\"}\n\nSCHEMATIC_ID=\"\u003Cschematic-id>\"   # the id from the response\n\n# ISO for the VMs, and the installer image the machine config must reference\ncurl -LO \"https:\u002F\u002Ffactory.talos.dev\u002Fimage\u002F${SCHEMATIC_ID}\u002Fv1.14.0\u002Fmetal-amd64.iso\"\necho \"factory.talos.dev\u002Fmetal-installer\u002F${SCHEMATIC_ID}:v1.14.0\"\n","bash",[29,98,99,121,126,132,147,151,157,173],{"__ignoreMap":43},[47,100,101,105,109,112,115,118],{"class":49,"line":50},[47,102,104],{"class":103},"svObZ","curl",[47,106,108],{"class":107},"sDLfK"," -X",[47,110,111],{"class":90}," POST",[47,113,114],{"class":107}," --data-binary",[47,116,117],{"class":90}," @schematic.yaml",[47,119,120],{"class":90}," https:\u002F\u002Ffactory.talos.dev\u002Fschematics\n",[47,122,123],{"class":49,"line":57},[47,124,125],{"class":53},"# {\"id\":\"\u003Cschematic-id>\",\"schematic\":\"customization:\\n    systemExtensions: ...\"}\n",[47,127,128],{"class":49,"line":68},[47,129,131],{"emptyLinePlaceholder":130},true,"\n",[47,133,134,137,141,144],{"class":49,"line":76},[47,135,136],{"class":64},"SCHEMATIC_ID",[47,138,140],{"class":139},"snl16","=",[47,142,143],{"class":90},"\"\u003Cschematic-id>\"",[47,145,146],{"class":53},"   # the id from the response\n",[47,148,149],{"class":49,"line":84},[47,150,131],{"emptyLinePlaceholder":130},[47,152,154],{"class":49,"line":153},6,[47,155,156],{"class":53},"# ISO for the VMs, and the installer image the machine config must reference\n",[47,158,160,162,165,168,170],{"class":49,"line":159},7,[47,161,104],{"class":103},[47,163,164],{"class":107}," -LO",[47,166,167],{"class":90}," \"https:\u002F\u002Ffactory.talos.dev\u002Fimage\u002F${",[47,169,136],{"class":64},[47,171,172],{"class":90},"}\u002Fv1.14.0\u002Fmetal-amd64.iso\"\n",[47,174,176,179,182,184],{"class":49,"line":175},8,[47,177,178],{"class":107},"echo",[47,180,181],{"class":90}," \"factory.talos.dev\u002Fmetal-installer\u002F${",[47,183,136],{"class":64},[47,185,186],{"class":90},"}:v1.14.0\"\n",[11,188,189,190,193],{},"Schematics are content-addressed, so the same YAML always yields the same ID. Keep that ID with the cluster's patches: from Talos 1.14 on, installer images come from the Image Factory, and every future ",[29,191,192],{},"talosctl upgrade"," has to reference the same schematic or the node loses its extensions.",[11,195,196],{},"Then the VM. The shape follows what the module linked from the Talos Hyper-V guide does (Generation 2, Secure Boot off, ISO as the first boot device) plus the settings a shared estate needs:",[198,199,200,212,222,228,234],"ul",{},[201,202,203,207,208,211],"li",{},[204,205,206],"strong",{},"Secure Boot off."," The standard Talos ISO isn't a SecureBoot image; Talos publishes separate ",[29,209,210],{},"-secureboot"," assets signed with Sidero Labs' own key, and enrolling that key requires the firmware to be in setup mode. The Talos docs don't cover doing that on Hyper-V, so I don't half-configure it: Secure Boot is explicitly off.",[201,213,214,217,218,221],{},[204,215,216],{},"A static MAC per VM",", from a range reserved for the cluster. Talos can then match the NIC by MAC with a ",[29,219,220],{},"LinkAliasConfig"," instead of trusting interface naming, and the network team's reservations never go stale.",[201,223,224,227],{},[204,225,226],{},"An access-mode VLAN"," on the vNIC, so the node lands on the cluster VLAN with no tagging inside the guest.",[201,229,230,233],{},[204,231,232],{},"Static memory and no checkpoints."," Rolling an etcd member's disk back to an older point in time is never what you want, and I'd rather Kubernetes see a fixed memory size than a balloon.",[201,235,236,239],{},[204,237,238],{},"Sizing from Talos' system requirements."," Control plane nodes get at least the recommended 4 cores, 4 GiB and 100 GiB. Talos' amd64 images also require a CPU that exposes the x86-64-v2 microarchitecture level; a VM below that level halts at boot with a message saying so.",[11,241,242],{},"This script builds the VM and writes the node's Talos patch at the same time, so the MAC in the config is the MAC on the VM:",[38,244,248],{"className":245,"code":246,"language":247,"meta":43,"style":43},"language-powershell shiki shiki-themes github-dark","#Requires -Modules Hyper-V\n#Requires -RunAsAdministrator\n\u003C#\n.SYNOPSIS\n    Creates a Talos Linux VM on a Hyper-V host and writes its Talos node patch.\n\n.DESCRIPTION\n    Builds a Generation 2 VM with Secure Boot off, a static MAC address, an\n    access-mode VLAN, static memory, checkpoints disabled and the Talos ISO as\n    the first boot device. Writes patches\u002Fnodes\u002F\u003CName>.yaml with a hostname,\n    a link alias pinned to the static MAC, and the node's static address, so\n    the Talos config matches the VM without anyone copying MACs by hand.\n    Run it on the Hyper-V host (or a cluster node that owns the storage path).\n\n.PARAMETER Name\n    VM name and Talos hostname, for example talos-cp1.\n\n.PARAMETER IPAddress\n    Static address in CIDR form, for example 10.20.30.11\u002F24.\n\n.PARAMETER Gateway\n    Default gateway for the node.\n\n.PARAMETER StaticMacAddress\n    MAC address without separators, for example 00155D1E1E0B. Keep it inside\n    a range your DHCP and IPAM teams have reserved for the cluster.\n\n.PARAMETER SwitchName\n    External virtual switch the cluster VLAN is trunked to.\n\n.PARAMETER VlanId\n    Access VLAN for the Talos node NIC.\n\n.PARAMETER IsoPath\n    Path to the Talos ISO (from the Image Factory schematic) on the host.\n\n.PARAMETER VMPath\n    Folder for the VM configuration and its VHDX files.\n\n.PARAMETER ProcessorCount\n    Virtual processors. Talos recommends 4 for control plane nodes.\n\n.PARAMETER MemoryBytes\n    Static memory. Talos recommends 4 GiB for control plane nodes; the 8 GB\n    default leaves room for workloads on nodes that also run pods.\n\n.PARAMETER OsDiskBytes\n    System disk size. Talos recommends 100 GiB.\n\n.PARAMETER DataDiskBytes\n    Optional second VHDX for workload storage (for example a CSI backend).\n\n.PARAMETER PatchDirectory\n    Where to write the node patch. Defaults to .\\patches\\nodes.\n\n.EXAMPLE\n    .\\New-TalosHyperVNode.ps1 -Name talos-cp1 -IPAddress 10.20.30.11\u002F24 -Gateway 10.20.30.1 -StaticMacAddress 00155D1E1E0B -SwitchName vSwitch-Trunk -VlanId 230 -IsoPath C:\\ISO\\talos-hyperv-amd64.iso -VMPath C:\\ClusterStorage\\Volume1\\Talos\n#>\n[CmdletBinding(SupportsShouldProcess)]\nparam(\n    [Parameter(Mandatory)] [string] $Name,\n    [Parameter(Mandatory)] [ValidatePattern('^\\d{1,3}(\\.\\d{1,3}){3}\u002F\\d{1,2}$')] [string] $IPAddress,\n    [Parameter(Mandatory)] [string] $Gateway,\n    [Parameter(Mandatory)] [ValidatePattern('^[0-9A-Fa-f]{12}$')] [string] $StaticMacAddress,\n    [Parameter(Mandatory)] [string] $SwitchName,\n    [Parameter(Mandatory)] [ValidateRange(1, 4094)] [int] $VlanId,\n    [Parameter(Mandatory)] [string] $IsoPath,\n    [Parameter(Mandatory)] [string] $VMPath,\n    [int] $ProcessorCount = 4,\n    [long] $MemoryBytes = 8GB,\n    [long] $OsDiskBytes = 100GB,\n    [long] $DataDiskBytes = 0,\n    [string] $PatchDirectory = (Join-Path -Path (Get-Location) -ChildPath 'patches\\nodes')\n)\n\n$ErrorActionPreference = 'Stop'\n\nif (Get-VM -Name $Name -ErrorAction SilentlyContinue) {\n    throw \"A VM named $Name already exists on this host.\"\n}\n\n$vhdFolder = Join-Path -Path $VMPath -ChildPath \"$Name\\Virtual Hard Disks\"\n$osDiskPath = Join-Path -Path $vhdFolder -ChildPath \"$Name-os.vhdx\"\n\nif ($PSCmdlet.ShouldProcess($Name, 'Create Talos VM')) {\n    New-Item -Path $vhdFolder -ItemType Directory -Force | Out-Null\n\n    New-VM -Name $Name -Generation 2 -MemoryStartupBytes $MemoryBytes -NewVHDPath $osDiskPath `\n        -NewVHDSizeBytes $OsDiskBytes -SwitchName $SwitchName -Path $VMPath | Out-Null\n\n    # Fixed CPU and memory, and no checkpoints: reverting an etcd member or a\n    # node's disk to an older point in time is never what you want.\n    Set-VM -Name $Name -ProcessorCount $ProcessorCount -StaticMemory -MemoryStartupBytes $MemoryBytes `\n        -CheckpointType Disabled -AutomaticCheckpointsEnabled $false\n\n    Set-VMNetworkAdapter -VMName $Name -StaticMacAddress $StaticMacAddress\n    Set-VMNetworkAdapterVlan -VMName $Name -Access -VlanId $VlanId\n\n    if ($DataDiskBytes -gt 0) {\n        $dataDiskPath = Join-Path -Path $vhdFolder -ChildPath \"$Name-data.vhdx\"\n        New-VHD -Path $dataDiskPath -SizeBytes $DataDiskBytes -Dynamic | Out-Null\n        Add-VMHardDiskDrive -VMName $Name -Path $dataDiskPath\n    }\n\n    # The standard Talos ISO is not a SecureBoot image (Talos publishes separate\n    # -secureboot assets), so Secure Boot is off, as in the Talos Hyper-V guide.\n    Add-VMDvdDrive -VMName $Name -Path $IsoPath\n    Set-VMFirmware -VMName $Name -EnableSecureBoot Off -FirstBootDevice (Get-VMDvdDrive -VMName $Name)\n}\n\n# Talos matches the NIC by MAC, in lowercase colon-separated form.\n$macForTalos = (($StaticMacAddress.ToLower() -split '(..)') -ne '') -join ':'\n\n$patch = @\"\napiVersion: v1alpha1\nkind: HostnameConfig\nhostname: $Name\nauto: off\n---\napiVersion: v1alpha1\nkind: LinkAliasConfig\nname: net0\nselector:\n  match: mac(link.permanent_addr) == \"$macForTalos\"\n---\napiVersion: v1alpha1\nkind: LinkConfig\nname: net0\naddresses:\n  - address: $IPAddress\nroutes:\n  - gateway: $Gateway\n\"@\n\nNew-Item -Path $PatchDirectory -ItemType Directory -Force | Out-Null\n$patchPath = Join-Path -Path $PatchDirectory -ChildPath \"$Name.yaml\"\n# WriteAllText writes UTF-8 without a byte order mark on every PowerShell version.\n[System.IO.File]::WriteAllText($patchPath, $patch)\n\nif ($PSCmdlet.ShouldProcess($Name, 'Start VM')) {\n    Start-VM -Name $Name\n}\n\n[pscustomobject]@{\n    Name       = $Name\n    MacAddress = $macForTalos\n    VlanId     = $VlanId\n    Address    = $IPAddress\n    Patch      = $patchPath\n}\n","powershell",[29,249,250,265,272,277,285,290,294,301,306,312,318,324,330,336,341,352,358,363,373,379,384,394,400,405,415,421,427,432,442,448,453,463,469,474,484,490,495,505,511,516,526,532,537,547,553,559,564,574,580,585,595,601,606,616,622,627,635,641,647,665,674,700,730,750,779,799,836,856,876,893,912,929,946,988,993,998,1010,1015,1036,1051,1057,1062,1090,1116,1121,1142,1168,1173,1204,1226,1231,1237,1243,1269,1285,1290,1306,1326,1331,1348,1373,1398,1413,1419,1424,1430,1436,1451,1479,1484,1489,1495,1528,1533,1544,1550,1556,1565,1571,1577,1582,1588,1594,1600,1612,1617,1622,1628,1633,1639,1648,1654,1663,1669,1674,1697,1722,1728,1744,1749,1767,1778,1783,1788,1805,1816,1827,1838,1849,1860],{"__ignoreMap":43},[47,251,252,255,258,262],{"class":49,"line":50},[47,253,254],{"class":53},"#",[47,256,257],{"class":139},"Requires -Modules",[47,259,261],{"class":260},"s9osk"," Hyper",[47,263,264],{"class":53},"-V\n",[47,266,267,269],{"class":49,"line":57},[47,268,254],{"class":53},[47,270,271],{"class":139},"Requires -RunAsAdministrator\n",[47,273,274],{"class":49,"line":68},[47,275,276],{"class":53},"\u003C#\n",[47,278,279,282],{"class":49,"line":76},[47,280,281],{"class":107},".",[47,283,284],{"class":139},"SYNOPSIS\n",[47,286,287],{"class":49,"line":84},[47,288,289],{"class":53},"    Creates a Talos Linux VM on a Hyper-V host and writes its Talos node patch.\n",[47,291,292],{"class":49,"line":153},[47,293,131],{"emptyLinePlaceholder":130},[47,295,296,298],{"class":49,"line":159},[47,297,281],{"class":107},[47,299,300],{"class":139},"DESCRIPTION\n",[47,302,303],{"class":49,"line":175},[47,304,305],{"class":53},"    Builds a Generation 2 VM with Secure Boot off, a static MAC address, an\n",[47,307,309],{"class":49,"line":308},9,[47,310,311],{"class":53},"    access-mode VLAN, static memory, checkpoints disabled and the Talos ISO as\n",[47,313,315],{"class":49,"line":314},10,[47,316,317],{"class":53},"    the first boot device. Writes patches\u002Fnodes\u002F\u003CName>.yaml with a hostname,\n",[47,319,321],{"class":49,"line":320},11,[47,322,323],{"class":53},"    a link alias pinned to the static MAC, and the node's static address, so\n",[47,325,327],{"class":49,"line":326},12,[47,328,329],{"class":53},"    the Talos config matches the VM without anyone copying MACs by hand.\n",[47,331,333],{"class":49,"line":332},13,[47,334,335],{"class":53},"    Run it on the Hyper-V host (or a cluster node that owns the storage path).\n",[47,337,339],{"class":49,"line":338},14,[47,340,131],{"emptyLinePlaceholder":130},[47,342,344,346,349],{"class":49,"line":343},15,[47,345,281],{"class":107},[47,347,348],{"class":139},"PARAMETER",[47,350,351],{"class":139}," Name\n",[47,353,355],{"class":49,"line":354},16,[47,356,357],{"class":53},"    VM name and Talos hostname, for example talos-cp1.\n",[47,359,361],{"class":49,"line":360},17,[47,362,131],{"emptyLinePlaceholder":130},[47,364,366,368,370],{"class":49,"line":365},18,[47,367,281],{"class":107},[47,369,348],{"class":139},[47,371,372],{"class":139}," IPAddress\n",[47,374,376],{"class":49,"line":375},19,[47,377,378],{"class":53},"    Static address in CIDR form, for example 10.20.30.11\u002F24.\n",[47,380,382],{"class":49,"line":381},20,[47,383,131],{"emptyLinePlaceholder":130},[47,385,387,389,391],{"class":49,"line":386},21,[47,388,281],{"class":107},[47,390,348],{"class":139},[47,392,393],{"class":139}," Gateway\n",[47,395,397],{"class":49,"line":396},22,[47,398,399],{"class":53},"    Default gateway for the node.\n",[47,401,403],{"class":49,"line":402},23,[47,404,131],{"emptyLinePlaceholder":130},[47,406,408,410,412],{"class":49,"line":407},24,[47,409,281],{"class":107},[47,411,348],{"class":139},[47,413,414],{"class":139}," StaticMacAddress\n",[47,416,418],{"class":49,"line":417},25,[47,419,420],{"class":53},"    MAC address without separators, for example 00155D1E1E0B. Keep it inside\n",[47,422,424],{"class":49,"line":423},26,[47,425,426],{"class":53},"    a range your DHCP and IPAM teams have reserved for the cluster.\n",[47,428,430],{"class":49,"line":429},27,[47,431,131],{"emptyLinePlaceholder":130},[47,433,435,437,439],{"class":49,"line":434},28,[47,436,281],{"class":107},[47,438,348],{"class":139},[47,440,441],{"class":139}," SwitchName\n",[47,443,445],{"class":49,"line":444},29,[47,446,447],{"class":53},"    External virtual switch the cluster VLAN is trunked to.\n",[47,449,451],{"class":49,"line":450},30,[47,452,131],{"emptyLinePlaceholder":130},[47,454,456,458,460],{"class":49,"line":455},31,[47,457,281],{"class":107},[47,459,348],{"class":139},[47,461,462],{"class":139}," VlanId\n",[47,464,466],{"class":49,"line":465},32,[47,467,468],{"class":53},"    Access VLAN for the Talos node NIC.\n",[47,470,472],{"class":49,"line":471},33,[47,473,131],{"emptyLinePlaceholder":130},[47,475,477,479,481],{"class":49,"line":476},34,[47,478,281],{"class":107},[47,480,348],{"class":139},[47,482,483],{"class":139}," IsoPath\n",[47,485,487],{"class":49,"line":486},35,[47,488,489],{"class":53},"    Path to the Talos ISO (from the Image Factory schematic) on the host.\n",[47,491,493],{"class":49,"line":492},36,[47,494,131],{"emptyLinePlaceholder":130},[47,496,498,500,502],{"class":49,"line":497},37,[47,499,281],{"class":107},[47,501,348],{"class":139},[47,503,504],{"class":139}," VMPath\n",[47,506,508],{"class":49,"line":507},38,[47,509,510],{"class":53},"    Folder for the VM configuration and its VHDX files.\n",[47,512,514],{"class":49,"line":513},39,[47,515,131],{"emptyLinePlaceholder":130},[47,517,519,521,523],{"class":49,"line":518},40,[47,520,281],{"class":107},[47,522,348],{"class":139},[47,524,525],{"class":139}," ProcessorCount\n",[47,527,529],{"class":49,"line":528},41,[47,530,531],{"class":53},"    Virtual processors. Talos recommends 4 for control plane nodes.\n",[47,533,535],{"class":49,"line":534},42,[47,536,131],{"emptyLinePlaceholder":130},[47,538,540,542,544],{"class":49,"line":539},43,[47,541,281],{"class":107},[47,543,348],{"class":139},[47,545,546],{"class":139}," MemoryBytes\n",[47,548,550],{"class":49,"line":549},44,[47,551,552],{"class":53},"    Static memory. Talos recommends 4 GiB for control plane nodes; the 8 GB\n",[47,554,556],{"class":49,"line":555},45,[47,557,558],{"class":53},"    default leaves room for workloads on nodes that also run pods.\n",[47,560,562],{"class":49,"line":561},46,[47,563,131],{"emptyLinePlaceholder":130},[47,565,567,569,571],{"class":49,"line":566},47,[47,568,281],{"class":107},[47,570,348],{"class":139},[47,572,573],{"class":139}," OsDiskBytes\n",[47,575,577],{"class":49,"line":576},48,[47,578,579],{"class":53},"    System disk size. Talos recommends 100 GiB.\n",[47,581,583],{"class":49,"line":582},49,[47,584,131],{"emptyLinePlaceholder":130},[47,586,588,590,592],{"class":49,"line":587},50,[47,589,281],{"class":107},[47,591,348],{"class":139},[47,593,594],{"class":139}," DataDiskBytes\n",[47,596,598],{"class":49,"line":597},51,[47,599,600],{"class":53},"    Optional second VHDX for workload storage (for example a CSI backend).\n",[47,602,604],{"class":49,"line":603},52,[47,605,131],{"emptyLinePlaceholder":130},[47,607,609,611,613],{"class":49,"line":608},53,[47,610,281],{"class":107},[47,612,348],{"class":139},[47,614,615],{"class":139}," PatchDirectory\n",[47,617,619],{"class":49,"line":618},54,[47,620,621],{"class":53},"    Where to write the node patch. Defaults to .\\patches\\nodes.\n",[47,623,625],{"class":49,"line":624},55,[47,626,131],{"emptyLinePlaceholder":130},[47,628,630,632],{"class":49,"line":629},56,[47,631,281],{"class":107},[47,633,634],{"class":139},"EXAMPLE\n",[47,636,638],{"class":49,"line":637},57,[47,639,640],{"class":53},"    .\\New-TalosHyperVNode.ps1 -Name talos-cp1 -IPAddress 10.20.30.11\u002F24 -Gateway 10.20.30.1 -StaticMacAddress 00155D1E1E0B -SwitchName vSwitch-Trunk -VlanId 230 -IsoPath C:\\ISO\\talos-hyperv-amd64.iso -VMPath C:\\ClusterStorage\\Volume1\\Talos\n",[47,642,644],{"class":49,"line":643},58,[47,645,646],{"class":53},"#>\n",[47,648,650,653,656,659,662],{"class":49,"line":649},59,[47,651,652],{"class":64},"[",[47,654,655],{"class":107},"CmdletBinding",[47,657,658],{"class":64},"(",[47,660,661],{"class":260},"SupportsShouldProcess",[47,663,664],{"class":64},")]\n",[47,666,668,671],{"class":49,"line":667},60,[47,669,670],{"class":139},"param",[47,672,673],{"class":64},"(\n",[47,675,677,680,683,685,688,691,694,697],{"class":49,"line":676},61,[47,678,679],{"class":64},"    [",[47,681,682],{"class":107},"Parameter",[47,684,658],{"class":64},[47,686,687],{"class":260},"Mandatory",[47,689,690],{"class":64},")] [",[47,692,693],{"class":139},"string",[47,695,696],{"class":64},"] $Name",[47,698,699],{"class":139},",\n",[47,701,703,705,707,709,711,713,716,718,721,723,725,728],{"class":49,"line":702},62,[47,704,679],{"class":64},[47,706,682],{"class":107},[47,708,658],{"class":64},[47,710,687],{"class":260},[47,712,690],{"class":64},[47,714,715],{"class":107},"ValidatePattern",[47,717,658],{"class":64},[47,719,720],{"class":90},"'^\\d{1,3}(\\.\\d{1,3}){3}\u002F\\d{1,2}$'",[47,722,690],{"class":64},[47,724,693],{"class":139},[47,726,727],{"class":64},"] $IPAddress",[47,729,699],{"class":139},[47,731,733,735,737,739,741,743,745,748],{"class":49,"line":732},63,[47,734,679],{"class":64},[47,736,682],{"class":107},[47,738,658],{"class":64},[47,740,687],{"class":260},[47,742,690],{"class":64},[47,744,693],{"class":139},[47,746,747],{"class":64},"] $Gateway",[47,749,699],{"class":139},[47,751,753,755,757,759,761,763,765,767,770,772,774,777],{"class":49,"line":752},64,[47,754,679],{"class":64},[47,756,682],{"class":107},[47,758,658],{"class":64},[47,760,687],{"class":260},[47,762,690],{"class":64},[47,764,715],{"class":107},[47,766,658],{"class":64},[47,768,769],{"class":90},"'^[0-9A-Fa-f]{12}$'",[47,771,690],{"class":64},[47,773,693],{"class":139},[47,775,776],{"class":64},"] $StaticMacAddress",[47,778,699],{"class":139},[47,780,782,784,786,788,790,792,794,797],{"class":49,"line":781},65,[47,783,679],{"class":64},[47,785,682],{"class":107},[47,787,658],{"class":64},[47,789,687],{"class":260},[47,791,690],{"class":64},[47,793,693],{"class":139},[47,795,796],{"class":64},"] $SwitchName",[47,798,699],{"class":139},[47,800,802,804,806,808,810,812,815,817,820,823,826,828,831,834],{"class":49,"line":801},66,[47,803,679],{"class":64},[47,805,682],{"class":107},[47,807,658],{"class":64},[47,809,687],{"class":260},[47,811,690],{"class":64},[47,813,814],{"class":107},"ValidateRange",[47,816,658],{"class":64},[47,818,819],{"class":107},"1",[47,821,822],{"class":139},",",[47,824,825],{"class":107}," 4094",[47,827,690],{"class":64},[47,829,830],{"class":139},"int",[47,832,833],{"class":64},"] $VlanId",[47,835,699],{"class":139},[47,837,839,841,843,845,847,849,851,854],{"class":49,"line":838},67,[47,840,679],{"class":64},[47,842,682],{"class":107},[47,844,658],{"class":64},[47,846,687],{"class":260},[47,848,690],{"class":64},[47,850,693],{"class":139},[47,852,853],{"class":64},"] $IsoPath",[47,855,699],{"class":139},[47,857,859,861,863,865,867,869,871,874],{"class":49,"line":858},68,[47,860,679],{"class":64},[47,862,682],{"class":107},[47,864,658],{"class":64},[47,866,687],{"class":260},[47,868,690],{"class":64},[47,870,693],{"class":139},[47,872,873],{"class":64},"] $VMPath",[47,875,699],{"class":139},[47,877,879,881,883,886,888,891],{"class":49,"line":878},69,[47,880,679],{"class":64},[47,882,830],{"class":139},[47,884,885],{"class":64},"] $ProcessorCount ",[47,887,140],{"class":139},[47,889,890],{"class":107}," 4",[47,892,699],{"class":139},[47,894,896,898,901,904,906,909],{"class":49,"line":895},70,[47,897,679],{"class":64},[47,899,900],{"class":139},"long",[47,902,903],{"class":64},"] $MemoryBytes ",[47,905,140],{"class":139},[47,907,908],{"class":107}," 8",[47,910,911],{"class":139},"GB,\n",[47,913,915,917,919,922,924,927],{"class":49,"line":914},71,[47,916,679],{"class":64},[47,918,900],{"class":139},[47,920,921],{"class":64},"] $OsDiskBytes ",[47,923,140],{"class":139},[47,925,926],{"class":107}," 100",[47,928,911],{"class":139},[47,930,932,934,936,939,941,944],{"class":49,"line":931},72,[47,933,679],{"class":64},[47,935,900],{"class":139},[47,937,938],{"class":64},"] $DataDiskBytes ",[47,940,140],{"class":139},[47,942,943],{"class":107}," 0",[47,945,699],{"class":139},[47,947,949,951,953,956,958,961,964,967,970,973,976,979,982,985],{"class":49,"line":948},73,[47,950,679],{"class":64},[47,952,693],{"class":139},[47,954,955],{"class":64},"] $PatchDirectory ",[47,957,140],{"class":139},[47,959,960],{"class":64}," (",[47,962,963],{"class":107},"Join-Path",[47,965,966],{"class":139}," -",[47,968,969],{"class":64},"Path (",[47,971,972],{"class":107},"Get-Location",[47,974,975],{"class":64},") ",[47,977,978],{"class":139},"-",[47,980,981],{"class":64},"ChildPath ",[47,983,984],{"class":90},"'patches\\nodes'",[47,986,987],{"class":64},")\n",[47,989,991],{"class":49,"line":990},74,[47,992,987],{"class":64},[47,994,996],{"class":49,"line":995},75,[47,997,131],{"emptyLinePlaceholder":130},[47,999,1001,1004,1007],{"class":49,"line":1000},76,[47,1002,1003],{"class":107},"$ErrorActionPreference",[47,1005,1006],{"class":139}," =",[47,1008,1009],{"class":90}," 'Stop'\n",[47,1011,1013],{"class":49,"line":1012},77,[47,1014,131],{"emptyLinePlaceholder":130},[47,1016,1018,1021,1023,1026,1028,1031,1033],{"class":49,"line":1017},78,[47,1019,1020],{"class":139},"if",[47,1022,960],{"class":64},[47,1024,1025],{"class":107},"Get-VM",[47,1027,966],{"class":139},[47,1029,1030],{"class":64},"Name $Name ",[47,1032,978],{"class":139},[47,1034,1035],{"class":64},"ErrorAction SilentlyContinue) {\n",[47,1037,1039,1042,1045,1048],{"class":49,"line":1038},79,[47,1040,1041],{"class":139},"    throw",[47,1043,1044],{"class":90}," \"A VM named ",[47,1046,1047],{"class":64},"$Name",[47,1049,1050],{"class":90}," already exists on this host.\"\n",[47,1052,1054],{"class":49,"line":1053},80,[47,1055,1056],{"class":64},"}\n",[47,1058,1060],{"class":49,"line":1059},81,[47,1061,131],{"emptyLinePlaceholder":130},[47,1063,1065,1068,1070,1073,1075,1078,1080,1082,1085,1087],{"class":49,"line":1064},82,[47,1066,1067],{"class":64},"$vhdFolder ",[47,1069,140],{"class":139},[47,1071,1072],{"class":107}," Join-Path",[47,1074,966],{"class":139},[47,1076,1077],{"class":64},"Path $VMPath ",[47,1079,978],{"class":139},[47,1081,981],{"class":64},[47,1083,1084],{"class":90},"\"",[47,1086,1047],{"class":64},[47,1088,1089],{"class":90},"\\Virtual Hard Disks\"\n",[47,1091,1093,1096,1098,1100,1102,1105,1107,1109,1111,1113],{"class":49,"line":1092},83,[47,1094,1095],{"class":64},"$osDiskPath ",[47,1097,140],{"class":139},[47,1099,1072],{"class":107},[47,1101,966],{"class":139},[47,1103,1104],{"class":64},"Path $vhdFolder ",[47,1106,978],{"class":139},[47,1108,981],{"class":64},[47,1110,1084],{"class":90},[47,1112,1047],{"class":64},[47,1114,1115],{"class":90},"-os.vhdx\"\n",[47,1117,1119],{"class":49,"line":1118},84,[47,1120,131],{"emptyLinePlaceholder":130},[47,1122,1124,1126,1128,1131,1134,1136,1139],{"class":49,"line":1123},85,[47,1125,1020],{"class":139},[47,1127,960],{"class":64},[47,1129,1130],{"class":107},"$PSCmdlet",[47,1132,1133],{"class":64},".ShouldProcess($Name",[47,1135,822],{"class":139},[47,1137,1138],{"class":90}," 'Create Talos VM'",[47,1140,1141],{"class":64},")) {\n",[47,1143,1145,1148,1150,1152,1154,1157,1159,1162,1165],{"class":49,"line":1144},86,[47,1146,1147],{"class":107},"    New-Item",[47,1149,966],{"class":139},[47,1151,1104],{"class":64},[47,1153,978],{"class":139},[47,1155,1156],{"class":64},"ItemType Directory ",[47,1158,978],{"class":139},[47,1160,1161],{"class":64},"Force ",[47,1163,1164],{"class":139},"|",[47,1166,1167],{"class":107}," Out-Null\n",[47,1169,1171],{"class":49,"line":1170},87,[47,1172,131],{"emptyLinePlaceholder":130},[47,1174,1176,1179,1181,1183,1185,1188,1191,1193,1196,1198,1201],{"class":49,"line":1175},88,[47,1177,1178],{"class":107},"    New-VM",[47,1180,966],{"class":139},[47,1182,1030],{"class":64},[47,1184,978],{"class":139},[47,1186,1187],{"class":64},"Generation ",[47,1189,1190],{"class":107},"2",[47,1192,966],{"class":139},[47,1194,1195],{"class":64},"MemoryStartupBytes $MemoryBytes ",[47,1197,978],{"class":139},[47,1199,1200],{"class":64},"NewVHDPath $osDiskPath ",[47,1202,1203],{"class":139},"`\n",[47,1205,1207,1210,1213,1215,1218,1220,1222,1224],{"class":49,"line":1206},89,[47,1208,1209],{"class":139},"        -",[47,1211,1212],{"class":64},"NewVHDSizeBytes $OsDiskBytes ",[47,1214,978],{"class":139},[47,1216,1217],{"class":64},"SwitchName $SwitchName ",[47,1219,978],{"class":139},[47,1221,1077],{"class":64},[47,1223,1164],{"class":139},[47,1225,1167],{"class":107},[47,1227,1229],{"class":49,"line":1228},90,[47,1230,131],{"emptyLinePlaceholder":130},[47,1232,1234],{"class":49,"line":1233},91,[47,1235,1236],{"class":53},"    # Fixed CPU and memory, and no checkpoints: reverting an etcd member or a\n",[47,1238,1240],{"class":49,"line":1239},92,[47,1241,1242],{"class":53},"    # node's disk to an older point in time is never what you want.\n",[47,1244,1246,1249,1251,1253,1255,1258,1260,1263,1265,1267],{"class":49,"line":1245},93,[47,1247,1248],{"class":107},"    Set-VM",[47,1250,966],{"class":139},[47,1252,1030],{"class":64},[47,1254,978],{"class":139},[47,1256,1257],{"class":64},"ProcessorCount $ProcessorCount ",[47,1259,978],{"class":139},[47,1261,1262],{"class":64},"StaticMemory ",[47,1264,978],{"class":139},[47,1266,1195],{"class":64},[47,1268,1203],{"class":139},[47,1270,1272,1274,1277,1279,1282],{"class":49,"line":1271},94,[47,1273,1209],{"class":139},[47,1275,1276],{"class":64},"CheckpointType Disabled ",[47,1278,978],{"class":139},[47,1280,1281],{"class":64},"AutomaticCheckpointsEnabled ",[47,1283,1284],{"class":107},"$false\n",[47,1286,1288],{"class":49,"line":1287},95,[47,1289,131],{"emptyLinePlaceholder":130},[47,1291,1293,1296,1298,1301,1303],{"class":49,"line":1292},96,[47,1294,1295],{"class":107},"    Set-VMNetworkAdapter",[47,1297,966],{"class":139},[47,1299,1300],{"class":64},"VMName $Name ",[47,1302,978],{"class":139},[47,1304,1305],{"class":64},"StaticMacAddress $StaticMacAddress\n",[47,1307,1309,1312,1314,1316,1318,1321,1323],{"class":49,"line":1308},97,[47,1310,1311],{"class":107},"    Set-VMNetworkAdapterVlan",[47,1313,966],{"class":139},[47,1315,1300],{"class":64},[47,1317,978],{"class":139},[47,1319,1320],{"class":64},"Access ",[47,1322,978],{"class":139},[47,1324,1325],{"class":64},"VlanId $VlanId\n",[47,1327,1329],{"class":49,"line":1328},98,[47,1330,131],{"emptyLinePlaceholder":130},[47,1332,1334,1337,1340,1343,1345],{"class":49,"line":1333},99,[47,1335,1336],{"class":139},"    if",[47,1338,1339],{"class":64}," ($DataDiskBytes ",[47,1341,1342],{"class":139},"-gt",[47,1344,943],{"class":107},[47,1346,1347],{"class":64},") {\n",[47,1349,1351,1354,1356,1358,1360,1362,1364,1366,1368,1370],{"class":49,"line":1350},100,[47,1352,1353],{"class":64},"        $dataDiskPath ",[47,1355,140],{"class":139},[47,1357,1072],{"class":107},[47,1359,966],{"class":139},[47,1361,1104],{"class":64},[47,1363,978],{"class":139},[47,1365,981],{"class":64},[47,1367,1084],{"class":90},[47,1369,1047],{"class":64},[47,1371,1372],{"class":90},"-data.vhdx\"\n",[47,1374,1376,1379,1381,1384,1386,1389,1391,1394,1396],{"class":49,"line":1375},101,[47,1377,1378],{"class":107},"        New-VHD",[47,1380,966],{"class":139},[47,1382,1383],{"class":64},"Path $dataDiskPath ",[47,1385,978],{"class":139},[47,1387,1388],{"class":64},"SizeBytes $DataDiskBytes ",[47,1390,978],{"class":139},[47,1392,1393],{"class":64},"Dynamic ",[47,1395,1164],{"class":139},[47,1397,1167],{"class":107},[47,1399,1401,1404,1406,1408,1410],{"class":49,"line":1400},102,[47,1402,1403],{"class":107},"        Add-VMHardDiskDrive",[47,1405,966],{"class":139},[47,1407,1300],{"class":64},[47,1409,978],{"class":139},[47,1411,1412],{"class":64},"Path $dataDiskPath\n",[47,1414,1416],{"class":49,"line":1415},103,[47,1417,1418],{"class":64},"    }\n",[47,1420,1422],{"class":49,"line":1421},104,[47,1423,131],{"emptyLinePlaceholder":130},[47,1425,1427],{"class":49,"line":1426},105,[47,1428,1429],{"class":53},"    # The standard Talos ISO is not a SecureBoot image (Talos publishes separate\n",[47,1431,1433],{"class":49,"line":1432},106,[47,1434,1435],{"class":53},"    # -secureboot assets), so Secure Boot is off, as in the Talos Hyper-V guide.\n",[47,1437,1439,1442,1444,1446,1448],{"class":49,"line":1438},107,[47,1440,1441],{"class":107},"    Add-VMDvdDrive",[47,1443,966],{"class":139},[47,1445,1300],{"class":64},[47,1447,978],{"class":139},[47,1449,1450],{"class":64},"Path $IsoPath\n",[47,1452,1454,1457,1459,1461,1463,1466,1468,1471,1474,1476],{"class":49,"line":1453},108,[47,1455,1456],{"class":107},"    Set-VMFirmware",[47,1458,966],{"class":139},[47,1460,1300],{"class":64},[47,1462,978],{"class":139},[47,1464,1465],{"class":64},"EnableSecureBoot Off ",[47,1467,978],{"class":139},[47,1469,1470],{"class":64},"FirstBootDevice (",[47,1472,1473],{"class":107},"Get-VMDvdDrive",[47,1475,966],{"class":139},[47,1477,1478],{"class":64},"VMName $Name)\n",[47,1480,1482],{"class":49,"line":1481},109,[47,1483,1056],{"class":64},[47,1485,1487],{"class":49,"line":1486},110,[47,1488,131],{"emptyLinePlaceholder":130},[47,1490,1492],{"class":49,"line":1491},111,[47,1493,1494],{"class":53},"# Talos matches the NIC by MAC, in lowercase colon-separated form.\n",[47,1496,1498,1501,1503,1506,1509,1512,1514,1517,1520,1522,1525],{"class":49,"line":1497},112,[47,1499,1500],{"class":64},"$macForTalos ",[47,1502,140],{"class":139},[47,1504,1505],{"class":64}," (($StaticMacAddress.ToLower() ",[47,1507,1508],{"class":139},"-split",[47,1510,1511],{"class":90}," '(..)'",[47,1513,975],{"class":64},[47,1515,1516],{"class":139},"-ne",[47,1518,1519],{"class":90}," ''",[47,1521,975],{"class":64},[47,1523,1524],{"class":139},"-join",[47,1526,1527],{"class":90}," ':'\n",[47,1529,1531],{"class":49,"line":1530},113,[47,1532,131],{"emptyLinePlaceholder":130},[47,1534,1536,1539,1541],{"class":49,"line":1535},114,[47,1537,1538],{"class":64},"$patch ",[47,1540,140],{"class":139},[47,1542,1543],{"class":90}," @\"\n",[47,1545,1547],{"class":49,"line":1546},115,[47,1548,1549],{"class":90},"apiVersion: v1alpha1\n",[47,1551,1553],{"class":49,"line":1552},116,[47,1554,1555],{"class":90},"kind: HostnameConfig\n",[47,1557,1559,1562],{"class":49,"line":1558},117,[47,1560,1561],{"class":90},"hostname: ",[47,1563,1564],{"class":64},"$Name\n",[47,1566,1568],{"class":49,"line":1567},118,[47,1569,1570],{"class":90},"auto: off\n",[47,1572,1574],{"class":49,"line":1573},119,[47,1575,1576],{"class":90},"---\n",[47,1578,1580],{"class":49,"line":1579},120,[47,1581,1549],{"class":90},[47,1583,1585],{"class":49,"line":1584},121,[47,1586,1587],{"class":90},"kind: LinkAliasConfig\n",[47,1589,1591],{"class":49,"line":1590},122,[47,1592,1593],{"class":90},"name: net0\n",[47,1595,1597],{"class":49,"line":1596},123,[47,1598,1599],{"class":90},"selector:\n",[47,1601,1603,1606,1609],{"class":49,"line":1602},124,[47,1604,1605],{"class":90},"  match: mac(link.permanent_addr) == \"",[47,1607,1608],{"class":64},"$macForTalos",[47,1610,1611],{"class":90},"\"\n",[47,1613,1615],{"class":49,"line":1614},125,[47,1616,1576],{"class":90},[47,1618,1620],{"class":49,"line":1619},126,[47,1621,1549],{"class":90},[47,1623,1625],{"class":49,"line":1624},127,[47,1626,1627],{"class":90},"kind: LinkConfig\n",[47,1629,1631],{"class":49,"line":1630},128,[47,1632,1593],{"class":90},[47,1634,1636],{"class":49,"line":1635},129,[47,1637,1638],{"class":90},"addresses:\n",[47,1640,1642,1645],{"class":49,"line":1641},130,[47,1643,1644],{"class":90},"  - address: ",[47,1646,1647],{"class":64},"$IPAddress\n",[47,1649,1651],{"class":49,"line":1650},131,[47,1652,1653],{"class":90},"routes:\n",[47,1655,1657,1660],{"class":49,"line":1656},132,[47,1658,1659],{"class":90},"  - gateway: ",[47,1661,1662],{"class":64},"$Gateway\n",[47,1664,1666],{"class":49,"line":1665},133,[47,1667,1668],{"class":90},"\"@\n",[47,1670,1672],{"class":49,"line":1671},134,[47,1673,131],{"emptyLinePlaceholder":130},[47,1675,1677,1680,1682,1685,1687,1689,1691,1693,1695],{"class":49,"line":1676},135,[47,1678,1679],{"class":107},"New-Item",[47,1681,966],{"class":139},[47,1683,1684],{"class":64},"Path $PatchDirectory ",[47,1686,978],{"class":139},[47,1688,1156],{"class":64},[47,1690,978],{"class":139},[47,1692,1161],{"class":64},[47,1694,1164],{"class":139},[47,1696,1167],{"class":107},[47,1698,1700,1703,1705,1707,1709,1711,1713,1715,1717,1719],{"class":49,"line":1699},136,[47,1701,1702],{"class":64},"$patchPath ",[47,1704,140],{"class":139},[47,1706,1072],{"class":107},[47,1708,966],{"class":139},[47,1710,1684],{"class":64},[47,1712,978],{"class":139},[47,1714,981],{"class":64},[47,1716,1084],{"class":90},[47,1718,1047],{"class":64},[47,1720,1721],{"class":90},".yaml\"\n",[47,1723,1725],{"class":49,"line":1724},137,[47,1726,1727],{"class":53},"# WriteAllText writes UTF-8 without a byte order mark on every PowerShell version.\n",[47,1729,1731,1733,1736,1739,1741],{"class":49,"line":1730},138,[47,1732,652],{"class":64},[47,1734,1735],{"class":139},"System.IO.File",[47,1737,1738],{"class":64},"]::WriteAllText($patchPath",[47,1740,822],{"class":139},[47,1742,1743],{"class":64}," $patch)\n",[47,1745,1747],{"class":49,"line":1746},139,[47,1748,131],{"emptyLinePlaceholder":130},[47,1750,1752,1754,1756,1758,1760,1762,1765],{"class":49,"line":1751},140,[47,1753,1020],{"class":139},[47,1755,960],{"class":64},[47,1757,1130],{"class":107},[47,1759,1133],{"class":64},[47,1761,822],{"class":139},[47,1763,1764],{"class":90}," 'Start VM'",[47,1766,1141],{"class":64},[47,1768,1770,1773,1775],{"class":49,"line":1769},141,[47,1771,1772],{"class":107},"    Start-VM",[47,1774,966],{"class":139},[47,1776,1777],{"class":64},"Name $Name\n",[47,1779,1781],{"class":49,"line":1780},142,[47,1782,1056],{"class":64},[47,1784,1786],{"class":49,"line":1785},143,[47,1787,131],{"emptyLinePlaceholder":130},[47,1789,1791,1793,1796,1799,1802],{"class":49,"line":1790},144,[47,1792,652],{"class":64},[47,1794,1795],{"class":139},"pscustomobject",[47,1797,1798],{"class":64},"]",[47,1800,1801],{"class":139},"@",[47,1803,1804],{"class":64},"{\n",[47,1806,1808,1811,1813],{"class":49,"line":1807},145,[47,1809,1810],{"class":64},"    Name       ",[47,1812,140],{"class":139},[47,1814,1815],{"class":64}," $Name\n",[47,1817,1819,1822,1824],{"class":49,"line":1818},146,[47,1820,1821],{"class":64},"    MacAddress ",[47,1823,140],{"class":139},[47,1825,1826],{"class":64}," $macForTalos\n",[47,1828,1830,1833,1835],{"class":49,"line":1829},147,[47,1831,1832],{"class":64},"    VlanId     ",[47,1834,140],{"class":139},[47,1836,1837],{"class":64}," $VlanId\n",[47,1839,1841,1844,1846],{"class":49,"line":1840},148,[47,1842,1843],{"class":64},"    Address    ",[47,1845,140],{"class":139},[47,1847,1848],{"class":64}," $IPAddress\n",[47,1850,1852,1855,1857],{"class":49,"line":1851},149,[47,1853,1854],{"class":64},"    Patch      ",[47,1856,140],{"class":139},[47,1858,1859],{"class":64}," $patchPath\n",[47,1861,1863],{"class":49,"line":1862},150,[47,1864,1056],{"class":64},[11,1866,1867],{},"Running it for the first control plane node looks like this:",[38,1869,1874],{"className":1870,"code":1872,"language":1873,"meta":43},[1871],"language-text","Name       : talos-cp1\nMacAddress : 00:15:5d:1e:1e:0b\nVlanId     : 230\nAddress    : 10.20.30.11\u002F24\nPatch      : C:\\talos\\lab\\patches\\nodes\\talos-cp1.yaml\n","text",[29,1875,1872],{"__ignoreMap":43},[11,1877,1878],{},"After the config is applied and the node has installed itself to disk, remove the DVD drive. The Talos Hyper-V guide warns that Talos might fail to boot if the ISO stays attached:",[38,1880,1882],{"className":245,"code":1881,"language":247,"meta":43,"style":43},"Get-VMDvdDrive -VMName talos-cp1 | Remove-VMDvdDrive\nSet-VMFirmware -VMName talos-cp1 -FirstBootDevice (Get-VMHardDiskDrive -VMName talos-cp1 -ControllerLocation 0)\n",[29,1883,1884,1903],{"__ignoreMap":43},[47,1885,1886,1888,1890,1893,1895,1898,1900],{"class":49,"line":50},[47,1887,1473],{"class":107},[47,1889,966],{"class":139},[47,1891,1892],{"class":64},"VMName talos",[47,1894,978],{"class":139},[47,1896,1897],{"class":64},"cp1 ",[47,1899,1164],{"class":139},[47,1901,1902],{"class":107}," Remove-VMDvdDrive\n",[47,1904,1905,1908,1910,1912,1914,1916,1918,1920,1923,1925,1927,1929,1931,1933,1936,1939],{"class":49,"line":57},[47,1906,1907],{"class":107},"Set-VMFirmware",[47,1909,966],{"class":139},[47,1911,1892],{"class":64},[47,1913,978],{"class":139},[47,1915,1897],{"class":64},[47,1917,978],{"class":139},[47,1919,1470],{"class":64},[47,1921,1922],{"class":107},"Get-VMHardDiskDrive",[47,1924,966],{"class":139},[47,1926,1892],{"class":64},[47,1928,978],{"class":139},[47,1930,1897],{"class":64},[47,1932,978],{"class":139},[47,1934,1935],{"class":64},"ControllerLocation ",[47,1937,1938],{"class":107},"0",[47,1940,987],{"class":64},[11,1942,1943,1944,1949],{},"If you already run Hyper-V failover clusters, the Talos VMs are just more cluster roles. The same placement rules that keep two domain controllers off one host apply to control plane nodes: three etcd members on one host is one host failure away from losing quorum. ",[1945,1946,1948],"a",{"href":1947},"\u002F2026\u002F06\u002F03\u002Fhyper-v-deploying-a-two-node-failover-cluster-on-a-budget\u002F","Hyper-V: Deploying a Two-Node Failover Cluster on a Budget"," covers the host side.",[18,1951,1953],{"id":1952},"networking-is-where-the-two-estates-actually-meet","Networking is where the two estates actually meet",[11,1955,1956],{},"The existing estate has its own VLAN structure, its own DHCP scopes, and firewall rules built around the assumption that everything on a given VLAN is a traditional Windows or Linux VM with predictable, mostly-static behavior. Kubernetes doesn't share that assumption: pods come and go, services get new endpoints, and a CNI like Cilium makes its own routing decisions on top of whatever the physical network provides.",[11,1958,1959,1960,1963],{},"So the Talos nodes live on a dedicated VLAN (",[29,1961,1962],{},"10.20.30.0\u002F24"," in these examples), and the cluster's pod and service ranges are picked from space that isn't routed anywhere else in the estate. The shared cluster patch sets those ranges, adds a Layer 2 VIP for the Kubernetes API (the control plane nodes elect an owner through etcd, so no load balancer is needed), removes the default Flannel CNI so Cilium can be installed per Talos' Cilium guide, and pins the installer image to the schematic:",[38,1965,1967],{"className":40,"code":1966,"language":42,"meta":43,"style":43},"# patches\u002Fcontrolplane.yaml\napiVersion: v1alpha1\nkind: KubeNetworkConfig\npodSubnets:\n  - 172.28.0.0\u002F16\nserviceSubnets:\n  - 172.29.0.0\u002F16\n---\napiVersion: v1alpha1\nkind: KubeFlannelCNIConfig\n$patch: delete\n---\napiVersion: v1alpha1\nkind: Layer2VIPConfig\nname: 10.20.30.10\nlink: net0\n---\napiVersion: v1alpha1\nkind: UnattendedInstallConfig\ninstaller:\n  image: factory.talos.dev\u002Fmetal-installer\u002F\u003Cschematic-id>:v1.14.0\nprovisioning:\n  diskSelector:\n    match: disk.dev_path == \"\u002Fdev\u002Fsda\"\n",[29,1968,1969,1974,1985,1995,2002,2010,2017,2024,2028,2036,2045,2055,2059,2067,2076,2086,2096,2100,2108,2117,2124,2134,2141,2148],{"__ignoreMap":43},[47,1970,1971],{"class":49,"line":50},[47,1972,1973],{"class":53},"# patches\u002Fcontrolplane.yaml\n",[47,1975,1976,1979,1982],{"class":49,"line":57},[47,1977,1978],{"class":60},"apiVersion",[47,1980,1981],{"class":64},": ",[47,1983,1984],{"class":90},"v1alpha1\n",[47,1986,1987,1990,1992],{"class":49,"line":68},[47,1988,1989],{"class":60},"kind",[47,1991,1981],{"class":64},[47,1993,1994],{"class":90},"KubeNetworkConfig\n",[47,1996,1997,2000],{"class":49,"line":76},[47,1998,1999],{"class":60},"podSubnets",[47,2001,65],{"class":64},[47,2003,2004,2007],{"class":49,"line":84},[47,2005,2006],{"class":64},"  - ",[47,2008,2009],{"class":90},"172.28.0.0\u002F16\n",[47,2011,2012,2015],{"class":49,"line":153},[47,2013,2014],{"class":60},"serviceSubnets",[47,2016,65],{"class":64},[47,2018,2019,2021],{"class":49,"line":159},[47,2020,2006],{"class":64},[47,2022,2023],{"class":90},"172.29.0.0\u002F16\n",[47,2025,2026],{"class":49,"line":175},[47,2027,1576],{"class":103},[47,2029,2030,2032,2034],{"class":49,"line":308},[47,2031,1978],{"class":60},[47,2033,1981],{"class":64},[47,2035,1984],{"class":90},[47,2037,2038,2040,2042],{"class":49,"line":314},[47,2039,1989],{"class":60},[47,2041,1981],{"class":64},[47,2043,2044],{"class":90},"KubeFlannelCNIConfig\n",[47,2046,2047,2050,2052],{"class":49,"line":320},[47,2048,2049],{"class":60},"$patch",[47,2051,1981],{"class":64},[47,2053,2054],{"class":90},"delete\n",[47,2056,2057],{"class":49,"line":326},[47,2058,1576],{"class":103},[47,2060,2061,2063,2065],{"class":49,"line":332},[47,2062,1978],{"class":60},[47,2064,1981],{"class":64},[47,2066,1984],{"class":90},[47,2068,2069,2071,2073],{"class":49,"line":338},[47,2070,1989],{"class":60},[47,2072,1981],{"class":64},[47,2074,2075],{"class":90},"Layer2VIPConfig\n",[47,2077,2078,2081,2083],{"class":49,"line":343},[47,2079,2080],{"class":60},"name",[47,2082,1981],{"class":64},[47,2084,2085],{"class":107},"10.20.30.10\n",[47,2087,2088,2091,2093],{"class":49,"line":354},[47,2089,2090],{"class":60},"link",[47,2092,1981],{"class":64},[47,2094,2095],{"class":90},"net0\n",[47,2097,2098],{"class":49,"line":360},[47,2099,1576],{"class":103},[47,2101,2102,2104,2106],{"class":49,"line":365},[47,2103,1978],{"class":60},[47,2105,1981],{"class":64},[47,2107,1984],{"class":90},[47,2109,2110,2112,2114],{"class":49,"line":375},[47,2111,1989],{"class":60},[47,2113,1981],{"class":64},[47,2115,2116],{"class":90},"UnattendedInstallConfig\n",[47,2118,2119,2122],{"class":49,"line":381},[47,2120,2121],{"class":60},"installer",[47,2123,65],{"class":64},[47,2125,2126,2129,2131],{"class":49,"line":386},[47,2127,2128],{"class":60},"  image",[47,2130,1981],{"class":64},[47,2132,2133],{"class":90},"factory.talos.dev\u002Fmetal-installer\u002F\u003Cschematic-id>:v1.14.0\n",[47,2135,2136,2139],{"class":49,"line":396},[47,2137,2138],{"class":60},"provisioning",[47,2140,65],{"class":64},[47,2142,2143,2146],{"class":49,"line":402},[47,2144,2145],{"class":60},"  diskSelector",[47,2147,65],{"class":64},[47,2149,2150,2153,2155],{"class":49,"line":407},[47,2151,2152],{"class":60},"    match",[47,2154,1981],{"class":64},[47,2156,2157],{"class":90},"disk.dev_path == \"\u002Fdev\u002Fsda\"\n",[11,2159,2160,2161,2164,2165,2168],{},"The subnet lists replace the defaults on merge rather than appending, per the patching guide, and the Flannel removal is the documented Talos 1.14 way to set the CNI to none. The VIP must come from the nodes' own subnet and must not be handed out by DHCP. The VIP documentation also says not to use it as a ",[29,2162,2163],{},"talosconfig"," endpoint, because it disappears exactly when etcd or the API server is broken, so ",[29,2166,2167],{},"talosctl"," points at the three node addresses.",[11,2170,2171],{},"For the network team, the useful artifact isn't a Kubernetes diagram. It's the port list. Talos' ingress firewall guide gives it: apid on TCP 50000, trustd on TCP 50001, the Kubernetes API on TCP 6443, etcd on TCP 2379-2380 between control plane nodes only, kubelet on TCP 10250 inside the cluster, and the CNI's VXLAN port (UDP 8472 for Cilium, 4789 for Flannel). I enforce the same thing on the nodes with Talos' own ingress firewall, so the cluster doesn't depend solely on the estate's ACLs. The doc's example opens apid and the API to everyone; I narrow both to the cluster VLAN plus the management subnet the jump hosts live in:",[38,2173,2175],{"className":40,"code":2174,"language":42,"meta":43,"style":43},"# patches\u002Ffirewall-controlplane.yaml\napiVersion: v1alpha1\nkind: NetworkDefaultActionConfig\ningress: block\n---\napiVersion: v1alpha1\nkind: NetworkRuleConfig\nname: apid-ingress\nportSelector:\n  ports:\n    - 50000\n  protocol: tcp\ningress:\n  - subnet: 10.20.30.0\u002F24\n  - subnet: 10.20.0.0\u002F24\n---\napiVersion: v1alpha1\nkind: NetworkRuleConfig\nname: kubernetes-api-ingress\nportSelector:\n  ports:\n    - 6443\n  protocol: tcp\ningress:\n  - subnet: 10.20.30.0\u002F24\n  - subnet: 10.20.0.0\u002F24\n---\napiVersion: v1alpha1\nkind: NetworkRuleConfig\nname: trustd-ingress\nportSelector:\n  ports:\n    - 50001\n  protocol: tcp\ningress:\n  - subnet: 10.20.30.0\u002F24\n---\napiVersion: v1alpha1\nkind: NetworkRuleConfig\nname: kubelet-ingress\nportSelector:\n  ports:\n    - 10250\n  protocol: tcp\ningress:\n  - subnet: 10.20.30.0\u002F24\n---\napiVersion: v1alpha1\nkind: NetworkRuleConfig\nname: etcd-ingress\nportSelector:\n  ports:\n    - 2379-2380\n  protocol: tcp\ningress:\n  - subnet: 10.20.30.11\u002F32\n  - subnet: 10.20.30.12\u002F32\n  - subnet: 10.20.30.13\u002F32\n---\napiVersion: v1alpha1\nkind: NetworkRuleConfig\nname: cni-vxlan\nportSelector:\n  ports:\n    - 8472\n  protocol: udp\ningress:\n  - subnet: 10.20.30.0\u002F24\n",[29,2176,2177,2182,2190,2199,2209,2213,2221,2230,2239,2246,2253,2261,2271,2277,2289,2300,2304,2312,2320,2329,2335,2341,2348,2356,2362,2372,2382,2386,2394,2402,2411,2417,2423,2430,2438,2444,2454,2458,2466,2474,2483,2489,2495,2502,2510,2516,2526,2530,2538,2546,2555,2561,2567,2574,2582,2588,2599,2610,2621,2625,2633,2641,2650,2656,2662,2669,2678,2684],{"__ignoreMap":43},[47,2178,2179],{"class":49,"line":50},[47,2180,2181],{"class":53},"# patches\u002Ffirewall-controlplane.yaml\n",[47,2183,2184,2186,2188],{"class":49,"line":57},[47,2185,1978],{"class":60},[47,2187,1981],{"class":64},[47,2189,1984],{"class":90},[47,2191,2192,2194,2196],{"class":49,"line":68},[47,2193,1989],{"class":60},[47,2195,1981],{"class":64},[47,2197,2198],{"class":90},"NetworkDefaultActionConfig\n",[47,2200,2201,2204,2206],{"class":49,"line":76},[47,2202,2203],{"class":60},"ingress",[47,2205,1981],{"class":64},[47,2207,2208],{"class":90},"block\n",[47,2210,2211],{"class":49,"line":84},[47,2212,1576],{"class":103},[47,2214,2215,2217,2219],{"class":49,"line":153},[47,2216,1978],{"class":60},[47,2218,1981],{"class":64},[47,2220,1984],{"class":90},[47,2222,2223,2225,2227],{"class":49,"line":159},[47,2224,1989],{"class":60},[47,2226,1981],{"class":64},[47,2228,2229],{"class":90},"NetworkRuleConfig\n",[47,2231,2232,2234,2236],{"class":49,"line":175},[47,2233,2080],{"class":60},[47,2235,1981],{"class":64},[47,2237,2238],{"class":90},"apid-ingress\n",[47,2240,2241,2244],{"class":49,"line":308},[47,2242,2243],{"class":60},"portSelector",[47,2245,65],{"class":64},[47,2247,2248,2251],{"class":49,"line":314},[47,2249,2250],{"class":60},"  ports",[47,2252,65],{"class":64},[47,2254,2255,2258],{"class":49,"line":320},[47,2256,2257],{"class":64},"    - ",[47,2259,2260],{"class":107},"50000\n",[47,2262,2263,2266,2268],{"class":49,"line":326},[47,2264,2265],{"class":60},"  protocol",[47,2267,1981],{"class":64},[47,2269,2270],{"class":90},"tcp\n",[47,2272,2273,2275],{"class":49,"line":332},[47,2274,2203],{"class":60},[47,2276,65],{"class":64},[47,2278,2279,2281,2284,2286],{"class":49,"line":338},[47,2280,2006],{"class":64},[47,2282,2283],{"class":60},"subnet",[47,2285,1981],{"class":64},[47,2287,2288],{"class":90},"10.20.30.0\u002F24\n",[47,2290,2291,2293,2295,2297],{"class":49,"line":343},[47,2292,2006],{"class":64},[47,2294,2283],{"class":60},[47,2296,1981],{"class":64},[47,2298,2299],{"class":90},"10.20.0.0\u002F24\n",[47,2301,2302],{"class":49,"line":354},[47,2303,1576],{"class":103},[47,2305,2306,2308,2310],{"class":49,"line":360},[47,2307,1978],{"class":60},[47,2309,1981],{"class":64},[47,2311,1984],{"class":90},[47,2313,2314,2316,2318],{"class":49,"line":365},[47,2315,1989],{"class":60},[47,2317,1981],{"class":64},[47,2319,2229],{"class":90},[47,2321,2322,2324,2326],{"class":49,"line":375},[47,2323,2080],{"class":60},[47,2325,1981],{"class":64},[47,2327,2328],{"class":90},"kubernetes-api-ingress\n",[47,2330,2331,2333],{"class":49,"line":381},[47,2332,2243],{"class":60},[47,2334,65],{"class":64},[47,2336,2337,2339],{"class":49,"line":386},[47,2338,2250],{"class":60},[47,2340,65],{"class":64},[47,2342,2343,2345],{"class":49,"line":396},[47,2344,2257],{"class":64},[47,2346,2347],{"class":107},"6443\n",[47,2349,2350,2352,2354],{"class":49,"line":402},[47,2351,2265],{"class":60},[47,2353,1981],{"class":64},[47,2355,2270],{"class":90},[47,2357,2358,2360],{"class":49,"line":407},[47,2359,2203],{"class":60},[47,2361,65],{"class":64},[47,2363,2364,2366,2368,2370],{"class":49,"line":417},[47,2365,2006],{"class":64},[47,2367,2283],{"class":60},[47,2369,1981],{"class":64},[47,2371,2288],{"class":90},[47,2373,2374,2376,2378,2380],{"class":49,"line":423},[47,2375,2006],{"class":64},[47,2377,2283],{"class":60},[47,2379,1981],{"class":64},[47,2381,2299],{"class":90},[47,2383,2384],{"class":49,"line":429},[47,2385,1576],{"class":103},[47,2387,2388,2390,2392],{"class":49,"line":434},[47,2389,1978],{"class":60},[47,2391,1981],{"class":64},[47,2393,1984],{"class":90},[47,2395,2396,2398,2400],{"class":49,"line":444},[47,2397,1989],{"class":60},[47,2399,1981],{"class":64},[47,2401,2229],{"class":90},[47,2403,2404,2406,2408],{"class":49,"line":450},[47,2405,2080],{"class":60},[47,2407,1981],{"class":64},[47,2409,2410],{"class":90},"trustd-ingress\n",[47,2412,2413,2415],{"class":49,"line":455},[47,2414,2243],{"class":60},[47,2416,65],{"class":64},[47,2418,2419,2421],{"class":49,"line":465},[47,2420,2250],{"class":60},[47,2422,65],{"class":64},[47,2424,2425,2427],{"class":49,"line":471},[47,2426,2257],{"class":64},[47,2428,2429],{"class":107},"50001\n",[47,2431,2432,2434,2436],{"class":49,"line":476},[47,2433,2265],{"class":60},[47,2435,1981],{"class":64},[47,2437,2270],{"class":90},[47,2439,2440,2442],{"class":49,"line":486},[47,2441,2203],{"class":60},[47,2443,65],{"class":64},[47,2445,2446,2448,2450,2452],{"class":49,"line":492},[47,2447,2006],{"class":64},[47,2449,2283],{"class":60},[47,2451,1981],{"class":64},[47,2453,2288],{"class":90},[47,2455,2456],{"class":49,"line":497},[47,2457,1576],{"class":103},[47,2459,2460,2462,2464],{"class":49,"line":507},[47,2461,1978],{"class":60},[47,2463,1981],{"class":64},[47,2465,1984],{"class":90},[47,2467,2468,2470,2472],{"class":49,"line":513},[47,2469,1989],{"class":60},[47,2471,1981],{"class":64},[47,2473,2229],{"class":90},[47,2475,2476,2478,2480],{"class":49,"line":518},[47,2477,2080],{"class":60},[47,2479,1981],{"class":64},[47,2481,2482],{"class":90},"kubelet-ingress\n",[47,2484,2485,2487],{"class":49,"line":528},[47,2486,2243],{"class":60},[47,2488,65],{"class":64},[47,2490,2491,2493],{"class":49,"line":534},[47,2492,2250],{"class":60},[47,2494,65],{"class":64},[47,2496,2497,2499],{"class":49,"line":539},[47,2498,2257],{"class":64},[47,2500,2501],{"class":107},"10250\n",[47,2503,2504,2506,2508],{"class":49,"line":549},[47,2505,2265],{"class":60},[47,2507,1981],{"class":64},[47,2509,2270],{"class":90},[47,2511,2512,2514],{"class":49,"line":555},[47,2513,2203],{"class":60},[47,2515,65],{"class":64},[47,2517,2518,2520,2522,2524],{"class":49,"line":561},[47,2519,2006],{"class":64},[47,2521,2283],{"class":60},[47,2523,1981],{"class":64},[47,2525,2288],{"class":90},[47,2527,2528],{"class":49,"line":566},[47,2529,1576],{"class":103},[47,2531,2532,2534,2536],{"class":49,"line":576},[47,2533,1978],{"class":60},[47,2535,1981],{"class":64},[47,2537,1984],{"class":90},[47,2539,2540,2542,2544],{"class":49,"line":582},[47,2541,1989],{"class":60},[47,2543,1981],{"class":64},[47,2545,2229],{"class":90},[47,2547,2548,2550,2552],{"class":49,"line":587},[47,2549,2080],{"class":60},[47,2551,1981],{"class":64},[47,2553,2554],{"class":90},"etcd-ingress\n",[47,2556,2557,2559],{"class":49,"line":597},[47,2558,2243],{"class":60},[47,2560,65],{"class":64},[47,2562,2563,2565],{"class":49,"line":603},[47,2564,2250],{"class":60},[47,2566,65],{"class":64},[47,2568,2569,2571],{"class":49,"line":608},[47,2570,2257],{"class":64},[47,2572,2573],{"class":90},"2379-2380\n",[47,2575,2576,2578,2580],{"class":49,"line":618},[47,2577,2265],{"class":60},[47,2579,1981],{"class":64},[47,2581,2270],{"class":90},[47,2583,2584,2586],{"class":49,"line":624},[47,2585,2203],{"class":60},[47,2587,65],{"class":64},[47,2589,2590,2592,2594,2596],{"class":49,"line":629},[47,2591,2006],{"class":64},[47,2593,2283],{"class":60},[47,2595,1981],{"class":64},[47,2597,2598],{"class":90},"10.20.30.11\u002F32\n",[47,2600,2601,2603,2605,2607],{"class":49,"line":637},[47,2602,2006],{"class":64},[47,2604,2283],{"class":60},[47,2606,1981],{"class":64},[47,2608,2609],{"class":90},"10.20.30.12\u002F32\n",[47,2611,2612,2614,2616,2618],{"class":49,"line":643},[47,2613,2006],{"class":64},[47,2615,2283],{"class":60},[47,2617,1981],{"class":64},[47,2619,2620],{"class":90},"10.20.30.13\u002F32\n",[47,2622,2623],{"class":49,"line":649},[47,2624,1576],{"class":103},[47,2626,2627,2629,2631],{"class":49,"line":667},[47,2628,1978],{"class":60},[47,2630,1981],{"class":64},[47,2632,1984],{"class":90},[47,2634,2635,2637,2639],{"class":49,"line":676},[47,2636,1989],{"class":60},[47,2638,1981],{"class":64},[47,2640,2229],{"class":90},[47,2642,2643,2645,2647],{"class":49,"line":702},[47,2644,2080],{"class":60},[47,2646,1981],{"class":64},[47,2648,2649],{"class":90},"cni-vxlan\n",[47,2651,2652,2654],{"class":49,"line":732},[47,2653,2243],{"class":60},[47,2655,65],{"class":64},[47,2657,2658,2660],{"class":49,"line":752},[47,2659,2250],{"class":60},[47,2661,65],{"class":64},[47,2663,2664,2666],{"class":49,"line":781},[47,2665,2257],{"class":64},[47,2667,2668],{"class":107},"8472\n",[47,2670,2671,2673,2675],{"class":49,"line":801},[47,2672,2265],{"class":60},[47,2674,1981],{"class":64},[47,2676,2677],{"class":90},"udp\n",[47,2679,2680,2682],{"class":49,"line":838},[47,2681,2203],{"class":60},[47,2683,65],{"class":64},[47,2685,2686,2688,2690,2692],{"class":49,"line":858},[47,2687,2006],{"class":64},[47,2689,2283],{"class":60},[47,2691,1981],{"class":64},[47,2693,2288],{"class":90},[11,2695,2696,2697,2700],{},"Roll a default-block firewall out with ",[29,2698,2699],{},"--mode=try"," first. If a rule is wrong and you lock yourself out, Talos reverts the change after the timeout instead of leaving you at the Hyper-V console of a node with no shell.",[11,2702,2703],{},"Ingress for applications is the one deliberate, documented crossing point between \"legacy VLAN\" and \"cluster network.\" Everything else in the estate talks to the cluster through that door rather than learning about pod IPs.",[18,2705,2707],{"id":2706},"storage-means-picking-your-dependency-deliberately","Storage means picking your dependency deliberately",[11,2709,2710,2711,2714],{},"Hyper-V's storage story (CSVs, Storage Spaces Direct, whatever SAN sits behind it) and Kubernetes' storage story (CSI drivers, StorageClasses, PersistentVolumes) don't talk to each other by default. I didn't want Talos nodes depending on the same storage fabric in a way that could let a Kubernetes storage problem cascade into the Hyper-V estate or the other way round. Talos node OS disks are ordinary VHDX files on existing storage; that part is fine, it's just another VM disk. Persistent workload storage inside the cluster goes through a CSI driver with its own backend, kept operationally separate from the Hyper-V storage stack. Talos' storage guide walks through the options it documents on Talos (Rook\u002FCeph, Longhorn, Mayastor, Piraeus\u002FLINSTOR, SeaweedFS, and vendor drivers such as Dell PowerStore and Synology). The ",[29,2712,2713],{},"-DataDiskBytes"," parameter in the script exists for the replicated options that want a raw disk per node. That separation costs some duplication, but a bad day in one storage system doesn't automatically become a bad day in the other.",[18,2716,2718],{"id":2717},"the-estate-doesnt-need-to-know-kubernetes-exists","The estate doesn't need to know Kubernetes exists",[11,2720,2721,2722,2724,2725,2727,2728,2731,2732,2735],{},"The System Center and VMM tooling that manages the rest of the fleet doesn't understand Talos nodes as anything other than VMs, and I've left it that way on purpose. Talos' API and ",[29,2723,2167],{}," handle node lifecycle, upgrades and configuration; VMM's job is limited to \"this VM exists, is powered on, and lives on the right host,\" the same as any other guest. Two estate processes needed an explicit exception: patch orchestration and backup. Host patching treats the Talos VMs like any other clustered role, which is fine as long as only one host (and so at most one control plane node) is out at a time, but Talos OS upgrades go through ",[29,2726,192],{},", never through the Windows patch cycle. And VM-level backup of Talos nodes is the wrong unit: what you need back after a disaster is the ",[29,2729,2730],{},"secrets.yaml",", the patches, and an etcd snapshot (",[29,2733,2734],{},"talosctl etcd snapshot","), not a VHDX of a node that can be rebuilt from its config in minutes. Trying to make the legacy tooling Kubernetes-aware would have meant fighting both toolchains at once. Keeping the boundary sharp let each one do the job it's actually good at.",[18,2737,2739],{"id":2738},"references","References",[198,2741,2742,2750,2764,2771,2778,2790,2797,2809,2819],{},[201,2743,2744],{},[1945,2745,2749],{"href":2746,"rel":2747},"https:\u002F\u002Fdocs.siderolabs.com\u002Ftalos\u002Fv1.14\u002Fplatform-specific-installations\u002Fvirtualized-platforms\u002Fhyper-v",[2748],"nofollow","Hyper-V (Talos platform guide)",[201,2751,2752,2757,2758,2763],{},[1945,2753,2756],{"href":2754,"rel":2755},"https:\u002F\u002Fdocs.siderolabs.com\u002Ftalos\u002Fv1.14\u002Flearn-more\u002Fimage-factory",[2748],"Image Factory"," and ",[1945,2759,2762],{"href":2760,"rel":2761},"https:\u002F\u002Fdocs.siderolabs.com\u002Ftalos\u002Fv1.14\u002Fconfigure-your-talos-cluster\u002Flifecycle-management\u002Fupgrading-talos",[2748],"Upgrading Talos Linux"," (Factory installer images from 1.14)",[201,2765,2766],{},[1945,2767,2770],{"href":2768,"rel":2769},"https:\u002F\u002Fdocs.siderolabs.com\u002Ftalos\u002Fv1.14\u002Fplatform-specific-installations\u002Fbare-metal-platforms\u002Fsecureboot",[2748],"SecureBoot",[201,2772,2773],{},[1945,2774,2777],{"href":2775,"rel":2776},"https:\u002F\u002Fdocs.siderolabs.com\u002Ftalos\u002Fv1.14\u002Fgetting-started\u002Fsystem-requirements",[2748],"System Requirements",[201,2779,2780,2757,2785],{},[1945,2781,2784],{"href":2782,"rel":2783},"https:\u002F\u002Fdocs.siderolabs.com\u002Ftalos\u002Fv1.14\u002Fnetworking\u002Fadvanced\u002Fvip",[2748],"Virtual (shared) IP",[1945,2786,2789],{"href":2787,"rel":2788},"https:\u002F\u002Fdocs.siderolabs.com\u002Ftalos\u002Fv1.14\u002Fnetworking\u002Fconfiguration\u002Faliases",[2748],"Link Aliases",[201,2791,2792],{},[1945,2793,2796],{"href":2794,"rel":2795},"https:\u002F\u002Fdocs.siderolabs.com\u002Ftalos\u002Fv1.14\u002Fnetworking\u002Fingress-firewall",[2748],"Ingress Firewall",[201,2798,2799,2757,2804],{},[1945,2800,2803],{"href":2801,"rel":2802},"https:\u002F\u002Fdocs.siderolabs.com\u002Fkubernetes-guides\u002Fcni\u002Fdeploying-cilium",[2748],"Deploy Cilium CNI",[1945,2805,2808],{"href":2806,"rel":2807},"https:\u002F\u002Fdocs.siderolabs.com\u002Fkubernetes-guides\u002Fcsi\u002Fstorage",[2748],"Storage",[201,2810,2811,960,2816,2818],{},[1945,2812,2815],{"href":2813,"rel":2814},"https:\u002F\u002Fgithub.com\u002Fsiderolabs\u002Fextensions",[2748],"Siderolabs extensions catalog",[29,2817,31],{},")",[201,2820,2821,2822,2827,2828,2827,2833,2827,2837],{},"Microsoft Hyper-V module: ",[1945,2823,2826],{"href":2824,"rel":2825},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fhyper-v\u002Fnew-vm",[2748],"New-VM",", ",[1945,2829,2832],{"href":2830,"rel":2831},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fhyper-v\u002Fset-vm",[2748],"Set-VM",[1945,2834,1907],{"href":2835,"rel":2836},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fhyper-v\u002Fset-vmfirmware",[2748],[1945,2838,2841],{"href":2839,"rel":2840},"https:\u002F\u002Flearn.microsoft.com\u002Fen-us\u002Fpowershell\u002Fmodule\u002Fhyper-v\u002Fset-vmnetworkadapter",[2748],"Set-VMNetworkAdapter",[2843,2844,2845],"style",{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":43,"searchDepth":57,"depth":57,"links":2847},[2848,2849,2850,2851,2852],{"id":20,"depth":57,"text":21},{"id":1952,"depth":57,"text":1953},{"id":2706,"depth":57,"text":2707},{"id":2717,"depth":57,"text":2718},{"id":2738,"depth":57,"text":2739},"techcolumnist",[2855],"engineering","2026-07-08T14:00:00Z","Introducing a Talos Kubernetes cluster into an existing Hyper-V estate: VM build script, Image Factory schematic, VLAN, VIP, firewall and storage boundaries.","md",false,null,{},"\u002Fblog\u002F2026\u002F07\u002F08\u002Fkubernetes-running-talos-alongside-a-legacy-hyper-v-estate",{"title":6,"description":2857},[2853],"blog\u002F2026\u002F07\u002F08\u002Fkubernetes-running-talos-alongside-a-legacy-hyper-v-estate",[2867,2868,2869],"talos","kubernetes","hyper-v","2026-09-13T03:22:28Z","\u002F2026\u002F07\u002F08\u002Fkubernetes-running-talos-alongside-a-legacy-hyper-v-estate\u002F","FikbJAm2m3Ju1EfBKr4jpWvMDXaw1rLqawKlWYylh4s",{"title":2874,"description":2875,"date":2876,"url":2877,"categories":2878,"tags":2880,"image":2860,"readingTime":175,"canonical":2853,"sites":2884,"series":2860,"seriesOrder":2860},"Infrastructure: Documenting an Undocumented Network, Discovery First","Document an undocumented network from what it already knows: DHCP leases, AD, ARP and switch MAC tables, then a scoped nmap pass. Scripts included.","2026-07-15T14:00:00Z","\u002F2026\u002F07\u002F15\u002Finfrastructure-a-discovery-first-approach-to-documenting-an-undocumented-network\u002F",[2855,2879],"strategy",[2881,2882,2883],"discovery","network","python",[2853],{"title":2886,"description":2887,"date":2888,"url":2889,"categories":2890,"tags":2891,"image":2860,"readingTime":159,"canonical":2853,"sites":2894,"series":2860,"seriesOrder":2860},"Windows Server: TCP Stack Tuning for a 10GbE Storage Network","Field notes on getting 10GbE-class throughput from Windows Server storage links: RSS, SMB Multichannel, autotuning, offloads, jumbo frames, and a baseline script.","2026-07-01T14:00:00Z","\u002F2026\u002F07\u002F01\u002Fwindows-server-tcp-stack-tuning-for-a-10gbe-storage-network\u002F",[2855],[2892,2893,2882],"windows","tcp",[2853],[2896,2904,2912],{"title":2897,"description":2898,"date":2899,"url":2900,"categories":2901,"tags":2902,"image":2860,"readingTime":84,"canonical":2853,"sites":2903,"series":2860,"seriesOrder":2860},"Hyper-V to Talos: Rethinking the Virtualization Stack","Why moving workloads off Hyper-V VMs onto a Talos Kubernetes cluster changed the whole stack, with an inventory script and a VM-to-manifest example.","2026-09-16T14:00:00Z","\u002F2026\u002F09\u002F16\u002Fhyper-v-to-talos-rethinking-the-virtualization-stack\u002F",[2855,2879],[2869,2867,2868],[2853],{"title":2905,"description":2906,"date":2907,"url":2908,"categories":2909,"tags":2910,"image":2860,"readingTime":159,"canonical":2853,"sites":2911,"series":2860,"seriesOrder":2860},"Talos Linux: Upgrading a Cluster Without a Maintenance Window","Rolling Talos and Kubernetes upgrades through a cluster one node at a time: preflight checks, etcd snapshots, Image Factory installers, and scripts.","2026-08-26T14:00:00Z","\u002F2026\u002F08\u002F26\u002Ftalos-linux-upgrading-a-cluster-without-a-maintenance-window\u002F",[2855],[2867,2868],[2853],{"title":2913,"description":2914,"date":2915,"url":2916,"categories":2917,"tags":2918,"image":2860,"readingTime":153,"canonical":2853,"sites":2919,"series":2860,"seriesOrder":2860},"Talos Linux: What Immutable Infrastructure Buys You in Production","Where an immutable, API-managed OS pays off under Kubernetes and where it bites: drift, upgrades, try-mode config changes, and debugging without SSH.","2026-03-25T14:00:00Z","\u002F2026\u002F03\u002F25\u002Ftalos-linux-what-immutable-infrastructure-actually-buys-you-in-production\u002F",[2855,2879],[2867,2868],[2853],{"doc":2860,"posts":2921},[],1790052514061]