Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/kwok-nvsentinel-remediation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ jobs:
# The event exporter (#2621), which reads the datastore a step adds.
- mixin: nvsentinel-observe,nvsentinel-event-exporter
deployer: helm
# The log collector's file server runs on emptyDir under KWOK
# (kwok/scripts/validate-scheduling.sh); EKS's GPU Operator installs
# the driver, so CheckNVSentinelLogCollectorCoherent accepts it.
- mixin: 'nvsentinel-remediation,nvsentinel-health-events-analyzer,nvsentinel-log-collector'
deployer: helm
steps:
- name: Checkout Code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
Expand Down
157 changes: 157 additions & 0 deletions .github/workflows/nvsentinel-log-collector-e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Runtime Kind test for the nvsentinel-log-collector mixin.
#
# Installs the remediation step with the log collector, and the health events
# analyzer that live remediation requires, via the bundle's own install.sh,
# sends one synthetic GPU fault into platform-connectors, and checks
# that fault-remediation runs the collector Job on the node, that the bug report
# it uploads is listed by the in-cluster file server, that the file server's
# volume took the --storage-class value, and that the GPU reset is requested
# only after collection. The collector runs in its MOCK_MODE: a Kind node has no
# GPU driver. Not wired into `make qualify`: it needs a Kind cluster.
#
# Path filter kept narrow for the same reason as nvsentinel-preflight-e2e.yaml.

name: NVSentinel Log Collector E2E

on:
push:
branches: [main]
paths: &paths
- 'recipes/mixins/nvsentinel-remediation.yaml'
- 'recipes/mixins/nvsentinel-health-events-analyzer.yaml'
- 'recipes/mixins/nvsentinel-log-collector.yaml'
- 'pkg/bundler/validations/nvsentinel_log_collector.go'
- 'pkg/bundler/validations/checks.go'
- 'recipes/registry.yaml'
- 'recipes/components/nvsentinel/**'
- 'recipes/components/nvsentinel-mongodb/**'
- 'recipes/components/psmdb-operator/**'
# The tested overlay inherits kind.yaml, which inherits base.yaml, and
# base.yaml is where nvsentinel enters the chain at all.
- 'recipes/overlays/h100-kind-training.yaml'
- 'recipes/overlays/kind.yaml'
- 'recipes/overlays/base.yaml'
# The run installs cert-manager, for the Percona cluster's certificates,
# and prometheus-operator-crds from the bundle.
- 'recipes/components/cert-manager/**'
- 'recipes/components/prometheus-operator-crds/**'
- 'tests/e2e/nvsentinel-log-collector/**'
- 'pkg/bundler/deployer/localformat/templates/**'
# run.sh sources tools/common and is invoked through a make target.
- 'tools/common'
- 'Makefile'
- '.github/workflows/nvsentinel-log-collector-e2e.yaml'
- '.github/actions/setup-build-tools/**'
- '.github/actions/prep-kind-runner/**'
- '.github/actions/load-versions/**'
- '.settings.yaml'
pull_request:
branches: [main]
paths: *paths
workflow_dispatch: {}

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
test:
name: NVSentinel Log Collector E2E
# mongod 8.0 before 8.0.35 exits at startup on the ubuntu-24.04 image's
# 7.0 kernel (https://jira.mongodb.org/browse/SERVER-131779). Return to
# ubuntu-24.04 once the Percona MongoDB pin is 8.0.35 or newer.
runs-on: ubuntu-22.04
# The script's bounded waits sum to ~70 minutes worst case (node Ready 2,
# cert-manager 10, Percona datastore 15, nvsentinel rollout 15, event
# delivery 3, collection 15, reset request 5, proto fetch 1, port-forward
# and fetches 4), before kind create, go build and the installs' own helm
# waits. A healthy run takes a fraction of that.
timeout-minutes: 100
steps:
- name: Checkout Code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Load versions
id: versions
uses: ./.github/actions/load-versions

- name: Prep Kind runner
uses: ./.github/actions/prep-kind-runner

- name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: ${{ steps.versions.outputs.go }}
cache: false

# run.sh's has_tools gate also needs jq and curl, which the runner image
# already ships; installing only some of the rest fails the lane before
# it exercises anything.
- name: Install Kind, kubectl, Helm and yq
uses: ./.github/actions/setup-build-tools
with:
install_kind: 'true'
kind_version: '${{ steps.versions.outputs.kind }}'
install_kubectl: 'true'
kubectl_version: '${{ steps.versions.outputs.kubectl }}'
install_helm: 'true'
helm_version: '${{ steps.versions.outputs.helm }}'
install_yq: 'true'
yq_version: '${{ steps.versions.outputs.yq }}'

