Borescope: a shell for the containers that have no shell

TL;DR: check out borescope, for all your shell-less K8s Juju debugging needs¹.

Debugging issues with K8s charms, where the workload containers have no shell, can be inconvenient. You can rebuild the image to include a shell (base: bare to an Ubuntu base, for example), or drop in busybox or similar, but that generally slows things down. Pebble provides a solution for you: you can exec and work with files with Pebble, even indirectly through the charm container, since the sockets are shared there. However, remembering the syntax for the push and pull (and so on) commands is still less convenient than just ssh’ing into a shell.

However, everything is a file. So what if we had a shell that had Pebble as the backend, abstracting away “everything is a file” into a familiar interface?

I thought this was an interesting idea to play with, so in September last year, I started building Cascade. I was curious how far I could get, wanted to limit myself to only rich and typer as dependencies) and I also wanted a new project to play around with agentic development. This was before the big changes at the end of the year, so was very much collaboration between me and Opus/Sonnet, rather than letting it do what it wanted, but still a good learning experience.

I got pretty far, with the usual shell behaviour (piping, tab completion, history, …) and commands (cp, touch, grep, …) that you’d expect, plus a few more bits, including one of the slowest top commands you’ll see (there are a lot of /proc files to pull!).

And then I carried on, adding more and more commands, and it got a bit out of hand :joy:. I eventually showed Cascade to the Charm Tech in our team demo session at the Gothenburg sprint. After that, I thought I’d try to get it a bit more polished and workable, and came up with a plan to work through the commands, in order of importance, and get them working really well. This proved tricky with the bulky codebase and I didn’t get very far.

Recently, I decided to revive this, but start fresh. No strict dependency limits (although still trying to keep it fairly minimal), working with much more capable agentic support (and in a different way, where I focused far more heavily on design and review and much less on writing code), taking the lessons from Cascade but applying them fresh. Most importantly, only implementing a small set of shell functionality that seems the most useful, and potentially building on from there.

The result is Borescope (“used for visual inspection work where the target area is inaccessible by other means, or where accessibility may require destructive, time consuming and/or expensive dismounting activities”).

scene2

It’s simple to use, just snap install or uv tool install, and point it at a unit. It’ll drop you into a familiar feeling shell of the first workload container (you can select other ones if needed). As well as common shell commands and functionality, the Pebble commands (services, notices, plan, …) are there as first-class citizens.

(As seen in the image above, you can also use --command to run a single command, integrating it into whatever other scripts you have.)

It works in two ways:

  • If you’re outside of the charm container, then you don’t generally have access to the Pebble sockets. In this situation, Borescope will run juju ssh (or juju exec) commands to run pebble in the charm container (I have a Python package that wraps the Pebble CLI into the ops.Pebble shape). There’s a bit of a performance penalty, but it’s simple to use and works¹ even if you can’t or don’t want to install anything in the charm container.
  • If you are in the charm container (use --here), then everything is much simpler, and it just talks to the appropriate socket as you’d expect.

I’d love feedback – on the idea itself, from actually using it, on the implementation, or however else! Open issues or PRs, or reach out to me here or in Mattermost or Matrix (or, because I still love it, email).

¹ There is one catch with the SSH approach: it needs Pebble 1.31.0 or newer, which no Juju has yet (I built my own). That version adds a --format flag to many Pebble commands, which greatly simplifies using the CLI as an API. There are older versions of Shimmer that didn’t need this, so in theory Borescope could use those, but I hope the newer Pebble will come to Juju 4 fairly soon.

2 Likes