diff --git a/api/v1/store.go b/api/v1/store.go index 6caa89d..520ed0a 100644 --- a/api/v1/store.go +++ b/api/v1/store.go @@ -341,7 +341,7 @@ type RedisSpec struct { } type FPMSpec struct { - // +kubebuilder:validation:Enum=static;dynamic;ondemand + // +kubebuilder:validation:Enum=static;dynamic;ondemand;operator // +kubebuilder:default=static ProcessManagement string `json:"processManagement"` diff --git a/api/v1/store_env.go b/api/v1/store_env.go index b9a9000..ae90343 100644 --- a/api/v1/store_env.go +++ b/api/v1/store_env.go @@ -144,7 +144,7 @@ func (s *Store) getSessionCache() []corev1.EnvVar { } func (f *FPMSpec) getFPMConfiguration() []corev1.EnvVar { - if f.ProcessManagement != "dynamic" { + if f.ProcessManagement != "dynamic" && f.ProcessManagement != "operator" { return []corev1.EnvVar{ { Name: "FPM_PM", diff --git a/internal/deployment/admin.go b/internal/deployment/admin.go index 323e840..92cbd83 100644 --- a/internal/deployment/admin.go +++ b/internal/deployment/admin.go @@ -75,8 +75,16 @@ func AdminDeployment(store v1.Store) *appsv1.Deployment { annotations := util.GetDefaultContainerAnnotations(appName, store, store.Spec.AdminDeploymentContainer.Annotations) - // Merge containerSpec.ExtraEnvs to override with merged values from AdminDeploymentContainer envs := util.MergeEnv(store.GetEnv(), containerSpec.ExtraEnvs) + if store.Spec.FPM.ProcessManagement == "operator" { + if containerSpec.Resources.Limits.Memory() != nil && containerSpec.Resources.Limits.Memory().Value() != 0 { + phpEnvs := GetCalculatedPHPFPMValues(int(containerSpec.Resources.Limits.Memory().Value() / (1024 * 1024))) + envs = util.MergeEnv(envs, phpEnvs) + } else { + phpEnvs := GetCalculatedPHPFPMValues(2048) + envs = util.MergeEnv(envs, phpEnvs) + } + } containers := append(containerSpec.ExtraContainers, corev1.Container{ LivenessProbe: &corev1.Probe{ diff --git a/internal/deployment/storefront.go b/internal/deployment/storefront.go index ba99004..a9f81af 100644 --- a/internal/deployment/storefront.go +++ b/internal/deployment/storefront.go @@ -79,8 +79,17 @@ func StorefrontDeployment(store v1.Store) *appsv1.Deployment { annotations := util.GetDefaultContainerAnnotations(appName, store, store.Spec.StorefrontDeploymentContainer.Annotations) - // Merge containerSpec.ExtraEnvs to override with merged values from StorefrontDeploymentContainer envs := util.MergeEnv(store.GetEnv(), containerSpec.ExtraEnvs) + if store.Spec.FPM.ProcessManagement == "operator" { + if containerSpec.Resources.Limits.Memory() != nil && containerSpec.Resources.Limits.Memory().Value() != 0 { + phpEnvs := GetCalculatedPHPFPMValues(int(containerSpec.Resources.Limits.Memory().Value() / (1024 * 1024))) + envs = util.MergeEnv(envs, phpEnvs) + } else { + phpEnvs := GetCalculatedPHPFPMValues(2048) + envs = util.MergeEnv(envs, phpEnvs) + fmt.Println("envs: ", phpEnvs) + } + } containers := append(containerSpec.ExtraContainers, corev1.Container{ Name: DEPLOYMENT_STOREFRONT_CONTAINER_NAME, diff --git a/internal/deployment/util.go b/internal/deployment/util.go index 4f9d293..6619131 100644 --- a/internal/deployment/util.go +++ b/internal/deployment/util.go @@ -3,14 +3,23 @@ package deployment import ( "context" "fmt" + "math" v1 "github.com/shopware/shopware-operator/api/v1" appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" ) +const ( + startServersRatio = 0.25 + minSpareServersRatio = 0.2 + maxSpareServersRatio = 0.375 + memoryPerChildMiB = 80 //Every PHP-FPM process in an empty shop uses 70.6MiB +) + func getDeploymentCondition( deployment *appsv1.Deployment, storeReplicas int32, @@ -92,3 +101,33 @@ func GetStoreDeploymentImage( } return "", fmt.Errorf("could not find storefront deployment container") } + +func GetCalculatedPHPFPMValues(memoryLimitMiB int) []corev1.EnvVar { + maxChildren := int(math.Round(float64(memoryLimitMiB / memoryPerChildMiB))) + startServers := int(math.Round(float64(maxChildren) * startServersRatio)) + minSpare := int(math.Round(float64(maxChildren) * minSpareServersRatio)) + maxSpare := int(math.Round(float64(maxChildren)*maxSpareServersRatio) + 1) + + return []corev1.EnvVar{ + { + Name: "FPM_PM", + Value: "dynamic", + }, + { + Name: "FPM_PM_MAX_CHILDREN", + Value: fmt.Sprintf("%d", maxChildren), + }, + { + Name: "FPM_PM_START_SERVERS", + Value: fmt.Sprintf("%d", startServers), + }, + { + Name: "FPM_PM_MIN_SPARE_SERVERS", + Value: fmt.Sprintf("%d", minSpare), + }, + { + Name: "FPM_PM_MAX_SPARE_SERVERS", + Value: fmt.Sprintf("%d", maxSpare), + }, + } +}