mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-15 05:09:44 +08:00
* feat(kubernetes): add sidecar supervisor topology Add the Kubernetes sidecar supervisor topology, its Helm/Skaffold configuration, topology documentation, and sidecar e2e matrix coverage. Skip root-only sandbox identity rewriting when process enforcement is network-only so the low-permission sidecar process container can start successfully. Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(supervisor): avoid similar process id names Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(supervisor): avoid similar process id names Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(sandbox): avoid similar proxy id names Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * docs(kubernetes): clarify sidecar topology limits Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(kubernetes): keep sidecar process leaf capless Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(kubernetes): refresh sidecar provider env snapshots Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * test(supervisor): align hot-swap identity regression Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(kubernetes): stage sidecar mtls files before proxy chown Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(kubernetes): simplify sidecar supervisor topology Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * chore(helm): reuse sidecar skaffold values Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(supervisor): avoid similar iptables helper names Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(e2e): harden kube gateway wrapper setup Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(supervisor): avoid nft batch rollback on OCP Run nftables setup as individual commands so optional conntrack and log expressions can fail without rolling back required table, chain, and reject rules. Signed-off-by: Seth Jennings <sjenning@redhat.com> Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(kubernetes): preserve process identity in sidecar topology Render sidecar pods with a shared process namespace, keep binary-aware network policy enabled, and move Kubernetes sidecar settings under the nested sidecar config table. Also apply unprivileged Landlock/seccomp setup in NetworkOnly supervisor mode so sidecar topology keeps sandbox child hardening without privileged process setup. Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * refactor(kubernetes): replace sidecar snapshots with control socket Coordinate sidecar policy and provider bootstrap over a local Unix socket so the process leaf no longer reads policy/provider snapshot files. Report entrypoint startup through the control channel and keep gateway credentials confined to the network sidecar. Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * feat(kubernetes): support relaxed sidecar network identity Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(sandbox): satisfy sidecar clippy lint Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * refactor(kubernetes): standardize topology naming Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(sandbox): satisfy linux clippy timeout import Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(kubernetes): support kata sidecar on ipv4 pods Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(kubernetes): satisfy linux clippy for sidecar fallback Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * chore(kubernetes): remove stale supervisor topology references Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(kubernetes): enable sidecar binary policy inspection Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(kubernetes): harden sidecar control boundary Signed-off-by: Taylor Mutch <taylormutch@gmail.com> * fix(kubernetes): couple sidecar supervisor lifecycles Signed-off-by: Taylor Mutch <taylormutch@gmail.com> --------- Signed-off-by: Taylor Mutch <taylormutch@gmail.com> Signed-off-by: Seth Jennings <sjenning@redhat.com> Co-authored-by: Seth Jennings <sjenning@redhat.com>
253 lines
12 KiB
Plaintext
253 lines
12 KiB
Plaintext
---
|
|
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
title: "Set Up OpenShell on Kubernetes"
|
|
sidebar-title: "Setup"
|
|
description: "Deploy the OpenShell gateway to a Kubernetes cluster using the official Helm chart from GHCR."
|
|
keywords: "Generative AI, Cybersecurity, Kubernetes, Helm, Gateway, Deployment, OCI, GHCR, Installation"
|
|
position: 1
|
|
---
|
|
|
|
<Warning>
|
|
The OpenShell Helm chart is experimental and under active development. Templates, values, and defaults can change between releases. Do not use it in production.
|
|
</Warning>
|
|
|
|
Use the Kubernetes deployment when the gateway should run on a shared cluster, in a cloud environment, or as part of team infrastructure. The Helm chart handles PKI bootstrap, RBAC, sandbox namespace setup, and the gateway workload. It uses a StatefulSet by default for the SQLite database, and can render a Deployment when `server.externalDbSecret` points at an external database.
|
|
|
|
## Prerequisites
|
|
|
|
Make sure the following are in place before you install.
|
|
|
|
| Prerequisite | Required | Notes |
|
|
|---|---|---|
|
|
| Kubernetes 1.29+ with RBAC enabled | Yes | No additional notes. |
|
|
| Helm 3.x | Yes | No additional notes. |
|
|
| Agent Sandbox controller and CRDs | Yes | Install before the OpenShell chart. Refer to [Install Agent Sandbox](#install-agent-sandbox). |
|
|
| cert-manager | No | Refer to [Managing Certificates](/kubernetes/managing-certificates). Use cert-manager only if you prefer it over the built-in PKI job. |
|
|
| Kubernetes Gateway API | No | Refer to [Ingress](/kubernetes/ingress). Use it only for external access without port-forwarding. |
|
|
|
|
## Install Agent Sandbox
|
|
|
|
OpenShell uses the [Agent Sandbox](https://agent-sandbox.sigs.k8s.io) Kubernetes SIG project to provision sandbox pods. Install the Agent Sandbox controller and its CRDs on your cluster before installing the OpenShell Helm chart.
|
|
|
|
Apply the latest release manifest:
|
|
|
|
```shell
|
|
kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/latest/download/manifest.yaml
|
|
```
|
|
|
|
This creates the `agent-sandbox-system` namespace, installs the `sandboxes.agents.x-k8s.io` CRD, and starts the controller.
|
|
|
|
<Note>
|
|
**Air-gapped clusters:** mirror the manifest above and the `registry.k8s.io/agent-sandbox/agent-sandbox-controller` image referenced inside it to your internal registry, then point the manifest's image reference at your mirror before applying. You will also need to mirror the OpenShell gateway and sandbox images — see the chart's `image.repository` value for the gateway and `server.sandboxImage` / `server.supervisorImage` for the sandbox runtime.
|
|
</Note>
|
|
|
|
Confirm the controller pod is running before proceeding:
|
|
|
|
```shell
|
|
kubectl -n agent-sandbox-system get pods
|
|
```
|
|
|
|
The controller pod should reach `Running` status within a few seconds. For cluster-specific setup instructions, including KinD and GKE walkthroughs, refer to the [Agent Sandbox getting started guide](https://agent-sandbox.sigs.k8s.io/docs/getting_started/).
|
|
|
|
### Upgrade Agent Sandbox
|
|
|
|
OpenShell detects the served Agent Sandbox `Sandbox` API when the Kubernetes gateway first needs it and caches that choice for the gateway process. If you upgrade Agent Sandbox in place, restart the OpenShell gateway after the Agent Sandbox controller and CRD rollout completes so the gateway can detect the served API versions again. Existing sandboxes keep running during the upgrade, and the restarted gateway can continue managing them.
|
|
|
|
## Install OpenShell
|
|
|
|
<Steps>
|
|
|
|
## Create the namespace
|
|
|
|
```shell
|
|
kubectl create namespace openshell
|
|
```
|
|
|
|
## Install the chart
|
|
|
|
Install from the OCI registry on GHCR. Replace `<version>` with the chart version you want to install.
|
|
|
|
```shell
|
|
helm upgrade --install openshell \
|
|
oci://ghcr.io/nvidia/openshell/helm-chart \
|
|
--version <version> \
|
|
--namespace openshell
|
|
```
|
|
|
|
To use the latest development build instead of a stable release:
|
|
|
|
```shell
|
|
helm upgrade --install openshell \
|
|
oci://ghcr.io/nvidia/openshell/helm-chart \
|
|
--version 0.0.0-dev \
|
|
--namespace openshell
|
|
```
|
|
|
|
The chart automatically generates PKI secrets on first install using pre-install Helm hooks. No manual secret creation is required.
|
|
|
|
## Wait for the gateway to be ready
|
|
|
|
```shell
|
|
kubectl -n openshell rollout status statefulset/openshell
|
|
```
|
|
|
|
If you set `workload.kind=deployment`, wait on the Deployment instead:
|
|
|
|
```shell
|
|
kubectl -n openshell rollout status deployment/openshell
|
|
```
|
|
|
|
## Connect to the gateway
|
|
|
|
For local evaluation, use a port-forward:
|
|
|
|
```shell
|
|
kubectl -n openshell port-forward svc/openshell 8080:8080
|
|
```
|
|
|
|
<Warning>
|
|
The port-forward is for local evaluation only. For shared environments, expose the gateway through your ingress controller or access proxy. Refer to [Ingress](/kubernetes/ingress) for an external access option.
|
|
</Warning>
|
|
|
|
## Install the TLS client bundle
|
|
|
|
The chart generates an mTLS bundle for transport security. Kubernetes deployments do not use that bundle as user authentication; configure OIDC or a trusted access proxy as described in [Access Control](/kubernetes/access-control). For local port-forwarded access, copy the generated bundle so the CLI can verify the gateway certificate:
|
|
|
|
```shell
|
|
mkdir -p ~/.config/openshell/gateways/k8s/mtls
|
|
kubectl -n openshell get secret openshell-client-tls \
|
|
-o jsonpath='{.data.ca\.crt}' | base64 -d > ~/.config/openshell/gateways/k8s/mtls/ca.crt
|
|
kubectl -n openshell get secret openshell-client-tls \
|
|
-o jsonpath='{.data.tls\.crt}' | base64 -d > ~/.config/openshell/gateways/k8s/mtls/tls.crt
|
|
kubectl -n openshell get secret openshell-client-tls \
|
|
-o jsonpath='{.data.tls\.key}' | base64 -d > ~/.config/openshell/gateways/k8s/mtls/tls.key
|
|
```
|
|
|
|
The server certificate SANs include `localhost` and `127.0.0.1`, so hostname verification passes over the port-forward without extra flags.
|
|
|
|
## Register with the CLI
|
|
|
|
In another terminal, register the gateway with the user authentication mode you configured and verify it is reachable. For example, with OIDC:
|
|
|
|
```shell
|
|
openshell gateway add https://127.0.0.1:8080 --local --name k8s \
|
|
--oidc-issuer https://your-idp.example.com/realms/openshell \
|
|
--oidc-client-id openshell-cli
|
|
openshell status
|
|
```
|
|
|
|
</Steps>
|
|
|
|
## Configure Chart Values
|
|
|
|
The most commonly changed values are:
|
|
|
|
| Value | Purpose |
|
|
|---|---|
|
|
| `image.repository` / `image.tag` | Gateway container image. Defaults to `ghcr.io/nvidia/openshell/gateway:latest`. |
|
|
| `replicaCount` | Number of gateway replicas. Leave at `1` unless you are explicitly testing multi-replica behavior. |
|
|
| `workload.kind` | Gateway workload controller. Use `statefulset` for SQLite or `deployment` with `server.externalDbSecret`. |
|
|
| `workload.allowMultiReplicaStatefulSet` | Allow `replicaCount > 1` with `workload.kind=statefulset`. Prefer Deployment for external database-backed multi-replica gateways. |
|
|
| `server.sandboxNamespace` | Namespace where sandbox pods are created. Defaults to the Helm release namespace when left empty. |
|
|
| `server.externalDbSecret` | Secret containing a PostgreSQL connection URI in the `uri` key. Use when the database is managed outside the chart. |
|
|
| `server.sandboxImage` | Default sandbox image used when a sandbox does not specify one. |
|
|
| `server.sandboxImagePullSecrets` | Image pull secrets attached to sandbox pods. Referenced Secrets must exist in the sandbox namespace. |
|
|
| `server.grpcEndpoint` | Endpoint that sandbox supervisors use to call back to the gateway. Must be reachable from inside the cluster. |
|
|
| `server.appArmorProfile` | AppArmor profile requested for sandbox agent containers. Defaults to `Unconfined`. |
|
|
| `server.disableTls` | Run the gateway over plaintext HTTP. Use only behind a trusted transport. |
|
|
| `server.auth.allowUnauthenticatedUsers` | Accept user-facing calls without OIDC or mTLS credentials. Use only for trusted local development or a fully trusted access proxy. |
|
|
| `server.enableLoopbackServiceHttp` | Enable local plaintext HTTP for loopback sandbox service URLs. Defaults to `true`. |
|
|
| `pkiInitJob.serverDnsNames` / `certManager.serverDnsNames` | Additional gateway server DNS SANs. Wildcard SANs also enable sandbox service URLs under that domain. |
|
|
| `supervisor.sideloadMethod` | How the supervisor binary is delivered into sandbox pods. Leave empty to auto-detect based on cluster version: clusters running Kubernetes 1.35 or later use `image-volume` (ImageVolume GA in 1.36); older clusters use `init-container`. Set explicitly to `image-volume` on Kubernetes 1.33 or 1.34 with the ImageVolume feature gate enabled, or to `init-container` to force the legacy path on any version. |
|
|
| `supervisor.topology` | Sandbox pod topology. Refer to [Topology](/kubernetes/topology). |
|
|
| `supervisor.sidecar.proxyUid` | Non-root UID used when sidecar process/binary-aware network policy is disabled. The default binary-aware sidecar runs as UID 0 instead. The configured UID must not match the sandbox UID. |
|
|
|
|
Use a values file for repeatable deployments:
|
|
|
|
```shell
|
|
helm upgrade --install openshell \
|
|
oci://ghcr.io/nvidia/openshell/helm-chart \
|
|
--version <version> \
|
|
--namespace openshell \
|
|
--values my-values.yaml
|
|
```
|
|
|
|
The chart defaults `server.appArmorProfile` to `Unconfined` because
|
|
runtime/default AppArmor profiles can block the supervisor's network namespace
|
|
mount setup on AppArmor-enabled nodes. Set `server.appArmorProfile` to an empty
|
|
string to omit the field, `RuntimeDefault` to force the runtime default, or
|
|
`Localhost/<profile-name>` when you load and manage a localhost profile on each
|
|
node.
|
|
|
|
To use private sandbox images, create a `kubernetes.io/dockerconfigjson` Secret
|
|
in the sandbox namespace and reference its name:
|
|
|
|
```shell
|
|
kubectl -n openshell create secret docker-registry regcred \
|
|
--docker-server=registry.example.com \
|
|
--docker-username="$REGISTRY_USER" \
|
|
--docker-password="$REGISTRY_TOKEN"
|
|
```
|
|
|
|
```yaml
|
|
server:
|
|
sandboxImage: registry.example.com/team/openshell-sandbox:latest
|
|
sandboxImagePullSecrets:
|
|
- name: regcred
|
|
```
|
|
|
|
## RBAC
|
|
|
|
The chart creates the following RBAC resources in the release namespace:
|
|
|
|
| Resource | Scope | Name |
|
|
|---|---|---|
|
|
| ServiceAccount | Namespace | `openshell` |
|
|
| ServiceAccount | Namespace | `openshell-sandbox` (for sandbox pods) |
|
|
| Role + RoleBinding | Namespace | `openshell-sandbox` |
|
|
| ClusterRole + ClusterRoleBinding | Cluster | `openshell-node-reader` |
|
|
|
|
The namespaced Role covers sandbox lifecycle and identity:
|
|
|
|
| API Group | Resource | Verbs |
|
|
|---|---|---|
|
|
| `agents.x-k8s.io` | `sandboxes`, `sandboxes/status` | create, delete, get, list, patch, update, watch |
|
|
| `""` | `events` | get, list, watch |
|
|
| `""` | `pods` | get |
|
|
|
|
The ClusterRole grants node inspection and token validation:
|
|
|
|
| API Group | Resource | Verbs |
|
|
|---|---|---|
|
|
| `authentication.k8s.io` | `tokenreviews` | create |
|
|
| `""` | `nodes` | get, list, watch |
|
|
|
|
To use an existing ServiceAccount instead of creating one, set `serviceAccount.create=false` and supply its name:
|
|
|
|
```shell
|
|
helm upgrade --install openshell \
|
|
oci://ghcr.io/nvidia/openshell/helm-chart \
|
|
--version <version> \
|
|
--namespace openshell \
|
|
--set serviceAccount.create=false \
|
|
--set serviceAccount.name=my-existing-sa
|
|
```
|
|
|
|
The ServiceAccount must already have the Role and ClusterRole bindings described above.
|
|
|
|
## Probes
|
|
|
|
The gateway exposes `/healthz` for process liveness and `/readyz` for dependency-aware readiness on the health port. The Helm chart wires both into Kubernetes probes:
|
|
|
|
- `startupProbe` and `livenessProbe` use `/healthz`.
|
|
- `readinessProbe` uses `/readyz`, which reflects the latest result of an in-process background database check.
|
|
|
|
## Next Steps
|
|
|
|
- To choose between combined and sidecar sandbox pods, refer to [Topology](/kubernetes/topology).
|
|
- To enable automatic certificate rotation with cert-manager, refer to [Managing Certificates](/kubernetes/managing-certificates).
|
|
- To expose the gateway externally without port-forwarding, refer to [Ingress](/kubernetes/ingress).
|
|
- To configure OIDC or reverse-proxy authentication, refer to [Access Control](/kubernetes/access-control).
|
|
- To create your first sandbox, refer to [Manage Sandboxes](/sandboxes/manage-sandboxes).
|