From 4726d39688e116a64b6f0178b5800f6b6416ff43 Mon Sep 17 00:00:00 2001 From: Omar Pakker Date: Fri, 12 Nov 2021 15:01:05 +0100 Subject: [PATCH] osd: set blkdevmapper capabilities The OSD blkdevmapper init container relies on the MKNOD capability, which it does not actually request. As a result, deployments fail on Kubernetes clusters that do not happen to assign this capability to all containers by default. Solve this by updating the container spec securityContext to explicitly request the capability it relies on. Closes: https://github.com/rook/rook/issues/9156 Signed-off-by: Omar Pakker --- pkg/operator/ceph/cluster/osd/spec.go | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/pkg/operator/ceph/cluster/osd/spec.go b/pkg/operator/ceph/cluster/osd/spec.go index 4e0df032b116..7dd339f7a807 100644 --- a/pkg/operator/ceph/cluster/osd/spec.go +++ b/pkg/operator/ceph/cluster/osd/spec.go @@ -773,6 +773,19 @@ func (c *Cluster) getActivateOSDInitContainer(configDir, namespace, osdID string return volume, container } +// The blockdevmapper container copies the device node file, which is regarded as a device special file. +// To be able to perform this action, the CAP_MKNOD capability is required. +// Provide a securityContext which requests the MKNOD capability for the container to function properly. +func getBlockDevMapperContext() *v1.SecurityContext { + return &v1.SecurityContext{ + Capabilities: &v1.Capabilities{ + Add: []v1.Capability{ + "MKNOD", + }, + }, + } +} + // Currently we can't mount a block mode pv directly to a privileged container // So we mount it to a non privileged init container and then copy it to a common directory mounted inside init container // and the privileged provision container. @@ -792,7 +805,7 @@ func (c *Cluster) getPVCInitContainer(osdProps osdProperties) v1.Container { }, }, VolumeMounts: []v1.VolumeMount{getPvcOSDBridgeMount(osdProps.pvc.ClaimName)}, - SecurityContext: controller.PodSecurityContext(), + SecurityContext: getBlockDevMapperContext(), Resources: osdProps.resources, } } @@ -824,7 +837,7 @@ func (c *Cluster) getPVCInitContainerActivate(mountPath string, osdProps osdProp }, }, VolumeMounts: []v1.VolumeMount{getPvcOSDBridgeMountActivate(mountPath, osdProps.pvc.ClaimName)}, - SecurityContext: controller.PodSecurityContext(), + SecurityContext: getBlockDevMapperContext(), Resources: osdProps.resources, } } @@ -931,7 +944,7 @@ func (c *Cluster) generateEncryptionCopyBlockContainer(resources v1.ResourceRequ // volumeMountPVCName is crucial, especially when the block we copy is the metadata block // its value must be the name of the block PV so that all init containers use the same bridge (the emptyDir shared by all the init containers) VolumeMounts: []v1.VolumeMount{getPvcOSDBridgeMountActivate(mountPath, volumeMountPVCName), getDeviceMapperMount()}, - SecurityContext: controller.PodSecurityContext(), + SecurityContext: getBlockDevMapperContext(), Resources: resources, } } @@ -978,7 +991,7 @@ func (c *Cluster) getPVCMetadataInitContainer(mountPath string, osdProps osdProp Name: fmt.Sprintf("%s-bridge", osdProps.metadataPVC.ClaimName), }, }, - SecurityContext: controller.PodSecurityContext(), + SecurityContext: getBlockDevMapperContext(), Resources: osdProps.resources, } } @@ -1012,7 +1025,7 @@ func (c *Cluster) getPVCMetadataInitContainerActivate(mountPath string, osdProps // We need to call getPvcOSDBridgeMountActivate() so that we can copy the metadata block into the "main" empty dir // This empty dir is passed along every init container VolumeMounts: []v1.VolumeMount{getPvcOSDBridgeMountActivate(mountPath, osdProps.pvc.ClaimName)}, - SecurityContext: controller.PodSecurityContext(), + SecurityContext: getBlockDevMapperContext(), Resources: osdProps.resources, } } @@ -1038,7 +1051,7 @@ func (c *Cluster) getPVCWalInitContainer(mountPath string, osdProps osdPropertie Name: fmt.Sprintf("%s-bridge", osdProps.walPVC.ClaimName), }, }, - SecurityContext: controller.PodSecurityContext(), + SecurityContext: getBlockDevMapperContext(), Resources: osdProps.resources, } } @@ -1072,7 +1085,7 @@ func (c *Cluster) getPVCWalInitContainerActivate(mountPath string, osdProps osdP // We need to call getPvcOSDBridgeMountActivate() so that we can copy the wal block into the "main" empty dir // This empty dir is passed along every init container VolumeMounts: []v1.VolumeMount{getPvcOSDBridgeMountActivate(mountPath, osdProps.pvc.ClaimName)}, - SecurityContext: controller.PodSecurityContext(), + SecurityContext: getBlockDevMapperContext(), Resources: osdProps.resources, } }