Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:cherry-pick cpu 和 memory requests 支持可配置 #1210

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 41 additions & 17 deletions operator/api/v1alpha1/projectconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,27 @@ type PaaSAnalysisConfig struct {
Enabled bool `json:"enabled"`
}

// ResLimitConfig contains bkapp resource limit
type ResLimitConfig struct {
// ProcDefaultCPULimits is process's default cpu quota
ProcDefaultCPULimits string `json:"procDefaultCPULimits"`
// ResLimitsConfig contains bkapp resource limits
type ResLimitsConfig struct {
// ProcDefaultCPULimit is process's default cpu quota
ProcDefaultCPULimit string `json:"procDefaultCPULimit"`

// ProcDefaultMemLimits is process's default memory quota
ProcDefaultMemLimits string `json:"procDefaultMemLimits"`
// ProcDefaultMemLimit is process's default memory quota
ProcDefaultMemLimit string `json:"procDefaultMemLimit"`

// MaxReplicas is single instance max replica num
MaxReplicas int32 `json:"maxReplicas"`
}

// ResRequestsConfig contains bkapp resource requests
type ResRequestsConfig struct {
// ProcDefaultCPURequest is process's default cpu request
ProcDefaultCPURequest string `json:"procDefaultCPURequest"`

// ProcDefaultMemRequest is process's default memory request
ProcDefaultMemRequest string `json:"procDefaultMemRequest"`
}

// AutoscalingConfig contains the config for autoscaling
type AutoscalingConfig struct {
// Enabled indicates whether autoscaling is enabled
Expand All @@ -84,7 +93,8 @@ type ProjectConfig struct {

Platform PlatformConfig `json:"platform"`
IngressPlugin IngressPluginConfig `json:"ingressPlugin"`
ResLimit ResLimitConfig `json:"resLimit"`
ResLimits ResLimitsConfig `json:"resLimits"`
ResRequests ResRequestsConfig `json:"resRequests"`
Autoscaling AutoscalingConfig `json:"autoscaling"`
MaxProcesses int32 `json:"maxProcesses"`
}
Expand All @@ -102,9 +112,13 @@ func NewProjectConfig() *ProjectConfig {
}

// 资源预设默认值
conf.ResLimit.ProcDefaultCPULimits = "4000m"
conf.ResLimit.ProcDefaultMemLimits = "1024Mi"
conf.ResLimit.MaxReplicas = 5
conf.ResLimits.ProcDefaultCPULimit = "4000m"
conf.ResLimits.ProcDefaultMemLimit = "1024Mi"
conf.ResLimits.MaxReplicas = 5

// 资源请求默认值
conf.ResRequests.ProcDefaultMemRequest = ""
conf.ResRequests.ProcDefaultCPURequest = ""

conf.MaxProcesses = 8

Expand All @@ -124,17 +138,27 @@ func (p *ProjectConfig) GetMaxProcesses() int32 {

// GetProcMaxReplicas returns the max replicas of a process
func (p *ProjectConfig) GetProcMaxReplicas() int32 {
return p.ResLimit.MaxReplicas
return p.ResLimits.MaxReplicas
}

// GetProcDefaultCpuLimit returns the default cpu limit of a process
func (p *ProjectConfig) GetProcDefaultCpuLimit() string {
return p.ResLimits.ProcDefaultCPULimit
}

// GetProcDefaultMemLimit returns the default memory limit of a process
func (p *ProjectConfig) GetProcDefaultMemLimit() string {
return p.ResLimits.ProcDefaultMemLimit
}

// GetProcDefaultCpuLimits returns the default cpu limits of a process
func (p *ProjectConfig) GetProcDefaultCpuLimits() string {
return p.ResLimit.ProcDefaultCPULimits
// GetProcDefaultCpuRequest returns the default cpu request of a process
func (p *ProjectConfig) GetProcDefaultCpuRequest() string {
return p.ResRequests.ProcDefaultCPURequest
}

// GetProcDefaultMemLimits returns the default memory limits of a process
func (p *ProjectConfig) GetProcDefaultMemLimits() string {
return p.ResLimit.ProcDefaultMemLimits
// GetProcDefaultMemRequest returns the default cpu limit of a process
func (p *ProjectConfig) GetProcDefaultMemRequest() string {
return p.ResRequests.ProcDefaultMemRequest
}

// GetIngressClassName returns the ingress class name
Expand Down
26 changes: 21 additions & 5 deletions operator/api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 23 additions & 9 deletions operator/config/crd/bases/paas.bk.tencent.com_projectconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -208,23 +208,36 @@ spec:
- ingressClassName
- sentryDSN
type: object
resLimit:
description: ResLimitConfig contains bkapp resource limit
resLimits:
description: ResLimitsConfig contains bkapp resource limits
properties:
maxReplicas:
description: MaxReplicas is single instance max replica num
format: int32
type: integer
procDefaultCPULimits:
description: ProcDefaultCPULimits is process's default cpu quota
procDefaultCPULimit:
description: ProcDefaultCPULimit is process's default cpu quota
type: string
procDefaultMemLimits:
description: ProcDefaultMemLimits is process's default memory quota
procDefaultMemLimit:
description: ProcDefaultMemLimit is process's default memory quota
type: string
required:
- maxReplicas
- procDefaultCPULimits
- procDefaultMemLimits
- procDefaultCPULimit
- procDefaultMemLimit
type: object
resRequests:
description: ResRequestsConfig contains bkapp resource requests
properties:
procDefaultCPURequest:
description: ProcDefaultCPURequest is process's default cpu request
type: string
procDefaultMemRequest:
description: ProcDefaultMemRequest is process's default memory request
type: string
required:
- procDefaultCPURequest
- procDefaultMemRequest
type: object
syncPeriod:
description: SyncPeriod determines the minimum frequency at which watched
Expand Down Expand Up @@ -259,7 +272,8 @@ spec:
- ingressPlugin
- maxProcesses
- platform
- resLimit
- resLimits
- resRequests
type: object
served: true
storage: true
5 changes: 4 additions & 1 deletion operator/config/samples/paas_v1alpha1_projectconfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ platformConfig:
sentryDSN: ""
## when there are multiple ingress controllers in your cluster, setting the ingressClassName is necessary.
ingressClassName: ""
resLimitConfig:
resLimitsConfig:
procDefaultCPULimits: "500m"
procDefaultMemLimits: "256Mi"
maxReplicas: 5
resRequestsConfig:
procDefaultCPURequest: ""
procDefaultMemRequest: ""

## leaderElectionReleaseOnCancel defines if the leader should step down volume
## when the Manager ends. This requires the binary to immediately end when the
Expand Down
18 changes: 14 additions & 4 deletions operator/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ type ProjectConfigReader interface {
// Process related methods
GetMaxProcesses() int32
GetProcMaxReplicas() int32
GetProcDefaultCpuLimits() string
GetProcDefaultMemLimits() string
GetProcDefaultCpuLimit() string
GetProcDefaultMemLimit() string
GetProcDefaultCpuRequest() string
GetProcDefaultMemRequest() string

// Platform related methods
GetIngressClassName() string
Expand All @@ -44,14 +46,22 @@ func (d defaultConfig) GetProcMaxReplicas() int32 {
return 5
}

func (d defaultConfig) GetProcDefaultCpuLimits() string {
func (d defaultConfig) GetProcDefaultCpuLimit() string {
return "4"
}

func (d defaultConfig) GetProcDefaultMemLimits() string {
func (d defaultConfig) GetProcDefaultMemLimit() string {
return "1Gi"
}

func (d defaultConfig) GetProcDefaultCpuRequest() string {
return ""
}

func (d defaultConfig) GetProcDefaultMemRequest() string {
return ""
}

func (d defaultConfig) GetIngressClassName() string {
return "nginx"
}
Expand Down
4 changes: 2 additions & 2 deletions operator/pkg/controllers/resources/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,8 @@ var _ = Describe("Test build deployments from BkApp", func() {

// The resource requirements should be the default value defined in project config
// TODO: enhance below tests to check real plans
Expect(cWebRes.Limits.Cpu().String()).To(Equal(config.Global.GetProcDefaultCpuLimits()))
Expect(cWebRes.Limits.Memory().String()).To(Equal(config.Global.GetProcDefaultMemLimits()))
Expect(cWebRes.Limits.Cpu().String()).To(Equal(config.Global.GetProcDefaultCpuLimit()))
Expect(cWebRes.Limits.Memory().String()).To(Equal(config.Global.GetProcDefaultMemLimit()))
})

It("legacy version", func() {
Expand Down
30 changes: 28 additions & 2 deletions operator/pkg/controllers/resources/env_overlay.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ package resources
import (
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
logf "sigs.k8s.io/controller-runtime/pkg/log"

paasv1alpha2 "bk.tencent.com/paas-app-operator/api/v1alpha2"
"bk.tencent.com/paas-app-operator/pkg/config"
"bk.tencent.com/paas-app-operator/pkg/utils/kubetypes"
"bk.tencent.com/paas-app-operator/pkg/utils/quota"
)

var log_env_overlay = logf.Log.WithName("env_overlay")

// ReplicasGetter get replicas from BkApp object
type ReplicasGetter struct {
bkapp *paasv1alpha2.BkApp
Expand Down Expand Up @@ -253,7 +256,7 @@ func (r *ProcResourcesGetter) fromQuotaPlan(plan paasv1alpha2.ResQuotaPlan) core
case paasv1alpha2.ResQuotaPlan4C4G:
cpuRaw, memRaw = "4000m", "4096Mi"
default:
cpuRaw, memRaw = config.Global.GetProcDefaultCpuLimits(), config.Global.GetProcDefaultMemLimits()
cpuRaw, memRaw = config.Global.GetProcDefaultCpuLimit(), config.Global.GetProcDefaultMemLimit()
}
return r.calculateResources(cpuRaw, memRaw)
}
Expand All @@ -265,18 +268,41 @@ func (r *ProcResourcesGetter) calculateResources(cpu, memory string) corev1.Reso
cpuQuota, _ := quota.NewQuantity(cpu, quota.CPU)
memQuota, _ := quota.NewQuantity(memory, quota.Memory)

// 配置 cpu request
// 当配置了 ProcDefaultCpuRequest, 优先使用该值作为 CPU Request 配额
minCpuQuota, _ := quota.NewQuantity("200m", quota.CPU)
procDefaultCpuRequest := config.Global.GetProcDefaultCpuRequest()
if procDefaultCpuRequest != "" {
cpuRequestOverlay, err := quota.NewQuantity(procDefaultCpuRequest, quota.CPU)
if err != nil {
log_env_overlay.Error(err, "Fail to set cpu request", "DefaultCpuRequest", procDefaultCpuRequest)
} else {
minCpuQuota = cpuRequestOverlay
}
}

// 配置 mem request
var divisor int64 = 2
medMemQuota, _ := quota.NewQuantity("2048Mi", quota.Memory)
if memQuota.Cmp(*medMemQuota) == -1 {
divisor = 4
}
minMemQuota := quota.Div(memQuota, divisor)
// 当配置了 ProcDefaultMemLimit,优先使用该值作为 Memory Request 配额
procDefaultMemRequest := config.Global.GetProcDefaultMemRequest()
if procDefaultMemRequest != "" {
memoryRequestOverlay, err := quota.NewQuantity(procDefaultMemRequest, quota.Memory)
if err != nil {
log_env_overlay.Error(err, "Fail to set memory request", "DefaultMemRequest", procDefaultMemRequest)
} else {
minMemQuota = memoryRequestOverlay
}
}

return corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceCPU: *minCpuQuota,
corev1.ResourceMemory: *quota.Div(memQuota, divisor),
corev1.ResourceMemory: *minMemQuota,
},
Limits: corev1.ResourceList{
corev1.ResourceCPU: *cpuQuota,
Expand Down
24 changes: 24 additions & 0 deletions operator/pkg/controllers/resources/env_overlay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

paasv1alpha1 "bk.tencent.com/paas-app-operator/api/v1alpha1"
paasv1alpha2 "bk.tencent.com/paas-app-operator/api/v1alpha2"
"bk.tencent.com/paas-app-operator/pkg/config"
"bk.tencent.com/paas-app-operator/pkg/utils/kubetypes"
)

Expand Down Expand Up @@ -265,6 +267,28 @@ var _ = Describe("Environment overlay related functions", func() {
Expect(resReq.Limits.Memory().Equal(resource.MustParse("1Gi"))).To(BeTrue())
})

It("Get Default Requests", func() {
originalConfig := config.Global
projConf := paasv1alpha1.NewProjectConfig()
projConf.ResRequests.ProcDefaultCPURequest = "100m"
projConf.ResRequests.ProcDefaultMemRequest = "128Mi"
config.SetConfig(projConf)
defer config.SetConfig(originalConfig)

bkapp.SetAnnotations(map[string]string{paasv1alpha2.EnvironmentKey: "stag"})
bkapp.Spec.EnvOverlay = &paasv1alpha2.AppEnvOverlay{
ResQuotas: []paasv1alpha2.ResQuotaOverlay{
{EnvName: "stag", Process: "web", Plan: paasv1alpha2.ResQuotaPlan4C1G},
},
}
getter := NewProcResourcesGetter(bkapp)
resReq, _ := getter.GetByProc("web")
Expect(resReq.Requests.Cpu().Equal(resource.MustParse("100m"))).To(BeTrue())
Expect(resReq.Requests.Memory().Equal(resource.MustParse("128Mi"))).To(BeTrue())
Expect(resReq.Limits.Cpu().Equal(resource.MustParse("4"))).To(BeTrue())
Expect(resReq.Limits.Memory().Equal(resource.MustParse("1Gi"))).To(BeTrue())
})

It("Get Standard", func() {
bkapp.Spec.Processes[1].ResQuotaPlan = paasv1alpha2.ResQuotaPlan4C2G
getter := NewProcResourcesGetter(bkapp)
Expand Down
4 changes: 2 additions & 2 deletions operator/pkg/controllers/resources/hooks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ var _ = Describe("HookUtils", func() {
Expect(len(hook.Pod.Spec.Containers[0].Env)).To(Equal(0))
// 容器资源配额
hookRes := hook.Pod.Spec.Containers[0].Resources
Expect(hookRes.Limits.Cpu().String()).To(Equal(config.Global.GetProcDefaultCpuLimits()))
Expect(hookRes.Limits.Cpu().String()).To(Equal(config.Global.GetProcDefaultCpuLimit()))
Expect(
hookRes.Limits.Memory().String(),
).To(Equal(config.Global.GetProcDefaultMemLimits()))
).To(Equal(config.Global.GetProcDefaultMemLimit()))

// 镜像拉取密钥
Expect(
Expand Down