tftsr-devops_investigation/docs/architecture/adrs/ADR-009-bundled-kubectl-binary.md
Shaun Arman e5593cbfe2 docs: add ADRs for shell safety, MCP transport, kubectl bundling
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>
2026-06-05 08:12:19 -05:00

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/config may 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:

  1. 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)
  2. 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)
  3. Bundle kubectl as resource file

    • Works offline
    • Consistent version
    • No user setup required
    • Increases installer size (~50MB per platform)
    • Need to update kubectl periodically
  4. Kubernetes client library (k8s-openapi crate)

    • No binary needed
    • Native Rust implementation
    • Complex API (YAML → Rust types)
    • Doesn't support kubectl apply -f directly
    • 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.sh to 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 +x works across all distros

Future Enhancements

  1. Optional system kubectl: Add "Use system kubectl" toggle in Settings (falls back to bundled if not found)
  2. Version display: Show kubectl version in Settings UI
  3. Auto-update: Download newer kubectl if available (requires secure checksum verification)
  4. Plugin support: Bundle common kubectl plugins (kubectx, kubens, stern)

  • 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)