Last active
May 12, 2026 08:18
-
-
Save ManuelSimon/a5fff61743c2b8469e01d2ec281a88ae to your computer and use it in GitHub Desktop.
This script automates the collection of RKE2/containerd logs, CNI configurations, and Event Viewer logs. It also executes runtime diagnostics (crictl, ctr, named pipe checks, EDR scans) and bundles the results and logs into a single compressed zip file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <# | |
| .SYNOPSIS | |
| RKE2 Windows Worker Node Log & Diagnostics Collector | |
| .DESCRIPTION | |
| This script automates the collection of RKE2/containerd logs, CNI configurations, and Event Viewer logs. | |
| It also executes runtime diagnostics (crictl, ctr, named pipe checks, EDR scans) and bundles | |
| the results and logs into a single compressed zip file. | |
| .NOTES | |
| Must be run as Administrator. | |
| #> | |
| #Requires -RunAsAdministrator | |
| $Timestamp = Get-Date -Format "yyyyMMdd_HHmmss" | |
| $TempDir = "C:\rke2_logs_temp_$Timestamp" | |
| $ZipPath = "C:\rke2_windows_logs_$Timestamp.zip" | |
| if (Test-Path $TempDir) { Remove-Item -Path $TempDir -Recurse -Force } | |
| New-Item -ItemType Directory -Path $TempDir -Force | Out-Null | |
| $DiagFile = "$TempDir\diagnostics_summary.txt" | |
| Add-Content -Path $DiagFile -Value "RKE2 Windows Diagnostics Summary" | |
| Add-Content -Path $DiagFile -Value "======================================" | |
| Add-Content -Path $DiagFile -Value "Date: $(Get-Date)" | |
| Add-Content -Path $DiagFile -Value "Node: $env:COMPUTERNAME`n" | |
| function Log-Diag { | |
| param([string]$Message, [string]$Color = "White") | |
| Write-Host $Message -ForegroundColor $Color | |
| Add-Content -Path $DiagFile -Value $Message | |
| } | |
| Log-Diag "Starting RKE2 Windows Log Collection..." "Cyan" | |
| # --------------------------------------------------------- | |
| # 1. Gather Directories and Files | |
| # --------------------------------------------------------- | |
| Log-Diag "`n[1/5] Copying Configuration and Log Directories..." "Yellow" | |
| $DirsToCopy = @( | |
| "C:\var\lib\rancher\rke2\agent\logs", | |
| "C:\var\lib\rancher\rke2\agent\etc", | |
| "C:\var\lib\rancher\rke2\agent\images", | |
| "C:\ProgramData\containerd", | |
| "C:\var\lib\rancher\rke2\agent\containerd\state", | |
| "C:\Program Files\containerd\cni\conf", | |
| "C:\etc\cni\net.d", | |
| "C:\var\lib\cni", | |
| "C:\var\lib\rancher\rke2\agent\containerd\containerd.log", | |
| "C:\var\log\pods" | |
| ) | |
| foreach ($dir in $DirsToCopy) { | |
| if (Test-Path $dir) { | |
| $DirName = $dir -replace 'C:\\', '' -replace '\\', '_' | |
| $Dest = Join-Path $TempDir $DirName | |
| if ((Get-Item $dir) -is [System.IO.FileInfo]) { | |
| Copy-Item -Path $dir -Destination $Dest -Force -ErrorAction SilentlyContinue | |
| } else { | |
| New-Item -ItemType Directory -Path $Dest -Force | Out-Null | |
| # Copy all files resolving symbolic links so zip archives don't break | |
| Copy-Item -Path "$dir\*" -Destination $Dest -Recurse -Force -ErrorAction SilentlyContinue | |
| } | |
| Log-Diag " -> Collected: $dir" | |
| } else { | |
| # Note: It is 100% normal for legacy/default CNI paths like C:\Program Files\containerd to be missing in RKE2. | |
| Log-Diag " -> Missing: $dir (Normal if not using this specific path/plugin)" "DarkGray" | |
| } | |
| } | |
| # Safely copy top-level agent files (excluding keys and kubeconfigs for security) | |
| $AgentRoot = "C:\var\lib\rancher\rke2\agent" | |
| if (Test-Path $AgentRoot) { | |
| $AgentRootDest = Join-Path $TempDir "var_lib_rancher_rke2_agent_root" | |
| New-Item -ItemType Directory -Path $AgentRootDest -Force | Out-Null | |
| Get-ChildItem -Path $AgentRoot -File | Where-Object { $_.Extension -notmatch '\.key|\.kubeconfig' } | Copy-Item -Destination $AgentRootDest -Force -ErrorAction SilentlyContinue | |
| Log-Diag " -> Collected: $AgentRoot (top-level files, excluding secrets)" | |
| } | |
| # --------------------------------------------------------- | |
| # 2. Extract Event Logs | |
| # --------------------------------------------------------- | |
| Log-Diag "`n[2/5] Extracting Windows Event Logs (Application)..." "Yellow" | |
| $EventSources = @("rke2", "rancher-wins", "containerd") | |
| foreach ($source in $EventSources) { | |
| Log-Diag " -> Exporting $source events..." | |
| $outFile = "$TempDir\eventlog_$source.txt" | |
| Get-EventLog -LogName Application -Source $source -Newest 2500 -ErrorAction SilentlyContinue | ` | |
| Format-Table -Property TimeGenerated, ReplacementStrings -Wrap | Out-File -FilePath $outFile -Encoding utf8 | |
| } | |
| # --------------------------------------------------------- | |
| # 3. Execute Diagnostic Tests | |
| # --------------------------------------------------------- | |
| Log-Diag "`n[3/5] Running Diagnostic Tests..." "Yellow" | |
| # Test A: Named Pipes | |
| Log-Diag "--- Testing Containerd Named Pipes ---" | |
| try { | |
| $pipes = [System.IO.Directory]::GetFiles("\\.\\pipe\\") | Select-String "containerd-containerd" | |
| if ($pipes) { | |
| Log-Diag "Result: OK (Found containerd named pipes)" "Green" | |
| $pipes | Out-File "$TempDir\diag_named_pipes.txt" -Encoding utf8 | |
| } else { | |
| Log-Diag "Result: NOT PASSED (No containerd named pipes found)" "Red" | |
| } | |
| } catch { | |
| Log-Diag "Result: ERROR ($($_.Exception.Message))" "Red" | |
| } | |
| # Test B: crictl execution | |
| Log-Diag "`n--- Testing crictl connectivity ---" | |
| $Env:CONTAINER_RUNTIME_ENDPOINT = "npipe:////./pipe/containerd-containerd" | |
| $crictlPath = "C:\var\lib\rancher\rke2\bin\crictl.exe" | |
| if (Test-Path $crictlPath) { | |
| $crictlOut = & $crictlPath info 2>&1 | |
| if ($LASTEXITCODE -eq 0) { | |
| Log-Diag "Result: OK (crictl info connected successfully)" "Green" | |
| } else { | |
| Log-Diag "Result: NOT PASSED (crictl info failed to connect)" "Red" | |
| } | |
| $crictlOut | Out-File "$TempDir\diag_crictl_info.txt" -Encoding utf8 | |
| & $crictlPath version 2>&1 | Out-File "$TempDir\diag_crictl_version.txt" -Encoding utf8 | |
| & $crictlPath ps -a 2>&1 | Out-File "$TempDir\diag_crictl_ps.txt" -Encoding utf8 | |
| & $crictlPath pods 2>&1 | Out-File "$TempDir\diag_crictl_pods.txt" -Encoding utf8 | |
| & $crictlPath images 2>&1 | Out-File "$TempDir\diag_crictl_images.txt" -Encoding utf8 | |
| & $crictlPath stats 2>&1 | Out-File "$TempDir\diag_crictl_stats.txt" -Encoding utf8 | |
| } else { | |
| Log-Diag "Result: SKIPPED (crictl.exe not found)" "DarkGray" | |
| } | |
| # Test C: ctr execution | |
| Log-Diag "`n--- Testing ctr connectivity ---" | |
| $ctrPath = "C:\var\lib\rancher\rke2\bin\ctr.exe" | |
| if (Test-Path $ctrPath) { | |
| $ctrOut = & $ctrPath --address "\\.\pipe\containerd-containerd" --namespace k8s.io container ls 2>&1 | |
| if ($LASTEXITCODE -eq 0) { | |
| Log-Diag "Result: OK (ctr container ls succeeded)" "Green" | |
| } else { | |
| Log-Diag "Result: NOT PASSED (ctr container ls failed)" "Red" | |
| } | |
| $ctrOut | Out-File "$TempDir\diag_ctr_containers.txt" -Encoding utf8 | |
| & $ctrPath --address "\\.\pipe\containerd-containerd" --namespace k8s.io image ls 2>&1 | Out-File "$TempDir\diag_ctr_images.txt" -Encoding utf8 | |
| } else { | |
| Log-Diag "Result: SKIPPED (ctr.exe not found)" "DarkGray" | |
| } | |
| # Test D: Local kubelet health via kubectl | |
| Log-Diag "`n--- Testing Local Kubelet (kubectl) ---" | |
| $Env:KUBECONFIG = "C:\var\lib\rancher\rke2\agent\kubelet.kubeconfig" | |
| $kubectlPath = "C:\var\lib\rancher\rke2\bin\kubectl.exe" | |
| if (Test-Path $kubectlPath) { | |
| $kbOut = & $kubectlPath version 2>&1 | |
| if ($LASTEXITCODE -eq 0) { | |
| Log-Diag "Result: OK (kubectl connected successfully)" "Green" | |
| } else { | |
| Log-Diag "Result: NOT PASSED (kubectl failed to connect)" "Red" | |
| } | |
| # Create directory for kubernetes objects | |
| $kubeDir = Join-Path $TempDir "kubectl" | |
| New-Item -ItemType Directory -Path $kubeDir -Force | Out-Null | |
| Log-Diag " -> Gathering kubectl cluster state..." | |
| $kbOut | Out-File "$kubeDir\version.txt" -Encoding utf8 | |
| & $kubectlPath get nodes -o wide 2>&1 | Out-File "$kubeDir\nodes.txt" -Encoding utf8 | |
| & $kubectlPath describe nodes 2>&1 | Out-File "$kubeDir\nodes_describe.txt" -Encoding utf8 | |
| & $kubectlPath get pods -A -o wide 2>&1 | Out-File "$kubeDir\pods.txt" -Encoding utf8 | |
| & $kubectlPath describe pods -A 2>&1 | Out-File "$kubeDir\pods_describe.txt" -Encoding utf8 | |
| & $kubectlPath get svc -A -o wide 2>&1 | Out-File "$kubeDir\services.txt" -Encoding utf8 | |
| } else { | |
| Log-Diag "Result: SKIPPED (kubectl.exe not found)" "DarkGray" | |
| } | |
| # Test E: WMI Process Arguments | |
| Log-Diag "`n--- Extracting Process Arguments (WMI) ---" | |
| $processes = Get-WmiObject Win32_Process | Where-Object {$_.Name -match 'containerd.exe|rke2.exe|kubelet.exe|kube-proxy.exe'} | Select-Object Name, CommandLine | |
| if ($processes) { | |
| Log-Diag "Result: OK (Saved to diag_process_args.txt)" "Green" | |
| $processes | Format-List | Out-File "$TempDir\diag_process_args.txt" -Encoding utf8 | |
| } else { | |
| Log-Diag "Result: WARNING (No RKE2/containerd processes found running)" "Red" | |
| } | |
| # Test F: Security and EDR Checks | |
| Log-Diag "`n--- Checking EDR / Filter Drivers ---" | |
| $edrServices = Get-Service | Where-Object {$_.DisplayName -match "Defender|Symantec|McAfee|CrowdStrike|Sentinel|Carbon|Trend|FireEye"} | |
| if ($edrServices) { | |
| Log-Diag "Result: WARNING (Found potential EDR/AV services. Saved to diag_edr_services.txt)" "Yellow" | |
| $edrServices | Format-Table -AutoSize | Out-File "$TempDir\diag_edr_services.txt" -Encoding utf8 | |
| } else { | |
| Log-Diag "Result: OK (No recognized EDR services matched)" "Green" | |
| } | |
| & fltmc.exe 2>&1 | Out-File "$TempDir\diag_filter_drivers.txt" -Encoding utf8 | |
| # --------------------------------------------------------- | |
| # 4. Gather OS, Network, and System Information | |
| # --------------------------------------------------------- | |
| Log-Diag "`n[4/5] Gathering OS, Network, and System Information..." "Yellow" | |
| $SysDir = Join-Path $TempDir "system" | |
| $NetDir = Join-Path $TempDir "network" | |
| New-Item -ItemType Directory -Path $SysDir -Force | Out-Null | |
| New-Item -ItemType Directory -Path $NetDir -Force | Out-Null | |
| Log-Diag " -> Collecting System Info..." | |
| & systeminfo 2>&1 | Out-File "$SysDir\systeminfo.txt" -Encoding utf8 | |
| Get-Process 2>&1 | Out-File "$SysDir\processes.txt" -Encoding utf8 | |
| Get-Service 2>&1 | Out-File "$SysDir\services.txt" -Encoding utf8 | |
| Get-Volume 2>&1 | Out-File "$SysDir\volumes.txt" -Encoding utf8 | |
| Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* -ErrorAction SilentlyContinue | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Out-File "$SysDir\installed_apps_32.txt" -Encoding utf8 | |
| Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* -ErrorAction SilentlyContinue | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Out-File "$SysDir\installed_apps_64.txt" -Encoding utf8 | |
| Log-Diag " -> Collecting Network Info..." | |
| & ipconfig /all 2>&1 | Out-File "$NetDir\ipconfig.txt" -Encoding utf8 | |
| Get-NetAdapter 2>&1 | Out-File "$NetDir\netadapters.txt" -Encoding utf8 | |
| Get-NetRoute 2>&1 | Out-File "$NetDir\routes.txt" -Encoding utf8 | |
| & netstat -ano 2>&1 | Out-File "$NetDir\netstat.txt" -Encoding utf8 | |
| & netsh winhttp show proxy 2>&1 | Out-File "$NetDir\proxy_winhttp.txt" -Encoding utf8 | |
| Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -ErrorAction SilentlyContinue | Select-Object ProxyServer, ProxyEnable | Out-File "$NetDir\proxy_ie.txt" -Encoding utf8 | |
| Log-Diag " -> Collecting HNS (Host Networking Service) Info..." | |
| if (Get-Command Get-HnsNetwork -ErrorAction SilentlyContinue) { | |
| Get-HnsNetwork 2>&1 | Out-File "$NetDir\hns_networks.txt" -Encoding utf8 | |
| Get-HnsEndpoint 2>&1 | Out-File "$NetDir\hns_endpoints.txt" -Encoding utf8 | |
| } | |
| if (Get-Command hnsdiag -ErrorAction SilentlyContinue) { | |
| & hnsdiag list all 2>&1 | Out-File "$NetDir\hnsdiag.txt" -Encoding utf8 | |
| } | |
| Log-Diag " -> Collecting Firewall Info..." | |
| Get-NetFirewallProfile 2>&1 | Out-File "$NetDir\firewall_profiles.txt" -Encoding utf8 | |
| Get-NetFirewallRule | Where-Object Enabled -eq $true | Select-Object DisplayName, Profile, Direction, Action 2>&1 | Out-File "$NetDir\firewall_rules_enabled.txt" -Encoding utf8 | |
| # --------------------------------------------------------- | |
| # 5. Finalize and Archive | |
| # --------------------------------------------------------- | |
| Log-Diag "`n[5/5] Compressing artifacts..." "Yellow" | |
| Compress-Archive -Path "$TempDir\*" -DestinationPath $ZipPath -Force | |
| Remove-Item -Path $TempDir -Recurse -Force | |
| Write-Host "`n========================================================" -ForegroundColor Cyan | |
| Write-Host "Collection Complete!" -ForegroundColor Green | |
| Write-Host "Please provide the following file to SUSE Rancher Support:" -ForegroundColor White | |
| Write-Host "-> $ZipPath" -ForegroundColor Cyan | |
| Write-Host "========================================================`n" -ForegroundColor Cyan |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment