diff --git a/api/v1alpha1/tenantcontrolplane_types.go b/api/v1alpha1/tenantcontrolplane_types.go index 40d1f05..a3411a3 100644 --- a/api/v1alpha1/tenantcontrolplane_types.go +++ b/api/v1alpha1/tenantcontrolplane_types.go @@ -4,6 +4,7 @@ package v1alpha1 import ( + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -107,6 +108,10 @@ type DeploymentSpec struct { // empty definition that uses the default runtime handler. // More info: https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class RuntimeClassName string `json:"runtimeClassName,omitempty"` + // Strategy describes how to replace existing pods with new ones for the given Tenant Control Plane. + // Default value is set to Rolling Update, with a blue/green strategy. + // +kubebuilder:default={type:"RollingUpdate",rollingUpdate:{maxUnavailable:0,maxSurge:"100%"}} + Strategy appsv1.DeploymentStrategy `json:"strategy,omitempty"` // If specified, the Tenant Control Plane pod's tolerations. // More info: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ Tolerations []corev1.Toleration `json:"tolerations,omitempty"` diff --git a/internal/builders/controlplane/deployment.go b/internal/builders/controlplane/deployment.go index d696997..9273099 100644 --- a/internal/builders/controlplane/deployment.go +++ b/internal/builders/controlplane/deployment.go @@ -59,17 +59,40 @@ func (d *Deployment) SetContainers(podSpec *corev1.PodSpec, tcp *kamajiv1alpha1. d.buildKine(podSpec, tcp) } -func (d *Deployment) SetStrategy(deployment *appsv1.DeploymentSpec) { - maxSurge := intstr.FromString("100%") - - maxUnavailable := intstr.FromInt(0) - +func (d *Deployment) SetStrategy(deployment *appsv1.DeploymentSpec, tcp *kamajiv1alpha1.TenantControlPlane) { deployment.Strategy = appsv1.DeploymentStrategy{ - Type: appsv1.RollingUpdateDeploymentStrategyType, - RollingUpdate: &appsv1.RollingUpdateDeployment{ + Type: tcp.Spec.ControlPlane.Deployment.Strategy.Type, + } + // If it's recreate strategy, we don't need any RollingUpdate params + if tcp.Spec.ControlPlane.Deployment.Strategy.Type == appsv1.RecreateDeploymentStrategyType { + tcp.Spec.ControlPlane.Deployment.Strategy.RollingUpdate = nil + + return + } + // In case of no RollingUpdate options, Kamaji will perform a blue/green rollout: + // this will ensure to avoid round-robin between old and new version, + // useful especially during the Kubernetes version upgrade phase. + if tcp.Spec.ControlPlane.Deployment.Strategy.RollingUpdate == nil { + maxSurge := intstr.FromString("100%") + + maxUnavailable := intstr.FromInt(0) + + deployment.Strategy.RollingUpdate = &appsv1.RollingUpdateDeployment{ MaxUnavailable: &maxUnavailable, MaxSurge: &maxSurge, - }, + } + + return + } + + deployment.Strategy.RollingUpdate = &appsv1.RollingUpdateDeployment{} + + if tcp.Spec.ControlPlane.Deployment.Strategy.RollingUpdate.MaxUnavailable != nil { + deployment.Strategy.RollingUpdate.MaxUnavailable = tcp.Spec.ControlPlane.Deployment.Strategy.RollingUpdate.MaxUnavailable + } + + if tcp.Spec.ControlPlane.Deployment.Strategy.RollingUpdate.MaxSurge != nil { + deployment.Strategy.RollingUpdate.MaxSurge = tcp.Spec.ControlPlane.Deployment.Strategy.RollingUpdate.MaxSurge } } diff --git a/internal/resources/k8s_deployment_resource.go b/internal/resources/k8s_deployment_resource.go index d0fdafd..e5da43d 100644 --- a/internal/resources/k8s_deployment_resource.go +++ b/internal/resources/k8s_deployment_resource.go @@ -82,7 +82,7 @@ func (r *KubernetesDeploymentResource) mutate(ctx context.Context, tenantControl d.SetNodeSelector(&r.resource.Spec.Template.Spec, tenantControlPlane) d.SetToleration(&r.resource.Spec.Template.Spec, tenantControlPlane) d.SetAffinity(&r.resource.Spec.Template.Spec, tenantControlPlane) - d.SetStrategy(&r.resource.Spec) + d.SetStrategy(&r.resource.Spec, tenantControlPlane) d.SetSelector(&r.resource.Spec, tenantControlPlane) d.SetTopologySpreadConstraints(&r.resource.Spec, tenantControlPlane.Spec.ControlPlane.Deployment.TopologySpreadConstraints) d.SetRuntimeClass(&r.resource.Spec.Template.Spec, tenantControlPlane)