Apply rail-knative's declared Knative CPU requests in the installer (RAIL-BS-WP-0015).
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 8s

install.sh now renders the checksum-verified upstream assets through kustomize
overlays: CRDs first and verbatim, then serving-core and kourier with the six
CPU requests lowered live on 2026-09-21, the Kourier Service as ClusterIP and
the Envoy image pinned. verify.sh checks the requests read-only, and
tests/test_knative_render.py proves the render offline against upstream and
rail-knative's declaration. Not run against the cluster.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 63291@bnt-lap001
Assistant-Session: 8bd77868-ca68-4f49-bb1e-d539ecc0d703
This commit is contained in:
codex 2026-09-21 18:45:47 +02:00
parent 4abd781ce3
commit 3a5432270e
11 changed files with 465 additions and 16 deletions

View file

@ -2,7 +2,20 @@
`install.sh` verifies repository-pinned SHA-256 checksums for the upstream
Serving and Kourier v1.22.0 assets before applying them over SSH. It is
idempotent. Kourier is kept `ClusterIP`; public entry through Traefik, DNS, and
idempotent.
It does not apply the upstream manifests as published. `render.sh` (also
usable on its own, with no cluster contact) renders them through the kustomize
overlays in `overlays/`: CRDs verbatim and first, because `serving-core.yaml`
repeats one of them; then serving-core and kourier with the CPU requests that
rail-knative declares in `substrate/v1.22.0/cpu-requests.patch.yaml`
(activator 50m, autoscaler/controller/webhook/net-kourier-controller 30m,
3scale-kourier-gateway 50m), the Kourier Service as `ClusterIP` and the Envoy
gateway image pinned to `ENVOY_IMAGE`. Memory requests and all limits stay
upstream. Applying the unpatched upstream files restores 300m/200m/100m and
exhausts railiance01's CPU requests again. `tests/test_knative_render.py`
proves the render offline and fails if these overlays drift from rail-knative's
declaration. `install.sh` needs a local `kubectl` for `kubectl kustomize`. Kourier is kept `ClusterIP`; public entry through Traefik, DNS, and
TLS requires separate reef admission evidence.
The installer enables only Knative's
@ -10,7 +23,8 @@ The installer enables only Knative's
containers for fail-closed admission checks such as verifying that egress
policy has reconciled before application code starts.
Run `install.sh railiance01`, then `verify.sh railiance01`.
Run `install.sh railiance01`, then `verify.sh railiance01`; `verify.sh` is
read-only and also checks the six CPU requests and the Envoy pin.
Before workload admission, rollback deletes Kourier, Serving core, then CRDs
using the same verified assets. After Knative Services exist, removal requires

View file

@ -1,25 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail
root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$root/release-lock.env"
target="${1:-railiance01}"
stage="$(mktemp -d)"
trap 'rm -rf "$stage"' EXIT
download() {
curl -fsSL --retry 3 "$1" -o "$2"
printf '%s %s\n' "$3" "$2" | sha256sum --check --status
}
serving="https://github.com/knative/serving/releases/download/knative-v${KNATIVE_VERSION}"
kourier="https://github.com/knative-extensions/net-kourier/releases/download/knative-v${KNATIVE_VERSION}"
download "$serving/serving-crds.yaml" "$stage/crds.yaml" "$SERVING_CRDS_SHA256"
download "$serving/serving-core.yaml" "$stage/core.yaml" "$SERVING_CORE_SHA256"
download "$kourier/kourier.yaml" "$stage/kourier.yaml" "$KOURIER_SHA256"
# Checksum-verified upstream assets, rendered with the declared CPU requests
# (rail-knative substrate/v1.22.0), Kourier ClusterIP and the Envoy pin.
"$root/render.sh" "$stage"
# CRDs first and separately: serving-core.yaml repeats one of them.
ssh "$target" kubectl apply -f - < "$stage/crds.yaml"
ssh "$target" kubectl apply -f - < "$stage/core.yaml"
ssh "$target" kubectl apply -f - < "$stage/serving-core.rendered.yaml"
ssh "$target" kubectl wait --for=condition=Available deployment --all -n knative-serving --timeout=300s
ssh "$target" kubectl apply -f - < "$stage/kourier.yaml"
ssh "$target" kubectl set image deployment/3scale-kourier-gateway -n kourier-system "kourier-gateway=$ENVOY_IMAGE"
ssh "$target" kubectl apply -f - < "$stage/kourier.rendered.yaml"
ssh "$target" kubectl patch configmap/config-network -n knative-serving --type merge -p '{"data":{"ingress-class":"kourier.ingress.networking.knative.dev"}}'
ssh "$target" kubectl patch configmap/config-features -n knative-serving --type merge -p '{"data":{"kubernetes.podspec-init-containers":"enabled"}}'
ssh "$target" kubectl patch service/kourier -n kourier-system --type merge -p '{"spec":{"type":"ClusterIP"}}'
ssh "$target" kubectl wait --for=condition=Available deployment --all -n kourier-system --timeout=300s

