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
52 changes: 32 additions & 20 deletions controllers/object_controls.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,67 +264,75 @@ var SubscriptionPathMap = map[string](MountPathToVolumeSource){
"/run/secrets/etc-pki-entitlement": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/pki/entitlement",
Type: ptr.To(corev1.HostPathDirectory),
Type: new(corev1.HostPathDirectoryOrCreate),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟨 Absent subscriptions modify host configuration

On unsubscribed nodes, DirectoryOrCreate and FileOrCreate create subscription paths on the host. Kubelet changes protected host configuration instead of leaving missing subscription data untouched.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

},
},
"/run/secrets/redhat.repo": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/yum.repos.d/redhat.repo",
Type: ptr.To(corev1.HostPathFile),
Type: new(corev1.HostPathFileOrCreate),
},
},
"/run/secrets/rhsm": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/rhsm",
Type: ptr.To(corev1.HostPathDirectory),
Type: new(corev1.HostPathDirectoryOrCreate),
},
},
// FileOrCreate does not create parents. A separate directory volume
// lets kubelet create the repo directory and retry file setup if needed.
"/run/secrets/yum.repos.d": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/yum.repos.d",
Type: new(corev1.HostPathDirectoryOrCreate),
Comment thread
tariq1890 marked this conversation as resolved.
},
},
},
"rhcos": {
"/run/secrets/etc-pki-entitlement": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/pki/entitlement",
Type: ptr.To(corev1.HostPathDirectory),
Type: new(corev1.HostPathDirectory),
},
},
"/run/secrets/redhat.repo": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/yum.repos.d/redhat.repo",
Type: ptr.To(corev1.HostPathFile),
Type: new(corev1.HostPathFile),
},
},
"/run/secrets/rhsm": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/rhsm",
Type: ptr.To(corev1.HostPathDirectory),
Type: new(corev1.HostPathDirectory),
},
},
},
"sles": {
"/etc/zypp/credentials.d": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/zypp/credentials.d",
Type: ptr.To(corev1.HostPathDirectory),
Type: new(corev1.HostPathDirectoryOrCreate),
},
},
"/etc/SUSEConnect": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/SUSEConnect",
Type: ptr.To(corev1.HostPathFileOrCreate),
Type: new(corev1.HostPathFileOrCreate),
},
},
},
"sl-micro": {
"/etc/zypp/credentials.d": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/zypp/credentials.d",
Type: ptr.To(corev1.HostPathDirectory),
Type: new(corev1.HostPathDirectoryOrCreate),
Comment thread
tariq1890 marked this conversation as resolved.
},
},
"/etc/SUSEConnect": corev1.VolumeSource{
HostPath: &corev1.HostPathVolumeSource{
Path: "/etc/SUSEConnect",
Type: ptr.To(corev1.HostPathFileOrCreate),
Type: new(corev1.HostPathFileOrCreate),
},
},
},
Expand Down Expand Up @@ -3786,15 +3794,10 @@ func transformDriverContainer(obj *appsv1.DaemonSet, config *gpuv1.ClusterPolicy

// set up subscription entitlements for RHEL(using K8s with a non-CRIO runtime) and SLES
if (osID == "rhel" && n.openshift == "" && n.runtime != gpuv1.CRIO) || osID == "sles" || osID == "sl-micro" {
pathToVolumeSource := MountPathToVolumeSource{}
if config.Driver.RepoConfig != nil && config.Driver.RepoConfig.ConfigMapName != "" && osID == "rhel" {
n.logger.Info("Skipping host subscription mounts because repoConfig is enabled", "OS", osID)
} else {
n.logger.Info("Mounting subscriptions into the driver container", "OS", osID)
pathToVolumeSource, err = n.getSubscriptionPathsToVolumeSources()
if err != nil {
return fmt.Errorf("ERROR: failed to get path items for subscription entitlements: %w", err)
}
n.logger.Info("Mounting subscriptions into the driver container", "OS", osID)
pathToVolumeSource, err := n.getSubscriptionPathsToVolumeSources()
if err != nil {
return fmt.Errorf("ERROR: failed to get path items for subscription entitlements: %w", err)
}

// sort host path volumes to ensure ordering is preserved when adding to pod spec
Expand All @@ -3812,7 +3815,16 @@ func transformDriverContainer(obj *appsv1.DaemonSet, config *gpuv1.ClusterPolicy
MountPath: mountPath,
ReadOnly: true,
}
driverContainer.VolumeMounts = append(driverContainer.VolumeMounts, volMountSubscription)
if mountPath == "/run/secrets/yum.repos.d" {
// The parent directory is needed only for kubelet's file creation.
manager := findContainerByName(podSpec.InitContainers, "k8s-driver-manager")
if manager == nil {
return fmt.Errorf("k8s-driver-manager initContainer is missing from the driver daemonset manifest")
}
manager.VolumeMounts = append(manager.VolumeMounts, volMountSubscription)
} else {
driverContainer.VolumeMounts = append(driverContainer.VolumeMounts, volMountSubscription)
}
Comment thread
tariq1890 marked this conversation as resolved.

subscriptionVol := corev1.Volume{Name: volMountSubscriptionName, VolumeSource: pathToVolumeSource[mountPath]}
podSpec.Volumes = append(podSpec.Volumes, subscriptionVol)
Expand Down
100 changes: 78 additions & 22 deletions controllers/transforms_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4861,41 +4861,72 @@ func TestTransformDriverSubscriptionMounts(t *testing.T) {
Namespace: "test-ns",
},
Data: map[string]string{
"redhat.repo": "[test-repo]",
"custom.repo": "[test-repo]",
},
}
mockClient := fake.NewFakeClient(repoConfigMap)

testCases := []struct {
description string
rhelHostPaths := map[string]corev1.HostPathType{
"/etc/pki/entitlement": corev1.HostPathDirectoryOrCreate,
"/etc/yum.repos.d/redhat.repo": corev1.HostPathFileOrCreate,
"/etc/rhsm": corev1.HostPathDirectoryOrCreate,
"/etc/yum.repos.d": corev1.HostPathDirectoryOrCreate,
}
rhelDriverMounts := []corev1.VolumeMount{
{Name: "subscription-config-0", MountPath: "/run/secrets/etc-pki-entitlement", ReadOnly: true},
{Name: "subscription-config-1", MountPath: "/run/secrets/redhat.repo", ReadOnly: true},
{Name: "subscription-config-2", MountPath: "/run/secrets/rhsm", ReadOnly: true},
}
suseDriverMounts := []corev1.VolumeMount{
{Name: "subscription-config-0", MountPath: "/etc/SUSEConnect", ReadOnly: true},
{Name: "subscription-config-1", MountPath: "/etc/zypp/credentials.d", ReadOnly: true},
}
testCases := map[string]struct {
osRelease string
osTag string
runtime string
repoConfigEnabled bool
expectSubscriptionMounts bool
expectedSubscriptionHostMap map[string]corev1.HostPathType
expectedSubscriptionMounts []corev1.VolumeMount
}{
{
description: "rhel with repo config skips host subscription mounts",
osRelease: "rhel",
osTag: "rhel8.10",
repoConfigEnabled: true,
expectSubscriptionMounts: false,
"rhel with custom repositories retains subscription mounts": {
osRelease: "rhel", osTag: "rhel8.10", runtime: "containerd",
repoConfigEnabled: true, expectedSubscriptionHostMap: rhelHostPaths, expectedSubscriptionMounts: rhelDriverMounts,
},
{
description: "rhel without repo config mounts host subscription paths",
osRelease: "rhel",
osTag: "rhel8.10",
expectSubscriptionMounts: true,
"rhel without custom repositories mounts subscription paths": {
osRelease: "rhel", osTag: "rhel8.10", runtime: "containerd",
expectedSubscriptionHostMap: rhelHostPaths, expectedSubscriptionMounts: rhelDriverMounts,
},
"rhel with docker mounts subscription paths": {
osRelease: "rhel", osTag: "rhel8.10", runtime: "docker",
repoConfigEnabled: true, expectedSubscriptionHostMap: rhelHostPaths, expectedSubscriptionMounts: rhelDriverMounts,
},
"rhel with crio skips subscription mounts": {
osRelease: "rhel", osTag: "rhel8.10", runtime: "crio", repoConfigEnabled: true,
},
"ubuntu skips subscription mounts": {
osRelease: "ubuntu", osTag: "ubuntu22.04", runtime: "containerd", repoConfigEnabled: true,
},
"sles creates missing subscription paths": {
osRelease: "sles", osTag: "sles15.6", runtime: "containerd", repoConfigEnabled: true,
expectedSubscriptionMounts: suseDriverMounts,
expectedSubscriptionHostMap: map[string]corev1.HostPathType{
"/etc/zypp/credentials.d": corev1.HostPathDirectoryOrCreate,
"/etc/SUSEConnect": corev1.HostPathFileOrCreate,
},
},
"sl-micro creates missing subscription paths": {
osRelease: "sl-micro", osTag: "sl-micro6.1", runtime: "containerd", repoConfigEnabled: true,
expectedSubscriptionMounts: suseDriverMounts,
expectedSubscriptionHostMap: map[string]corev1.HostPathType{
"/etc/pki/entitlement": corev1.HostPathDirectory,
"/etc/yum.repos.d/redhat.repo": corev1.HostPathFile,
"/etc/rhsm": corev1.HostPathDirectory,
"/etc/zypp/credentials.d": corev1.HostPathDirectoryOrCreate,
"/etc/SUSEConnect": corev1.HostPathFileOrCreate,
},
},
}

for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
ds := NewDaemonset().WithContainer(corev1.Container{Name: "nvidia-driver-ctr"}).
WithInitContainer(corev1.Container{Name: "k8s-driver-manager"})
cpSpec := &gpuv1.ClusterPolicySpec{
Expand All @@ -4918,7 +4949,7 @@ func TestTransformDriverSubscriptionMounts(t *testing.T) {

err := TransformDriver(ds.DaemonSet, cpSpec, ClusterPolicyController{
client: mockClient,
runtime: gpuv1.Containerd,
runtime: gpuv1.Runtime(tc.runtime),
operatorNamespace: "test-ns",
logger: ctrl.Log.WithName("test"),
gpuNodeOSRelease: tc.osRelease,
Expand All @@ -4929,7 +4960,32 @@ func TestTransformDriverSubscriptionMounts(t *testing.T) {
driverContainer := findContainerByName(ds.Spec.Template.Spec.Containers, "nvidia-driver-ctr")
require.NotNil(t, driverContainer)
assertSubscriptionHostPathVolumesForTransform(t, ds.Spec.Template.Spec.Volumes, tc.expectedSubscriptionHostMap)
assert.Equal(t, tc.expectSubscriptionMounts, hasSubscriptionVolumeMountForTransform(driverContainer.VolumeMounts))
expectedAdditionalMounts := append([]corev1.VolumeMount{}, tc.expectedSubscriptionMounts...)
if tc.repoConfigEnabled {
repoPaths := map[string]string{
"rhel": "/etc/yum.repos.d/custom.repo",
"ubuntu": "/etc/apt/sources.list.d/custom.repo",
"sles": "/etc/zypp/repos.d/custom.repo",
"sl-micro": "/etc/zypp/repos.d/custom.repo",
}
expectedAdditionalMounts = append(expectedAdditionalMounts, corev1.VolumeMount{
Name: "test-repo-config", MountPath: repoPaths[tc.osRelease],
SubPath: "custom.repo", ReadOnly: true,
})
}
assert.ElementsMatch(t, expectedAdditionalMounts, driverContainer.VolumeMounts)
expectedManagerMounts := []corev1.VolumeMount{}
if tc.osRelease == "rhel" && len(tc.expectedSubscriptionMounts) > 0 {
expectedManagerMounts = append(expectedManagerMounts, corev1.VolumeMount{
Name: "subscription-config-3", MountPath: "/run/secrets/yum.repos.d", ReadOnly: true,
})
}

manager := findContainerByName(ds.Spec.Template.Spec.InitContainers, "k8s-driver-manager")
require.NotNil(t, manager)
assert.ElementsMatch(t, expectedManagerMounts, manager.VolumeMounts)

assert.Equal(t, len(tc.expectedSubscriptionHostMap) > 0, hasSubscriptionVolumeMountForTransform(driverContainer.VolumeMounts))
})
}
}
Expand Down
5 changes: 3 additions & 2 deletions internal/state/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ type precompiledSpec struct {
}

type additionalConfigs struct {
VolumeMounts []corev1.VolumeMount
Volumes []corev1.Volume
DriverManagerVolumeMounts []corev1.VolumeMount
VolumeMounts []corev1.VolumeMount
Volumes []corev1.Volume
}

type driverRenderData struct {
Expand Down
Loading
Loading