Kubernetes#
Register a cluster once and every agent in the project can work against it with kubectl, under its own identity, without a kubeconfig ever reaching the sandbox.
Register a cluster#
curl -fsS -X POST \
-H "Authorization: Bearer $LENS_AGENTS_TOKEN" \
-H "Content-Type: application/json" \
https://agents.example.com/v1/projects/$PROJECT_ID/clusters \
-d '{
"name": "prod-eu",
"displayName": "Production EU",
"relayUrl": "tunnel://"
}'
Register a cluster called prod-eu ("Production EU") in the
production project, using a reverse tunnel, and give me the
tunnel token.
nexusctl cluster create --project production \
--name prod-eu \
--display-name "Production EU" \
--relay-url "tunnel://"
--relay-url decides how the platform reaches the cluster.
| Value | Mode |
|---|---|
tunnel:// |
The cluster opens a reverse tunnel to the platform. No inbound access required. |
| A relay endpoint URL | The platform dials a relay the cluster exposes. |
Pass --ca-certificate with a PEM bundle when the relay presents a self-signed certificate.
Reverse tunnel#
This is the mode to use for anything the platform cannot dial: clusters behind a corporate firewall, in a customer's network, on-prem, or in a different cloud.
The cluster runs a small relay that opens an outbound WebSocket to the platform and holds it open. There are no inbound ports to open, no VPN to run, and no public endpoint on the cluster.
graph LR
subgraph target [Target cluster]
relay[Relay]
api[Kubernetes API]
relay --> api
end
subgraph platform [Lens Agents]
server[Platform server]
end
relay -.->|outbound WebSocket| server
agent[Agent] --> server
Install the relay in the target cluster with the tunnel token the platform issued at registration:
JWKS="https://agents.example.com/v1/projects/<project-id>/.well-known/jwks.json"
helm install lens-agents-relay oci://ghcr.io/lensapp/charts/nexus-kube-relay \
--set config.mode=tunnel \
--set config.tunnelUrl="wss://agents.example.com" \
--set config.tunnelToken="<tunnel-token>" \
--set config.jwksUrl="$JWKS"
The relay verifies the platform's signed requests against the project's JWKS before touching the Kubernetes API, so a stolen tunnel connection is not enough to issue commands.
Rotate the tunnel token#
curl -fsS -X POST -H "Authorization: Bearer $LENS_AGENTS_TOKEN" \
https://agents.example.com/v1/clusters/$CLUSTER_ID/rotate-tunnel-token
Rotate the tunnel token for the prod-eu cluster and show me the
new one.
nexusctl cluster rotate-tunnel-token prod-eu --project production
The new token is printed once and never stored. Record it before it scrolls away, then update the relay's Helm release.
Agent identity, not a shared service account#
An agent does not get a kubeconfig. Requests are proxied through the platform, which signs each one with the project's key, and the relay presents the agent's identity to the Kubernetes API.
Two consequences worth planning around:
- Your Kubernetes RBAC applies. Bind roles to the agent identity and the cluster enforces the same limits it enforces for people. Read-only for an investigation agent is a
ClusterRole, not a promise. - Kubernetes audit logs name the agent. Cluster-side and platform-side audit agree on who did what.
Rotate the project keypair when needed:
curl -fsS -X POST -H "Authorization: Bearer $LENS_AGENTS_TOKEN" \
https://agents.example.com/v1/projects/$PROJECT_ID/rotate-keys
What agents can do#
The shell sandbox has kubectl preinstalled and pointed at registered clusters:
curl -fsS -X POST \
-H "Authorization: Bearer $LENS_AGENTS_TOKEN" \
-H "Content-Type: application/json" \
https://agents.example.com/v1/shell/exec \
-d '{"projectId": "'"$PROJECT_ID"'",
"command": "kubectl get pods -n payments"}'
Check the payments namespace on the prod-eu cluster. Any pods
crash-looping? Pull the logs for anything that is.
nexusctl shell exec -p production -- kubectl get pods -n payments
nexusctl shell exec -p production -- kubectl logs deploy/api --tail=100
The platform also proxies the Kubernetes API directly, which is what non-kubectl tooling uses:
GET|POST|PUT|PATCH|DELETE /v1/clusters/{clusterId}/proxy/{path}
Read, write, and delete are all reachable through it — which is exactly why the cluster-side RBAC binding matters more than the platform-side one.
Routing connectors through a cluster#
A service that only exists inside the target cluster can be reached the same way. Register it as a connector with --cluster prod-eu and its traffic rides the same tunnel instead of going direct.
Audit#
Every proxied call is recorded with the actor, the cluster, the verb, the resource path, the result, and the duration. Denied calls are recorded too. See Audit trail.
Related#
- AWS — EKS discovery and account access
- MCP connectors — services reachable through the tunnel
- Policies — granting cluster access to a set of agents
- Identity — why the agent has its own identity