Architecture decision records with sanitized content (proprietary references removed). - ADR-007: Three-Tier Shell Safety Classification - ADR-008: MCP Protocol Integration (HTTP transport) - ADR-009: Bundled kubectl Binary rationale Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
7.6 KiB
ADR-009: Bundle kubectl Binary for Cross-Platform Consistency
Date: 2026-06-02
Status: Accepted
Deciders: Shaun Arman, RJ Cooper
Context: Hackathon v1.0.0 — Shell Execution System
Context
TFTSR DevOps Investigation v1.0.0 introduced execute_shell_command tool for AI agents, with kubectl as a primary use case (diagnosing Kubernetes pod failures, checking deployments, viewing logs). kubectl is a critical tool for IT troubleshooting but has several challenges:
Problems with system kubectl:
- Version skew: User's kubectl may be v1.25 while cluster is v1.30 (API changes)
- Not installed: Many Windows/macOS users don't have kubectl
- PATH issues: kubectl in non-standard location (WSL, Homebrew, Chocolatey)
- Permission issues: System kubectl may require admin rights on Windows
- Configuration drift:
~/.kube/configmay be misconfigured or missing
Requirements:
- AI agents need reliable kubectl execution across all platforms
- Users should not need to install kubectl separately
- kubectl version should be consistent (no version skew errors)
- Work with multiple kubeconfig files (dev, staging, prod clusters)
Alternatives Considered:
-
Use system kubectl (require manual install)
- ✅ No binary bundling needed
- ❌ Poor UX — user must install kubectl separately
- ❌ Version skew issues
- ❌ PATH configuration required
- ❌ Windows complexity (WSL vs native)
-
Download kubectl at runtime (first use)
- ✅ No bloat in installer
- ✅ Always latest version
- ❌ Requires internet on first run
- ❌ Download failure = broken feature
- ❌ Security risk (MITM, checksum verification)
-
Bundle kubectl as resource file
- ✅ Works offline
- ✅ Consistent version
- ✅ No user setup required
- ❌ Increases installer size (~50MB per platform)
- ❌ Need to update kubectl periodically
-
Kubernetes client library (k8s-openapi crate)
- ✅ No binary needed
- ✅ Native Rust implementation
- ❌ Complex API (YAML → Rust types)
- ❌ Doesn't support
kubectl apply -fdirectly - ❌ No support for kubectl plugins
- ❌ AI agents know kubectl CLI, not k8s-openapi API
Decision
Bundle kubectl v1.30.0 binary for all platforms (Linux amd64/arm64, macOS arm64/Intel, Windows amd64) as a Tauri resource.
Implementation
Build-time binary download: scripts/download-kubectl.sh
#!/bin/bash
VERSION="1.30.0"
OS=$1 # linux, darwin, windows
ARCH=$2 # amd64, arm64
curl -LO "https://dl.k8s.io/release/v${VERSION}/bin/${OS}/${ARCH}/kubectl"
chmod +x kubectl
mv kubectl "binaries/kubectl-${OS}-${ARCH}"
CI/CD Integration: .github/workflows/release.yml
- name: Download kubectl binaries
run: |
./scripts/download-kubectl.sh linux amd64
./scripts/download-kubectl.sh linux arm64
./scripts/download-kubectl.sh darwin arm64
./scripts/download-kubectl.sh darwin amd64
./scripts/download-kubectl.sh windows amd64
Tauri Resource Bundling: src-tauri/tauri.conf.json
{
"tauri": {
"bundle": {
"resources": [
"binaries/kubectl-*"
]
}
}
}
Runtime Binary Extraction: src-tauri/src/shell/kubectl.rs
pub fn get_kubectl_path() -> Result<PathBuf, String> {
let resource_dir = tauri::api::path::resource_dir(...)
.ok_or("Failed to get resource directory")?;
#[cfg(target_os = "linux")]
let binary_name = if cfg!(target_arch = "aarch64") {
"kubectl-linux-arm64"
} else {
"kubectl-linux-amd64"
};
#[cfg(target_os = "macos")]
let binary_name = if cfg!(target_arch = "aarch64") {
"kubectl-darwin-arm64"
} else {
"kubectl-darwin-amd64"
};
#[cfg(target_os = "windows")]
let binary_name = "kubectl-windows-amd64.exe";
let kubectl_path = resource_dir.join(binary_name);
// Ensure executable permissions on Unix
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let metadata = std::fs::metadata(&kubectl_path)
.map_err(|e| format!("kubectl binary not found: {e}"))?;
let mut perms = metadata.permissions();
perms.set_mode(0o755);
std::fs::set_permissions(&kubectl_path, perms)?;
}
Ok(kubectl_path)
}
Execution with Custom Kubeconfig: src-tauri/src/shell/executor.rs
pub async fn execute_kubectl(command: &str, kubeconfig_id: Option<String>) -> Result<Output> {
let kubectl_path = kubectl::get_kubectl_path()?;
let mut cmd = Command::new(kubectl_path);
// Inject kubeconfig if provided
if let Some(id) = kubeconfig_id {
let kubeconfig = kubeconfig::get_and_decrypt(id)?;
let temp_path = write_temp_kubeconfig(kubeconfig)?;
cmd.env("KUBECONFIG", temp_path);
}
cmd.args(command.split_whitespace());
cmd.output().await
}
Version Selection Rationale
kubectl v1.30.0 (released April 2024):
- Compatibility: Supports Kubernetes v1.29, v1.30, v1.31 (n±1 version skew)
- Stability: 1.30 is a stable release (not beta)
- Feature coverage: Includes all common troubleshooting commands
- Size: ~50MB per platform (acceptable for installer)
Consequences
Positive
- Zero-configuration: kubectl works immediately after install
- Consistent behavior: Same kubectl version on all platforms
- Offline capable: No internet required for kubectl execution
- Kubeconfig flexibility: Users can upload multiple kubeconfig files
- Security: Binary checksum verified during CI build
- Reliability: No version skew errors with Kubernetes 1.29-1.31 clusters
Negative
- Installer size: Increases by ~50MB per platform (150MB total for all platforms)
- Update lag: kubectl version frozen until release
- Disk usage: Each install includes kubectl binary (no sharing across users)
- Maintenance: Need to periodically update kubectl version
Trade-offs
We chose reliability and UX over installer size. The 50MB increase is acceptable for a desktop application targeting IT engineers who likely have kubectl needs.
Mitigation Strategies
Installer size:
- Compress binaries in bundle (reduces to ~15MB per platform)
- Document minimum disk space requirement in README
kubectl version updates:
- Add
scripts/update-kubectl.shto automate version bumps - Schedule quarterly kubectl version reviews
- Document current version in CLAUDE.md and wiki
Platform-specific issues:
- Windows: Sign kubectl binary to avoid SmartScreen warnings
- macOS: Sign and notarize to pass Gatekeeper
- Linux: Verify
chmod +xworks across all distros
Future Enhancements
- Optional system kubectl: Add "Use system kubectl" toggle in Settings (falls back to bundled if not found)
- Version display: Show kubectl version in Settings UI
- Auto-update: Download newer kubectl if available (requires secure checksum verification)
- Plugin support: Bundle common kubectl plugins (kubectx, kubens, stern)
Related Decisions
- ADR-007: Three-Tier Shell Safety (kubectl commands classified as Tier 1/Tier 2)
- ADR-008: MCP Protocol Integration (alternative to bundling binaries — use MCP kubectl server)
References
- kubectl Releases: https://kubernetes.io/releases/
- Download Script:
scripts/download-kubectl.sh - Binary Management:
src-tauri/src/shell/kubectl.rs - Implementation PR: #30 (Hackathon v1.0.0)
- CI/CD:
.github/workflows/release.yml(kubectl download step) - Wiki:
docs/wiki/Shell-Execution.md(kubectl section)