Skip to content

Commit 7a6bee7

Browse files
committed
added auto scaling group type to simulate node group.
1 parent 24b4df0 commit 7a6bee7

File tree

2 files changed

+249
-0
lines changed

2 files changed

+249
-0
lines changed
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package huaweicloud
18+
19+
import (
20+
"fmt"
21+
22+
apiv1 "k8s.io/api/core/v1"
23+
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
24+
"k8s.io/klog/v2"
25+
schedulerframework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
26+
)
27+
28+
// AutoScalingGroup represents a HuaweiCloud's 'Auto Scaling Group' which also can be treated as a node group.
29+
type AutoScalingGroup struct {
30+
cloudServiceManager CloudServiceManager
31+
32+
groupID string
33+
minInstanceNumber int
34+
maxInstanceNumber int
35+
}
36+
37+
// Check if our AutoScalingGroup implements necessary interface.
38+
var _ cloudprovider.NodeGroup = &AutoScalingGroup{}
39+
40+
// MaxSize returns maximum size of the node group.
41+
func (asg *AutoScalingGroup) MaxSize() int {
42+
return asg.maxInstanceNumber
43+
}
44+
45+
// MinSize returns minimum size of the node group.
46+
func (asg *AutoScalingGroup) MinSize() int {
47+
return asg.minInstanceNumber
48+
}
49+
50+
// TargetSize returns the current target size of the node group. It is possible that the
51+
// number of nodes in Kubernetes is different at the moment but should be equal
52+
// to Size() once everything stabilizes (new nodes finish startup and registration or
53+
// removed nodes are deleted completely). Implementation required.
54+
//
55+
// Target size is desire instance number of the auto scaling group, and not equal to current instance number if the
56+
// auto scaling group is in increasing or decreasing process.
57+
func (asg *AutoScalingGroup) TargetSize() (int, error) {
58+
desireNumber, err := asg.cloudServiceManager.GetDesireInstanceNumber(asg.groupID)
59+
if err != nil {
60+
klog.Warningf("failed to get group target size. groupID: %s, error: %v", asg.groupID, err)
61+
return 0, err
62+
}
63+
64+
return desireNumber, nil
65+
}
66+
67+
// IncreaseSize increases the size of the node group. To delete a node you need
68+
// to explicitly name it and use DeleteNode. This function should wait until
69+
// node group size is updated. Implementation required.
70+
func (asg *AutoScalingGroup) IncreaseSize(delta int) error {
71+
err := asg.cloudServiceManager.IncreaseSizeInstance(asg.groupID, delta)
72+
if err != nil {
73+
klog.Warningf("failed to increase size for group: %s, error: %v", asg.groupID, err)
74+
return err
75+
}
76+
77+
return nil
78+
}
79+
80+
// DeleteNodes deletes nodes from this node group. Error is returned either on
81+
// failure or if the given node doesn't belong to this node group. This function
82+
// should wait until node group size is updated. Implementation required.
83+
func (asg *AutoScalingGroup) DeleteNodes(nodes []*apiv1.Node) error {
84+
instances, err := asg.cloudServiceManager.GetInstances(asg.groupID)
85+
if err != nil {
86+
klog.Warningf("failed to get nodes from group: %s, error: %v", asg.groupID, err)
87+
return err
88+
}
89+
90+
// TODO(RainbowMango): Check if all node in this group.
91+
// If one of the node is not belong to this group, just return error.
92+
93+
servers := make([]string, 0, len(instances))
94+
for _, instance := range instances {
95+
servers = append(servers, *instance.InstanceId)
96+
}
97+
98+
err = asg.cloudServiceManager.DeleteServers(servers)
99+
if err != nil {
100+
klog.Warningf("failed to delete nodes. error: %v", err)
101+
return err
102+
}
103+
104+
return nil
105+
}
106+
107+
// DecreaseTargetSize decreases the target size of the node group. This function
108+
// doesn't permit to delete any existing node and can be used only to reduce the
109+
// request for new nodes that have not been yet fulfilled. Delta should be negative.
110+
// It is assumed that cloud provider will not delete the existing nodes when there
111+
// is an option to just decrease the target. Implementation required.
112+
func (asg *AutoScalingGroup) DecreaseTargetSize(delta int) error {
113+
// TODO(RainbowMango): Just remove nodes from group not delete them?
114+
return cloudprovider.ErrNotImplemented
115+
}
116+
117+
// Id returns an unique identifier of the node group.
118+
func (asg *AutoScalingGroup) Id() string {
119+
return asg.groupID
120+
}
121+
122+
// Debug returns a string containing all information regarding this node group.
123+
func (asg *AutoScalingGroup) Debug() string {
124+
return asg.String()
125+
}
126+
127+
// Nodes returns a list of all nodes that belong to this node group.
128+
// It is required that Instance objects returned by this method have Id field set.
129+
// Other fields are optional.
130+
// This list should include also instances that might have not become a kubernetes node yet.
131+
func (asg *AutoScalingGroup) Nodes() ([]cloudprovider.Instance, error) {
132+
instances, err := asg.cloudServiceManager.GetInstances(asg.groupID)
133+
if err != nil {
134+
klog.Warningf("failed to get nodes from group: %s, error: %v", asg.groupID, err)
135+
return nil, err
136+
}
137+
if len(instances) == 0 {
138+
return nil, nil
139+
}
140+
141+
// TODO(RainbowMango) Convert AS instances to cloud provider instances. Especially convert status.
142+
providerInstances := make([]cloudprovider.Instance, 0, len(instances))
143+
for i := range instances {
144+
pInstances := cloudprovider.Instance{
145+
Id: *instances[i].InstanceId,
146+
Status: nil,
147+
}
148+
149+
providerInstances = append(providerInstances, pInstances)
150+
}
151+
return nil, nil
152+
}
153+
154+
// TemplateNodeInfo returns a schedulerframework.NodeInfo structure of an empty
155+
// (as if just started) node. This will be used in scale-up simulations to
156+
// predict what would a new node look like if a node group was expanded. The returned
157+
// NodeInfo is expected to have a fully populated Node object, with all of the labels,
158+
// capacity and allocatable information as well as all pods that are started on
159+
// the node by default, using manifest (most likely only kube-proxy). Implementation optional.
160+
func (asg *AutoScalingGroup) TemplateNodeInfo() (*schedulerframework.NodeInfo, error) {
161+
return nil, cloudprovider.ErrNotImplemented
162+
}
163+
164+
// Exist checks if the node group really exists on the cloud provider side. Allows to tell the
165+
// theoretical node group from the real one. Implementation required.
166+
func (asg *AutoScalingGroup) Exist() bool {
167+
// Since all group synced from remote and we do not support auto provision,
168+
// so we can assume that the group always exist.
169+
return true
170+
}
171+
172+
// Create creates the node group on the cloud provider side. Implementation optional.
173+
func (asg *AutoScalingGroup) Create() (cloudprovider.NodeGroup, error) {
174+
return nil, cloudprovider.ErrNotImplemented
175+
}
176+
177+
// Delete deletes the node group on the cloud provider side.
178+
// This will be executed only for autoprovisioned node groups, once their size drops to 0.
179+
// Implementation optional.
180+
func (asg *AutoScalingGroup) Delete() error {
181+
return cloudprovider.ErrNotImplemented
182+
}
183+
184+
// Autoprovisioned returns true if the node group is autoprovisioned. An autoprovisioned group
185+
// was created by CA and can be deleted when scaled to 0.
186+
//
187+
// Always return false because the node group should maintained by user.
188+
func (asg *AutoScalingGroup) Autoprovisioned() bool {
189+
return false
190+
}
191+
192+
// String dumps current groups meta data.
193+
func (asg *AutoScalingGroup) String() string {
194+
return fmt.Sprintf("group: %s min=%d max=%d", asg.groupID, asg.minInstanceNumber, asg.maxInstanceNumber)
195+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package huaweicloud
18+
19+
// ScalingGroupInstance is a dummy struct for ScalingGroupInstance. And it will be replaced later.
20+
type ScalingGroupInstance struct {
21+
InstanceId *string `json:"instance_id,omitempty"`
22+
}
23+
24+
// ElasticCloudServerService represents the elastic cloud server interfaces.
25+
// It should contains all request against elastic cloud server service.
26+
type ElasticCloudServerService interface {
27+
// DeleteServers deletes a group of server by ID.
28+
DeleteServers(serverIDs []string) error
29+
}
30+
31+
// AutoScalingService represents the auto scaling service interfaces.
32+
// It should contains all request against auto scaling service.
33+
type AutoScalingService interface {
34+
// GetDesireInstanceNumber gets the desire instance number of specific auto scaling group.
35+
GetDesireInstanceNumber(groupID string) (int, error)
36+
37+
// GetInstances gets the instances in an auto scaling group.
38+
GetInstances(groupID string) ([]ScalingGroupInstance, error)
39+
40+
// IncreaseSizeInstance increases the instance number of specific auto scaling group.
41+
// The delta should be non-negative.
42+
// IncreaseSizeInstance wait until instance number is updated.
43+
IncreaseSizeInstance(groupID string, delta int) error
44+
}
45+
46+
// CloudServiceManager represents the cloud service interfaces.
47+
// It should contains all requests against cloud services.
48+
type CloudServiceManager interface {
49+
// ElasticCloudServerService represents the elastic cloud server interfaces.
50+
ElasticCloudServerService
51+
52+
// AutoScalingService represents the auto scaling service interfaces.
53+
AutoScalingService
54+
}

0 commit comments

Comments
 (0)