Bastion: a jump host inside the Kubernetes cluster
The browser has no machine of yours to open a tunnel from, so the Bastion takes the terminal into the Kubernetes cluster, as a jump host: a temporary, unprivileged pod in the namespace you pick, from which you run ssh, curl, nc and the like against VMs, databases and services the cluster can reach.
What it does
- Creates a temporary pod in the chosen namespace and opens a terminal in it, in the bottom panel.
- The image is docker.io/nicolaka/netshoot:v0.16@sha256:b09d9b21381f47a79b3cbcb30da25266dc17186ea00ae65e99fdc51396f48e70 (pinned by digest).
- Tools in the image: ssh, scp, sftp, curl, dig, nslookup, host, nc, socat, telnet, nmap (-sT), iperf3, openssl, ip, ss, jq, git and vim.
- Optional: an SSH private key, sent once to the pod and written in memory to ~/.ssh/id_kubepier. It is never stored by Kubepier or logged, and it dies with the pod.
- There is no tunnel to your machine on the web: that is the desktop Secure tunnel.
How the bastion pod is created
- PodSecurity "restricted" profile: user 1000 (non-root), no privilege escalation, no capabilities, seccomp RuntimeDefault and a read-only root filesystem.
- HOME (16 Mi) and /tmp (64 Mi) are memory-backed.
- No ServiceAccount token and no Service variables: the pod does not talk to the Kubernetes API.
- Requests 50m CPU and 64 Mi memory, limited to 500m and 256 Mi.
- Without privileges there are no raw sockets: ping, mtr, traceroute and tcpdump do not work. Use nc -vz host port or curl.
Which one to use?
| Tool | Where | Where the connection starts | Use it when |
|---|---|---|---|
| Pod shell | Web and desktop | Inside an app container | You need to get into a running container. |
| Node shell | Web (admins) and desktop | A privileged pod on the node itself | The problem is the node: kubelet, disk, host network. |
| Bastion | Web only | A temporary unprivileged pod in the namespace | You want to test or reach, from the browser, a host only the cluster can reach (ssh, curl, nc). |
| Secure tunnel | Desktop only | Your machine, through the cluster | You want to use the clients on your machine (psql, DBeaver, browser, ssh) against a cluster service or a host in its network. |
Step by step: prerequisites
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: kubepier-bastion
namespace: <namespace>
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["create", "get", "delete", "list"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create", "get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kubepier-bastion
namespace: <namespace>
subjects:
- kind: ServiceAccount
name: kubepier-leitura
namespace: kubepier
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubepier-bastion - An organization on Pro or Team, and you with the admin role.
- The cluster credential needs create, get and delete on pods and create on pods/exec in the namespace. list on pods is optional: it lets Kubepier clean up your leftover bastions. Apply the Role below, replacing the subject with the cluster credential identity.
- Network: the bastion only reaches what the cluster network reaches. The namespace NetworkPolicies apply to it, and NSGs or security groups on the node subnet can block the target.
Step by step: open
- Open the cluster and click Bastion in the side menu.
- Under Namespace, enter where the pod will run (lowercase letters, digits and hyphens; default is default).
- If you will use ssh with a key, paste it into Chave SSH privada (opcional) / SSH private key (optional), or use Load file. Show and Hide toggle it.
- Click Open bastion. The screen shows each step: creating the pod, waiting for a node, pulling the image, running and, if any, key written to ~/.ssh/id_kubepier.
- The terminal opens once the pod is Running (up to 120 seconds).
Step by step: use it
Examples to copy into the bastion terminal:
# SSH to an internal VM (with the key pasted on open)
ssh -i ~/.ssh/id_kubepier ubuntu@10.0.1.20
# Does the database port answer?
nc -vz db.interno 5432
# Health check of an internal service
curl -v http://servico.interno:8080/health
# Name resolution from inside the cluster
dig api.interno
# Copy a file from one internal host to another, through the bastion
scp -i ~/.ssh/id_kubepier ubuntu@10.0.1.20:/var/log/app.log /tmp/
scp -i ~/.ssh/id_kubepier /tmp/app.log ubuntu@10.0.1.21:/tmp/ HOME and /tmp are memory-backed and vanish when the bastion closes. To bring files to your machine, use the desktop Secure tunnel.
Step by step: close
- Close the terminal: the pod is deleted right away.
- The pod also ends on its own after 2 hours, on an error, or if it is not Running within 120 seconds.
- After the session ends, New bastion opens another one.
What is accepted
- An existing namespace where the credential can create pods.
- A private key in BEGIN ... PRIVATE KEY format, up to 16 KB.
What is not accepted
- The Free plan; members.
- More than one bastion of yours in the same cluster.
- Opening one with 3 terminals already open (the bastion counts toward the shell limit).
- A key that does not look like a private key: the terminal opens without it.
- A tunnel to your machine (desktop only).
Limits and timeouts
| Limit | Value |
|---|---|
| Wait for the pod to be Running | 120 seconds |
| Maximum duration | 2 hours |
| Bastions per cluster | 1 per person |
| Open terminals (shell and bastion) | 3 per person |
| SSH key | up to 16 KB |
| Pod resources | 50m/64 Mi requested, 500m/256 Mi limit |
Audit
- Open and close go to the organization audit log (bastion_abrir and bastion_fechar), with who, when, cluster, namespace, pod and duration.
- Never what is typed, the terminal output or the key.
Common errors
- No permission: the credential needs create, get and delete on pods and create on pods/exec in the namespace.
- PodSecurity refused it: the bastion already follows the restricted profile; check the namespace PodSecurity label.
- An admission policy refused it: Kyverno, Gatekeeper or a webhook requires something else, such as images from the internal registry.
- Image not pulled: the nodes cannot reach Docker Hub: mirror docker.io/nicolaka/netshoot:v0.16@sha256:b09d9b21381f47a79b3cbcb30da25266dc17186ea00ae65e99fdc51396f48e70 into your registry.
- ResourceQuota: the namespace cannot fit 50m/64 Mi requested and a 500m/256 Mi limit.
- Not Running within 120 s: the pod was deleted; check the namespace events.
- Namespace does not exist: check the name.
- "Too Many Requests": you already have a bastion in this cluster or 3 terminals open.