# KEEP_CLUSTER so the cluster survives for the diagnostics below; the
# script's own EXIT trap would otherwise delete it before they run,
# leaving a failure with nothing to inspect. The always() step after
# diagnostics does the teardown instead.
- name: Run nvsentinel-log-collector e2e
env:
KEEP_CLUSTER: 'true'
run: make nvsentinel-log-collector-e2e

# run.sh writes its kubeconfig inside a mktemp dir and removes that dir on
# exit, so KEEP_CLUSTER leaves the cluster running but no credentials to
# reach it. Re-export before querying anything. cancelled() because a
# job timeout cancels rather than fails.
- name: Collect diagnostics on failure
if: ${{ failure() || cancelled() }}
run: |
set +e
cluster=aicr-nvsentinel-lc-e2e
export KUBECONFIG="${RUNNER_TEMP}/lc-diag.kubeconfig"
kind export kubeconfig --name "$cluster" --kubeconfig "$KUBECONFIG" || exit 0
kubectl get pods -A
kubectl get node -o yaml
kubectl -n nvsentinel get pvc,statefulset,deployment,job,perconaservermongodb,certificate
kubectl -n nvsentinel get events --sort-by=.lastTimestamp
kubectl -n nvsentinel describe pods --selector='!job-name'
kubectl get gpuresets.janitor.dgxc.nvidia.com -A -o yaml
kubectl -n nvsentinel logs -l app=log-collector --tail=200
for d in fault-quarantine node-drainer fault-remediation janitor nvsentinel-incluster-file-server; do
kubectl -n nvsentinel logs "deployment/$d" --tail=200
done
kubectl -n nvsentinel logs daemonset/platform-connectors --tail=200
kubectl -n nvsentinel logs deployment/psmdb-operator --tail=200
kubectl -n nvsentinel logs statefulset/nvsentinel-mongodb-rs0 -c mongod --tail=100

