From 7eb9371d844853e6b688d2c42f467b8f4d30056a Mon Sep 17 00:00:00 2001 From: yamatcha Date: Wed, 29 Jan 2025 04:53:10 +0000 Subject: [PATCH] Add securityContext field to overwriteContainers --- api/v1beta2/mysqlcluster_types.go | 23 ++++++ api/v1beta2/zz_generated.deepcopy.go | 10 +++ .../templates/generated/crds/moco_crds.yaml | 75 +++++++++++++++++ .../bases/moco.cybozu.com_mysqlclusters.yaml | 82 +++++++++++++++++++ ...inition_mysqlclusters.moco.cybozu.com.yaml | 82 +++++++++++++++++++ controllers/mysql_container.go | 3 + controllers/mysqlcluster_controller_test.go | 21 +++-- docs/crd_mysqlcluster_v1beta2.md | 3 +- docs/customize-system-container.md | 11 ++- 9 files changed, 299 insertions(+), 11 deletions(-) diff --git a/api/v1beta2/mysqlcluster_types.go b/api/v1beta2/mysqlcluster_types.go index 1e2aa592..6ab54e1e 100644 --- a/api/v1beta2/mysqlcluster_types.go +++ b/api/v1beta2/mysqlcluster_types.go @@ -455,6 +455,8 @@ const ( ) // OverwriteContainer defines the container spec used for overwriting. +// For more information, please read the following documentation. +// https://cybozu-go.github.io/moco/customize-system-container.html type OverwriteContainer struct { // Name of the container to overwrite. // +kubebuilder:validation:Required @@ -463,6 +465,10 @@ type OverwriteContainer struct { // Resources is the container resource to be overwritten. // +optional Resources *ResourceRequirementsApplyConfiguration `json:"resources,omitempty"` + + // SecurityContext is the container SecurityContext to be overwritten. + // +optional + SecurityContext *SecurityContextApplyConfiguration `json:"securityContext,omitempty"` } // ResourceRequirementsApplyConfiguration is the type defined to implement the DeepCopy method. @@ -482,6 +488,23 @@ func (in *ResourceRequirementsApplyConfiguration) DeepCopy() *ResourceRequiremen return out } +// SecurityContextApplyConfiguration is the type defined to implement the DeepCopy method. +type SecurityContextApplyConfiguration corev1ac.SecurityContextApplyConfiguration + +// DeepCopy is copying the receiver, creating a new OverwriteContainer. +func (in *SecurityContextApplyConfiguration) DeepCopy() *SecurityContextApplyConfiguration { + out := new(SecurityContextApplyConfiguration) + bytes, err := json.Marshal(in) + if err != nil { + panic("Failed to marshal") + } + err = json.Unmarshal(bytes, out) + if err != nil { + panic("Failed to unmarshal") + } + return out +} + // PersistentVolumeClaimSpecApplyConfiguration is the type defined to implement the DeepCopy method. type PersistentVolumeClaimSpecApplyConfiguration corev1ac.PersistentVolumeClaimSpecApplyConfiguration diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go index b12bdec4..3cd5a58e 100644 --- a/api/v1beta2/zz_generated.deepcopy.go +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -430,6 +430,10 @@ func (in *OverwriteContainer) DeepCopyInto(out *OverwriteContainer) { in, out := &in.Resources, &out.Resources *out = (*in).DeepCopy() } + if in.SecurityContext != nil { + in, out := &in.SecurityContext, &out.SecurityContext + *out = (*in).DeepCopy() + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OverwriteContainer. @@ -533,6 +537,12 @@ func (in *RestoreSpec) DeepCopy() *RestoreSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityContextApplyConfiguration) DeepCopyInto(out *SecurityContextApplyConfiguration) { + clone := in.DeepCopy() + *out = *clone +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceSpecApplyConfiguration) DeepCopyInto(out *ServiceSpecApplyConfiguration) { clone := in.DeepCopy() diff --git a/charts/moco/templates/generated/crds/moco_crds.yaml b/charts/moco/templates/generated/crds/moco_crds.yaml index af94f164..4e8ccaed 100644 --- a/charts/moco/templates/generated/crds/moco_crds.yaml +++ b/charts/moco/templates/generated/crds/moco_crds.yaml @@ -2342,6 +2342,81 @@ spec: description: ResourceList is a set of (resource name,... type: object type: object + securityContext: + description: SecurityContext is the container SecurityContext... + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + description: AppArmorProfileApplyConfiguration represents a... + properties: + localhostProfile: + type: string + type: + type: string + type: object + capabilities: + description: CapabilitiesApplyConfiguration represents a... + properties: + add: + items: + description: Capability represent POSIX capabilities type + type: string + type: array + drop: + items: + description: Capability represent POSIX capabilities type + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + description: SELinuxOptionsApplyConfiguration represents a... + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + description: SeccompProfileApplyConfiguration represents a... + properties: + localhostProfile: + type: string + type: + description: SeccompProfileType defines the supported seccomp... + type: string + type: object + windowsOptions: + description: WindowsSecurityContextOptionsApplyConfiguration... + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object required: - name type: object diff --git a/config/crd/bases/moco.cybozu.com_mysqlclusters.yaml b/config/crd/bases/moco.cybozu.com_mysqlclusters.yaml index 31ee1287..7934a39b 100644 --- a/config/crd/bases/moco.cybozu.com_mysqlclusters.yaml +++ b/config/crd/bases/moco.cybozu.com_mysqlclusters.yaml @@ -160,6 +160,88 @@ spec: description: ResourceList is a set of (resource name,... type: object type: object + securityContext: + description: SecurityContext is the container SecurityContext... + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + description: AppArmorProfileApplyConfiguration represents + a... + properties: + localhostProfile: + type: string + type: + type: string + type: object + capabilities: + description: CapabilitiesApplyConfiguration represents + a... + properties: + add: + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + description: SELinuxOptionsApplyConfiguration represents + a... + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + description: SeccompProfileApplyConfiguration represents + a... + properties: + localhostProfile: + type: string + type: + description: SeccompProfileType defines the supported + seccomp... + type: string + type: object + windowsOptions: + description: WindowsSecurityContextOptionsApplyConfiguration... + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object required: - name type: object diff --git a/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_mysqlclusters.moco.cybozu.com.yaml b/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_mysqlclusters.moco.cybozu.com.yaml index d923dffc..947278af 100644 --- a/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_mysqlclusters.moco.cybozu.com.yaml +++ b/config/crd/tests/apiextensions.k8s.io_v1_customresourcedefinition_mysqlclusters.moco.cybozu.com.yaml @@ -160,6 +160,88 @@ spec: description: ResourceList is a set of (resource name,... type: object type: object + securityContext: + description: SecurityContext is the container SecurityContext... + properties: + allowPrivilegeEscalation: + type: boolean + appArmorProfile: + description: AppArmorProfileApplyConfiguration represents + a... + properties: + localhostProfile: + type: string + type: + type: string + type: object + capabilities: + description: CapabilitiesApplyConfiguration represents + a... + properties: + add: + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + type: boolean + procMount: + type: string + readOnlyRootFilesystem: + type: boolean + runAsGroup: + format: int64 + type: integer + runAsNonRoot: + type: boolean + runAsUser: + format: int64 + type: integer + seLinuxOptions: + description: SELinuxOptionsApplyConfiguration represents + a... + properties: + level: + type: string + role: + type: string + type: + type: string + user: + type: string + type: object + seccompProfile: + description: SeccompProfileApplyConfiguration represents + a... + properties: + localhostProfile: + type: string + type: + description: SeccompProfileType defines the supported + seccomp... + type: string + type: object + windowsOptions: + description: WindowsSecurityContextOptionsApplyConfiguration... + properties: + gmsaCredentialSpec: + type: string + gmsaCredentialSpecName: + type: string + hostProcess: + type: boolean + runAsUserName: + type: string + type: object + type: object required: - name type: object diff --git a/controllers/mysql_container.go b/controllers/mysql_container.go index 44e84752..0717d89d 100644 --- a/controllers/mysql_container.go +++ b/controllers/mysql_container.go @@ -451,6 +451,9 @@ func updateContainerWithOverwriteContainers(cluster *mocov1beta2.MySQLCluster, c if overwrite.Resources != nil { container.WithResources((*corev1ac.ResourceRequirementsApplyConfiguration)(overwrite.Resources)) } + if overwrite.SecurityContext != nil { + container.WithSecurityContext((*corev1ac.SecurityContextApplyConfiguration)(overwrite.SecurityContext)) + } } } } diff --git a/controllers/mysqlcluster_controller_test.go b/controllers/mysqlcluster_controller_test.go index 04ca76ca..bc27b3d7 100644 --- a/controllers/mysqlcluster_controller_test.go +++ b/controllers/mysqlcluster_controller_test.go @@ -1053,6 +1053,8 @@ var _ = Describe("MySQLCluster reconciler", func() { WithLimits(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("100m")}). WithRequests(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("100m")}), ), + SecurityContext: (*mocov1beta2.SecurityContextApplyConfiguration)(corev1ac.SecurityContext(). + WithCapabilities(corev1ac.Capabilities().WithDrop("ALL"))), }, { Name: mocov1beta2.ExporterContainerName, @@ -1060,6 +1062,8 @@ var _ = Describe("MySQLCluster reconciler", func() { WithLimits(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("200m")}). WithRequests(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("200m")}), ), + SecurityContext: (*mocov1beta2.SecurityContextApplyConfiguration)(corev1ac.SecurityContext(). + WithCapabilities(corev1ac.Capabilities().WithDrop("ALL"))), }, { Name: mocov1beta2.InitContainerName, @@ -1067,6 +1071,8 @@ var _ = Describe("MySQLCluster reconciler", func() { WithLimits(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("300m")}). WithRequests(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("300m")}), ), + SecurityContext: (*mocov1beta2.SecurityContextApplyConfiguration)(corev1ac.SecurityContext(). + WithCapabilities(corev1ac.Capabilities().WithAdd("SYS_NICE"))), }, } @@ -1157,10 +1163,8 @@ var _ = Describe("MySQLCluster reconciler", func() { for _, c := range sts.Spec.Template.Spec.Containers { Expect(c.Name).NotTo(Equal(constants.SlowQueryLogAgentContainerName)) Expect(c.SecurityContext).NotTo(BeNil()) - Expect(c.SecurityContext.RunAsUser).NotTo(BeNil()) - Expect(*c.SecurityContext.RunAsUser).To(Equal(int64(constants.ContainerUID))) - Expect(c.SecurityContext.RunAsGroup).NotTo(BeNil()) - Expect(*c.SecurityContext.RunAsGroup).To(Equal(int64(constants.ContainerGID))) + Expect(c.SecurityContext.RunAsUser).To(BeNil()) + Expect(c.SecurityContext.RunAsGroup).To(BeNil()) switch c.Name { case constants.MysqldContainerName: Expect(c.StartupProbe).NotTo(BeNil()) @@ -1176,12 +1180,14 @@ var _ = Describe("MySQLCluster reconciler", func() { Expect(c.Args).To(ContainElements("--mysqld-localhost", "true")) Expect(c.Resources.Requests).To(Equal(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("100m")})) Expect(c.Resources.Limits).To(Equal(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("100m")})) + Expect(c.SecurityContext.Capabilities.Drop).To(Equal("ALL")) case constants.ExporterContainerName: foundExporter = true Expect(c.Image).To(Equal(testExporterImage)) Expect(c.Args).To(HaveLen(3)) Expect(c.Resources.Requests).To(Equal(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("200m")})) Expect(c.Resources.Limits).To(Equal(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("200m")})) + Expect(c.SecurityContext.Capabilities.Drop).To(Equal("ALL")) case "dummy": foundDummyContainer = true Expect(c.Image).To(Equal("dummy:latest")) @@ -1194,15 +1200,14 @@ var _ = Describe("MySQLCluster reconciler", func() { foundInitDummyContainer := false for _, c := range sts.Spec.Template.Spec.InitContainers { Expect(c.SecurityContext).NotTo(BeNil()) - Expect(c.SecurityContext.RunAsUser).NotTo(BeNil()) - Expect(*c.SecurityContext.RunAsUser).To(Equal(int64(constants.ContainerUID))) - Expect(c.SecurityContext.RunAsGroup).NotTo(BeNil()) - Expect(*c.SecurityContext.RunAsGroup).To(Equal(int64(constants.ContainerGID))) + Expect(c.SecurityContext.RunAsUser).To(BeNil()) + Expect(c.SecurityContext.RunAsGroup).To(BeNil()) switch c.Name { case constants.InitContainerName: Expect(c.Args).To(ContainElement(fmt.Sprintf("%s=1", constants.MocoInitLowerCaseTableNamesFlag))) Expect(c.Resources.Requests).To(Equal(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("300m")})) Expect(c.Resources.Limits).To(Equal(corev1.ResourceList{corev1.ResourceCPU: resource.MustParse("300m")})) + Expect(c.SecurityContext.Capabilities.Add).To(Equal("SYS_NICE")) case "init-dummy": foundInitDummyContainer = true Expect(c.Image).To(Equal("init-dummy:latest")) diff --git a/docs/crd_mysqlcluster_v1beta2.md b/docs/crd_mysqlcluster_v1beta2.md index 8e9c589b..0fb40eda 100644 --- a/docs/crd_mysqlcluster_v1beta2.md +++ b/docs/crd_mysqlcluster_v1beta2.md @@ -122,12 +122,13 @@ ObjectMeta is metadata of objects. This is partially copied from metav1.ObjectMe #### OverwriteContainer -OverwriteContainer defines the container spec used for overwriting. +OverwriteContainer defines the container spec used for overwriting. For more information, please read the following documentation. https://cybozu-go.github.io/moco/customize-system-container.html | Field | Description | Scheme | Required | | ----- | ----------- | ------ | -------- | | name | Name of the container to overwrite. | [OverwriteableContainerName](https://pkg.go.dev/github.com/cybozu-go/moco/api/v1beta2#OverwriteableContainerName) | true | | resources | Resources is the container resource to be overwritten. | *[ResourceRequirementsApplyConfiguration](https://pkg.go.dev/k8s.io/client-go/applyconfigurations/core/v1#ResourceRequirementsApplyConfiguration) | false | +| securityContext | SecurityContext is the container SecurityContext to be overwritten. | *SecurityContextApplyConfiguration | false | [Back to Custom Resources](#custom-resources) diff --git a/docs/customize-system-container.md b/docs/customize-system-container.md index ea3e184f..63844f73 100644 --- a/docs/customize-system-container.md +++ b/docs/customize-system-container.md @@ -4,7 +4,7 @@ MOCO has containers that are automatically added by the system in addition to co (e.g. `agent`, `moco-init` etc...) The `MySQLCluster.spec.podTemplate.overwriteContainers` field can be used to overwrite such containers. -Currently, only container resources can be overwritten. +Currently, only container resources and securityContexts can be overwritten. `overwriteContainers` is only available in MySQLCluster v1beta2. ```yaml @@ -24,11 +24,15 @@ spec: resources: requests: cpu: 50m + - name: moco-init + securityContext: + capabilities: + add: ["SYS_NICE"] ``` ## System containers -The following is a list of system containers used by MOCO. +The following is a list of system containers and default resource settings. Specifying container names in `overwriteContainers` that are not listed here will result in an error in API validation. | Name | Default CPU Requests/Limits | Default Memory Requests/Limits | Description | @@ -37,3 +41,6 @@ Specifying container names in `overwriteContainers` that are not listed here wil | moco-init | `100m` / `100m` | `300Mi` / `300Mi` | Initializes MySQL data directory and create a configuration snippet to give instance specific configuration values such as server_id and admin_address. | | slow-log | `100m` / `100m` | `20Mi` / `20Mi` | Sidecar container for outputting slow query logs. | | mysqld-exporter | `200m` / `200m` | `100Mi` / `100Mi` | MySQL server exporter sidecar container. | + +All system containers are configured runAsUser=1000 and runAsGroup=1000 in securityContext. +If you specify securityContext in `overwriteContainers`, this configuration of specified container will be overwritten. \ No newline at end of file