|
| 1 | +--- |
| 2 | +name: deploy-openshell-cluster |
| 3 | +description: Deploy OpenShell gateway with Helm on Kubernetes or OpenShift, auto-detect cluster type, apply OpenShift-only SCC/security overrides when needed, and configure SQLite or PostgreSQL persistence. Use when the user asks to deploy OpenShell to a cluster, reinstall the Helm release, or enable postgres.enabled with internal or external mode. |
| 4 | +--- |
| 5 | + |
| 6 | +# Deploy OpenShell Cluster |
| 7 | + |
| 8 | +Use `deploy/helm/openshell/README.md` as the source of truth, then apply this workflow. |
| 9 | + |
| 10 | +Default behavior: |
| 11 | + |
| 12 | +- SQLite by default (`postgres.enabled=false`) |
| 13 | +- Optional PostgreSQL (`postgres.enabled=true`) via: |
| 14 | + - `postgres.mode=internal` (deploy bundled Postgres dependency) |
| 15 | + - `postgres.mode=external` (use external database settings) |
| 16 | + |
| 17 | +## Inputs |
| 18 | + |
| 19 | +```bash |
| 20 | +NAMESPACE="${NAMESPACE:-openshell}" |
| 21 | +RELEASE_NAME="${RELEASE_NAME:-openshell}" |
| 22 | +CHART_REF="${CHART_REF:-oci://ghcr.io/nvidia/openshell/helm-chart}" |
| 23 | +CHART_VERSION="${CHART_VERSION:-}" |
| 24 | +GATEWAY_TAG="${GATEWAY_TAG:-}" # e.g. dev or fa84e437... |
| 25 | +POSTGRES_ENABLED="${POSTGRES_ENABLED:-false}" # true|false |
| 26 | +POSTGRES_MODE="${POSTGRES_MODE:-internal}" # internal|external |
| 27 | +POSTGRES_DB="${POSTGRES_DB:-openshell}" |
| 28 | +POSTGRES_USER="${POSTGRES_USER:-openshell}" |
| 29 | +POSTGRES_PASSWORD="${POSTGRES_PASSWORD:-}" # required when postgres is enabled |
| 30 | +POSTGRES_HOST="${POSTGRES_HOST:-}" # required for external mode |
| 31 | +POSTGRES_PORT="${POSTGRES_PORT:-5432}" |
| 32 | +``` |
| 33 | + |
| 34 | +## Step 1: Verify cluster login |
| 35 | + |
| 36 | +Before any deployment action, confirm the user is authenticated to a cluster. |
| 37 | + |
| 38 | +```bash |
| 39 | +if ! kubectl auth can-i get pods >/dev/null 2>&1; then |
| 40 | + echo "Not authenticated to a Kubernetes/OpenShift cluster." |
| 41 | + echo "Please log in first (for OpenShift: oc login <api-server>), then retry." |
| 42 | + exit 1 |
| 43 | +fi |
| 44 | +``` |
| 45 | + |
| 46 | +If the check fails, stop and ask the user to log in before continuing. |
| 47 | + |
| 48 | +## Step 2: Choose namespace (with upgrade prompt) |
| 49 | + |
| 50 | +Namespace selection rules: |
| 51 | + |
| 52 | +1. If user explicitly provides a namespace, use it. |
| 53 | +2. If user does not provide a namespace, default to `openshell`. |
| 54 | +3. If `openshell` already has a running gateway and user did not explicitly ask for upgrade, ask: |
| 55 | + - upgrade existing deployment in `openshell`, or |
| 56 | + - deploy fresh into a new namespace. |
| 57 | + |
| 58 | +Detect existing gateway in `openshell`: |
| 59 | + |
| 60 | +```bash |
| 61 | +EXISTING_IN_OPENSHIFT=false |
| 62 | +if helm status openshell -n openshell >/dev/null 2>&1; then |
| 63 | + EXISTING_IN_OPENSHIFT=true |
| 64 | +elif kubectl get statefulset openshell -n openshell >/dev/null 2>&1; then |
| 65 | + EXISTING_IN_OPENSHIFT=true |
| 66 | +fi |
| 67 | +``` |
| 68 | + |
| 69 | +When `EXISTING_IN_OPENSHIFT=true` and namespace was not explicitly specified, stop and ask the user for a choice before proceeding. |
| 70 | + |
| 71 | +## Step 3: Select gateway/chart version |
| 72 | + |
| 73 | +If user explicitly provides `GATEWAY_TAG`, use it. |
| 74 | + |
| 75 | +If user explicitly provides `CHART_VERSION`, use it as-is. |
| 76 | + |
| 77 | +If neither `GATEWAY_TAG` nor `CHART_VERSION` is provided: |
| 78 | + |
| 79 | +1. Fetch recent gateway tags from [GHCR package page](https://github.com/nvidia/OpenShell/pkgs/container/openshell%2Fgateway) (or equivalent API/CLI output). |
| 80 | +2. Ask the user which tag to deploy. |
| 81 | +3. Convert chosen gateway tag to Helm chart dev format: |
| 82 | + - gateway tag `dev` -> `CHART_VERSION=0.0.0-dev` |
| 83 | + - gateway tag `<tag>` (commit-like or custom) -> `CHART_VERSION=0.0.0-<tag>` |
| 84 | + |
| 85 | +Example prompt to user: |
| 86 | + |
| 87 | +- "I found recent gateway tags: `dev`, `fa84e437...`, `3460e5fd...`. Which one should I deploy?" |
| 88 | + |
| 89 | +If user does not choose, default to: |
| 90 | + |
| 91 | +```bash |
| 92 | +GATEWAY_TAG="dev" |
| 93 | +CHART_VERSION="0.0.0-dev" |
| 94 | +``` |
| 95 | + |
| 96 | +If `GATEWAY_TAG` is provided and `CHART_VERSION` is empty: |
| 97 | + |
| 98 | +```bash |
| 99 | +CHART_VERSION="0.0.0-${GATEWAY_TAG}" |
| 100 | +``` |
| 101 | + |
| 102 | +If `CHART_VERSION` is provided and `GATEWAY_TAG` is empty, derive `GATEWAY_TAG` when possible: |
| 103 | + |
| 104 | +```bash |
| 105 | +case "${CHART_VERSION}" in |
| 106 | + 0.0.0-*) GATEWAY_TAG="${CHART_VERSION#0.0.0-}" ;; |
| 107 | + *) GATEWAY_TAG="dev" ;; # fallback |
| 108 | +esac |
| 109 | +``` |
| 110 | + |
| 111 | +## Step 4: Detect cluster type |
| 112 | + |
| 113 | +```bash |
| 114 | +CLUSTER_TYPE="kubernetes" |
| 115 | +if kubectl get clusterversion version >/dev/null 2>&1; then |
| 116 | + CLUSTER_TYPE="openshift" |
| 117 | +fi |
| 118 | +echo "Detected cluster type: ${CLUSTER_TYPE}" |
| 119 | +``` |
| 120 | + |
| 121 | +## Step 5: Install shared prerequisites |
| 122 | + |
| 123 | +```bash |
| 124 | +kubectl apply -f https://github.com/kubernetes-sigs/agent-sandbox/releases/latest/download/manifest.yaml |
| 125 | +kubectl get namespace "${NAMESPACE}" >/dev/null 2>&1 || kubectl create namespace "${NAMESPACE}" |
| 126 | +``` |
| 127 | + |
| 128 | +## Step 6: Apply OpenShift-only prerequisites |
| 129 | + |
| 130 | +Run only when `CLUSTER_TYPE=openshift`. |
| 131 | + |
| 132 | +```bash |
| 133 | +if [ "${CLUSTER_TYPE}" = "openshift" ]; then |
| 134 | + oc adm policy add-scc-to-user privileged -z openshell-sandbox -n "${NAMESPACE}" |
| 135 | +fi |
| 136 | +``` |
| 137 | + |
| 138 | +## Step 7: Deploy Helm release |
| 139 | + |
| 140 | +```bash |
| 141 | +HELM_ARGS=( |
| 142 | + upgrade --install "${RELEASE_NAME}" "${CHART_REF}" |
| 143 | + --version "${CHART_VERSION}" |
| 144 | + --namespace "${NAMESPACE}" |
| 145 | + --set "image.tag=${GATEWAY_TAG}" |
| 146 | + --set "supervisor.image.tag=${GATEWAY_TAG}" |
| 147 | + --set "postgres.enabled=${POSTGRES_ENABLED}" |
| 148 | + --wait |
| 149 | +) |
| 150 | + |
| 151 | +if [ "${POSTGRES_ENABLED}" = "true" ]; then |
| 152 | + HELM_ARGS+=(--set "postgres.mode=${POSTGRES_MODE}") |
| 153 | + if [ "${POSTGRES_MODE}" = "external" ]; then |
| 154 | + HELM_ARGS+=( |
| 155 | + --set "postgres.external.host=${POSTGRES_HOST}" |
| 156 | + --set "postgres.external.port=${POSTGRES_PORT}" |
| 157 | + --set "postgres.external.username=${POSTGRES_USER}" |
| 158 | + --set "postgres.external.password=${POSTGRES_PASSWORD}" |
| 159 | + --set "postgres.external.database=${POSTGRES_DB}" |
| 160 | + ) |
| 161 | + else |
| 162 | + HELM_ARGS+=( |
| 163 | + --set "postgres.auth.username=${POSTGRES_USER}" |
| 164 | + --set "postgres.auth.password=${POSTGRES_PASSWORD}" |
| 165 | + --set "postgres.auth.database=${POSTGRES_DB}" |
| 166 | + ) |
| 167 | + fi |
| 168 | +fi |
| 169 | + |
| 170 | +if [ "${CLUSTER_TYPE}" = "openshift" ]; then |
| 171 | + HELM_ARGS+=( |
| 172 | + --set server.disableTls=true |
| 173 | + --set podSecurityContext.fsGroup=null |
| 174 | + --set securityContext.runAsUser=null |
| 175 | + ) |
| 176 | +fi |
| 177 | + |
| 178 | +helm "${HELM_ARGS[@]}" |
| 179 | +``` |
| 180 | + |
| 181 | +This keeps Kubernetes installs aligned with the README default `helm install` path and applies OpenShift-specific overrides only on OpenShift. |
| 182 | + |
| 183 | +## Step 8: Verify deployment |
| 184 | + |
| 185 | +```bash |
| 186 | +kubectl get pods -n "${NAMESPACE}" |
| 187 | +kubectl rollout status statefulset/"${RELEASE_NAME}" -n "${NAMESPACE}" |
| 188 | +helm get values "${RELEASE_NAME}" -n "${NAMESPACE}" |
| 189 | +``` |
| 190 | + |
| 191 | +Check persistence mode: |
| 192 | + |
| 193 | +- SQLite default: `postgres.enabled=false` |
| 194 | +- Internal Postgres: `postgres.enabled=true`, `postgres.mode=internal` |
| 195 | +- External Postgres: `postgres.enabled=true`, `postgres.mode=external` |
0 commit comments