Skip to content

Commit d394325

Browse files
committed
feat(supervisor): report experimental bootstrap health over TCP
experimental-bootstrap now takes --health-port instead of a Unix health socket. It binds the dedicated supervisor's wildcard readiness listener, reachable at the Pod IP, and accepts and closes connections while the process runs. The chart probes the named container port health (5502) with native kubelet tcpSocket checks and drops the health-only emptyDir. No filesystem state remains to clean up after an unclean exit. Dedicated supervisors keep --health-socket-path and health --socket. Signed-off-by: Drew Newberry <anewberry@nvidia.com>
1 parent 7438e4e commit d394325

7 files changed

Lines changed: 60 additions & 44 deletions

File tree

‎.agents/skills/helm-dev-environment/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ gatewayConfig:
7171
The gateway chart creates a separate, single-replica idle supervisor Deployment
7272
in the release namespace, regardless of shared/managed/operator workspace mode.
7373
Use a supervisor image built from this branch: the bootstrap subcommand is new.
74-
Check its rollout and exec health probes separately; no sandbox sessions route
75-
through it. `workspace` is reserved and rejected. Omit the field to disable it.
74+
Check its rollout and TCP health probes (container port `health`, 5502)
75+
separately; no sandbox sessions route through it. `workspace` is reserved and rejected. Omit the field to disable it.
7676

7777
### 2. Deploy OpenShell
7878

‎crates/openshell-supervisor/README.md‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ backend or enable a Windows workload runtime.
6363

6464
## Experimental deployment bootstrap
6565

66-
`openshell-supervisor experimental-bootstrap --health-socket /run/openshell/health.sock`
67-
starts an idle process for the Kubernetes gateway topology experiment. The private
68-
Unix socket supports the existing `health --socket` command. No sandbox session
69-
listener, gateway authentication, or tenant routing is started. SIGTERM and SIGINT
70-
close the listener and remove the socket. This subcommand is Unix-only.
66+
`openshell-supervisor experimental-bootstrap --health-port 5502` starts an idle
67+
process for the Kubernetes gateway topology experiment. The wildcard TCP health
68+
port accepts and closes connections for kubelet `tcpSocket` probes and reports
69+
process health only; it keeps no filesystem state. No sandbox session listener,
70+
gateway authentication, or tenant routing is started. SIGTERM and SIGINT close
71+
the listener. This subcommand is Unix-only.

‎crates/openshell-supervisor/src/experimental.rs‎

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ use clap::Parser;
77
#[cfg(unix)]
88
use miette::IntoDiagnostic;
99
use miette::Result;
10-
use std::path::PathBuf;
1110

1211
#[derive(Debug, Parser)]
1312
#[command(name = "openshell-supervisor experimental-bootstrap")]
1413
#[command(about = "Start an idle experimental supervisor; does not accept sandbox sessions")]
1514
struct Args {
16-
/// Private socket reporting process health, not sandbox readiness.
15+
/// TCP port accepting connections while the process runs; reports process
16+
/// health, not sandbox readiness.
1717
#[arg(long)]
18-
health_socket: PathBuf,
18+
health_port: u16,
1919
}
2020

2121
pub fn run(raw_args: &[String]) -> Result<()> {
@@ -37,28 +37,24 @@ fn run_platform(args: Args) -> Result<()> {
3737
let mut interrupt =
3838
tokio::signal::unix::signal(tokio::signal::unix::SignalKind::interrupt())
3939
.into_diagnostic()?;
40-
// The private emptyDir survives a container restart after an unclean exit.
41-
match std::fs::remove_file(&args.health_socket) {
42-
Ok(()) => {}
43-
Err(error) if error.kind() == std::io::ErrorKind::NotFound => {}
44-
Err(error) => return Err(error).into_diagnostic(),
45-
}
46-
let listener = tokio::net::UnixListener::bind(&args.health_socket).into_diagnostic()?;
40+
let health = openshell_supervisor::bind_readiness_tcp(args.health_port)
41+
.and_then(tokio::net::TcpListener::from_std)
42+
.into_diagnostic()?;
4743
eprintln!("Experimental supervisor bootstrap started; sandbox sessions are disabled");
48-
let result = loop {
44+
loop {
4945
tokio::select! {
50-
result = listener.accept() => {
46+
// A connection is the whole check; nothing is exchanged.
47+
result = health.accept() => {
5148
if let Err(error) = result {
52-
break Err(error).into_diagnostic();
49+
eprintln!("experimental supervisor health accept failed: {error}");
50+
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
5351
}
5452
}
55-
_ = terminate.recv() => break Ok(()),
56-
_ = interrupt.recv() => break Ok(()),
53+
_ = terminate.recv() => break,
54+
_ = interrupt.recv() => break,
5755
}
58-
};
59-
drop(listener);
60-
std::fs::remove_file(&args.health_socket).into_diagnostic()?;
61-
result
56+
}
57+
Ok(())
6258
})
6359
}
6460

