From 0c33ade1bca79ac1cada33608a596b04d005af2a Mon Sep 17 00:00:00 2001 From: Damien Ciabrini Date: Wed, 22 Mar 2023 16:16:20 +0000 Subject: [PATCH] galera: support for node selection and pod affinity Add a spec option to drive the node selection during pod assignment, as well as preferred pod antiafinity to separate galera pods when possible. --- api/bases/mariadb.openstack.org_galeras.yaml | 6 ++++++ api/v1beta1/galera_types.go | 3 +++ api/v1beta1/zz_generated.deepcopy.go | 9 +++++++- .../bases/mariadb.openstack.org_galeras.yaml | 6 ++++++ pkg/statefulset.go | 21 +++++++++++++++++-- 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/api/bases/mariadb.openstack.org_galeras.yaml b/api/bases/mariadb.openstack.org_galeras.yaml index e7f8b004..2b7632f8 100644 --- a/api/bases/mariadb.openstack.org_galeras.yaml +++ b/api/bases/mariadb.openstack.org_galeras.yaml @@ -55,6 +55,12 @@ spec: default: quay.io/tripleozedcentos9/openstack-mariadb:current-tripleo description: Name of the galera container image to run type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector to target subset of worker nodes running + this service + type: object replicas: default: 1 description: Size of the galera cluster deployment diff --git a/api/v1beta1/galera_types.go b/api/v1beta1/galera_types.go index 93786b99..be1e3afa 100644 --- a/api/v1beta1/galera_types.go +++ b/api/v1beta1/galera_types.go @@ -41,6 +41,9 @@ type GaleraSpec struct { // Size of the galera cluster deployment Replicas int32 `json:"replicas"` // +kubebuilder:validation:Optional + // NodeSelector to target subset of worker nodes running this service + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + // +kubebuilder:validation:Optional // Adoption configuration AdoptionRedirect AdoptionRedirectSpec `json:"adoptionRedirect"` } diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 989b2a90..bc2e2bee 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -46,7 +46,7 @@ func (in *Galera) DeepCopyInto(out *Galera) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - out.Spec = in.Spec + in.Spec.DeepCopyInto(&out.Spec) in.Status.DeepCopyInto(&out.Status) } @@ -118,6 +118,13 @@ func (in *GaleraList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GaleraSpec) DeepCopyInto(out *GaleraSpec) { *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } out.AdoptionRedirect = in.AdoptionRedirect } diff --git a/config/crd/bases/mariadb.openstack.org_galeras.yaml b/config/crd/bases/mariadb.openstack.org_galeras.yaml index e7f8b004..2b7632f8 100644 --- a/config/crd/bases/mariadb.openstack.org_galeras.yaml +++ b/config/crd/bases/mariadb.openstack.org_galeras.yaml @@ -55,6 +55,12 @@ spec: default: quay.io/tripleozedcentos9/openstack-mariadb:current-tripleo description: Name of the galera container image to run type: string + nodeSelector: + additionalProperties: + type: string + description: NodeSelector to target subset of worker nodes running + this service + type: object replicas: default: 1 description: Size of the galera cluster deployment diff --git a/pkg/statefulset.go b/pkg/statefulset.go index 7f3828e6..2333e69d 100644 --- a/pkg/statefulset.go +++ b/pkg/statefulset.go @@ -1,6 +1,8 @@ package mariadb import ( + common "github.com/openstack-k8s-operators/lib-common/modules/common" + "github.com/openstack-k8s-operators/lib-common/modules/common/affinity" mariadbv1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -16,7 +18,7 @@ func StatefulSet(g *mariadbv1.Galera) *appsv1.StatefulSet { runAsUser := int64(0) storage := g.Spec.StorageClass storageRequest := resource.MustParse(g.Spec.StorageRequest) - dep := &appsv1.StatefulSet{ + sts := &appsv1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: g.Namespace, @@ -259,5 +261,20 @@ func StatefulSet(g *mariadbv1.Galera) *appsv1.StatefulSet { }, }, } - return dep + + // If possible two pods of the same service should not + // run on the same worker node. If this is not possible + // the get still created on the same worker node. + sts.Spec.Template.Spec.Affinity = affinity.DistributePods( + common.AppSelector, + []string{ + name, + }, + corev1.LabelHostname, + ) + if g.Spec.NodeSelector != nil && len(g.Spec.NodeSelector) > 0 { + sts.Spec.Template.Spec.NodeSelector = g.Spec.NodeSelector + } + + return sts }