Skip to content

Add setup-k8s.sh: generic Kubernetes install path#142

Open
moonlight16 wants to merge 3 commits into
kagenti:mainfrom
moonlight16:feat/setup-k8s
Open

Add setup-k8s.sh: generic Kubernetes install path#142
moonlight16 wants to merge 3 commits into
kagenti:mainfrom
moonlight16:feat/setup-k8s

Conversation

@moonlight16

Copy link
Copy Markdown
Member

Add a generic Kubernetes install script, filling the gap between setup-kind.sh (local Kind) and setup-ocp.sh (OpenShift).

Why

Deploying on a real, non-OpenShift Kubernetes cluster (k3s, EKS, GKE, on-prem, …) fits neither existing script:

  • setup-kind.sh assumes a local single-node Kind cluster and builds + kind loads the image — no good on a remote cluster.
  • setup-ocp.sh assumes OpenShift-specific machinery: OLM operators (OpenShift Serverless, Custom Metrics Autoscaler) and auto-created Routes — none of which exist on vanilla k8s.

Today that means hand-porting one of them. This adds the missing generic path.

What

setup-k8s.sh installs the same stack (Knative Serving + Kourier, agent-sandbox controller, Redis, sandbox pool, LLM secret, harness ksvc) on any Kubernetes cluster, reusing the shared base manifests with cluster-specifics injected via flags — mirroring setup-ocp.sh’s render_overlay_dir sed approach, so nothing is forked. Plus README-k8s.md.

How the three scripts differ:

setup-kind.sh setup-k8s.sh (new) setup-ocp.sh
Target local Kind (1 node) any vanilla K8s OpenShift 4.x
Knative / KEDA raw manifests raw manifests OLM operators
Images build + kind load prebuilt --image refs (in-cluster build documented) prebuilt / built-in oc new-build
Namespace default --namespace --namespace
StorageClass cluster default --storage-class (default: cluster default) cluster default
Ingress port-forward port-forward or --ingress nodeport auto Route

Knobs: --namespace, --image/--sandbox-image, --storage-class (incl. ibm-scale-csi for GPFS), --ingress, --with-keda, --context, --dry-run. Model via SH_MODEL/SH_MODEL_CUSTOM.

Why it is safe

  • Purely additive — two new files, no changes to existing scripts or manifests.
  • Reuses base manifests via runtime substitution; nothing forked to drift.
  • Logs go to stderr, so --dry-run emits clean, pipeable YAML.

Notes

Testing

Derived from a working k3s deployment (this stack ran BugStone Acts 1 & 2 end-to-end). --dry-run renders valid manifests for both default-storage and --storage-class ibm-scale-csi; bash -n clean.

@pdettori pdettori left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Purely additive PR (two new files: setup-k8s.sh + README-k8s.md) adding a generic-Kubernetes install path that sits between setup-kind.sh and setup-ocp.sh. Nicely structured: reuses the shared base manifests via runtime sed substitution (no forked YAMLs), set -euo pipefail, logs to stderr so --dry-run emits clean pipeable YAML, and mirrors the sibling scripts' shape. All CI green (shellcheck, hadolint, DCO, Trivy, CodeQL).

One functional break (blocking) and one portability suggestion below.

Author: moonlight16 (MEMBER — maintainer)
Areas reviewed: Shell, YAML/manifests, Docs
Commits: 2, all signed-off
CI: all passing


must-fix — kubectl set env on a Knative Service

Step 7 sets the model env with kubectl set env ksvc/serverless-harness. set env only supports built-in workload types; on the Knative Service CRD it fails with no kind "Service" registered for serving.knative.dev/v1. Under set -euo pipefail this aborts the script at its final step whenever SH_MODEL or SH_MODEL_CUSTOM is set — which is exactly the "Choosing the model" / self-hosted-endpoint path the README documents. Both setup-kind.sh and setup-ocp.sh avoid this by using kubectl patch ksvc --type merge.

suggestion — non-portable \n in the --storage-class sed

The storage-class injection relies on \n in the sed replacement, which only expands to a newline under GNU sed. On BSD/macOS sed it becomes a literal n and corrupts the YAML. Since --storage-class ibm-scale-csi is a headline feature and this script commonly runs from a workstation, a portable insertion would be safer. Default-storage path is unaffected.

Assisted-By: Claude Code