‎crates/openshell-supervisor/src/lib.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,9 @@ impl ReadinessEndpoint {
175175
}
176176
}
177177

178-
/// Falls back to IPv4 when the network namespace has IPv6 disabled.
179-
fn bind_readiness_tcp(port: u16) -> std::io::Result<std::net::TcpListener> {
178+
/// Binds a nonblocking wildcard listener reachable at the Pod IP. Falls back to
179+
/// IPv4 when the network namespace has IPv6 disabled.
180+
pub fn bind_readiness_tcp(port: u16) -> std::io::Result<std::net::TcpListener> {
180181
use socket2::{Domain, Socket, Type};
181182

182183
let bind = |domain: Domain, address: std::net::SocketAddr| {

‎deploy/helm/openshell/templates/experimental-supervisor.yaml‎

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,12 @@ spec:
5252
imagePullPolicy: {{ get (dict "always" "Always" "if_not_present" "IfNotPresent" "never" "Never") (get $kubernetes "supervisor_image_pull_policy" | default "if_not_present") | quote }}
5353
args:
5454
- experimental-bootstrap
55-
- --health-socket
56-
- /run/openshell/health.sock
55+
- --health-port
56+
- "5502"
57+
ports:
58+
- name: health
59+
containerPort: 5502
60+
protocol: TCP
5761
securityContext:
5862
allowPrivilegeEscalation: false
5963
readOnlyRootFilesystem: true
@@ -66,15 +70,9 @@ spec:
6670
limits:
6771
memory: 128Mi
6872
readinessProbe:
69-
exec:
70-
command: [/openshell-supervisor, health, --socket, /run/openshell/health.sock]
73+
tcpSocket:
74+
port: health
7175
livenessProbe:
72-
exec:
73-
command: [/openshell-supervisor, health, --socket, /run/openshell/health.sock]
74-
volumeMounts:
75-
- name: health
76-
mountPath: /run/openshell
77-
volumes:
78-
- name: health
79-
emptyDir: {}
76+
tcpSocket:
77+
port: health
8078
{{- end }}

‎deploy/helm/openshell/tests/experimental_supervisor_test.yaml‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,28 @@ tests:
3434
path: spec.template.spec.containers[0].image
3535
value: example.com/supervisor:experiment
3636
- equal:
37-
path: spec.template.spec.containers[0].args[0]
38-
value: experimental-bootstrap
37+
path: spec.template.spec.containers[0].args
38+
value: [experimental-bootstrap, --health-port, "5502"]
39+
- equal:
40+
path: spec.template.spec.containers[0].ports
41+
value:
42+
- name: health
43+
containerPort: 5502
44+
protocol: TCP
45+
- equal:
46+
path: spec.template.spec.containers[0].readinessProbe
47+
value:
48+
tcpSocket:
49+
port: health
50+
- equal:
51+
path: spec.template.spec.containers[0].livenessProbe
52+
value:
53+
tcpSocket:
54+
port: health
55+
- notExists:
56+
path: spec.template.spec.containers[0].volumeMounts
57+
- notExists:
58+
path: spec.template.spec.volumes
3959
- equal:
4060
path: spec.template.spec.automountServiceAccountToken
4161
value: false

‎skills/debug-openshell-cluster/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ When the installed gateway configuration enables
5555
`[openshell.drivers.kubernetes].experimental_supervisor_topology = "gateway"`,
5656
Helm creates `<fullname>-experimental-supervisor` in the gateway namespace.
5757
Inspect that Deployment separately from per-sandbox supervisor Pods. This applies
58-
to shared, managed, and operator workspace modes. Its probes report idle process
59-
health, not sandbox session readiness; it does not serve sandboxes yet. Consult
58+
to shared, managed, and operator workspace modes. Its TCP probes on container
59+
port `health` (5502) report idle process health, not sandbox session readiness; it does not serve sandboxes yet. Consult
6060
the published gateway configuration reference for the installed version. Omit
6161
the setting and upgrade the release to remove the experimental Deployment.
6262

0 commit comments

Comments
 (0)