diff --git a/api/api/api_interface.go b/api/api/api_interface.go index ea5499e613..8289acc41b 100644 --- a/api/api/api_interface.go +++ b/api/api/api_interface.go @@ -61,6 +61,7 @@ type ClusterInterface interface { DeleteLangVersion(w http.ResponseWriter, r *http.Request) Upgrade(w http.ResponseWriter, r *http.Request) ListUpgradeStatus(w http.ResponseWriter, r *http.Request) + SetOverScore(w http.ResponseWriter, r *http.Request) } // NodesInterface - diff --git a/api/api_routers/version2/v2Routers.go b/api/api_routers/version2/v2Routers.go index 6a0e25f902..b41def5857 100644 --- a/api/api_routers/version2/v2Routers.go +++ b/api/api_routers/version2/v2Routers.go @@ -413,6 +413,7 @@ func (v2 *V2) clusterRouter() chi.Router { r.Post("/langVersion", controller.GetManager().CreateLangVersion) r.Put("/langVersion", controller.GetManager().UpdateLangVersion) r.Delete("/langVersion", controller.GetManager().DeleteLangVersion) + r.Post("/over_score", controller.GetManager().SetOverScore) return r } diff --git a/api/controller/cluster.go b/api/controller/cluster.go index aa3e898a58..6120656be5 100644 --- a/api/controller/cluster.go +++ b/api/controller/cluster.go @@ -661,3 +661,18 @@ func (c *ClusterController) GetRegionStatus(w http.ResponseWriter, r *http.Reque } httputil.ReturnSuccess(r, w, regionInfo) } + +func (c *ClusterController) SetOverScore(w http.ResponseWriter, r *http.Request) { + var overScore model.OverScore + if ok := httputil.ValidatorRequestStructAndErrorResponse(r, w, &overScore, nil); !ok { + httputil.ReturnError(r, w, 400, "failed to parse parameters") + return + } + // 根据语言标识和版本号,获取语言版本信息。 + err := db.GetManager().OverScoreDao().UpdateOverScoreRat(overScore.OverScoreRate) + if err != nil { + httputil.ReturnError(r, w, 400, fmt.Sprintf("update over score failure: %v", err)) + return + } + return +} diff --git a/api/model/model.go b/api/model/model.go index 01206f91d0..2b0f64b9bd 100644 --- a/api/model/model.go +++ b/api/model/model.go @@ -2361,3 +2361,8 @@ type UpdateLangVersion struct { Show bool `json:"show"` FirstChoice bool `json:"first_choice"` } + +// OverScore - +type OverScore struct { + OverScoreRate string `json:"over_score_rate"` +} diff --git a/db/dao/dao.go b/db/dao/dao.go index 1aa7f5c3c3..c49cd5702e 100644 --- a/db/dao/dao.go +++ b/db/dao/dao.go @@ -676,3 +676,10 @@ type LongVersionDao interface { CreateLangVersion(lang, version, eventID, fileName string, show bool) error DeleteLangVersion(lang, version string) (string, error) } + +// OverScoreDao over score pack +type OverScoreDao interface { + Dao + UpdateOverScoreRat(OverScoreRate string) error + GetOverScoreRate() (*model.EnterpriseOverScore, error) +} diff --git a/db/db.go b/db/db.go index 0caf3c6c2d..ded7536cba 100644 --- a/db/db.go +++ b/db/db.go @@ -52,6 +52,8 @@ type Manager interface { K8sResourceDaoTransactions(db *gorm.DB) dao.K8sResourceDao LongVersionDao() dao.LongVersionDao LongVersionDaoTransactions(db *gorm.DB) dao.LongVersionDao + OverScoreDao() dao.OverScoreDao + OverScoreDaoTransactions(db *gorm.DB) dao.OverScoreDao EnterpriseDao() dao.EnterpriseDao TenantDao() dao.TenantDao TenantDaoTransactions(db *gorm.DB) dao.TenantDao diff --git a/db/model/application.go b/db/model/application.go index 5c3eb7ba4f..07ec285a7f 100644 --- a/db/model/application.go +++ b/db/model/application.go @@ -155,3 +155,14 @@ type EnterpriseLanguageVersion struct { func (k *EnterpriseLanguageVersion) TableName() string { return "enterprise_language_version" } + +// EnterpriseOverScore language model +type EnterpriseOverScore struct { + Model + OverScoreRate string `gorm:"column:over_score_rate;uniqueIndex:idx_over_score_rate" json:"over_score_rate"` +} + +// TableName return tableName "k8s_resources" +func (k *EnterpriseOverScore) TableName() string { + return "enterprise_over_score" +} diff --git a/db/mysql/dao/over_score.go b/db/mysql/dao/over_score.go new file mode 100644 index 0000000000..2af38533a2 --- /dev/null +++ b/db/mysql/dao/over_score.go @@ -0,0 +1,60 @@ +package dao + +import ( + "fmt" + "github.com/goodrain/rainbond/db/model" + "github.com/jinzhu/gorm" +) + +// OverScoreDaoImpl over score pack +type OverScoreDaoImpl struct { + DB *gorm.DB +} + +// AddModel add model +func (t *OverScoreDaoImpl) AddModel(mo model.Interface) error { + overScore, ok := mo.(*model.EnterpriseOverScore) + if !ok { + return fmt.Errorf("mo.(*model.EnterpriseOverScore) err") + } + return t.DB.Create(overScore).Error +} + +// UpdateModel update model +func (t *OverScoreDaoImpl) UpdateModel(mo model.Interface) error { + overScore, ok := mo.(*model.EnterpriseOverScore) + if !ok { + return fmt.Errorf("mo.(*model.overScore) err") + } + return t.DB.Save(overScore).Error +} + +// UpdateOverScoreRat update +func (t *OverScoreDaoImpl) UpdateOverScoreRat(OverScoreRate string) error { + osr, err := t.GetOverScoreRate() + if err != nil { + return err + } else { + osr.OverScoreRate = OverScoreRate + } + return t.DB.Save(osr).Error +} + +// GetOverScoreRate get over score rate +func (t *OverScoreDaoImpl) GetOverScoreRate() (*model.EnterpriseOverScore, error) { + var overScore model.EnterpriseOverScore + if err := t.DB.First(&overScore).Error; err != nil { + if err == gorm.ErrRecordNotFound { + // Create default record with rate 1 + overScore = model.EnterpriseOverScore{ + OverScoreRate: "1", + } + if err := t.DB.Create(&overScore).Error; err != nil { + return nil, err + } + return &overScore, nil + } + return nil, err + } + return &overScore, nil +} diff --git a/db/mysql/dao_impl.go b/db/mysql/dao_impl.go index 49033e7fcc..eea0b87c84 100644 --- a/db/mysql/dao_impl.go +++ b/db/mysql/dao_impl.go @@ -695,3 +695,17 @@ func (m *Manager) LongVersionDaoTransactions(db *gorm.DB) dao.LongVersionDao { DB: db, } } + +// OverScoreDao 超分比例 +func (m *Manager) OverScoreDao() dao.OverScoreDao { + return &mysqldao.OverScoreDaoImpl{ + DB: m.db, + } +} + +// OverScoreDaoTransactions 超分比例 事务 +func (m *Manager) OverScoreDaoTransactions(db *gorm.DB) dao.OverScoreDao { + return &mysqldao.OverScoreDaoImpl{ + DB: db, + } +} diff --git a/db/mysql/mysql.go b/db/mysql/mysql.go index d0a70acbb5..9d20fb3ca1 100644 --- a/db/mysql/mysql.go +++ b/db/mysql/mysql.go @@ -230,6 +230,7 @@ func (m *Manager) RegisterTableModel() { m.models = append(m.models, &model.K8sResource{}) m.models = append(m.models, &model.KeyValue{}) m.models = append(m.models, &model.EnterpriseLanguageVersion{}) + m.models = append(m.models, &model.EnterpriseOverScore{}) } // CheckTable check and create tables diff --git a/go.mod b/go.mod index 8976be0210..f07fd58c14 100644 --- a/go.mod +++ b/go.mod @@ -109,6 +109,7 @@ require ( github.com/grafana/pyroscope-go v1.2.0 github.com/helm/helm v2.17.0+incompatible github.com/openkruise/kruise-api v1.4.0-rc.0 + github.com/volcengine/volcengine-go-sdk v1.0.176 golang.org/x/sync v0.3.0 k8s.io/klog/v2 v2.100.1 k8s.io/metrics v0.26.4 @@ -242,6 +243,7 @@ require ( github.com/tidwall/pretty v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect + github.com/volcengine/volc-sdk-golang v1.0.23 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect diff --git a/go.sum b/go.sum index ed9aab66f2..f88e690b1c 100644 --- a/go.sum +++ b/go.sum @@ -241,6 +241,7 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:W github.com/ashanbrown/forbidigo v1.2.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde/go.mod h1:oG9Dnez7/ESBqc4EdrdNlryeo7d0KcW1ftXHm7nU/UU= github.com/auth0/go-jwt-middleware v1.0.1/go.mod h1:YSeUX3z6+TF2H+7padiEqNJ73Zy9vXW72U//IgN0BIM= +github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM= @@ -1971,6 +1972,10 @@ github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6Ac github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/volcengine/volc-sdk-golang v1.0.23 h1:anOslb2Qp6ywnsbyq9jqR0ljuO63kg9PY+4OehIk5R8= +github.com/volcengine/volc-sdk-golang v1.0.23/go.mod h1:AfG/PZRUkHJ9inETvbjNifTDgut25Wbkm2QoYBTbvyU= +github.com/volcengine/volcengine-go-sdk v1.0.176 h1:PJhKH9e5z/FMVYJthh9jzGYDY7kwnuQXvU+M3701hQg= +github.com/volcengine/volcengine-go-sdk v1.0.176/go.mod h1:gfEDc1s7SYaGoY+WH2dRrS3qiuDJMkwqyfXWCa7+7oA= github.com/wercker/stern v0.0.0-20190705090245-4fa46dd6987f/go.mod h1:+72MfLYlS87s4tqq+eVDANQ9GdILz0lkpAFlX/1+WWY= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/wonderflow/cert-manager-api v1.0.3/go.mod h1:1Se7MSg11/eNYlo4fWv6vOM55/jTBMOzg2DN1kVFiSc= diff --git a/worker/appm/conversion/version.go b/worker/appm/conversion/version.go index 713270fa57..0131a365ff 100644 --- a/worker/appm/conversion/version.go +++ b/worker/appm/conversion/version.go @@ -355,7 +355,11 @@ func getMainContainer(as *v1.AppService, version *dbmodel.VersionInfo, dv *volum if err != nil { return nil, err } - resources := handleResource(defaultResources, customResources) + osr, err := dbmanager.OverScoreDao().GetOverScoreRate() + if err != nil { + return nil, err + } + resources := handleResource(defaultResources, customResources, osr.OverScoreRate) ports := createPorts(as, dbmanager) imagename := version.ImageName if imagename == "" { @@ -1513,8 +1517,15 @@ func createSecurityContext(as *v1.AppService, dbmanager db.Manager) (*corev1.Sec return &securityContext, nil } -func handleResource(resources corev1.ResourceRequirements, customResources *corev1.ResourceRequirements) (res corev1.ResourceRequirements) { +func handleResource(resources corev1.ResourceRequirements, customResources *corev1.ResourceRequirements, OverScoreRate string) (res corev1.ResourceRequirements) { var haveMemory bool + + // 解析超分比例 + overScore := map[string]float64{"CPU": 1.0, "MEMORY": 1.0} // 默认值 + if err := json.Unmarshal([]byte(OverScoreRate), &overScore); err != nil { + fmt.Printf("Error parsing OverScoreRate: %v, using defaults\n", err) + } + if customResources != nil { for resourceName, quantity := range customResources.Limits { if resourceName == "memory" && quantity.String() != "" { @@ -1542,5 +1553,22 @@ func handleResource(resources corev1.ResourceRequirements, customResources *core resources = *customResources } } + + // 根据超分比例调整 Requests 和 Limits + if cpuRequest, ok := resources.Requests[corev1.ResourceCPU]; ok { + adjustedCPURequest := adjustResource(cpuRequest, overScore["CPU"]) + resources.Requests[corev1.ResourceCPU] = adjustedCPURequest + } + if memoryRequest, ok := resources.Requests[corev1.ResourceMemory]; ok { + adjustedMemoryRequest := adjustResource(memoryRequest, overScore["MEMORY"]) + resources.Requests[corev1.ResourceMemory] = adjustedMemoryRequest + } return resources } + +// 辅助函数:根据超分比例调整资源值 +func adjustResource(original resource.Quantity, rate float64) resource.Quantity { + originalValue := original.Value() + adjustedValue := int64(float64(originalValue) * rate) + return *resource.NewQuantity(adjustedValue, original.Format) +}