View file

@ -0,0 +1,36 @@
# CPU requests declared by rail-knative (substrate/v1.22.0/cpu-requests.patch.yaml),
# the documents of that file that target kourier.yaml. Only CPU requests are set;
# memory requests and all limits stay upstream. Live on railiance01 since
# 2026-09-21 (ADMINISTER @ realm:kubernetes/railiance01, activation=APPROVED by
# the founder). Keep in step with rail-knative: tests/test_knative_render.py
# fails if the two declarations disagree.
---
# upstream v1.22.0 request: 200m
apiVersion: apps/v1
kind: Deployment
metadata:
name: net-kourier-controller
namespace: knative-serving
spec:
template:
spec:
containers:
- name: controller
resources:
requests:
cpu: 30m
---
# upstream v1.22.0 request: 200m
apiVersion: apps/v1
kind: Deployment
metadata:
name: 3scale-kourier-gateway
namespace: kourier-system
spec:
template:
spec:
containers:
- name: kourier-gateway
resources:
requests:
cpu: 50m

View file

@ -0,0 +1,10 @@
# Overlay over the checksum-verified upstream kourier.yaml, which render.sh
# stages next to this file as upstream.yaml. render.sh appends the `images:`
# pin for the Envoy gateway from ENVOY_IMAGE in release-lock.env.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- upstream.yaml
patches:
- path: cpu-requests.patch.yaml
- path: service-clusterip.patch.yaml

View file

@ -0,0 +1,10 @@
# Kourier stays ClusterIP; public entry needs separate reef admission evidence.
# Declared here rather than patched after apply, so a re-run never flips the
# live Service to the upstream LoadBalancer type, even briefly.
apiVersion: v1
kind: Service
metadata:
name: kourier
namespace: kourier-system
spec:
type: ClusterIP

View file

@ -0,0 +1,66 @@
# CPU requests declared by rail-knative (substrate/v1.22.0/cpu-requests.patch.yaml),
# the documents of that file that target serving-core.yaml. Only CPU requests are set;
# memory requests and all limits stay upstream. Live on railiance01 since
# 2026-09-21 (ADMINISTER @ realm:kubernetes/railiance01, activation=APPROVED by
# the founder). Keep in step with rail-knative: tests/test_knative_render.py
# fails if the two declarations disagree.
---
# upstream v1.22.0 request: 300m
apiVersion: apps/v1
kind: Deployment
metadata:
name: activator
namespace: knative-serving
spec:
template:
spec:
containers:
- name: activator
resources:
requests:
cpu: 50m
---
# upstream v1.22.0 request: 100m
apiVersion: apps/v1
kind: Deployment
metadata:
name: autoscaler
namespace: knative-serving
spec:
template:
spec:
containers:
- name: autoscaler
resources:
requests:
cpu: 30m
---
# upstream v1.22.0 request: 100m
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller
namespace: knative-serving
spec:
template:
spec:
containers:
- name: controller
resources:
requests:
cpu: 30m
---
# upstream v1.22.0 request: 100m
apiVersion: apps/v1
kind: Deployment
metadata:
name: webhook
namespace: knative-serving
spec:
template:
spec:
containers:
- name: webhook
resources:
requests:
cpu: 30m

View file

@ -0,0 +1,9 @@
# Overlay over the checksum-verified upstream serving-core.yaml, which render.sh
# stages next to this file as upstream.yaml. Do not add the CRDs here: core.yaml
# repeats one of them, so they are applied separately and first.
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- upstream.yaml
patches:
- path: cpu-requests.patch.yaml

42
install/knative/render.sh Executable file
View file

