|
31 | 31 | $log | ConvertTo-Json -Compress | Write-Output |
32 | 32 | } |
33 | 33 |
|
| 34 | + Import-Module -Force C:\k\hns.v2.psm1 |
| 35 | +
|
34 | 36 | $nw = Get-HnsNetwork | Where Name -Eq azure |
35 | 37 | $nodeIpv4 = $nw.ManagementIP |
36 | 38 | $nodeIpv6 = $nw.ManagementIPv6 |
@@ -98,6 +100,11 @@ data: |
98 | 100 | foreach ($rule in $rules) { |
99 | 101 | $ruleId = $rule.Id |
100 | 102 | if ($expVfpRuleIds[$ruleId] -eq $null) { |
| 103 | + # Skip nodePort rules (destination port > 30000 and < 32768) |
| 104 | + $parts = $ruleId -split '_' |
| 105 | + $extPort = [int]$parts[$parts.Count - 4] |
| 106 | + if ($extPort -ge 30000 -and $extPort -lt 32768) { continue } |
| 107 | +
|
101 | 108 | $key = "${port}::${ruleId}" |
102 | 109 | $staleVfpRuleIds[$key] = @{ |
103 | 110 | Port = $port |
@@ -139,7 +146,10 @@ data: |
139 | 146 | $_.Policies[0].Protocol -eq $protocol |
140 | 147 | } |
141 | 148 |
|
142 | | - return [bool]$found |
| 149 | + if ($found) { |
| 150 | + return $null |
| 151 | + } |
| 152 | + return @{ DestIP = $destIP; DestPort = $destPort; Protocol = $protocol } |
143 | 153 | } |
144 | 154 |
|
145 | 155 | $iterationIntervalSeconds = if ($env:ITERATION_INTERVAL_SECONDS) { [int]$env:ITERATION_INTERVAL_SECONDS } else { 60 } |
@@ -183,22 +193,94 @@ data: |
183 | 193 | if ($orphanVfpRules.Count -eq 0) { |
184 | 194 | Write-KustoLog -Level 'Info' -Event 'NoOrphanRules' -Message 'No orphan VFP rules found.' |
185 | 195 | } else { |
| 196 | + $hnsPolicies = Get-HnsPolicyList |
| 197 | + $unmatchedPolicies = @{} |
186 | 198 | foreach ($entry in $orphanVfpRules.Values) { |
187 | 199 | $ruleProps = @{ |
188 | 200 | Port = $entry.Port |
189 | 201 | Layer = $entry.Layer |
190 | 202 | Group = $entry.Group |
191 | 203 | RuleId = $entry.RuleId |
192 | 204 | } |
193 | | - Write-KustoLog -Level 'Warning' -Event 'OrphanRuleDetected' -Message "Orphan VFP rule detected." -Properties $ruleProps |
194 | 205 |
|
195 | | - if (-not (Test-VfpRuleHasMatchingPolicy -port $entry.Port -layer $entry.Layer -group $entry.Group -ruleId $entry.RuleId -hnsPolicies $hnsPolicies)) { |
196 | | - Write-KustoLog -Level 'Warning' -Event 'OrphanRuleNoPolicy' -Message "Rule has no matching HNS policy and is a candidate for removal." -Properties $ruleProps |
| 206 | + $result = Test-VfpRuleHasMatchingPolicy -port $entry.Port -layer $entry.Layer -group $entry.Group -ruleId $entry.RuleId -hnsPolicies $hnsPolicies |
| 207 | + if ($result) { |
| 208 | + Write-KustoLog -Level 'Warning' -Event 'OrphanRuleDetected' -Message "Orphan VFP rule detected." -Properties $ruleProps |
197 | 209 | # Remove the orphan rule |
198 | | - vfpctrl.exe /port $entry.Port /layer $entry.Layer /group $entry.Group /delete-rule /rule $entry.RuleId |
199 | | - } else { |
200 | | - Write-KustoLog -Level 'Info' -Event 'OrphanRuleHasPolicy' -Message "Rule has a matching HNS policy and should not be removed." -Properties $ruleProps |
| 210 | + vfpctrl /remove-rule /port $entry.Port /layer $entry.Layer /group $entry.Group /rule $entry.RuleId |
| 211 | + Write-KustoLog -Level 'Info' -Event 'OrphanRuleRemoved' -Message "Orphan VFP rule removed." -Properties $ruleProps |
| 212 | + # Collect unique VIP/port/protocol for LB create+delete |
| 213 | + $ruleIdParts = $entry.RuleId -split '_' |
| 214 | + $result.IntPort = [int]$ruleIdParts[-3] |
| 215 | + $policyKey = "$($result.DestIP)::$($result.DestPort)::$($result.Protocol)" |
| 216 | + if (-not $unmatchedPolicies.ContainsKey($policyKey)) { |
| 217 | + $unmatchedPolicies[$policyKey] = $result |
| 218 | + } |
| 219 | + } |
| 220 | + } |
| 221 | +
|
| 222 | + # Create and delete temporary LB policies to force HNS cleanup of stale VFP rules |
| 223 | + if ($unmatchedPolicies.Count -gt 0) { |
| 224 | + Write-KustoLog -Level 'Info' -Event 'LBPolicyCleanup' -Message "Creating and deleting temporary LB policies to trigger cleanup." -Properties @{ UnmatchedPolicyCount = $unmatchedPolicies.Count } |
| 225 | + ipmo -Force C:\k\hns.v2.psm1 |
| 226 | + $ipStackCount = (Get-HnsNetwork)[0].Ipams.Count |
| 227 | + $epId = (Get-HnsEndpoint | Where-Object { $_.IpConfigurations.Count -ge $ipStackCount })[0].Id |
| 228 | + Write-KustoLog -Level 'Info' -Event 'EndpointSelection' -Message "Endpoints selected for LB cleanup." -Properties @{ |
| 229 | + EndpointId = if ($epId) { $epId } else { 'none' } |
| 230 | + } |
| 231 | + foreach ($policy in $unmatchedPolicies.Values) { |
| 232 | + $isIPv6 = $policy.DestIP -match ':' |
| 233 | +
|
| 234 | + try { |
| 235 | + $VIP = $policy.DestIP |
| 236 | + $InternalPort = $policy.IntPort |
| 237 | + $ExternalPort = $policy.DestPort |
| 238 | + $Protocol = $policy.Protocol |
| 239 | +
|
| 240 | + if ($VIP -eq $null -or $InternalPort -eq $null -or $ExternalPort -eq $null -or $Protocol -eq $null) { |
| 241 | + continue |
| 242 | + } |
| 243 | +
|
| 244 | + Write-KustoLog -Level 'Info' -Event 'TempLBCreateStart' -Message "Creating temporary LB policy." -Properties @{ |
| 245 | + VIP = $VIP |
| 246 | + IntPort = $InternalPort |
| 247 | + ExtPort = $ExternalPort |
| 248 | + Protocol = $Protocol |
| 249 | + IsIPv6 = $isIPv6 |
| 250 | + EndpointId = $epId |
| 251 | + } |
| 252 | +
|
| 253 | + if ($isIPv6) { |
| 254 | + $lb = New-HnsLoadBalancer -Endpoints @("$epId") -InternalPort $InternalPort -ExternalPort $ExternalPort -Protocol $Protocol -VIP $VIP -IPv6 -DSR -Verbose |
| 255 | + } else { |
| 256 | + $lb = New-HnsLoadBalancer -Endpoints @("$epId") -InternalPort $InternalPort -ExternalPort $ExternalPort -Protocol $Protocol -VIP $VIP -DSR -Verbose |
| 257 | + } |
| 258 | +
|
| 259 | + Write-KustoLog -Level 'Info' -Event 'TempLBCreated' -Message "Temporary LB policy created." -Properties @{ |
| 260 | + PolicyId = $lb.Id |
| 261 | + VIP = $VIP |
| 262 | + IntPort = $InternalPort |
| 263 | + ExtPort = $ExternalPort |
| 264 | + Protocol = $Protocol |
| 265 | + EndpointId = $epId |
| 266 | + } |
| 267 | +
|
| 268 | + $lb | Remove-HnsLoadBalancer |
| 269 | +
|
| 270 | + Write-KustoLog -Level 'Info' -Event 'TempLBDeleted' -Message "Temporary LB policy deleted." -Properties @{ |
| 271 | + PolicyId = $lb.Id |
| 272 | + VIP = $VIP |
| 273 | + IntPort = $InternalPort |
| 274 | + ExtPort = $ExternalPort |
| 275 | + Protocol = $Protocol |
| 276 | + EndpointId = $epId |
| 277 | + } |
| 278 | +
|
| 279 | + } catch { |
| 280 | + Write-KustoLog -Level 'Error' -Event 'TempLBFailed' -Message "Failed to create/delete temporary LB policy: $_" -Properties $lbProps |
| 281 | + } |
201 | 282 | } |
| 283 | + Write-KustoLog -Level 'Info' -Event 'LBPolicyCleanupCompleted' -Message "LB policy cleanup completed." -Properties @{ UnmatchedPolicyCount = $unmatchedPolicies.Count } |
202 | 284 | } |
203 | 285 | } |
204 | 286 |
|
@@ -242,9 +324,9 @@ spec: |
242 | 324 | imagePullPolicy: IfNotPresent |
243 | 325 | env: |
244 | 326 | - name: ITERATION_INTERVAL_SECONDS |
245 | | - value: "30" |
| 327 | + value: "60" |
246 | 328 | - name: PASS2_DELAY_SECONDS |
247 | | - value: "10" |
| 329 | + value: "120" |
248 | 330 | command: |
249 | 331 | - powershell.exe |
250 | 332 | - -File |
|
0 commit comments