Skip to content

Commit

Permalink
Merge pull request #338 from linkernetworks/johnlin/request-resource
Browse files Browse the repository at this point in the history
[Task] request resource for autoscale
  • Loading branch information
John-Lin authored Oct 5, 2018
2 parents 9d48908 + 8d4d572 commit de21ad1
Show file tree
Hide file tree
Showing 15 changed files with 227 additions and 118 deletions.
37 changes: 31 additions & 6 deletions src/deployment/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
v2beta1 "k8s.io/api/autoscaling/v2beta1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"gopkg.in/mgo.v2/bson"
Expand Down Expand Up @@ -347,17 +348,41 @@ func CreateDeployment(sp *serviceprovider.Container, deploy *entity.Deployment)
volumeMounts = append(volumeMounts, configMapMounts...)

var containers []corev1.Container
var c corev1.Container

securityContext := generateContainerSecurity(deploy)
envVars := generateEnvVars(deploy)
for _, container := range deploy.Containers {
containers = append(containers, corev1.Container{
Name: container.Name,
Image: container.Image,
Command: container.Command,

for _, deployContainer := range deploy.Containers {
c = corev1.Container{
Name: deployContainer.Name,
Image: deployContainer.Image,
Command: deployContainer.Command,
VolumeMounts: volumeMounts,
SecurityContext: securityContext,
Env: envVars,
})
}
if deployContainer.ResourceRequestCPU != 0 {
c.Resources = corev1.ResourceRequirements{
Requests: corev1.ResourceList{
"cpu": resource.MustParse(strconv.Itoa(deployContainer.ResourceRequestCPU) + "m"),
},
}
} else if deployContainer.ResourceRequestMemory != 0 {
c.Resources = corev1.ResourceRequirements{
Requests: corev1.ResourceList{
"memory": resource.MustParse(strconv.Itoa(deployContainer.ResourceRequestMemory) + "Mi"),
},
}
} else if deployContainer.ResourceRequestMemory != 0 && deployContainer.ResourceRequestCPU != 0 {
c.Resources = corev1.ResourceRequirements{
Requests: corev1.ResourceList{
"cpu": resource.MustParse(strconv.Itoa(deployContainer.ResourceRequestCPU) + "m"),
"memory": resource.MustParse(strconv.Itoa(deployContainer.ResourceRequestMemory) + "Mi"),
},
}
}
containers = append(containers, c)
}

p := appsv1.Deployment{
Expand Down
32 changes: 20 additions & 12 deletions src/deployment/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,11 @@ func (suite *DeploymentTestSuite) TestGenerateConfigMap() {
func (suite *DeploymentTestSuite) TestCreateDeployment() {
containers := []entity.Container{
{
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
ResourceRequestCPU: 40,
ResourceRequestMemory: 0,
},
}

Expand All @@ -195,9 +197,11 @@ func (suite *DeploymentTestSuite) TestCreateDeployment() {
func (suite *DeploymentTestSuite) TestCreateDeploymentFailWithoutVolume() {
containers := []entity.Container{
{
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
ResourceRequestCPU: 0,
ResourceRequestMemory: 0,
},
}

Expand All @@ -218,9 +222,11 @@ func (suite *DeploymentTestSuite) TestCreateDeploymentFailWithoutVolume() {
func (suite *DeploymentTestSuite) TestCreateDeploymentFailWithoutNetwork() {
containers := []entity.Container{
{
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
ResourceRequestCPU: 30,
ResourceRequestMemory: 20,
},
}

Expand Down Expand Up @@ -482,9 +488,11 @@ func (suite *DeploymentTestSuite) TestCreateDeploymentWithNetworkTypes() {
func (suite *DeploymentTestSuite) TestCreateDeploymentWithAutoscaler() {
containers := []entity.Container{
{
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
ResourceRequestCPU: 0,
ResourceRequestMemory: 30,
},
}

Expand Down
45 changes: 23 additions & 22 deletions src/entity/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,23 @@ type DeploymentConfig struct {

// Deployment is the structure for deployment info
type Deployment struct {
ID bson.ObjectId `bson:"_id,omitempty" json:"id" validate:"-"`
OwnerID bson.ObjectId `bson:"ownerID,omitempty" json:"ownerID" validate:"-"`
Name string `bson:"name" json:"name" validate:"required,k8sname"`
Namespace string `bson:"namespace" json:"namespace" validate:"required"`
Labels map[string]string `bson:"labels,omitempty" json:"labels" validate:"required,dive,keys,printascii,endkeys,required,printascii"`
EnvVars map[string]string `bson:"envVars,omitempty" json:"envVars" validate:"required,dive,keys,printascii,endkeys,required,printascii"`
Containers []Container `bson:"containers" json:"containers" validate:"required,dive,required"`
Volumes []DeploymentVolume `bson:"volumes,omitempty" json:"volumes" validate:"required,dive,required"`
ConfigMaps []DeploymentConfig `bson:"configMaps,omitempty" json:"configMaps" validate:"required,dive,required"`
Networks []DeploymentNetwork `bson:"networks,omitempty" json:"networks" validate:"required,dive,required"`
Capability bool `bson:"capability" json:"capability" validate:"-"`
NetworkType string `bson:"networkType" json:"networkType" validate:"required,eq=host|eq=cluster|eq=custom"`
NodeAffinity []string `bson:"nodeAffinity" json:"nodeAffinity" validate:"required"`
IsAutoscaler bool `bson:"isAutoscaler" json:"isAutoscaler" validate:"-"`
AutoscalerInfo AutoscalerInfo `bson:"autoscalerInfo" json:"autoscalerInfo" validate:"-"`
CreatedBy User `json:"createdBy" validate:"-"`
CreatedAt *time.Time `bson:"createdAt,omitempty" json:"createdAt,omitempty" validate:"-"`
ID bson.ObjectId `bson:"_id,omitempty" json:"id" validate:"-"`
OwnerID bson.ObjectId `bson:"ownerID,omitempty" json:"ownerID" validate:"-"`
Name string `bson:"name" json:"name" validate:"required,k8sname"`
Namespace string `bson:"namespace" json:"namespace" validate:"required"`
Labels map[string]string `bson:"labels,omitempty" json:"labels" validate:"required,dive,keys,printascii,endkeys,required,printascii"`
EnvVars map[string]string `bson:"envVars,omitempty" json:"envVars" validate:"required,dive,keys,printascii,endkeys,required,printascii"`
Containers []Container `bson:"containers" json:"containers" validate:"required,dive,required"`
Volumes []DeploymentVolume `bson:"volumes,omitempty" json:"volumes" validate:"required,dive,required"`
ConfigMaps []DeploymentConfig `bson:"configMaps,omitempty" json:"configMaps" validate:"required,dive,required"`
Networks []DeploymentNetwork `bson:"networks,omitempty" json:"networks" validate:"required,dive,required"`
Capability bool `bson:"capability" json:"capability" validate:"-"`
NetworkType string `bson:"networkType" json:"networkType" validate:"required,eq=host|eq=cluster|eq=custom"`
NodeAffinity []string `bson:"nodeAffinity" json:"nodeAffinity" validate:"required"`
IsEnableAutoscale bool `bson:"isEnableAutoscale" json:"isEnableAutoscale" validate:"-"`
AutoscalerInfo AutoscalerInfo `bson:"autoscalerInfo" json:"autoscalerInfo" validate:"-"`
CreatedBy User `json:"createdBy" validate:"-"`
CreatedAt *time.Time `bson:"createdAt,omitempty" json:"createdAt,omitempty" validate:"-"`

Replicas int32 `bson:"replicas" json:"replicas" validate:"required"`
}
Expand All @@ -85,11 +85,12 @@ type AutoscalerInfo struct {
Name string `bson:"name" json:"name" validate:"required,k8sname"`
Namespace string `bson:"namespace" json:"namespace" validate:"required"`
// ScaleTargetRef is deployment name
ScaleTargetRefName string `bson:"scaleTargetRefName" json:"scaleTargetRefName" validate:"required,k8sname"`
ResourceName corev1.ResourceName `bson:"resourceName" json:"resourceName" validate:"required,eq=cpu|eq=memory"`
MinReplicas int32 `bson:"minReplicas" json:"minReplicas" validate:"required,numeric"`
MaxReplicas int32 `bson:"maxReplicas" json:"maxReplicas" validate:"required,numeric"`
TargetAverageUtilization int32 `bson:"targetAverageUtilization" json:"targetAverageUtilization" validate:"required,numeric"`
ScaleTargetRefName string `bson:"scaleTargetRefName" json:"scaleTargetRefName" validate:"required,k8sname"`
IsCapableAutoscaleResources [2]string `bson:"isCapableAutoscaleResources" json:"isCapableAutoscaleResources" validate:"-"`
ResourceName corev1.ResourceName `bson:"resourceName" json:"resourceName" validate:"required,eq=cpu|eq=memory"`
MinReplicas int32 `bson:"minReplicas" json:"minReplicas" validate:"required,numeric"`
MaxReplicas int32 `bson:"maxReplicas" json:"maxReplicas" validate:"required,numeric"`
TargetAverageUtilization int32 `bson:"targetAverageUtilization" json:"targetAverageUtilization" validate:"required,numeric"`
}

// GetCollection - get model mongo collection name.
Expand Down
8 changes: 5 additions & 3 deletions src/entity/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ const (

// Container is the structure for init Container info
type Container struct {
Name string `bson:"name" json:"name" validate:"required,k8sname"`
Image string `bson:"image" json:"image" validate:"required"`
Command []string `bson:"command" json:"command" validate:"required,dive,required"`
Name string `bson:"name" json:"name" validate:"required,k8sname"`
Image string `bson:"image" json:"image" validate:"required"`
Command []string `bson:"command" json:"command" validate:"required,dive,required"`
ResourceRequestCPU int `bson:"resourceRequestCPU" json:"resourceRequestCPU" validate:"-"`
ResourceRequestMemory int `bson:"resourceRequestMemory" json:"resourceRequestMemory" validate:"-"`
}

// PodRouteGw is the structure for add IP routing table with gateway
Expand Down
8 changes: 5 additions & 3 deletions src/server/handler_app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ func (suite *AppTestSuite) TestCreateApp() {
namespace := "default"
containers := []entity.Container{
{
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
ResourceRequestCPU: 0,
ResourceRequestMemory: 0,
},
}
tName := namesgenerator.GetRandomName(0)
Expand Down
59 changes: 48 additions & 11 deletions src/server/handler_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import (
"github.com/linkernetworks/vortex/src/net/http/query"
"github.com/linkernetworks/vortex/src/server/backend"
"github.com/linkernetworks/vortex/src/web"
"k8s.io/api/apps/v1"
appv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"

mgo "gopkg.in/mgo.v2"
Expand All @@ -39,6 +40,21 @@ func createDeploymentHandler(ctx *web.Context) {
return
}

// autoscale resource request setting prerequisite check
for _, container := range p.Containers {
if container.ResourceRequestCPU != 0 {
p.AutoscalerInfo.IsCapableAutoscaleResources[0] = "cpu"
}
if container.ResourceRequestMemory != 0 {
p.AutoscalerInfo.IsCapableAutoscaleResources[1] = "memory"
}
}

if p.NetworkType == entity.DeploymentCustomNetwork {
// clear the array
p.AutoscalerInfo.IsCapableAutoscaleResources = [2]string{}
}

if err := sp.Validator.Struct(p); err != nil {
response.BadRequest(req.Request, resp.ResponseWriter, err)
return
Expand Down Expand Up @@ -83,6 +99,7 @@ func createDeploymentHandler(ctx *web.Context) {
}
return
}

if err := session.Insert(entity.DeploymentCollectionName, &p); err != nil {
if mgo.IsDup(err) {
response.Conflict(req.Request, resp.ResponseWriter, fmt.Errorf("Deployment Name: %s already existed", p.Name))
Expand Down Expand Up @@ -255,25 +272,36 @@ func uploadDeploymentYAMLHandler(ctx *web.Context) {
return
}

deploymentObj, ok := obj.(*v1.Deployment)
deploymentObj, ok := obj.(*appv1.Deployment)
if !ok {
response.BadRequest(req.Request, resp.ResponseWriter, fmt.Errorf("The YAML file is not for creating deployment"))
return
}

d := entity.Deployment{
ID: bson.NewObjectId(),
OwnerID: bson.ObjectIdHex(userID),
Name: deploymentObj.ObjectMeta.Name,
Namespace: deploymentObj.ObjectMeta.Namespace,
NetworkType: entity.DeploymentClusterNetwork,
Replicas: *deploymentObj.Spec.Replicas,
ID: bson.NewObjectId(),
OwnerID: bson.ObjectIdHex(userID),
Name: deploymentObj.ObjectMeta.Name,
Namespace: deploymentObj.ObjectMeta.Namespace,
Replicas: *deploymentObj.Spec.Replicas,
}

if d.Namespace == "" {
d.Namespace = "default"
}

// autoscale resource request setting prerequisite check
for _, container := range deploymentObj.Spec.Template.Spec.Containers {
// check if map contains cpu key
if _, ok := container.Resources.Requests[corev1.ResourceCPU]; ok {
d.AutoscalerInfo.IsCapableAutoscaleResources[0] = "cpu"
}
// check if map contains memory key
if _, ok := container.Resources.Requests[corev1.ResourceMemory]; ok {
d.AutoscalerInfo.IsCapableAutoscaleResources[1] = "memory"
}
}

session := sp.Mongo.NewSession()
session.C(entity.DeploymentCollectionName).EnsureIndex(mgo.Index{
Key: []string{"name"},
Expand Down Expand Up @@ -375,9 +403,18 @@ func updateAutoscalerHandler(ctx *web.Context) {
return
}

// Update autoscalerInfo
deployment.IsAutoscaler = enableAutoscaler
deployment.AutoscalerInfo = autoscalerInfo
// update autoscalerInfo
deployment.IsEnableAutoscale = enableAutoscaler

// update all autoscaler infomation
deployment.AutoscalerInfo.Name = autoscalerInfo.Name
deployment.AutoscalerInfo.Namespace = autoscalerInfo.Namespace
deployment.AutoscalerInfo.ScaleTargetRefName = autoscalerInfo.ScaleTargetRefName
deployment.AutoscalerInfo.ResourceName = autoscalerInfo.ResourceName
deployment.AutoscalerInfo.MinReplicas = autoscalerInfo.MinReplicas
deployment.AutoscalerInfo.MaxReplicas = autoscalerInfo.MaxReplicas
deployment.AutoscalerInfo.TargetAverageUtilization = autoscalerInfo.TargetAverageUtilization

modifier := bson.M{
"$set": deployment,
}
Expand Down
Loading

0 comments on commit de21ad1

Please sign in to comment.