dsh-kubernetes
dsh-kubernetesgives DeepSeek Harness a safe Kubernetes capability: inspect workloads, retrieve bounded logs and events, diagnose common failures, and perform approval-gated changes.
A community plugin for DeepSeek Harness (DSH). It is not a kubectl wrapper — it turns Kubernetes into a structured, Agent-friendly runtime capability with a read-first security model.
DSH Agent
↓
Generic Kubernetes Tools (10)
↓
ctx.kubernetes capability service
↓
KubernetesService (policy · diagnosis · bounding)
↓
KubernetesClientProvider (@kubernetes/client-node)
↓
Kubernetes API
Highlights
- Read-first by default —
readOnly: trueout of the box. Real writes require explicit opt-in and survive the DSH approval gate. - 10 structured tools — every tool returns JSON with a schema plus a compact text rendering; no fragile CLI output parsing.
k8s_diagnoseevidence engine — walks Deployment/StatefulSet → Pods → containers → events → bounded logs and classifies likely failure categories (CrashLoopBackOff, ImagePullBackOff, OOMKilled, probe failures, …). No inner LLM: the plugin collects evidence, the DSH Agent reasons.- Bounded, sanitized logs —
tailLines/sinceSeconds/container/previous/maxCharswith hard caps. Logs are UNTRUSTED DATA: secret-shaped values are redacted, ANSI/control characters stripped. - Secrets never leak —
k8s_describe secretreturns metadata, type and data keys only. Credential-shaped fields (token,password,client-key-data, service-account tokens, containerenvsecrets, …) are redacted everywhere. - Controlled
k8s_apply— server-side dry-run by default; real applies are denied under read-only policy, or escalated to approval (ask) when writes are enabled, with cluster/namespace context and production-risk warnings in the reason.
Installation
dsh plugin add dsh-kubernetes # from npm (once published)
# or from a packed tarball:
npm pack
dsh plugin add ./dsh-kubernetes-0.1.0.tgz
Library use outside DSH also works — the package exports a host-agnostic API:
import { KubernetesClientProvider, DiagnosisEngine, KubernetesService } from 'dsh-kubernetes';
Configuration
The plugin resolves kubeconfig with standard priority: explicit kubeconfigPath → KUBECONFIG env → ~/.kube/config → in-cluster service account. Context is never switched silently.
| Option | Default | Description |
|---|---|---|
readOnly |
true |
Read-only mode. Disables real writes even if allowWrite is true. |
allowWrite |
false |
Master switch for write operations. Real applies additionally require approval. |
context |
– | Explicit kubeconfig context override. |
namespace |
context namespace / default |
Default namespace override. |
kubeconfigPath |
– | Explicit kubeconfig file path. |
maxLogChars |
8000 |
Hard cap of characters per log excerpt (500–20000). |
maxLogTailLines |
200 |
Hard cap of tail lines per log request (1–500). |
maxLogSinceSeconds |
3600 |
Hard cap of the log time window in seconds (10–21600). |
Profile example — the plugin's bundled cordis.patch.yml inserts itself with safe defaults automatically; override by id in your own profile layer if needed:
- id: dsh-kubernetes
config:
readOnly: true
allowWrite: false
Tools
| Tool | Access | What it does |
|---|---|---|
k8s_context |
read | Active context, cluster server, effective namespace, capabilities, all contexts (no credentials). |
k8s_namespaces |
read | Namespaces with phase. |
k8s_workloads |
read | Deployments/StatefulSets/DaemonSets with replicas + health, unhealthy-first. |
k8s_pods |
read | Pods with phase, health, restarts, container waiting reasons (cap 200). |
k8s_describe |
read | Sanitized resource describe. Secrets: metadata/type/data keys only. |
k8s_logs |
read | Bounded, sanitized, de-duplicated pod logs. |
k8s_events |
read | Events (optionally scoped to a resource), sanitized + bounded. |
k8s_diagnose |
read | Structured DiagnosisEvidence with likely failure categories. |
k8s_rollout |
read | Rollout status for a workload. |
k8s_apply |
gated | Server-side dry-run apply by default; real apply needs allowWrite and approval. |
Security model
readOnly=true (default) readOnly=false + allowWrite=true
──────────────────────── ─────────────────────────────────
get/list/describe ✓ get/list/describe ✓
logs/events ✓ logs/events ✓
apply dryRun=true ✓ apply dryRun=true ✓
apply dryRun=false ✗ deny apply dryRun=false → approval (ask)
- Write operations bind explicitly to context / cluster / namespace / resource and show them before approval.
- Contexts named like
prod/production/prdraise the risk level in the approval reason (string match is a hint, never proof of safety). - No
delete,exec,port-forward,scale,restartorrollbacktools in v1 — by design. - kubeconfig contents, tokens, client keys and certificates never enter tool results or the session.
Diagnosis demo
User: Why does production/order-service keep restarting?
Agent → k8s_diagnose(Deployment/order-service)
Evidence:
- deployment: 3 desired / 1 ready — progressing
- pods: 3 total; 2× CrashLoopBackOff (unhealthy)
- containers: last termination OOMKilled (exit 137), restarts 14
- memory limit: 512Mi on all containers
- relevant events: BackOff ×14 (Warning)
- bounded logs (tail 40, redacted): "OOMkilled while serving traffic"
- likelyCategories: ["crash-loop", "oom-killed"]
The plugin marks categories as likely, never as certain facts — final reasoning stays with the DSH Agent.
Dry-run / approval demo
Agent → k8s_apply(manifest, dryRun=true)
Result: applied (server-side dry-run): ConfigMap/order-service-config (namespace default)
User: looks good, apply it for real
Agent → k8s_apply(manifest, dryRun=false)
Approval request (ask):
k8s_apply with dryRun=false targets context "kind-dsh-e2e" (namespace "default").
Approve to perform the real change.
Under the default read-only policy the same call is denied outright:
{ kind: "deny", reason: "real apply denied: plugin is read-only (readOnly=true, allowWrite=false). Set allowWrite=true and readOnly=false to enable approval-gated writes." }
Compatibility
| Component | Tested with |
|---|---|
| DeepSeek Harness plugin API | @deepseek-ai/dsh-tools 0.1.0-rc.6 |
| Cordis runtime | @deepseek-ai/cordis 4.0.1 |
| Kubernetes client | @kubernetes/client-node 1.4.0 |
| Kubernetes cluster | kind v1.32.2 (E2E), standard API groups core/v1, apps/v1 |
| Node.js | ≥ 18.18 (tested on 22.x) |
Known limitations
- v1 targets standard Kubernetes only (OpenShift / EKS/GKE/AKS-specific auth flows untested; standard kubeconfig works).
k8s_applyperforms server-side apply for create/update; no delete, no exec, no port-forward, no scale/rollback tools.- Rollout status is computed for Deployment/StatefulSet/DaemonSet; other kinds return
unknown. - Log redaction uses pattern heuristics — exhaustive secret detection is not guaranteed.
- CRDs are not listed by
k8s_workloads(core workload kinds only);k8s_describeworks for arbitrary kinds.
Uninstall
dsh plugin remove dsh-kubernetes
All service/tool registrations are attached to the plugin fiber — removal rolls them back completely, with no residual listeners or processes.
Development
npm install
npm run lint # tsc --noEmit
npm test # 105 unit + mock-API + contract + cordis tests
npm run build
# Real-cluster E2E (throwaway cluster only):
kind create cluster --name dsh-e2e
DSH_K8S_E2E=1 npm run test:e2e
No comments yet. Be the first to write one.