@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Render exactly what install.sh applies, without touching any cluster.
# render.sh <stage-dir>
# Downloads the upstream v1.22.0 assets (reusing files already in <stage-dir>
# only when their pinned SHA-256 matches), verifies every checksum, and writes:
# <stage-dir>/crds.yaml upstream CRDs, verbatim (applied first)
# <stage-dir>/serving-core.rendered.yaml serving-core + declared CPU requests
# <stage-dir>/kourier.rendered.yaml kourier + CPU requests, ClusterIP, Envoy pin
# Needs curl, sha256sum and a local kubectl with built-in kustomize.
set -euo pipefail
root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$root/release-lock.env"
stage="${1:?usage: render.sh <stage-dir>}"
mkdir -p "$stage"
fetch() {
local url="$1" out="$2" sum="$3"
if ! printf '%s %s\n' "$sum" "$out" | sha256sum --check --status 2>/dev/null; then
curl -fsSL --retry 3 "$url" -o "$out"
printf '%s %s\n' "$sum" "$out" | sha256sum --check --status \
|| { echo "checksum mismatch: $url" >&2; rm -f "$out"; exit 1; }
fi
}
serving="https://github.com/knative/serving/releases/download/knative-v${KNATIVE_VERSION}"
kourier="https://github.com/knative-extensions/net-kourier/releases/download/knative-v${KNATIVE_VERSION}"
fetch "$serving/serving-crds.yaml" "$stage/crds.yaml" "$SERVING_CRDS_SHA256"
fetch "$serving/serving-core.yaml" "$stage/core.yaml" "$SERVING_CORE_SHA256"
fetch "$kourier/kourier.yaml" "$stage/kourier.yaml" "$KOURIER_SHA256"
build() {
local overlay="$1" asset="$2" out="$3" dir="$stage/overlay-$1"
rm -rf "$dir"
cp -r "$root/overlays/$overlay" "$dir"
cp "$stage/$asset" "$dir/upstream.yaml"
if [ "$overlay" = kourier ]; then
printf 'images:\n - name: docker.io/envoyproxy/envoy\n newName: %s\n digest: %s\n' \
"${ENVOY_IMAGE%@*}" "${ENVOY_IMAGE#*@}" >> "$dir/kustomization.yaml"
fi
kubectl kustomize "$dir" > "$stage/$out"
}
build serving-core core.yaml serving-core.rendered.yaml
build kourier kourier.yaml kourier.rendered.yaml

View file

@ -1,10 +1,28 @@
#!/usr/bin/env bash
# Read-only checks of the installed Knative substrate.
set -euo pipefail
root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$root/release-lock.env"
target="${1:-railiance01}"
ssh "$target" 'set -e
test "$(kubectl get namespace knative-serving -o go-template="{{index .metadata.labels \"app.kubernetes.io/version\"}}")" = "1.22.0"
test "$(kubectl get service kourier -n kourier-system -o jsonpath="{.spec.type}")" = "ClusterIP"
test "$(kubectl get configmap config-network -n knative-serving -o jsonpath="{.data.ingress-class}")" = "kourier.ingress.networking.knative.dev"
test "$(kubectl get configmap config-features -n knative-serving -o jsonpath="{.data.kubernetes\\.podspec-init-containers}")" = "enabled"
test "$(kubectl get deployment 3scale-kourier-gateway -n kourier-system -o jsonpath="{.spec.template.spec.containers[?(@.name==\"kourier-gateway\")].image}")" = "'"$ENVOY_IMAGE"'"
kubectl wait --for=condition=Available deployment --all -n knative-serving --timeout=120s
kubectl wait --for=condition=Available deployment --all -n kourier-system --timeout=120s'
# Declared CPU requests (rail-knative substrate/v1.22.0/cpu-requests.patch.yaml).
while read -r ns deploy container cpu; do
got="$(ssh "$target" kubectl get deployment "$deploy" -n "$ns" \
-o "jsonpath={.spec.template.spec.containers[?(@.name==\"$container\")].resources.requests.cpu}")"
[ "$got" = "$cpu" ] || { echo "cpu request $ns/$deploy/$container: want $cpu, got ${got:-<none>}" >&2; exit 1; }
done <<'LIST'
knative-serving activator activator 50m
knative-serving autoscaler autoscaler 30m
knative-serving controller controller 30m
knative-serving webhook webhook 30m
knative-serving net-kourier-controller controller 30m
kourier-system 3scale-kourier-gateway kourier-gateway 50m
LIST
echo "knative substrate verified"