Kubernetes (kubectl + kubeconfig)
Paste a view-only ServiceAccount kubeconfig and the agent runs kubectl reads against the cluster; which verbs and flags pass, what Connect and verify runs, and the save-time checks.
How-to · Updated 2026-10-27 · Describes release 0.1.164
Overview
A kubectl connection gives the agents direct, read-only cluster access from a pasted kubeconfig, with no MCP server in between. The Incident agent reads pods, events, rollouts and logs through it (Kubernetes is one of the five categories that agent needs), the Compliance agent reads cluster state for its controls, and the estate x-ray harvests the inventory from it. A second, write-role kubectl connection is how an approved deployment restart runs.
The binary runs on the platform host, or inside a private-network agent for a cluster whose API is private; in that case the agent's image must include kubectl.
Setup
Before you start
- The
datasources.managepermission; the built-in owner and operator roles carry it. - A kubeconfig for a view-only ServiceAccount that may also
getandlistnodes(Installation). - The API server reachable from the platform, or a private-network agent in the cluster's network.
Installation
Create a dedicated ServiceAccount bound to the built-in view role in the namespaces the agent may read, plus get and list on nodes, which the connection check needs; the default view role alone does not allow the node probe. Export a kubeconfig whose current context names that account, the cluster's CA embedded as certificate-authority-data and, when the account is namespace-bound, the namespace. Connect Kubernetes has a copy-and-run command that does exactly this for one namespace and prints aiops-readonly.kubeconfig. Exclude Secrets, pods/exec and every write from the role; the platform refuses writes anyway, but RBAC is the real boundary. A token from kubectl create token expires; decide how it is renewed.
Configuration
- Open Settings · Data in → Data sources and select Connect datasource.
- Under Type, choose Kubernetes (kubectl + kubeconfig). Enter a Connection name; the connected list shows it, and per-connection agent tools are named after it.
- Fill the fields:
| Field (portal label) | API key | Value |
|---|---|---|
| kubeconfig YAML | kubeconfig |
The complete file, line breaks preserved; a secret, parsed as YAML on save |
| Namespaces the service account may read, when it is not allowed to list them cluster-wide; comma-separated (optional) | namespaces |
payments, checkout when the account is bound with RoleBindings only |
- Optionally, open Optional · describe this environment and fill What should AIOps know about it? with the cluster, the namespaces and the critical services.
- Under Use this connection for, choose Investigate only and select Connect and verify.
The same connection through the API (POST /api/aiops/{tenant_id}/datasources, requires datasources.manage; the kubeconfig goes in secret_values, and one posted in config is moved there):
{
"type_key": "kubectl",
"name": "prod-eks",
"description": "Production cluster; checkout and payments run in the payments namespace.",
"config": {
"namespaces": "payments, checkout"
},
"secret_values": {
"kubeconfig": "apiVersion: v1\nkind: Config\nclusters:\n- name: estate\n cluster:\n server: https://<api-server>\n certificate-authority-data: <base64>\ncontexts:\n- name: estate\n context:\n cluster: estate\n user: aiops-reader\n namespace: payments\ncurrent-context: estate\nusers:\n- name: aiops-reader\n user:\n token: <service-account token>\n"
},
"role": "read",
"enabled": true
}
The save validates the paste: 'kubeconfig' is not valid YAML (…) — paste the full file preserving line breaks or 'kubeconfig' does not parse as a YAML mapping — line breaks were probably lost in the paste is a 400 at save time, not a failure mid-investigation. The accepted kubeconfig forms are a user with a static token (a ServiceAccount token) or with client-certificate-data and client-key-data, and a cluster with certificate-authority-data; everything the file needs is inside it. A kubeconfig whose user runs a credential plugin (exec, such as aws eks get-token or kubelogin, or the older auth-provider), or that names a file on the platform host (tokenFile, client-certificate, client-key, certificate-authority as a path), is refused the same way with This kubeconfig runs a credential plugin (users[].user.exec or auth-provider) or names a file on the platform host (tokenFile, client-certificate, client-key, certificate-authority); the platform does neither. Use a kubeconfig with a static token or a service-account token and embedded certificate data (certificate-authority-data, client-*-data). The platform image ships no such plugin, kubectl would otherwise read the named file from the platform host (a tokenFile is sent to the kubeconfig's server as the bearer token), and a connection saved before this check gets the same message from every tool call and Test instead of running kubectl. The pasted kubeconfig is also the only identity kubectl can use: the platform strips the pod's in-cluster API discovery from every connector process, so a kubeconfig that resolves to no server ({}, a file without current-context) fails against localhost:8080 instead of answering with the platform's own service account, and a connection saved with a blank kubeconfig answers the connection's 'kubeconfig' is blank — paste it and save the connection before use instead of running kubectl.
Validation
Connect and verify, and Test on the row later, looks for kubectl on the host's PATH, tries kubectl --version, then runs kubectl get nodes --request-timeout=5s -o name with the kubeconfig written to a private file and passed through KUBECONFIG. You should see a dialog titled <connection name> is connected with Connected — verified from the control plane, and later in the row's Last test ok · binary found: /usr/local/bin/kubectl — … — 'kubectl get nodes --request-timeout=5s -o name' ok (node/<name>), the last line of the real output. A kubeconfig that does not parse, an API server that does not answer and a ServiceAccount without node read all fail here. When a private-network agent serves the workspace, the platform does not run the command itself: the row shows the check as queued, the agent runs it, and the result reads Connected — verified by your private-network agent.
If something fails
The dialog shows Needs a fix, what to fix and the check's own detail; the row is saved either way. Select Edit, correct the field the detail names and save again, or select Retry once a cause outside the form (network, vendor-side permission) is fixed. Every verdict this connector produces, and what to do about it, is in Troubleshooting below.
Data collected
Tools the agent gets
<name>_exec— runskubectlwith the argument vector the agent passes; a leadingkubectlin the vector is dropped. The kubeconfig's current context is preconfigured, and the tool description tells the agent not to pass--contextor--kubeconfigunless the connection notes name a context. Output is the merged stdout and stderr,exit code <n>first on a failure, capped at 20,000 characters; a command is killed after 60 seconds (timed out after 60s), and a missing binary at run time readscannot run 'kubectl': ….
A kubectl connection registers no HTTP tool. The estate x-ray uses the same tool under its own, stricter read set, which does not include logs or events.
Read surface
An investigation runs a kubectl call only when the platform's own kubectl adapter verifies it as a read, independently of the connection's verb list. What passes: the verbs get, describe, top, explain, api-resources, api-versions, cluster-info (not cluster-info dump), version, logs, events, help and auth can-i, optionally preceded by the global flags --context, --namespace or -n, --request-timeout and --v with their values. What is refused, never offered for approval: every other verb (apply, delete, scale, rollout restart, exec, cp, patch, edit), diff although the catalog lists it among the read verbs, any other leading flag, and anywhere in the vector --raw, --subresource, --server or -s, --kubeconfig, --token, --as, --client-*, --certificate-*, --insecure-*, --username and --password, so only the saved credential and the saved cluster are ever used. The refusal reads Investigation connections are read-only. This operation was not executed; prepare an incident change using a write connection and obtain approval.
The catalog's own list — get, describe, top, explain, api-resources, api-versions, cluster-info, version, logs, events, diff — is the approval gate's read set; the verified adapter above is the floor underneath it. The full rule table is under The read/write gate in detail in Connections and remediation access.
Inventory and namespaces
The estate inventory first lists each kind cluster-wide. When that is Forbidden, it reads kubectl get <kind> -n <namespace> for every namespace in Namespaces, else the current context's namespace, and its notes say namespace-scoped read: N namespace(s) from …. Nodes or namespaces that stay unreadable leave the pods without a host and the namespace-selector NetworkPolicies flagged, and a blast radius touching them is reported as estimated with that coverage gap.
Approved fixes
A deployment restart runs through a second kubectl connection saved as Approved changes only (separate credential) with Allow use for approved plans ticked, on a ServiceAccount scoped to the namespace and the verbs the fix needs. The namespace in that kubeconfig's context is the scope a restart may target; a context without one confirms none. How approvals and tiers apply is in Set up write connections.
Troubleshooting
| What you see | Cause | What to do |
|---|---|---|
400 'kubeconfig' is not valid YAML … or … does not parse as a YAML mapping … on save |
The paste lost its line breaks. | Paste the complete file into the multi-line field. |
This kubeconfig runs a credential plugin … or names a file on the platform host … on save, Test or a tool call |
The kubeconfig's user authenticates through exec or auth-provider (an EKS, GKE or AKS default kubeconfig), or a user or cluster points at a file path (tokenFile, client-certificate, client-key, certificate-authority) instead of embedding the data. |
Export a kubeconfig with a ServiceAccount token and certificate-authority-data (Installation); kubectl config set-cluster … --embed-certs=true embeds a CA. |
the connection's 'kubeconfig' is blank … on Test or a tool call |
The connection was saved without its kubeconfig. | Paste the file and save the connection. |
… dial tcp [::1]:8080: connect: connection refused |
The kubeconfig resolves to no server: no current-context, or a context whose cluster has no server. |
Paste the complete file (kubectl config view --minify --flatten). |
failed · binary 'kubectl' not found on PATH |
The host that runs the check has no kubectl. | Ask your platform operator; a private-network agent needs it in its image. |
failed · 'kubectl get nodes --request-timeout=5s -o name' failed (exit 1): … |
The tail of the output names it: a connection refused or timeout (API server unreachable), Unauthorized (expired or wrong token), Forbidden (no node read). |
Fix the kubeconfig or the RBAC at the source and Test again. |
failed · 'kubectl get nodes --request-timeout=5s -o name' timed out after 5s |
The API server does not answer the platform. | For a private API, install a private-network agent inside that network. |
| The row shows the check queued for the private agent and never returns | No live agent, or the agent's image lacks kubectl. | Check the agent's heartbeat under Connect, and its image. |
A kubectl delete, apply, exec or rollout restart answers Investigation connections are read-only. |
The verified read adapter. | Expected; a restart runs through the write connection after approval. |
kubectl diff or kubectl get --raw /… is refused although diff is a read verb |
The adapter verifies a fixed verb set and refuses --raw. |
Use get with -o yaml instead. |
| The agent sees one namespace only | The ServiceAccount is bound with RoleBindings and Namespaces is empty, so the inventory fell back to the context's namespace. | List the readable namespaces in Namespaces. |
An x-ray denies kubectl logs |
The x-ray read set excludes logs and events on purpose. |
Expected; investigations may read logs. |
The generic verdict strings are explained in Test a connection and read the failure. Every connection status word is in the status and error reference.
Next steps
- Select Discover this connection in the success dialog to find the services and dependencies behind it: Launch a scan.
- See what the inventory reads per namespace: Inventory and namespaces.
- Run approved fixes through a separate write connection: Approved fixes.
- See what else each agent needs in Choose your connection.