~/docs

Kubernetes

Record kubectl exec into pods on any Kubernetes cluster, including EKS, GKE and AKS.

↗ .mdmcp

On Kubernetes, shellz runs inside your pods' containers. Every kubectl exec into a container with shellz is recorded, and each pod shows up as a member of a fleet, named after the pod with its namespace and node.

This works on any cluster, managed or not, because nothing is installed on the nodes.

Before you start

  1. Create a fleet with the platform Kubernetes and copy its token.
  2. Add shellz to your image.

1. Store the token as a Secret

kubectl create secret generic shellz-fleet --from-literal=token=szf_<fleet token>

Create it in each namespace where the workload runs, or sync it from your secret manager (External Secrets, Sealed Secrets and so on) as usual.

2. Mount it into the container

deployment.yaml
spec:
  template:
    spec:
      terminationGracePeriodSeconds: 30
      containers:
        - name: app
          image: ghcr.io/acme/app:1.4
          command: ["/usr/local/bin/shellz", "run", "--"]
          args: ["/app/server", "--port", "8080"]
          env:
            - name: SHELLZ_POD_NAME
              valueFrom: { fieldRef: { fieldPath: metadata.name } }
            - name: SHELLZ_POD_NAMESPACE
              valueFrom: { fieldRef: { fieldPath: metadata.namespace } }
            - name: SHELLZ_NODE_NAME
              valueFrom: { fieldRef: { fieldPath: spec.nodeName } }
          volumeMounts:
            - name: shellz-fleet
              mountPath: /run/secrets/shellz-fleet-token
              subPath: token
              readOnly: true
      volumes:
        - name: shellz-fleet
          secret:
            secretName: shellz-fleet
            defaultMode: 0444
  • The token is mounted as a file, not passed as SHELLZ_FLEET_TOKEN, because environment variables are visible to every kubectl exec.
  • The downward-API variables name the member after its pod, namespace and node. Without them, shellz falls back to the pod's hostname and service-account namespace.
  • terminationGracePeriodSeconds: 30 (the Kubernetes default) leaves time for shellz to finish uploading recordings, which takes up to 20 seconds, before the kill.
  • If your image's ENTRYPOINT is already shellz, drop command and args.

Optionally, set SHELLZ_IMAGE to the image reference so it's shown in the dashboard.

3. Roll out and test

kubectl rollout status deploy/app
kubectl exec -it deploy/app -- bash

The fleet page lists each pod as a member, and the session appears in the dashboard within a second or two.

Probes

Exec liveness and readiness probes run without a terminal, so shellz never blocks them, even if recording is unavailable. A recording problem can't fail your probes or restart your pods.

Identical probe runs are grouped: the first run is recorded in full, later runs with the same output and exit status are counted on one row (×count) instead of being recorded again. A probe whose output changes is recorded each time. See Commands without a terminal.

Sidecars, init containers and multi-container pods

shellz records execs into the container it runs in. In a pod with several containers, add shellz to each container you want recorded. Init containers and sidecars that nobody execs into don't need it.

Ephemeral debug containers

kubectl debug adds a new ephemeral container from a separate image, which doesn't contain shellz, so it isn't recorded. If people use kubectl debug in production, restrict it with RBAC (the pods/ephemeralcontainers subresource) or an admission policy.

Removing shellz

Remove the shellz entrypoint from the deployment (or roll back to an image without it), then revoke or delete the fleet on its page.