From d05efc9cf0c330c52e785cfaf8e1e43c442df8a9 Mon Sep 17 00:00:00 2001 From: Andrew Mello Date: Thu, 29 Oct 2026 04:32:39 -0700 Subject: [PATCH 1/5] k8s: Node Feature Discovery v0.20.1 and agent-sandbox v1.0.8 Both were the newest releases on 2026-10-29 (GitHub releases, and the use-latest-version registry check), and each image is pinned to the index digest docker buildx imagetools resolves. - Node Feature Discovery v0.19.0 -> v0.20.1. It carries the GO-2026-6809 x509 fix and is built against the Kubernetes 1.37 libraries; its notes list no public API change. share/node-feature-discovery.yml is re-rendered with kubectl kustomize from v0.20.1's default overlay plus Intel's NodeFeatureRules v0.37.1, with the same patches and worker config (the header's kustomization reproduces the committed v0.19.0 body byte for byte before the bump). The body changes only in CRD descriptions, one master config comment, the config map's hash suffix and the image. NFD's default cpuid blacklist and its klauspost/cpuid (v2.4.0) are unchanged, so the launcher's label list stands. Image sha256:6fc5c9af...8379. - agent-sandbox v1.0.7 -> v1.0.8. The release file (sha256 e68bfae0...) adds only the optional failedPodPolicy field (default Retain) and the controller's new tag. The controller and the python runtime are re-pinned. The release's action items (the MCP output cap and the router kustomization) do not apply: k3d-gpu installs neither. Goldens: the audit goldens and fixtures name the new NFD tag and digest (the lock still holds 52 images), the remote sandbox golden names v1.0.8, and the lock-drift case edits the v0.20.1 pin. Checked on throwaway k3d clusters (rancher/k3s v1.37.1-k3s1 at the Dockerfile's digest, the manifest in the server's manifests directory, as the image bakes it): the three NFD pods run the v0.20.1 digest, Ready with no restarts, and publish the same 70 feature labels, keys and values, as v0.19.0 on the same node, both fresh and after an in-place upgrade from v0.19.0. `k3d-gpu sandbox up` from this tree brought up the v1.0.8 controller and a ready warm pool; a SandboxClaim adopted it and POST /execute answered. --- README.md | 6 ++-- images.lock | 12 +++---- scripts/k3d-gpu | 2 +- share/agent-sandbox-k3d.yml | 4 +-- share/agent-sandbox.yml | 22 ++++++++++--- share/node-feature-discovery.yml | 31 +++++++++++-------- tests/audit_test.sh | 2 +- tests/console/audit/chat-ui-noauth.golden | 2 +- tests/console/audit/chat-ui.golden | 2 +- tests/console/audit/default-json.golden | 4 +-- tests/console/audit/default.golden | 2 +- tests/console/audit/default.observed.json | 4 +-- .../default/crictl-k3d-gpu-server-0.json | 4 +-- tests/console/audit/image-digest-moved.golden | 2 +- tests/console/audit/image-no-digest.golden | 2 +- tests/console/audit/image-not-in-lock.golden | 2 +- tests/console/audit/ipv6-unauth.golden | 2 +- tests/console/audit/ipv6-unauth.observed.json | 4 +-- tests/console/audit/kubeconfig-0644.golden | 2 +- tests/console/audit/loopback-published.golden | 2 +- tests/console/audit/runtime-fetch.golden | 2 +- .../console/audit/runtime-fetch.observed.json | 4 +-- tests/console/audit/runtime-pull.golden | 2 +- tests/console/audit/unauth-published.golden | 2 +- tests/detect_test.sh | 4 +-- tests/remote/sandbox.golden | 4 +-- 26 files changed, 74 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index f2eb977d..4cfe8da4 100644 --- a/README.md +++ b/README.md @@ -713,7 +713,7 @@ documents GPU support for NVIDIA only. ### Node Feature Discovery Every cluster also runs [Node Feature Discovery](https://github.com/kubernetes-sigs/node-feature-discovery) -v0.19.0 with Intel's +v0.20.1 with Intel's [NodeFeatureRules](https://github.com/intel/intel-device-plugins-for-kubernetes/tree/v0.37.1/deployments/nfd/overlays/node-feature-rules) v0.37.1, baked into the image (namespace `node-feature-discovery`). About 30 s after `up`, nodes carry the host's CPU, kernel and PCI features. On an @@ -1485,7 +1485,7 @@ not switch the Intel GPU path. ### Agent sandboxes on E-cores `k3d-gpu sandbox up` installs [kubernetes-sigs/agent-sandbox](https://github.com/kubernetes-sigs/agent-sandbox) -v1.0.7 (controller image pinned by digest) and a `python-ecores` SandboxTemplate +v1.0.8 (controller image pinned by digest) and a `python-ecores` SandboxTemplate plus a one-replica warm pool in namespace `agent-sandbox`. Sandbox pods carry `k3d-gpu.io/cores: efficient` and request one CPU, so on a hybrid host untrusted agent tool execution runs on E-cores, apart from the P-cores that serve inference. @@ -1506,7 +1506,7 @@ EOF ``` The sandbox serves `POST /execute {"command": "..."}` on port 8888 -(`registry.k8s.io/agent-sandbox/python-runtime-sandbox:v1.0.7`, pinned by digest). +(`registry.k8s.io/agent-sandbox/python-runtime-sandbox:v1.0.8`, pinned by digest). What works on k3d, and what does not: diff --git a/images.lock b/images.lock index 3c46ff8c..6d9535a5 100644 --- a/images.lock +++ b/images.lock @@ -388,28 +388,28 @@ "tag": "v3.15.0" }, { - "digest": "sha256:f254384c24605436ce35d7077427559e24bda8f5691cff5a54a4c2e030d81083", + "digest": "sha256:e1d96312487eba7d8f001e848a9d4e644b7deea8c2a4564ccc318abb729be731", "name": "registry.k8s.io/agent-sandbox/agent-sandbox-controller", "sources": [ "share/agent-sandbox.yml" ], - "tag": "v1.0.7" + "tag": "v1.0.8" }, { - "digest": "sha256:fc92654c97fe5dff2a7935a845820981026c075d0c1014e5c2c569f5e58204f1", + "digest": "sha256:41da84809426098cb04cdafbb41855f15e3604f7455ef53816bad666e532e787", "name": "registry.k8s.io/agent-sandbox/python-runtime-sandbox", "sources": [ "share/agent-sandbox-k3d.yml" ], - "tag": "v1.0.7" + "tag": "v1.0.8" }, { - "digest": "sha256:2fa1c99ad09bdf2c8ad97706a4ad2fd548c84d5ecd70ba32a6152c667b96c4d2", + "digest": "sha256:6fc5c9af9176e1acb5ce57a4a1d0c0d3eb25cd34f5bdd0efefebf0efe45a8379", "name": "registry.k8s.io/nfd/node-feature-discovery", "sources": [ "share/node-feature-discovery.yml" ], - "tag": "v0.19.0" + "tag": "v0.20.1" }, { "digest": "sha256:5d064465d751a73a729e7ecdc32c0ba5de0df1d305debb60a3d9a85b4fd3a967", diff --git a/scripts/k3d-gpu b/scripts/k3d-gpu index 4ed9751e..50cd1711 100755 --- a/scripts/k3d-gpu +++ b/scripts/k3d-gpu @@ -6518,7 +6518,7 @@ cmd_logs() { # The profile labels them k3d-gpu.io/cores=efficient, so on a hybrid CPU the balloons # policy keeps them on E-cores, apart from P-core inference. That is placement, not # isolation: package power, LLC and DRAM bandwidth stay shared (EXPERIMENTS.md H3, H5). -SANDBOX_VERSION="v1.0.7" +SANDBOX_VERSION="v1.0.8" SANDBOX_NS="agent-sandbox" SANDBOX_POOL="python-ecores" SANDBOX_CRDS=( diff --git a/share/agent-sandbox-k3d.yml b/share/agent-sandbox-k3d.yml index 7b869650..23e30bd9 100644 --- a/share/agent-sandbox-k3d.yml +++ b/share/agent-sandbox-k3d.yml @@ -1,4 +1,4 @@ -# k3d-gpu sandbox profile for kubernetes-sigs/agent-sandbox v1.0.7 (share/agent-sandbox.yml). +# k3d-gpu sandbox profile for kubernetes-sigs/agent-sandbox v1.0.8 (share/agent-sandbox.yml). # Applied by `k3d-gpu sandbox up` once the controller and its CRDs are ready. # # Untrusted agent tool execution runs on E-cores: the pod label k3d-gpu.io/cores=efficient @@ -104,7 +104,7 @@ spec: type: RuntimeDefault containers: - name: python - image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v1.0.7@sha256:fc92654c97fe5dff2a7935a845820981026c075d0c1014e5c2c569f5e58204f1 + image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v1.0.8@sha256:41da84809426098cb04cdafbb41855f15e3604f7455ef53816bad666e532e787 env: - name: HOME value: /tmp diff --git a/share/agent-sandbox.yml b/share/agent-sandbox.yml index c625e922..b0ef834d 100644 --- a/share/agent-sandbox.yml +++ b/share/agent-sandbox.yml @@ -1,9 +1,9 @@ -# kubernetes-sigs/agent-sandbox v1.0.7: controller + extensions (Sandbox, SandboxTemplate, +# kubernetes-sigs/agent-sandbox v1.0.8: controller + extensions (Sandbox, SandboxTemplate, # SandboxClaim, SandboxWarmPool), installed by `k3d-gpu sandbox up`. Not baked into the node image. -# Source: https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v1.0.7/sandbox-with-extensions.yaml -# sha256 136c10c9347cb5a6740b351444cae82f404e883c3f520272257ba785f2af0da8 (as released) +# Source: https://github.com/kubernetes-sigs/agent-sandbox/releases/download/v1.0.8/sandbox-with-extensions.yaml +# sha256 e68bfae0bd9b6ff717745a4be04bcc909594ba32011b6a0891b77c4d7b5bf58a (as released) # One change from the release file: the controller image is pinned by digest -# (registry.k8s.io multi-arch index for :v1.0.7). Re-download and re-pin to bump. +# (registry.k8s.io multi-arch index for :v1.0.8). Re-download and re-pin to bump. apiVersion: v1 kind: Namespace metadata: @@ -310,6 +310,12 @@ spec: type: object spec: properties: + failedPodPolicy: + default: Retain + enum: + - Retain + - Recreate + type: string operatingMode: default: Running enum: @@ -4461,6 +4467,12 @@ spec: - Overrides - Disallowed type: string + failedPodPolicy: + default: Retain + enum: + - Retain + - Recreate + type: string networkPolicy: properties: egress: @@ -9008,7 +9020,7 @@ spec: - args: - --leader-elect=true - --extensions - image: registry.k8s.io/agent-sandbox/agent-sandbox-controller:v1.0.7@sha256:f254384c24605436ce35d7077427559e24bda8f5691cff5a54a4c2e030d81083 + image: registry.k8s.io/agent-sandbox/agent-sandbox-controller:v1.0.8@sha256:e1d96312487eba7d8f001e848a9d4e644b7deea8c2a4564ccc318abb729be731 name: agent-sandbox-controller ports: - containerPort: 8080 diff --git a/share/node-feature-discovery.yml b/share/node-feature-discovery.yml index 1548ab8b..5e950ea1 100644 --- a/share/node-feature-discovery.yml +++ b/share/node-feature-discovery.yml @@ -1,8 +1,8 @@ -# Node Feature Discovery v0.19.0 + Intel device-plugin NodeFeatureRules v0.37.1 +# Node Feature Discovery v0.20.1 + Intel device-plugin NodeFeatureRules v0.37.1 # Sources (pinned): -# https://github.com/kubernetes-sigs/node-feature-discovery/tree/v0.19.0/deployment/overlays/default +# https://github.com/kubernetes-sigs/node-feature-discovery/tree/v0.20.1/deployment/overlays/default # https://github.com/intel/intel-device-plugins-for-kubernetes/tree/v0.37.1/deployments/nfd/overlays/node-feature-rules -# image registry.k8s.io/nfd/node-feature-discovery:v0.19.0, pinned to its multi-arch index digest +# image registry.k8s.io/nfd/node-feature-discovery:v0.20.1, pinned to its multi-arch index digest # Rendered with `kubectl kustomize` over the kustomization below (the two upstream # trees unpacked from their release tarballs next to it). Re-render to bump. # @@ -25,11 +25,11 @@ # # kustomization.yaml: # resources: -# - node-feature-discovery-0.19.0/deployment/overlays/default +# - node-feature-discovery-0.20.1/deployment/overlays/default # - intel-device-plugins-for-kubernetes-0.37.1/deployments/nfd/overlays/node-feature-rules # images: # - name: registry.k8s.io/nfd/node-feature-discovery -# newTag: v0.19.0@sha256:2fa1c99ad09bdf2c8ad97706a4ad2fd548c84d5ecd70ba32a6152c667b96c4d2 +# newTag: v0.20.1@sha256:6fc5c9af9176e1acb5ce57a4a1d0c0d3eb25cd34f5bdd0efefebf0efe45a8379 # patches: # - target: {kind: DaemonSet, name: nfd-worker} # patch: |- @@ -89,7 +89,10 @@ spec: - name: v1alpha1 schema: openAPIV3Schema: - description: NodeFeatureGroup resource holds Node pools by featureGroup + description: |- + NodeFeatureGroup resource holds Node pools by featureGroup. + NodeFeatureGroup is namespaced (short name `nfg`) and has a status subresource. + Only objects in the namespace of nfd-master are processed. properties: apiVersion: description: |- @@ -365,6 +368,8 @@ spec: description: Nodes is a list of FeatureGroupNode in the cluster that match the featureGroupRules items: + description: FeatureGroupNode is a node that matches the rules of + a NodeFeatureGroup. properties: name: description: Name of the node. @@ -408,6 +413,7 @@ spec: description: |- NodeFeatureRule resource specifies a configuration for feature-based customization of node objects, such as node labeling. + NodeFeatureRule is cluster-scoped (short name `nfr`). properties: apiVersion: description: |- @@ -756,6 +762,7 @@ spec: description: |- NodeFeature resource holds the features discovered for one node in the cluster. + NodeFeature is namespaced. properties: apiVersion: description: |- @@ -1053,8 +1060,6 @@ data: # stderrthreshold: 2 # v: 0 # vmodule: - ## NOTE: the following options are not dynamically run-time configurable - ## and require a nfd-master restart to take effect after being changed # logDir: # logFile: # logFileMaxSize: 1800 @@ -1068,7 +1073,7 @@ data: # nfdApiParallelism: 10 kind: ConfigMap metadata: - name: nfd-master-conf-8kb68dgffh + name: nfd-master-conf-m6k266ccbh namespace: node-feature-discovery --- apiVersion: v1 @@ -1115,7 +1120,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.uid - image: registry.k8s.io/nfd/node-feature-discovery:v0.19.0@sha256:2fa1c99ad09bdf2c8ad97706a4ad2fd548c84d5ecd70ba32a6152c667b96c4d2 + image: registry.k8s.io/nfd/node-feature-discovery:v0.20.1@sha256:6fc5c9af9176e1acb5ce57a4a1d0c0d3eb25cd34f5bdd0efefebf0efe45a8379 imagePullPolicy: IfNotPresent livenessProbe: httpGet: @@ -1190,7 +1195,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.uid - image: registry.k8s.io/nfd/node-feature-discovery:v0.19.0@sha256:2fa1c99ad09bdf2c8ad97706a4ad2fd548c84d5ecd70ba32a6152c667b96c4d2 + image: registry.k8s.io/nfd/node-feature-discovery:v0.20.1@sha256:6fc5c9af9176e1acb5ce57a4a1d0c0d3eb25cd34f5bdd0efefebf0efe45a8379 imagePullPolicy: IfNotPresent livenessProbe: httpGet: @@ -1231,7 +1236,7 @@ spec: value: "" volumes: - configMap: - name: nfd-master-conf-8kb68dgffh + name: nfd-master-conf-m6k266ccbh name: nfd-master-conf --- apiVersion: apps/v1 @@ -1266,7 +1271,7 @@ spec: valueFrom: fieldRef: fieldPath: metadata.uid - image: registry.k8s.io/nfd/node-feature-discovery:v0.19.0@sha256:2fa1c99ad09bdf2c8ad97706a4ad2fd548c84d5ecd70ba32a6152c667b96c4d2 + image: registry.k8s.io/nfd/node-feature-discovery:v0.20.1@sha256:6fc5c9af9176e1acb5ce57a4a1d0c0d3eb25cd34f5bdd0efefebf0efe45a8379 imagePullPolicy: IfNotPresent livenessProbe: httpGet: diff --git a/tests/audit_test.sh b/tests/audit_test.sh index 77070367..b6d4a900 100755 --- a/tests/audit_test.sh +++ b/tests/audit_test.sh @@ -85,7 +85,7 @@ lock_drift "a bumped plain image pin in the launcher" \ lock_drift "a moved backend digest in the launcher" "vllm/vllm-openai-xpu: the repo pins sha256:$(printf 'e%.0s' {1..64})" \ "sed -i 's|vllm/vllm-openai-xpu@sha256:[0-9a-f]*|vllm/vllm-openai-xpu@sha256:$(printf 'e%.0s' {1..64})|' scripts/k3d-gpu" lock_drift "a changed pinned digest" "the repo pins sha256:$(printf 'f%.0s' {1..64})" \ - "sed -i 's/node-feature-discovery:v0.19.0@sha256:[0-9a-f]*/node-feature-discovery:v0.19.0@sha256:$(printf 'f%.0s' {1..64})/' share/node-feature-discovery.yml" + "sed -i 's/node-feature-discovery:v0.20.1@sha256:[0-9a-f]*/node-feature-discovery:v0.20.1@sha256:$(printf 'f%.0s' {1..64})/' share/node-feature-discovery.yml" lock_drift "a k3s bump" "images.lock is for k3s v1.37.1-k3s1, the Dockerfile pins v1.38.0-k3s1" \ "sed -i 's/^ARG K3S_TAG=.*/ARG K3S_TAG=\"v1.38.0-k3s1\"/' Dockerfile" lock_drift "a bumped test image" "not in images.lock: docker.io/nvidia/cuda:13.5.0-base-ubuntu26.04" \ diff --git a/tests/console/audit/chat-ui-noauth.golden b/tests/console/audit/chat-ui-noauth.golden index 0cfc1a94..1bfa9656 100644 --- a/tests/console/audit/chat-ui-noauth.golden +++ b/tests/console/audit/chat-ui-noauth.golden @@ -8,7 +8,7 @@ ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 ok image ghcr.io/open-webui/open-webui@sha256:10e6a78ba2d172493460a9e8a92c496aaa7a64dc4d26d622a2e95e0c736081c9: sha256:10e6a78ba2d1 in images.lock (share/agent-chat-ui.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 ok secret /stub/chat-ui-noauth/kubeconfig: mode 0600 FAIL app open-webui k3d-gpu-agent/deployment/open-webui: sign-in off (WEBUI_AUTH=False); a no-auth Open WebUI cannot later switch to accounts fix: set WEBUI_AUTH to "True" as share/agent-chat-ui.yml does diff --git a/tests/console/audit/chat-ui.golden b/tests/console/audit/chat-ui.golden index 77836e56..261bb113 100644 --- a/tests/console/audit/chat-ui.golden +++ b/tests/console/audit/chat-ui.golden @@ -8,7 +8,7 @@ ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 ok image ghcr.io/open-webui/open-webui@sha256:10e6a78ba2d172493460a9e8a92c496aaa7a64dc4d26d622a2e95e0c736081c9: sha256:10e6a78ba2d1 in images.lock (share/agent-chat-ui.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 ok secret /stub/chat-ui/kubeconfig: mode 0600 ok app open-webui k3d-gpu-agent/deployment/open-webui: sign-in on (WEBUI_AUTH) exit=0 diff --git a/tests/console/audit/default-json.golden b/tests/console/audit/default-json.golden index de4415d1..5d424772 100644 --- a/tests/console/audit/default-json.golden +++ b/tests/console/audit/default-json.golden @@ -57,11 +57,11 @@ "subject": "ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0" }, { - "detail": "sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0", + "detail": "sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0", "fix": null, "rule": "image", "status": "pass", - "subject": "registry.k8s.io/nfd/node-feature-discovery:v0.19.0" + "subject": "registry.k8s.io/nfd/node-feature-discovery:v0.20.1" }, { "detail": "mode 0600", diff --git a/tests/console/audit/default.golden b/tests/console/audit/default.golden index 5c56d5be..36e179bf 100644 --- a/tests/console/audit/default.golden +++ b/tests/console/audit/default.golden @@ -7,6 +7,6 @@ ok image docker.io/rancher/mirrored-coredns-coredns:1.14.7: sha256:7efd3c635b0 ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 ok secret /stub/default/kubeconfig: mode 0600 exit=0 diff --git a/tests/console/audit/default.observed.json b/tests/console/audit/default.observed.json index 000a1e83..306a4b86 100644 --- a/tests/console/audit/default.observed.json +++ b/tests/console/audit/default.observed.json @@ -65,11 +65,11 @@ }, { "digests": [ - "registry.k8s.io/nfd/node-feature-discovery@sha256:2fa1c99ad09bdf2c8ad97706a4ad2fd548c84d5ecd70ba32a6152c667b96c4d2" + "registry.k8s.io/nfd/node-feature-discovery@sha256:6fc5c9af9176e1acb5ce57a4a1d0c0d3eb25cd34f5bdd0efefebf0efe45a8379" ], "node": "k3d-gpu-server-0", "tags": [ - "registry.k8s.io/nfd/node-feature-discovery:v0.19.0" + "registry.k8s.io/nfd/node-feature-discovery:v0.20.1" ] } ], diff --git a/tests/console/audit/default/crictl-k3d-gpu-server-0.json b/tests/console/audit/default/crictl-k3d-gpu-server-0.json index 9f157f93..aaeb0fff 100644 --- a/tests/console/audit/default/crictl-k3d-gpu-server-0.json +++ b/tests/console/audit/default/crictl-k3d-gpu-server-0.json @@ -59,10 +59,10 @@ { "id": "sha256:5555555555555555555555555555555555555555555555555555555555555555", "repoTags": [ - "registry.k8s.io/nfd/node-feature-discovery:v0.19.0" + "registry.k8s.io/nfd/node-feature-discovery:v0.20.1" ], "repoDigests": [ - "registry.k8s.io/nfd/node-feature-discovery@sha256:2fa1c99ad09bdf2c8ad97706a4ad2fd548c84d5ecd70ba32a6152c667b96c4d2" + "registry.k8s.io/nfd/node-feature-discovery@sha256:6fc5c9af9176e1acb5ce57a4a1d0c0d3eb25cd34f5bdd0efefebf0efe45a8379" ], "size": "1000000", "uid": null, diff --git a/tests/console/audit/image-digest-moved.golden b/tests/console/audit/image-digest-moved.golden index d5308151..eb031ef8 100644 --- a/tests/console/audit/image-digest-moved.golden +++ b/tests/console/audit/image-digest-moved.golden @@ -8,6 +8,6 @@ ok image docker.io/rancher/mirrored-coredns-coredns:1.14.7: sha256:7efd3c635b0 ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 ok secret /stub/image-digest-moved/kubeconfig: mode 0600 exit=1 diff --git a/tests/console/audit/image-no-digest.golden b/tests/console/audit/image-no-digest.golden index a12633d5..c3ca5c28 100644 --- a/tests/console/audit/image-no-digest.golden +++ b/tests/console/audit/image-no-digest.golden @@ -9,6 +9,6 @@ ok image docker.io/rancher/mirrored-coredns-coredns:1.14.7: sha256:7efd3c635b0 ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 ok secret /stub/image-no-digest/kubeconfig: mode 0600 exit=1 diff --git a/tests/console/audit/image-not-in-lock.golden b/tests/console/audit/image-not-in-lock.golden index d27546d1..1c6e2949 100644 --- a/tests/console/audit/image-not-in-lock.golden +++ b/tests/console/audit/image-not-in-lock.golden @@ -9,6 +9,6 @@ ok image docker.io/rancher/mirrored-coredns-coredns:1.14.7: sha256:7efd3c635b0 ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 ok secret /stub/image-not-in-lock/kubeconfig: mode 0600 exit=1 diff --git a/tests/console/audit/ipv6-unauth.golden b/tests/console/audit/ipv6-unauth.golden index 066cdff8..931a5143 100644 --- a/tests/console/audit/ipv6-unauth.golden +++ b/tests/console/audit/ipv6-unauth.golden @@ -9,6 +9,6 @@ ok image docker.io/rancher/mirrored-coredns-coredns:1.14.7: sha256:7efd3c635b0 ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 ok secret /home/user/.kube/config: mode 0600 exit=1 diff --git a/tests/console/audit/ipv6-unauth.observed.json b/tests/console/audit/ipv6-unauth.observed.json index 5f935bc9..145ddda6 100644 --- a/tests/console/audit/ipv6-unauth.observed.json +++ b/tests/console/audit/ipv6-unauth.observed.json @@ -65,11 +65,11 @@ }, { "digests": [ - "registry.k8s.io/nfd/node-feature-discovery@sha256:2fa1c99ad09bdf2c8ad97706a4ad2fd548c84d5ecd70ba32a6152c667b96c4d2" + "registry.k8s.io/nfd/node-feature-discovery@sha256:6fc5c9af9176e1acb5ce57a4a1d0c0d3eb25cd34f5bdd0efefebf0efe45a8379" ], "node": "k3d-gpu-server-0", "tags": [ - "registry.k8s.io/nfd/node-feature-discovery:v0.19.0" + "registry.k8s.io/nfd/node-feature-discovery:v0.20.1" ] } ], diff --git a/tests/console/audit/kubeconfig-0644.golden b/tests/console/audit/kubeconfig-0644.golden index 1e83e9aa..cb56206a 100644 --- a/tests/console/audit/kubeconfig-0644.golden +++ b/tests/console/audit/kubeconfig-0644.golden @@ -7,7 +7,7 @@ ok image docker.io/rancher/mirrored-coredns-coredns:1.14.7: sha256:7efd3c635b0 ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 FAIL secret /stub/kubeconfig-0644/kubeconfig: mode 0644: readable beyond its owner fix: chmod 600 /stub/kubeconfig-0644/kubeconfig exit=1 diff --git a/tests/console/audit/loopback-published.golden b/tests/console/audit/loopback-published.golden index 503fda14..32d56271 100644 --- a/tests/console/audit/loopback-published.golden +++ b/tests/console/audit/loopback-published.golden @@ -8,6 +8,6 @@ ok image docker.io/rancher/mirrored-coredns-coredns:1.14.7: sha256:7efd3c635b0 ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 ok secret /stub/loopback-published/kubeconfig: mode 0600 exit=0 diff --git a/tests/console/audit/runtime-fetch.golden b/tests/console/audit/runtime-fetch.golden index 57d1672e..54b0c258 100644 --- a/tests/console/audit/runtime-fetch.golden +++ b/tests/console/audit/runtime-fetch.golden @@ -7,7 +7,7 @@ ok image docker.io/rancher/mirrored-coredns-coredns:1.14.7: sha256:7efd3c635b0 ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 FAIL fetch docker.io/openvino/model_server@sha256:a928903fe429f1e3e27107cc45932d30d95febfd2d1159dc50869c3eac76fc58: pulled at runtime on k3d-gpu-server-0 fix: pre-load the image (baked node image or air-gap bundle) so pods start with no pull ok secret /home/user/.kube/config: mode 0600 diff --git a/tests/console/audit/runtime-fetch.observed.json b/tests/console/audit/runtime-fetch.observed.json index cb58944a..48d32e1d 100644 --- a/tests/console/audit/runtime-fetch.observed.json +++ b/tests/console/audit/runtime-fetch.observed.json @@ -65,11 +65,11 @@ }, { "digests": [ - "registry.k8s.io/nfd/node-feature-discovery@sha256:2fa1c99ad09bdf2c8ad97706a4ad2fd548c84d5ecd70ba32a6152c667b96c4d2" + "registry.k8s.io/nfd/node-feature-discovery@sha256:6fc5c9af9176e1acb5ce57a4a1d0c0d3eb25cd34f5bdd0efefebf0efe45a8379" ], "node": "k3d-gpu-server-0", "tags": [ - "registry.k8s.io/nfd/node-feature-discovery:v0.19.0" + "registry.k8s.io/nfd/node-feature-discovery:v0.20.1" ] } ], diff --git a/tests/console/audit/runtime-pull.golden b/tests/console/audit/runtime-pull.golden index a2df96ca..4551858c 100644 --- a/tests/console/audit/runtime-pull.golden +++ b/tests/console/audit/runtime-pull.golden @@ -7,7 +7,7 @@ ok image docker.io/rancher/mirrored-coredns-coredns:1.14.7: sha256:7efd3c635b0 ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 FAIL fetch nvidia/cuda:13.4.3-base-ubuntu26.04: pulled at runtime on k3d-gpu-server-0 fix: pre-load the image (baked node image or air-gap bundle) so pods start with no pull FAIL fetch rancher/mirrored-coredns-coredns:1.14.7: pulled at runtime on k3d-gpu-server-0 diff --git a/tests/console/audit/unauth-published.golden b/tests/console/audit/unauth-published.golden index d814253b..6d5c5c63 100644 --- a/tests/console/audit/unauth-published.golden +++ b/tests/console/audit/unauth-published.golden @@ -9,6 +9,6 @@ ok image docker.io/rancher/mirrored-coredns-coredns:1.14.7: sha256:7efd3c635b0 ok image docker.io/rancher/mirrored-metrics-server:v0.9.0: sha256:d9862115e7c7 in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image docker.io/rancher/mirrored-pause:3.10.2: sha256:f548e0e8e3dc in images.lock (k3s-images.txt v1.37.1-k3s1); on k3d-gpu-server-0 ok image ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0: sha256:bacbef6f002f in images.lock (share/nri-balloons-guard.yml, share/nri-balloons.yml); on k3d-gpu-server-0 -ok image registry.k8s.io/nfd/node-feature-discovery:v0.19.0: sha256:2fa1c99ad09b in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 +ok image registry.k8s.io/nfd/node-feature-discovery:v0.20.1: sha256:6fc5c9af9176 in images.lock (share/node-feature-discovery.yml); on k3d-gpu-server-0 ok secret /stub/unauth-published/kubeconfig: mode 0600 exit=1 diff --git a/tests/detect_test.sh b/tests/detect_test.sh index 52761b6f..94554468 100755 --- a/tests/detect_test.sh +++ b/tests/detect_test.sh @@ -4696,8 +4696,8 @@ if grep -A1 -- '^ - name: HOME$' "${SHARE}/agent-sandbox-k3d.yml" | grep else FAILS=$((FAILS + 1)); echo "FAIL sandbox profile sets a writable HOME for pip (no 'name: HOME' followed by 'value: /tmp')" fi -manifest_has "sandbox runtime image pinned by digest" 'image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v1.0.7@sha256:[0-9a-f]{64}$' agent-sandbox-k3d.yml -manifest_has "agent-sandbox controller image pinned by digest" 'image: registry.k8s.io/agent-sandbox/agent-sandbox-controller:v1.0.7@sha256:[0-9a-f]{64}$' agent-sandbox.yml +manifest_has "sandbox runtime image pinned by digest" 'image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v1.0.8@sha256:[0-9a-f]{64}$' agent-sandbox-k3d.yml +manifest_has "agent-sandbox controller image pinned by digest" 'image: registry.k8s.io/agent-sandbox/agent-sandbox-controller:v1.0.8@sha256:[0-9a-f]{64}$' agent-sandbox.yml if grep -E 'image: ' "${SHARE}/agent-sandbox.yml" "${SHARE}/agent-sandbox-k3d.yml" | grep -v '@sha256:' | grep -v ':[[:space:]]*$' >/dev/null; then FAILS=$((FAILS + 1)); echo "FAIL every agent-sandbox image is pinned by digest" else diff --git a/tests/remote/sandbox.golden b/tests/remote/sandbox.golden index 4305346f..bc81aad7 100644 --- a/tests/remote/sandbox.golden +++ b/tests/remote/sandbox.golden @@ -1,5 +1,5 @@ # Rendered by `k3d-gpu sandbox up --remote`: egress is gaudi.example.net:443 only (104.21.77.178, 172.67.210.235, 2606:4700:3030::6815:4db2), no DNS. -# k3d-gpu sandbox profile for kubernetes-sigs/agent-sandbox v1.0.7 (share/agent-sandbox.yml). +# k3d-gpu sandbox profile for kubernetes-sigs/agent-sandbox v1.0.8 (share/agent-sandbox.yml). # Applied by `k3d-gpu sandbox up` once the controller and its CRDs are ready. # # Untrusted agent tool execution runs on E-cores: the pod label k3d-gpu.io/cores=efficient @@ -99,7 +99,7 @@ spec: type: RuntimeDefault containers: - name: python - image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v1.0.7@sha256:fc92654c97fe5dff2a7935a845820981026c075d0c1014e5c2c569f5e58204f1 + image: registry.k8s.io/agent-sandbox/python-runtime-sandbox:v1.0.8@sha256:41da84809426098cb04cdafbb41855f15e3604f7455ef53816bad666e532e787 env: - name: HOME value: /tmp From 8df72d57363f6dd838a1073f2cdfceba0f01cdb6 Mon Sep 17 00:00:00 2001 From: Andrew Mello Date: Thu, 29 Oct 2026 04:32:43 -0700 Subject: [PATCH 2/5] eat upstream: draft EAS patch 0003 pins nri-plugins v0.15.0 The unsent draft pinned the balloons chart to v0.14.0 as "the newest release today". v0.15.0 (2026-10-21) is the newest in the nri-plugins Helm index now, and EAS main (5767995) still has no chart pin, so a fresh install floats to v0.15.0. The patch is regenerated with git format-patch on EAS main with the version and its message changed; the issue draft and README follow. Re-checked on 2026-10-29: every patch applies to EAS main 5767995 on its own and as a series (checks/apply-check.sh). The role's advanced-balloon-values.yaml.j2, rendered with sample inputs in both reserved-CPU forms, goes through helm template for chart v0.15.0 (sha256 1c727a8d..., the digest k3d-gpu's own component pins), and the BalloonsPolicy validates against that chart's CRD with unknown fields rejected; the image resolves to nri-resource-policy-balloons:v0.15.0. --- docs/intel/upstream-eat.md | 2 +- integrations/eat/upstream/README.md | 6 +++--- integrations/eat/upstream/issue-k3s-byo.md | 2 +- .../patches/0003-eas-pin-nri-balloons-chart.patch | 12 ++++++------ 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/intel/upstream-eat.md b/docs/intel/upstream-eat.md index be300183..873004d5 100644 --- a/docs/intel/upstream-eat.md +++ b/docs/intel/upstream-eat.md @@ -78,7 +78,7 @@ EAS (main e8f3ebc; one concern per PR, in this order) ├── roles/kubernetes/tasks/apply_node_topology.yaml 0004 ├── docs/customize/node_topology.md 0004 "label by hand" text replaced ├── docs/deploy/topologies.md 0004 -├── roles/nri_cpu_balloons/defaults/main.yaml 0003 nri_cpu_balloons_chart_version: "v0.14.0" +├── roles/nri_cpu_balloons/defaults/main.yaml 0003 nri_cpu_balloons_chart_version: "v0.15.0" ├── roles/nri_cpu_balloons/tasks/install_advanced.yaml 0003 ├── docs/deploy/k3d.md 0005 new page "Single-Node Dev on k3d" └── docs/README.md 0005 +1 row under Deploy diff --git a/integrations/eat/upstream/README.md b/integrations/eat/upstream/README.md index 588af588..59f72604 100644 --- a/integrations/eat/upstream/README.md +++ b/integrations/eat/upstream/README.md @@ -30,7 +30,7 @@ These are drafts for Intel's repos. **None of them has been filed, opened or pus | # | Repo | What it does | Why it is upstreamable | |---|---|---|---| | [0002](patches/0002-eas-istio-global-platform.patch) | EAS | Adds `istio_platform` (default `""`) and passes it to the Istio chart as `global.platform`, on install and upgrade | Istio's platform prerequisites page sets `global.platform` for k3d and k3s. The cni chart's k3d, k3s, microk8s and openshift profiles move the CNI conf/bin dirs (openshift also switches to multus); gke blanks the bin dir and minikube moves the netns dir, so the knob is not k3s-only. The default renders byte-for-byte as today. | -| [0003](patches/0003-eas-pin-nri-balloons-chart.patch) | EAS | Pins the nri-plugins balloons chart to `v0.14.0` via `nri_cpu_balloons_chart_version` | Matches how the repo pins its other charts (`seaweedfs_chart_version`, `istio_csr_helm_chart_version`, ...). v0.14.0 is today's newest release, so no fresh install changes now. | +| [0003](patches/0003-eas-pin-nri-balloons-chart.patch) | EAS | Pins the nri-plugins balloons chart to `v0.15.0` via `nri_cpu_balloons_chart_version` | Matches how the repo pins its other charts (`seaweedfs_chart_version`, `istio_csr_helm_chart_version`, ...). v0.15.0 is today's newest release, so no fresh install changes now. | | [0004](patches/0004-eas-byo-node-topology-labels.patch) | EAS | Applies the `workload-class` node labels on multi-node BYO clusters, as on managed ones; updates the two docs that said "label by hand" | Fixes an install/teardown asymmetry: teardown already removes these labels from BYO nodes. Not k3s-specific. Single-node and the managed path are unchanged. **Behaviour change for existing multi-node BYO users**, kept small: nodes that already carry a `workload-class` label (set by hand, as the old docs said) keep it, and on BYO a kubeconfig without node list/patch RBAC skips labelling instead of failing the install. | | [0005](patches/0005-eas-docs-single-node-k3d.patch) | EAS | New `docs/deploy/k3d.md` "Single-Node Dev on k3d", linked from `docs/README.md` | Docs only. It builds on the documented BYO path and states the patches it relies on. | | [0006](patches/0006-eas-envoy-control-plane-affinity.patch) | EAS | In `roles/envoy_gateway/tasks/controller.yaml`, selects envoy's control-plane nodes by label presence (`operator: Exists`) instead of the exact value `""`, and sets `nodeSelector: null` so a re-install over an older EnvoyProxy drops the old selector | **Extra, found during review.** k3s sets `node-role.kubernetes.io/control-plane=true`, so today the envoy DaemonSet schedules zero pods on k3s and the gateway has no data plane. No change on kubeadm/Kubespray. | @@ -59,7 +59,7 @@ git am --signoff integrations/eat/upstream/patches/0002-eas-istio-global-platfor | `ansible-lint` 26.8.0 (the version EAS CI pins in `.github/workflows/ansible-lint.yml`) with EAS CI's exact flags (`--skip-list name,var-naming,fqcn,yaml,jinja,key-order roles/ playbooks/`) on the patched tree | `Passed: 0 failure(s), 0 warning(s)`, profile `production`, same as unpatched `main` (on `e8f3ebc`, 2026-10-19) | | `yamllint -d relaxed` on every YAML file the patches touch | no findings apart from line length; EAS CI skips the `yaml` rule | | 0002 behaviour, `helm template` of EAS `charts/istio` (base/istiod/cni/ztunnel 1.27.3) | `global.platform=k3d` mounts `/bin` + `/var/lib/rancher/k3s/agent/etc/cni/net.d`; unset keeps `/opt/cni/bin` + `/etc/cni/net.d`; unknown value fails `unknown platform`. The Jinja `values:` expression evaluates to `{}` when empty | -| 0003 behaviour | `advanced-balloon-values.yaml.j2`, rendered with sample inputs, goes through `helm template` for chart v0.14.0; the `BalloonsPolicy` validates against the v0.14.0 CRD schema; the image resolves to `ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.14.0` | +| 0003 behaviour | `advanced-balloon-values.yaml.j2`, rendered with sample inputs (both reserved-CPU forms, `` and `cpuset:`), goes through `helm template` for chart v0.15.0; the `BalloonsPolicy` validates against the v0.15.0 CRD schema with unknown fields rejected; the image resolves to `ghcr.io/containers/nri-plugins/nri-resource-policy-balloons:v0.15.0` (re-checked 2026-10-29 on EAS `main` `5767995`, when 0003 moved from v0.14.0) | | 0004 behaviour, [checks/eas-byo-topology.sh](checks/eas-byo-topology.sh) (stub `kubernetes.core`) | upstream: BYO 3 nodes → no labels (FAIL); patched: server `platform`, agents `inference`. BYO with one node already labelled → that node untouched; BYO with node list or patch denied → install succeeds, no labels; managed with patch denied → still fails. BYO 1 node, topology off, managed single- and multi-node all unchanged | | 0006 behaviour | the patched `EnvoyProxy` validates against the v1alpha1 CRD in gateway-helm v1.7.1, which includes `pod.affinity` and does not mark `nodeSelector` nullable | | 0006 re-install, [checks/eas-envoy-reinstall.py](checks/eas-envoy-reinstall.py) | models kubernetes.core 6.3.0 updating a custom resource (JSON merge patch, RFC 7386) over the object the unpatched task created. Without `nodeSelector: null` the old selector survives next to the affinity (FAIL); with it, gone. Fresh install: the null is pruned on create | @@ -77,7 +77,7 @@ integrations/eat/upstream/checks/eas-envoy-reinstall.py - **Istio platform profiles.** Taken from the cni 1.27.3 chart (`files/profile-platform-*.yaml`, `templates/zzz_profile.yaml`). k3d: conf `/var/lib/rancher/k3s/agent/etc/cni/net.d`, bin `/bin`. k3s: same conf, bin `/var/lib/rancher/k3s/data/cni`. microk8s: both under `/var/snap/microk8s`. minikube: only `cniNetnsDir`. gke: blanks `cniBinDir` for autodetection. openshift: conf `/etc/cni/multus/net.d`, bin `/var/lib/cni/bin`, multus, not chained. Also checked against Istio's [platform prerequisites](https://istio.io/latest/docs/ambient/install/platform-prerequisites/). That page also shows `global.platform=k3d` for k3d. - **k3s control-plane label value `"true"`.** [k3s-io/k3s pkg/server/server.go#L550](https://github.com/k3s-io/k3s/blob/843c32de489c25ccc1bde53d21c5fd7df23c706e/pkg/server/server.go#L550). - **k3s NRI.** Disabled only when k3s runs in a user namespace: [pkg/agent/templates/templates.go#L322-L325](https://github.com/k3s-io/k3s/blob/843c32de489c25ccc1bde53d21c5fd7df23c706e/pkg/agent/templates/templates.go#L322-L325). -- **nri-plugins.** Latest release `v0.14.0` (2026-08-21) per the GitHub releases API and the Helm repo index. The chart and app versions are `v0.14.0`. +- **nri-plugins.** Latest release `v0.15.0` (2026-10-21) per the GitHub releases API and the Helm repo index, read 2026-10-29. The chart and app versions are `v0.15.0`. - **k3d v5.9.0 flags used in 0005.** `--image`, `--k3s-arg ARG@NODEFILTER`, `-p ...@loadbalancer`, `--wait` and `kubeconfig get`, checked in k3d's docs at tag v5.9.0. `rancher/k3s:v1.34.12-k3s1` exists on Docker Hub, and its minor version matches EAS's pinned kubectl v1.34.3. ## Live probes (Gate 2) diff --git a/integrations/eat/upstream/issue-k3s-byo.md b/integrations/eat/upstream/issue-k3s-byo.md index 407e2d0c..6288c82e 100644 --- a/integrations/eat/upstream/issue-k3s-byo.md +++ b/integrations/eat/upstream/issue-k3s-byo.md @@ -96,7 +96,7 @@ The nri-plugins Helm release is installed with no `chart_version` ([roles/nri_cp This matters more on dev clusters: only one NRI resource policy can own a node, and a version drift between two installers is hard to diagnose. -**Fix (patch 0003):** `nri_cpu_balloons_chart_version: "v0.14.0"`. That is the newest release in the repo index today (published 2026-08-21), so a fresh install does not change now. The role's `advanced-balloon-values.yaml.j2`, rendered with sample inputs, passes `helm template` for v0.14.0, and the resulting `BalloonsPolicy` validates against that chart's CRD. +**Fix (patch 0003):** `nri_cpu_balloons_chart_version: "v0.15.0"`. That is the newest release in the repo index today (published 2026-10-21), so a fresh install does not change now. The role's `advanced-balloon-values.yaml.j2`, rendered with sample inputs, passes `helm template` for v0.15.0, and the resulting `BalloonsPolicy` validates against that chart's CRD. The same pattern exists in [EAT core/roles/nri_cpu_balloons/tasks/install_nri.yaml#L76-L104](https://github.com/intel/enterprise-agent-toolkit/blob/0ecf67a8331e8b502ef41e08bf6d2881416178c5/core/roles/nri_cpu_balloons/tasks/install_nri.yaml#L76-L104), which #19 removes. diff --git a/integrations/eat/upstream/patches/0003-eas-pin-nri-balloons-chart.patch b/integrations/eat/upstream/patches/0003-eas-pin-nri-balloons-chart.patch index 8a1fd931..e41883be 100644 --- a/integrations/eat/upstream/patches/0003-eas-pin-nri-balloons-chart.patch +++ b/integrations/eat/upstream/patches/0003-eas-pin-nri-balloons-chart.patch @@ -1,6 +1,6 @@ -From 23e5ffca1e4ccf37beebb0222df6438f3f87f39f Mon Sep 17 00:00:00 2001 +From 836b2a7d26ee33f90ed21553c2136233b245648b Mon Sep 17 00:00:00 2001 From: Andrew Mello -Date: Fri, 16 Oct 2026 04:43:09 -0700 +Date: Thu, 29 Oct 2026 03:41:08 -0700 Subject: [PATCH] nri_cpu_balloons: pin the nri-plugins chart version The Helm release is installed from the nri-plugins repo with no @@ -10,14 +10,14 @@ image tag to its appVersion). Two installs of the same commit can run different policy code, and a new upstream release can change behaviour under an existing deployment on re-run. -Add nri_cpu_balloons_chart_version, set to v0.14.0 (the newest release +Add nri_cpu_balloons_chart_version, set to v0.15.0 (the newest release in the repo index today, so this changes nothing for a fresh install now) and pass it as chart_version. Kept as a flat variable, like the other *_chart_version settings, so overriding the nri_cpu_balloons dict does not drop the pin. Checked statically: the role's advanced-balloon-values.yaml.j2, rendered -with sample inputs, goes through helm template for chart v0.14.0, and +with sample inputs, goes through helm template for chart v0.15.0, and the resulting BalloonsPolicy validates against that chart's CRD schema. --- roles/nri_cpu_balloons/defaults/main.yaml | 5 +++++ @@ -25,7 +25,7 @@ the resulting BalloonsPolicy validates against that chart's CRD schema. 2 files changed, 6 insertions(+) diff --git a/roles/nri_cpu_balloons/defaults/main.yaml b/roles/nri_cpu_balloons/defaults/main.yaml -index d8641f9..1616f79 100644 +index d8641f9..6c19019 100644 --- a/roles/nri_cpu_balloons/defaults/main.yaml +++ b/roles/nri_cpu_balloons/defaults/main.yaml @@ -24,6 +24,11 @@ nri_cpu_balloons: @@ -35,7 +35,7 @@ index d8641f9..1616f79 100644 +# nri-plugins chart version. Pinned so every install and re-run gets the same +# release instead of whatever the Helm repo serves as newest at the time. The +# plugin image tag follows the chart's appVersion. Bump deliberately. -+nri_cpu_balloons_chart_version: "v0.14.0" ++nri_cpu_balloons_chart_version: "v0.15.0" + # Reserved-CPU sizing. # From 68381da3ca31b6665281ac8e6e7c7de77e9d8516 Mon Sep 17 00:00:00 2001 From: Andrew Mello Date: Thu, 29 Oct 2026 04:33:01 -0700 Subject: [PATCH 3/5] ledger: wildct amendment P1, kubectl v1.37.2 Rule W7 pins kubectl v1.37.1, "the newest release on 2026-10-20". Kubernetes v1.37.2 came out on 2026-10-28 and is the newest now (dl.k8s.io stable.txt, read 2026-10-29); k3d v5.9.0 and helm v4.3.1 are still the newest of theirs. P1 moves W7's kubectl to v1.37.2, mechanics only. No wildct hold has run (smoke1 was discarded), and install.sh runs again before the first hold to install W7's newest k3d-gpu release, so every wildct row runs on it. bench/wildct/install.sh fetches v1.37.2 and checks it against its .sha256 file, as before; W7 points to P1. If wildct amendment R1 (PR #226) merges, its sentence keeping v1.37.1 is superseded. --- EXPERIMENTS.md | 21 ++++++++++++++++++++- bench/wildct/install.sh | 14 +++++++------- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/EXPERIMENTS.md b/EXPERIMENTS.md index db6584d3..11214f07 100644 --- a/EXPERIMENTS.md +++ b/EXPERIMENTS.md @@ -4181,7 +4181,8 @@ re-graded here. whose need never fits before the campaign ends is INCONCLUSIVE (not run), with the readings recorded. Everything this campaign creates on wildct is deleted at the end except the run records, which are copied back into the repo first. -7. **Pins.** k3d v5.9.0, helm v4.3.1, kubectl v1.37.1 (each the newest release on 2026-10-20) +7. **Pins.** k3d v5.9.0, helm v4.3.1, kubectl v1.37.1 (each the newest release on 2026-10-20; + kubectl v1.37.2 from [amendment P1](#wildct-amendment-p1-kubectl-v1372-2026-10-29)) in `~/k3dgpu-bench-wildct/bin`, checked against their upstream checksums (`bench/wildct/install.sh`); k3d-gpu: the newest release at the first hold (the first one carrying PR #180: 0.1.65 or later), its `.deb` checked against the release's `SHA256SUMS` and unpacked in @@ -4282,6 +4283,24 @@ request, discarded and disclosed). Then H52w (1 hold), H18w (1), H25w (1), H34w repeat a failed hold once. At most 12 holds in all. A protocol change is a dated amendment merged before the data it governs. +### Wildct amendment P1: kubectl v1.37.2 (2026-10-29) + +Recorded 2026-10-29, before any wildct hold (none has run; `smoke1` was discarded). Mechanics only. +No row's hypothesis, prediction, arm, model, statistic, threshold, cap, disk need, hold count or +order changes. + +Rule W7 pins kubectl v1.37.1, the newest release on 2026-10-20. Kubernetes v1.37.2 came out on +2026-10-28 and is the newest now (`dl.k8s.io/release/stable.txt`, read 2026-10-29); k3d v5.9.0 +and helm v4.3.1 are still the newest of theirs. W7 now reads kubectl v1.37.2. +`bench/wildct/install.sh` fetches it and checks it against its `.sha256` file (linux/amd64 +`c0448752...`), as before. The node images serve Kubernetes v1.37.1 (k3s v1.37.1+k3s1), so +client and server share a minor version, as before. `install.sh` runs again before +the first hold anyway, to install W7's newest k3d-gpu release (0.1.75 or later, not the 0.1.71 +installed on 2026-10-21), and that run installs kubectl v1.37.2. So every wildct row (H52w, +H18w, H25w, H28w, H34w, H57wa, H57wm and H57wb, and H59w if it is pre-registered under W7) runs on +it. If wildct amendment R1 (PR #226) merges, its sentence that keeps kubectl v1.37.1 is superseded +by this amendment. Each row's Reproduce header names the kubectl that ran. + ### H5 amendment A1: stage-1 harness and definitions (2026-10-19) Written 2026-10-19T22:30-07:00, before any H5 measurement. It fixes what the diff --git a/bench/wildct/install.sh b/bench/wildct/install.sh index aafe8c23..fa77522f 100755 --- a/bench/wildct/install.sh +++ b/bench/wildct/install.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash # install.sh K3D_GPU_VERSION: the wildct campaign's tools, pinned and checksum-checked, into # ~/k3dgpu-bench-wildct (EXPERIMENTS.md "Wildct pre-registration", rule W7); nothing -# system-wide. k3d v5.9.0, helm v4.3.1 and kubectl v1.37.1 (each the newest release on -# 2026-10-20) into bin/; the k3d-gpu release's .deb, checked against the release's -# SHA256SUMS, unpacked into k3d-gpu/ (k3d-gpu/usr/bin/k3d-gpu with K3D_GPU_SHARE pointing at -# k3d-gpu/usr/share/k3d-gpu); huggingface_hub 1.21.0 (crescent's pin) in hfvenv/. Prints -# every version and checksum. +# system-wide. k3d v5.9.0 and helm v4.3.1 (each the newest release on 2026-10-20) and kubectl +# v1.37.2 (the newest on 2026-10-29, wildct amendment P1) into bin/; the k3d-gpu release's +# .deb, checked against the release's SHA256SUMS, unpacked into k3d-gpu/ +# (k3d-gpu/usr/bin/k3d-gpu with K3D_GPU_SHARE pointing at k3d-gpu/usr/share/k3d-gpu); +# huggingface_hub 1.21.0 (crescent's pin) in hfvenv/. Prints every version and checksum. set -euo pipefail V=${1:?usage: install.sh K3D_GPU_VERSION} W=${HOME}/k3dgpu-bench-wildct @@ -23,8 +23,8 @@ check 0403a88ae20913d11b10a2467b50087721fea7581736da6b9d3992f5357fe54b helm.tgz tar -xzf helm.tgz linux-amd64/helm install -m 0755 linux-amd64/helm "${W}/bin/helm" -get https://dl.k8s.io/release/v1.37.1/bin/linux/amd64/kubectl kubectl -get https://dl.k8s.io/release/v1.37.1/bin/linux/amd64/kubectl.sha256 kubectl.sha256 +get https://dl.k8s.io/release/v1.37.2/bin/linux/amd64/kubectl kubectl +get https://dl.k8s.io/release/v1.37.2/bin/linux/amd64/kubectl.sha256 kubectl.sha256 check "$(cat kubectl.sha256)" kubectl install -m 0755 kubectl "${W}/bin/kubectl" From b68c9d46537034df39de7799a08894d9f21be7de Mon Sep 17 00:00:00 2001 From: Andrew Mello Date: Thu, 29 Oct 2026 04:33:17 -0700 Subject: [PATCH 4/5] ledger: cross-host amendment K1, kubectl v1.37.2 in ~/k3dgpu-xhost/bin Cross-host rule 5 pins kubectl v1.35.2 in ~/k3dgpu-xhost/bin, which bench/xhost/hold.sh puts first on PATH. The node image the cross-host rows run (0.1.61) serves Kubernetes v1.37.1, two minors past the client and outside kubectl's one-minor skew policy. Crescent amendment E4 (PR #238) moves shared rule 5's workspace, ~/k3dgpu-bench/bin; it does not touch this one. K1 moves rule 5's kubectl to v1.37.2 (the newest release, 2026-10-28; k3d v5.9.0 stays), mechanics only. It covers H28x's run 2 and H7x, whose first measuring holds have not run. H25x, H27x and H34x are records and keep what they ran. A row runs all its holds on the kubectl in place at its first measuring hold. Rule 5's tools had no script in this repo. bench/xhost/tools.sh installs exactly k3d v5.9.0 and kubectl v1.37.2 into ~/k3dgpu-xhost/bin, checks both against their upstream checksum files before installing either, and prints both versions. A run against the real upstream gave "k3d: OK", "kubectl: OK", k3d v5.9.0 and kubectl v1.37.2. tests/xhost_tools_test.sh (in CI) runs it against a curl shim: exactly the two binaries at the pinned versions, four downloads, nothing else touched, a checksum mismatch on either installs nothing, no download directory left behind. Five broken copies of tools.sh (old kubectl, an install before the second check, no kubectl check, an extra binary, no cleanup) each fail it. --- .github/workflows/ci.yml | 1 + EXPERIMENTS.md | 32 +++++++++++++- bench/xhost/tools.sh | 21 ++++++++++ tests/xhost_tools_test.sh | 87 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 1 deletion(-) create mode 100755 bench/xhost/tools.sh create mode 100755 tests/xhost_tools_test.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f75d16a..b1340c27 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -252,6 +252,7 @@ jobs: - run: python3 bench/eatflow/test_agentbench.py - run: python3 bench/eatflow/test_pairs.py - run: python3 bench/eatflow/test_solo.py + - run: tests/xhost_tools_test.sh - run: python3 bench/eatflow/test_h4345.py - run: python3 bench/models/test_export_qat_ov.py - run: python3 bench/models/test_qat_grid.py diff --git a/EXPERIMENTS.md b/EXPERIMENTS.md index 11214f07..a9414124 100644 --- a/EXPERIMENTS.md +++ b/EXPERIMENTS.md @@ -1735,7 +1735,7 @@ entries that ask for another, Xeon/AMX, XMX, non-throttling or quiet host, and t below showed the cause: without C1 the agent pod stayed Pending. C1 changes when the kubelet evicts, nothing else, and applies to both arms alike. X1's 97% guard stays. 5. **Pins.** k3d v5.9.0 and kubectl v1.35.2 in `~/k3dgpu-xhost/bin`, each checked against its - upstream checksum; node image `cryptoandcoffee/k3d-gpu:0.1.61` (the launcher's default at this pre-registration's base, set explicitly with `K3D_GPU_IMAGE` or `IMAGE` in every command, + upstream checksum (kubectl v1.37.2 for the rows [amendment K1](#cross-host-amendment-k1-kubectl-v1372-in-the-cross-host-workspace-2026-10-29) moves); node image `cryptoandcoffee/k3d-gpu:0.1.61` (the launcher's default at this pre-registration's base, set explicitly with `K3D_GPU_IMAGE` or `IMAGE` in every command, k3s v1.37.1; a change: the originals ran 0.1.28 (H25 run 4), 0.1.55 (H34) and 0.1.59 (H28), with the agent-manifest code unchanged since H25 run 4); OVMS `openvino/model_server@sha256:a928903f...76fc58` (2026.4.1, as every original row); `load.py`'s stress-ng pin. Models are downloaded on the host at the original @@ -1801,6 +1801,36 @@ failure C1 fixes. Smoke 2 (22:14-22:20Z, with C1): `up` 48 s, the agent pod Read C1 as `--k3s-arg ...@server:*`) had no taint after 90 s. No inference request was sent in either. Smoke records: `bench/xhost/results/2026-10-20/smoke{1,2}/`. +### Cross-host amendment K1: kubectl v1.37.2 in the cross-host workspace (2026-10-29) + +Recorded 2026-10-29, before any H7x hold and before H28x's run 2. Mechanics only. No hypothesis, +arm, model, node image, prediction, outcome table, scorer, threshold, cap or order changes. It +is pre-registered by its push time. + +1. **Why.** Rule 5 pins kubectl v1.35.2 in `~/k3dgpu-xhost/bin`, and `bench/xhost/hold.sh` puts + that directory first on `PATH`. The node image these rows run (0.1.61) serves Kubernetes + v1.37.1 (k3s v1.37.1+k3s1). Kubernetes' version skew policy supports kubectl within one minor + version of kube-apiserver, so v1.35 against v1.37 is outside it. No hold has failed from this. + Read on 2026-10-29: kubectl v1.37.2 (2026-10-28, `dl.k8s.io/release/stable.txt`) is the newest + release; k3d v5.9.0 is still its newest and stays. Crescent amendment E4 (PR #238) makes the + same move for shared rule 5's workspace, `~/k3dgpu-bench/bin`; this amendment covers the + cross-host workspace, which E4 does not touch. +2. **Pins.** k3d v5.9.0 (unchanged) and kubectl v1.37.2 (linux/amd64 sha256 `c0448752...`). + `bench/xhost/tools.sh`, new, installs exactly these two into `~/k3dgpu-xhost/bin`, each checked + against its upstream checksum file (k3d's `checksums.txt`, kubectl's `.sha256`), and prints + both versions. It touches nothing else. Rule 5's tools had no script in this repo until now. +3. **When.** `tools.sh` runs once on crescent from a clean checkout at or after this amendment's + merge, with the bench lock free and no cross-host row between holds. Its output goes into the + next cross-host row's records. +4. **Rows.** A row runs all its holds on the kubectl in place at its first measuring hold. Rows + whose first measuring hold starts after `tools.sh` has run use v1.37.2: H28x's run 2, if PR + #208's amendment R1 allows it, and H7x (PRs #196 and #235), if its pre-registration merges + under these rules. H25x, H27x and H34x have run and keep what they ran; H25x and H34x record + kubectl v1.35.2. A smoke, or a hold that measured nothing (H28x run 1), does not fix a row's + tools. +5. **Not changed.** The node image, the models, OVMS, `load.py`'s stress-ng pin and every other + item of rule 5. + ### H25x run (Xeon 6741P, 2026-10-21) ```text diff --git a/bench/xhost/tools.sh b/bench/xhost/tools.sh new file mode 100755 index 00000000..8b519fc4 --- /dev/null +++ b/bench/xhost/tools.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# tools.sh: the cross-host rows' k3d and kubectl in ~/k3dgpu-xhost/bin (EXPERIMENTS.md +# "Cross-host pre-registration" rule 5, as cross-host amendment K1 moves it), each checked +# against its upstream checksum file. Installs nothing else and touches no other file. Run on +# crescent from a clean checkout of this repo, with the bench lock free. Prints both versions. +set -euo pipefail +X=${HOME}/k3dgpu-xhost +K3D_V=v5.9.0 KUBECTL_V=v1.37.2 +mkdir -p "${X}/bin" +DL=$(mktemp -d "${X}/tools-dl.XXXXXX") +trap 'rm -rf "${DL}"' EXIT +cd "${DL}" +curl -fsSLo k3d "https://github.com/k3d-io/k3d/releases/download/${K3D_V}/k3d-linux-amd64" +curl -fsSLo k3d.sums "https://github.com/k3d-io/k3d/releases/download/${K3D_V}/checksums.txt" +curl -fsSLo kubectl "https://dl.k8s.io/release/${KUBECTL_V}/bin/linux/amd64/kubectl" +curl -fsSLo kubectl.sha256 "https://dl.k8s.io/release/${KUBECTL_V}/bin/linux/amd64/kubectl.sha256" +echo "$(grep 'k3d-linux-amd64$' k3d.sums | awk '{print $1}') k3d" | sha256sum -c +echo "$(cat kubectl.sha256) kubectl" | sha256sum -c +install -m755 k3d kubectl "${X}/bin/" +"${X}/bin/k3d" version | head -1 +"${X}/bin/kubectl" version --client | head -1 diff --git a/tests/xhost_tools_test.sh b/tests/xhost_tools_test.sh new file mode 100755 index 00000000..fdf052b3 --- /dev/null +++ b/tests/xhost_tools_test.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +# xhost_tools_test.sh: bench/xhost/tools.sh installs exactly k3d v5.9.0 and kubectl v1.37.2, +# each checked against its checksum file, into ~/k3dgpu-xhost/bin (EXPERIMENTS.md cross-host +# amendment K1). curl is a shim that serves fake binaries with matching checksum files and logs +# every URL; each fake binary logs its arguments. Real sha256sum and install. No network, no root. +# +# Usage: tests/xhost_tools_test.sh +set -uo pipefail + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +TOOLS=${ROOT}/bench/xhost/tools.sh +PASS=0 FAILS=0 +T=$(mktemp -d) +trap 'rm -rf "${T}"' EXIT +ok() { PASS=$((PASS + 1)); echo "ok $1"; } +fail() { FAILS=$((FAILS + 1)); echo "FAIL $1"; } +check() { local name=$1; shift; if "$@"; then ok "${name}"; else fail "${name}"; fi; } + +mkdir -p "${T}/shims" +# curl -fsSLo FILE URL. Each binary is built once per URL under $SHIM_DIR/art, so the checksum +# file served later matches it. SHIM_BAD= serves a wrong checksum for that tool. +cat > "${T}/shims/curl" <<'EOF' +#!/usr/bin/env bash +set -eu +out= url= +while [ $# -gt 0 ]; do case $1 in -fsSLo) out=$2; shift 2 ;; *) url=$1; shift ;; esac; done +echo "${url}" >> "${SHIM_DIR}/curl.log" +mkdir -p "${SHIM_DIR}/art" +art() { # art TOOL URL: the fake binary's path, built on first use + local f + f=${SHIM_DIR}/art/$(printf '%s' "$2" | sha256sum | cut -c1-16) + [ -e "${f}" ] || printf '#!/bin/sh\necho "%s %s"\necho "%s $*" >> "${SHIM_DIR}/run.log"\n' "$1" "$2" "$1" > "${f}" + echo "${f}" +} +sum() { # sum TOOL URL: the binary's sha256, or a wrong one for SHIM_BAD + if [ "${SHIM_BAD:-}" = "$1" ]; then printf '%064d' 0; else sha256sum "$(art "$1" "$2")" | cut -d' ' -f1; fi +} +case ${url} in + */checksums.txt) echo "$(sum k3d "${url%/checksums.txt}/k3d-linux-amd64") _dist/k3d-linux-amd64" > "${out}" ;; + */k3d-linux-amd64) cp "$(art k3d "${url}")" "${out}" ;; + */kubectl.sha256) sum kubectl "${url%.sha256}" > "${out}" ;; + */bin/linux/amd64/kubectl) cp "$(art kubectl "${url}")" "${out}" ;; + *) echo "curl shim: no artifact for ${url}" >&2; exit 22 ;; +esac +EOF +chmod +x "${T}/shims/curl" + +# run: tools.sh in a fresh HOME with the shim first on PATH; sets RC, OUT, H, S. +run() { + H=$(mktemp -d "${T}/home.XXXX") S=$(mktemp -d "${T}/shim.XXXX") + : > "${S}/curl.log"; : > "${S}/run.log" + mkdir -p "${H}/k3dgpu-xhost/runs" "${H}/k3dgpu-bench/bin" + echo keep > "${H}/k3dgpu-xhost/runs/campaign.log" + OUT=$(HOME=${H} SHIM_DIR=${S} PATH="${T}/shims:${PATH}" bash "${TOOLS}" 2>&1) + RC=$? +} +has() { grep -q -- "$1" "$2"; } +bins() { (cd "$1" 2>/dev/null && ls | sort | tr '\n' ' '); } +leftover_dl() { compgen -G "$1/tools-dl.*" > /dev/null; } + +run +check "tools.sh exits 0" [ "${RC}" -eq 0 ] +check "it installs k3d and kubectl only" [ "$(bins "${H}/k3dgpu-xhost/bin")" = "k3d kubectl " ] +check "it fetches kubectl v1.37.2" has '^https://dl.k8s.io/release/v1.37.2/bin/linux/amd64/kubectl$' "${S}/curl.log" +check "it fetches kubectl's checksum file" has '^https://dl.k8s.io/release/v1.37.2/bin/linux/amd64/kubectl.sha256$' "${S}/curl.log" +check "it fetches k3d v5.9.0 and its checksums" has 'k3d-io/k3d/releases/download/v5.9.0/checksums.txt$' "${S}/curl.log" +check "it fetches four files, nothing else" [ "$(wc -l < "${S}/curl.log")" -eq 4 ] +check "the kubectl it installs is the one it fetched" has 'kubectl https://dl.k8s.io/release/v1.37.2/' <(printf '%s\n' "${OUT}") +check "it prints both versions" eval 'has "^k3d version$" "${S}/run.log" && has "^kubectl version --client$" "${S}/run.log"' +check "it leaves no download dir" eval '! leftover_dl "${H}/k3dgpu-xhost"' +check "it keeps the cross-host records" [ "$(cat "${H}/k3dgpu-xhost/runs/campaign.log")" = keep ] +check "it does not touch the crescent workspace" [ -z "$(ls -A "${H}/k3dgpu-bench/bin")" ] + +# A second run replaces the binaries in place. +HOME_FIRST=${H} +OUT=$(HOME=${HOME_FIRST} SHIM_DIR=${S} PATH="${T}/shims:${PATH}" bash "${TOOLS}" 2>&1); RC=$? +check "a second run exits 0" [ "${RC}" -eq 0 ] + +for bad in kubectl k3d; do + SHIM_BAD=${bad} run + check "a ${bad} checksum mismatch fails" [ "${RC}" -ne 0 ] + check "a ${bad} checksum mismatch installs nothing" [ -z "$(ls -A "${H}/k3dgpu-xhost/bin")" ] + check "a ${bad} checksum mismatch leaves no download dir" eval '! leftover_dl "${H}/k3dgpu-xhost"' +done + +echo "${PASS} passed, ${FAILS} failed" +[ "${FAILS}" -eq 0 ] From bc1e601bfc0060b13e56d36d5f304dde3bd8da8c Mon Sep 17 00:00:00 2001 From: Andrew Mello Date: Thu, 29 Oct 2026 05:16:06 -0700 Subject: [PATCH 5/5] docs: the README's balloons Helm command and docs/intel.md name nri-plugins v0.15.0 The node image bakes the nri-plugins balloons chart v0.15.0 (component.conf, share/nri-balloons.yml, since #192), and v0.15.0 is still the newest release in the nri-plugins Helm index (2026-10-21, chart sha256 1c727a8d...). Two current-state lines still named v0.14.0: the README's `helm upgrade --install` that adopts the baked objects pinned `--version v0.14.0`, so following it would move a v0.15.0 node back to the older chart, and docs/intel.md said the image bakes balloons v0.14.0. Both now read v0.15.0. `helm template` of the chart from the repo at v0.15.0 renders the same kinds and the v0.15.0 image the baked manifest carries. The statements that describe v0.14.0's behaviour (docs/intel.md's CRD options and live run, docs/failure-modes.md's snapshot, the dated security audit, the H14 record) are left as they are. --- README.md | 2 +- docs/intel.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4cfe8da4..91789eeb 100644 --- a/README.md +++ b/README.md @@ -573,7 +573,7 @@ name in place of `gpu`): ```bash docker exec k3d-gpu-server-0 touch /var/lib/rancher/k3s/server/manifests/nri-balloons.yaml.skip helm upgrade --install nri-resource-policy-balloons nri-resource-policy-balloons \ - --repo https://containers.github.io/nri-plugins --version v0.14.0 \ + --repo https://containers.github.io/nri-plugins --version v0.15.0 \ --namespace kube-system -f values.yaml --force # Helm 4: --force-conflicts ``` diff --git a/docs/intel.md b/docs/intel.md index 7184fc1e..cd7f3d50 100644 --- a/docs/intel.md +++ b/docs/intel.md @@ -32,8 +32,8 @@ with detection, enablement and what k3d-gpu does with each, see the manifests into k3s's auto-deploy directory: [intel-device-plugins-for-kubernetes](https://github.com/intel/intel-device-plugins-for-kubernetes) `0.37.1` (GPU, NPU, DSA, IAA, QAT), `intel/gaudi-device-plugin:1.24.2-481` and - [nri-plugins](https://github.com/containers/nri-plugins/releases/tag/v0.14.0) - balloons `v0.14.0`. With the default image nothing is `kubectl apply`'d at + [nri-plugins](https://github.com/containers/nri-plugins/releases/tag/v0.15.0) + balloons `v0.15.0`. With the default image nothing is `kubectl apply`'d at run time. If a custom `K3D_GPU_IMAGE` lacks a baked DaemonSet, `up` applies the manifest from `K3D_GPU_SHARE`; for NVIDIA with no local manifest it falls back to the upstream `main` branch manifest from GitHub, which is unpinned.