- name: Delete Kind cluster
if: ${{ always() }}
run: kind delete cluster --name aicr-nvsentinel-lc-e2e || true
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
# health-events-analyzer one asserts the workload, its datastore wiring and
# that the mixin names every rule the chart ships, the event-exporter one
# asserts the workload, its OIDC Secret and datastore wiring and its config,
# and the CRD
# the log-collector one asserts the collector Job, the file server it uploads
# to and that server's volume and images, and the CRD
# exclusion one asserts the chart still ships mongodb-store's CRDs where
# nvsentinel's ownsCRDsExcludeSubcharts expects them.
# All are gated on testing.Short() -- `make
Expand Down Expand Up @@ -103,6 +104,7 @@ jobs:
TestNVSentinelSlinkyDrainerChartRender
TestNVSentinelHealthEventsAnalyzerChartRender
TestNVSentinelEventExporterChartRender
TestNVSentinelLogCollectorChartRender
)
pattern="^($(IFS='|'; echo "${tests[*]}"))$"
out=$(go test ./pkg/bundler/validations/... -run "$pattern" -v -count=1 2>&1) && rc=0 || rc=$?
Expand Down
39 changes: 31 additions & 8 deletions .github/workflows/vuln-scan-images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ jobs:
# opt-in nvsentinel-object-monitor (#2612), nvsentinel-preflight
# (#2610), nvsentinel-nic-health-monitor, nvsentinel-slurm-drain-monitor
# (#2611), remediation, nvsentinel-slinky-drainer (#2615),
# nvsentinel-health-events-analyzer (#2618) and
# nvsentinel-event-exporter (#2621) mixins, and no other job
# nvsentinel-health-events-analyzer (#2618), nvsentinel-event-exporter
# (#2621) and nvsentinel-log-collector (#2619) mixins, and no other job
# scans a mixin-gated image, so nothing else would surface a CVE in
# them.
# Because they are not built by this workflow they carry their
Expand All @@ -355,6 +355,14 @@ jobs:
- ghcr.io/nvidia/nvsentinel/slinky-drainer
- ghcr.io/nvidia/nvsentinel/health-events-analyzer
- ghcr.io/nvidia/nvsentinel/event-exporter
- ghcr.io/nvidia/nvsentinel/log-collector
- ghcr.io/nvidia/nvsentinel/file-server-cleanup
# The nvsentinel-log-collector mixin's file server, at the nvsentinel
# chart's own pins; its init container's busybox is the AICR pin
# below. bitnamilegacy is Bitnami's frozen archive and is never
# patched, so expect findings here.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
- docker.io/bitnamilegacy/nginx
- quay.io/martinhelmich/prometheus-nginxlog-exporter
# Percona, from the remediation mixins' separately bundled datastore
# (psmdb-operator, nvsentinel-mongodb). Pinned by AICR, by digest.
- docker.io/percona/percona-server-mongodb-operator
Expand All @@ -366,11 +374,14 @@ jobs:
# Third-party, pinned by AICR rather than the chart:
# global.initContainerImage, used by chown/permission init
# containers in the nic-health-monitor and audit-logging paths,
# and janitor-provider's generic reboot Job image. AICR overrides
# the chart's defaults for both -- the first in
# janitor-provider's generic reboot Job image, and the in-cluster
# file server's init container. AICR overrides the chart's defaults
# for all three -- the first in
# recipes/components/nvsentinel/values.yaml, the second
# (janitor-provider.csp.generic.rebootImage) in
# recipes/mixins/nvsentinel-remediation.yaml -- so what is scanned
# recipes/mixins/nvsentinel-remediation.yaml, the third
# (incluster-file-server.initImage) in
# recipes/mixins/nvsentinel-log-collector.yaml -- so what is scanned
# here is the override; keep them in step.
- docker.io/library/busybox
include:
Expand All @@ -381,9 +392,9 @@ jobs:
# TestSlurmDrainMonitorImagePinnedEverywhere,
# TestRemediationImagesPinnedEverywhere,
# TestSlinkyDrainerImagePinnedEverywhere,
# TestHealthEventsAnalyzerImagePinnedEverywhere and
# TestEventExporterImagePinnedEverywhere fail if these drift
# apart.
# TestHealthEventsAnalyzerImagePinnedEverywhere,
# TestEventExporterImagePinnedEverywhere and
# TestLogCollectorImagesPinnedEverywhere fail if these drift apart.
- image: ghcr.io/nvidia/nvsentinel/kubernetes-object-monitor
tag: v1.28.0
- image: ghcr.io/nvidia/nvsentinel/preflight
Expand Down Expand Up @@ -417,6 +428,18 @@ jobs:
tag: v1.28.0
- image: ghcr.io/nvidia/nvsentinel/event-exporter
tag: v1.28.0
- image: ghcr.io/nvidia/nvsentinel/log-collector
tag: v1.28.0
- image: ghcr.io/nvidia/nvsentinel/file-server-cleanup
tag: v1.28.0
# The nvsentinel chart's own pins for the file server's third-party
# images. The weekly TestNVSentinelLogCollectorChartRender fails if a
# chart bump moves them; TestLogCollectorImagesPinnedEverywhere then
# keeps this list, the mirror lane and the docs on the new tags.
- image: docker.io/bitnamilegacy/nginx
tag: 1.27.2-debian-12-r2
- image: quay.io/martinhelmich/prometheus-nginxlog-exporter
tag: v1.10.0
# AICR's own pins in recipes/components/{psmdb-operator,nvsentinel-mongodb};
# TestRemediationImagesPinnedEverywhere fails if these drift apart.
- image: docker.io/percona/percona-server-mongodb-operator
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,12 @@ nvsentinel-event-exporter-e2e: ## Live Kind test: nvsentinel-event-exporter deli
echo "Running nvsentinel-event-exporter mixin e2e test..."; \
tests/e2e/nvsentinel-event-exporter/run.sh

.PHONY: nvsentinel-log-collector-e2e
nvsentinel-log-collector-e2e: ## Live Kind test: nvsentinel-log-collector captures a node's diagnostics into the in-cluster file server before remediation (#2619)
@set -e; \
echo "Running nvsentinel-log-collector mixin e2e test..."; \
tests/e2e/nvsentinel-log-collector/run.sh

.PHONY: npd-nvsentinel-object-monitor-e2e
npd-nvsentinel-object-monitor-e2e: ## Live Kind test: an NPD Node condition becomes an NVSentinel health event (#2614)
@set -e; \
Expand Down
2 changes: 1 addition & 1 deletion docs/contributor/recipe.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ Mixin files currently in the tree: `os-ubuntu`, `os-talos`, `os-amazonlinux`, `o
`nvsentinel-object-monitor`, `nvsentinel-nic-health-monitor`,
`nvsentinel-preflight`, `nvsentinel-slurm-drain-monitor`, `nvsentinel-observe`,
`nvsentinel-quarantine`, `nvsentinel-remediation`, `nvsentinel-slinky-drainer`,
`nvsentinel-health-events-analyzer`, `nvsentinel-event-exporter`, `nvsentinel-datastore-eks`, `npd`.
`nvsentinel-health-events-analyzer`, `nvsentinel-event-exporter`, `nvsentinel-datastore-eks`, `nvsentinel-log-collector`, `npd`.

The OS-scoped mixins (`os-ubuntu`, `os-talos`, `os-amazonlinux`, `os-sles`) are
mutually exclusive:
Expand Down
Loading
Loading