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

[Task] autoscaler API #331

Merged
merged 5 commits into from
Oct 2, 2018
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
53 changes: 52 additions & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
- [Monitor Controllers](#monitor-controllers)
- [Monitor Certain Controller](#monitor-certain-controller)


## User

### Signup
Expand Down Expand Up @@ -1078,6 +1077,58 @@ Response Data:
}
```

### Update Autoscaler

`ResourceName` in json can only be "cpu" or "memory".
`ScaleTargetRefName` is the target kubernetes deployment name

Enable autoscaler

**PUT /v1/deployments/autoscale?enable=true**

Example:

```
curl -X PUT http://localhost:7890/v1/deployments/autoscale?enable=true
```

Request Data:

```json
{
"namespace": "default",
"scaleTargetRefName": "testDeploymentName",
"resourceName": "cpu",
"minReplicas": 1,
"maxReplicas": 5,
"targetAverageUtilization": 30
}
```

Disable autoscaler

**PUT /v1/deployments/autoscale?enable=false**

Example:

```
curl -X PUT http://localhost:7890/v1/deployments/autoscale?enable=false
```

Request Data:

```json
{
"namespace": "default",
"scaleTargetRefName": "testDeploymentName",
"resourceName": "cpu",
"minReplicas": 0,
"maxReplicas": 0,
"targetAverageUtilization": 0
}
```


## Service

### Create Service
Expand Down
39 changes: 38 additions & 1 deletion src/deployment/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
"github.com/linkernetworks/vortex/src/entity"
"github.com/linkernetworks/vortex/src/serviceprovider"
"github.com/linkernetworks/vortex/src/utils"
appsv1 "k8s.io/api/apps/v1"

appsv1 "k8s.io/api/apps/v1"
v2beta1 "k8s.io/api/autoscaling/v2beta1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

Expand Down Expand Up @@ -410,3 +411,39 @@ func CreateDeployment(sp *serviceprovider.Container, deploy *entity.Deployment)
func DeleteDeployment(sp *serviceprovider.Container, deploy *entity.Deployment) error {
return sp.KubeCtl.DeleteDeployment(deploy.Name, deploy.Namespace)
}

// CreateAutoscaler will create a autoscaler
func CreateAutoscaler(sp *serviceprovider.Container, autoscalerInfo entity.AutoscalerInfo) error {
autoscaler := v2beta1.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
// use deployment name to name autoscaler's name
Name: autoscalerInfo.ScaleTargetRefName,
Namespace: autoscalerInfo.Namespace,
},
Spec: v2beta1.HorizontalPodAutoscalerSpec{
ScaleTargetRef: v2beta1.CrossVersionObjectReference{
APIVersion: "extensions/v1beta",
Kind: "Deployment",
Name: autoscalerInfo.ScaleTargetRefName,
},
MinReplicas: &autoscalerInfo.MinReplicas,
MaxReplicas: autoscalerInfo.MaxReplicas,
Metrics: []v2beta1.MetricSpec{
{
Type: v2beta1.ResourceMetricSourceType,
Resource: &v2beta1.ResourceMetricSource{
Name: autoscalerInfo.ResourceName,
TargetAverageUtilization: &autoscalerInfo.TargetAverageUtilization,
},
},
},
},
}
_, err := sp.KubeCtl.CreateAutoscaler(&autoscaler, autoscalerInfo.Namespace)
return err
}

// DeleteAutoscaler will delete a autoscaler
func DeleteAutoscaler(sp *serviceprovider.Container, autoscalerInfo entity.AutoscalerInfo) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will autoscaler delete itself while the corresponding deployment is been removed ?

return sp.KubeCtl.DeleteAutoscaler(autoscalerInfo.ScaleTargetRefName, autoscalerInfo.Namespace)
}
47 changes: 47 additions & 0 deletions src/deployment/deployment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import (
"github.com/linkernetworks/vortex/src/serviceprovider"
"github.com/moby/moby/pkg/namesgenerator"
"github.com/stretchr/testify/suite"

corev1 "k8s.io/api/core/v1"

"gopkg.in/mgo.v2/bson"
)

Expand Down Expand Up @@ -475,3 +478,47 @@ func (suite *DeploymentTestSuite) TestCreateDeploymentWithNetworkTypes() {
})
}
}

func (suite *DeploymentTestSuite) TestCreateDeploymentWithAutoscaler() {
containers := []entity.Container{
{
Name: namesgenerator.GetRandomName(0),
Image: "busybox",
Command: []string{"sleep", "3600"},
},
}

testDeploymentName := namesgenerator.GetRandomName(0)
deploy := &entity.Deployment{
ID: bson.NewObjectId(),
Namespace: "default",
Name: testDeploymentName,
Containers: containers,
NetworkType: entity.DeploymentClusterNetwork,
EnvVars: map[string]string{
"MY_IP": "1.2.3.4",
},
}

autoscaler := entity.AutoscalerInfo{
Name: "test-autoscaler",
Namespace: "default",
ScaleTargetRefName: testDeploymentName,
ResourceName: corev1.ResourceCPU,
MinReplicas: 1,
MaxReplicas: 5,
TargetAverageUtilization: 30,
}

err := CreateDeployment(suite.sp, deploy)
suite.NoError(err)

err = CreateAutoscaler(suite.sp, autoscaler)
suite.NoError(err)

err = DeleteAutoscaler(suite.sp, autoscaler)
suite.NoError(err)

err = DeleteDeployment(suite.sp, deploy)
suite.NoError(err)
}
45 changes: 30 additions & 15 deletions src/entity/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"time"

"gopkg.in/mgo.v2/bson"
corev1 "k8s.io/api/core/v1"
)

const (
Expand Down Expand Up @@ -58,25 +59,39 @@ 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"`
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"`
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:"-"`

Replicas int32 `bson:"replicas" json:"replicas" validate:"required"`
}

// AutoscalerInfo is the structure for deploying a autoscaler with a deployment
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"`
}

// GetCollection - get model mongo collection name.
func (m Deployment) GetCollection() string {
return DeploymentCollectionName
Expand Down
22 changes: 22 additions & 0 deletions src/kubernetes/autoscaler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package kubernetes

import (
v1beta2 "k8s.io/api/autoscaling/v2beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// CreateAutoscaler will create a autoscaler
func (kc *KubeCtl) CreateAutoscaler(autoscaler *v1beta2.HorizontalPodAutoscaler, namespace string) (*v1beta2.HorizontalPodAutoscaler, error) {
return kc.Clientset.AutoscalingV2beta1().HorizontalPodAutoscalers(namespace).Create(autoscaler)
}

// GetAutoscaler will get a autoscaler
func (kc *KubeCtl) GetAutoscaler(name string, namespace string) (*v1beta2.HorizontalPodAutoscaler, error) {
return kc.Clientset.AutoscalingV2beta1().HorizontalPodAutoscalers(namespace).Get(name, metav1.GetOptions{})
}

// DeleteAutoscaler will delete a autoscaler
func (kc *KubeCtl) DeleteAutoscaler(name string, namespace string) error {
propagation := metav1.DeletePropagationForeground
return kc.Clientset.AutoscalingV2beta1().HorizontalPodAutoscalers(namespace).Delete(name, &metav1.DeleteOptions{PropagationPolicy: &propagation})
}
Loading