Skip to content

Instantly share code, notes, and snippets.

@ManuelSimon
Last active May 12, 2026 08:18
Show Gist options
  • Select an option

  • Save ManuelSimon/a5fff61743c2b8469e01d2ec281a88ae to your computer and use it in GitHub Desktop.

Select an option

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.
<#
.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