Comment thread deploy/knative/setup-k8s.sh Outdated
ENV_SETS=()
[ -n "${SH_MODEL:-}" ] && ENV_SETS+=("SH_MODEL=${SH_MODEL}")
[ -n "${SH_MODEL_CUSTOM:-}" ] && ENV_SETS+=("SH_MODEL_CUSTOM=${SH_MODEL_CUSTOM}")
[ "${#ENV_SETS[@]}" -gt 0 ] && "${KUBECTL[@]}" -n "$NAMESPACE" set env ksvc/serverless-harness "${ENV_SETS[@]}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must-fix: kubectl set env ksvc/... fails on the Knative Service CRD — set env only supports built-in workload types, and on a ksvc it errors with no kind "Service" registered for serving.knative.dev/v1. Because of set -euo pipefail, this aborts the whole script at the final step whenever SH_MODEL/SH_MODEL_CUSTOM is set — precisely the "Choosing the model" path the README documents.

Both siblings use kubectl patch ksvc --type merge instead. Two clean fixes:

  • SH_MODEL is already a literal env in service.yaml, so substitute it in render_base() alongside the image/namespace subs.
  • For SH_MODEL_CUSTOM (not in service.yaml), use a JSON-patch replace on /spec/template/spec/containers/0/env that upserts by name and preserves the ANTHROPIC_* secretKeyRefs — a plain merge-patch would drop them.

Comment thread deploy/knative/setup-k8s.sh Outdated
| if [ -n "$STORAGE_CLASS" ]; then
# Insert storageClassName above accessModes in each volumeClaimTemplate PVC spec
# (only the sandbox pool has these). Preserves the existing 8-space indent.
sed -e "s#^\( *\)accessModes: \[\"ReadWriteOnce\"\]#\1storageClassName: ${STORAGE_CLASS}\n\1accessModes: [\"ReadWriteOnce\"]#g"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: the \n in this sed replacement only expands to a newline under GNU sed. On BSD/macOS sed it inserts a literal n, producing malformed YAML (storageClassName: ibm-scale-csinaccessModes: ["ReadWriteOnce"]). Since this script typically runs from a workstation targeting a remote cluster and --storage-class ibm-scale-csi (GPFS) is a headline feature, consider a portable insertion (e.g. awk, or a printf-built newline). The default-storage path is unaffected.

The repo has setup-kind.sh (local Kind) and setup-ocp.sh (OpenShift) but no path
for a vanilla Kubernetes cluster (k3s, EKS, GKE, on-prem, ...): setup-kind.sh
assumes single-node Kind and builds+kind-loads the image; setup-ocp.sh assumes
OpenShift OLM operators and auto-created Routes. Neither fits a generic cluster.

Add setup-k8s.sh installing the same stack (Knative Serving + Kourier, agent-sandbox
controller, Redis, sandbox pool, LLM secret, harness ksvc) on any Kubernetes cluster,
reusing the shared base manifests with cluster-specifics injected via flags (mirrors
setup-ocp.sh's render_overlay_dir sed approach — no forked YAMLs). Plus README-k8s.md.

Knobs: --namespace, --image/--sandbox-image (prebuilt refs; any registry incl.
in-cluster), --storage-class (default: cluster default; e.g. ibm-scale-csi for GPFS),
--ingress none|nodeport, --with-keda, --context, --dry-run. Model via
SH_MODEL/SH_MODEL_CUSTOM. Logs go to stderr so --dry-run stdout is clean YAML.

Purely additive: two new files, no changes to existing scripts or manifests.
Derived from a working k3s deployment (ran BugStone Acts 1 & 2 end-to-end).

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Jeremy Cohn <Jeremy.Cohn@ibm.com>
Double-quote ${KUBECTL[@]} in the startup log line to avoid word re-splitting,
per the repo's shellcheck CI (SC2068).

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Jeremy Cohn <Jeremy.Cohn@ibm.com>
Address review feedback from pdettori on kagenti#142:

- kubectl set env does not work on a Knative Service (not a built-in
  workload kind recognized by that subcommand), so setting SH_MODEL or
  SH_MODEL_CUSTOM aborted the whole script under set -euo pipefail.
  Fix: inject both declaratively into service.yaml via render_base(),
  matching how every other cluster-specific value is already handled.

- The --storage-class insertion used sed's \n in a replacement string,
  which only expands to a newline under GNU sed; on BSD/macOS sed it
  inserts a literal 'n', producing malformed YAML. Fix: use awk with
  match()/substr() for indent-preserving line insertion instead.

Validated via --dry-run across the custom-model+GPFS path, the
SH_MODEL-only path, the default (no-flags) path, and namespace+storage-
class combined — all render valid YAML with correct substitutions and
no cross-contamination between flags.

Assisted-By: Claude (Anthropic AI) <noreply@anthropic.com>
Signed-off-by: Jeremy Cohn <Jeremy.Cohn@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants