Skip to content

Commit

Permalink
webhook: add node webhook for resource amplification (#1785)
Browse files Browse the repository at this point in the history
Signed-off-by: 逐灵 <fansong.cfs@alibaba-inc.com>
  • Loading branch information
hormes committed Jan 9, 2024
1 parent 2a46d60 commit c62d869
Show file tree
Hide file tree
Showing 18 changed files with 1,270 additions and 168 deletions.
7 changes: 7 additions & 0 deletions apis/extension/cpu_normalization.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ const (

// AnnotationCPUBasicInfo denotes the basic CPU info of the node.
AnnotationCPUBasicInfo = NodeDomainPrefix + "/cpu-basic-info"

// NormalizationRatioDiffEpsilon is the min difference between two cpu normalization ratios.
NormalizationRatioDiffEpsilon = 0.01
)

// GetCPUNormalizationRatio gets the cpu normalization ratio from the node.
Expand Down Expand Up @@ -90,6 +93,10 @@ func GetCPUNormalizationEnabled(node *corev1.Node) (*bool, error) {
return pointer.Bool(v), nil
}

func IsCPUNormalizationRatioDifferent(old, new float64) bool {
return old > new+NormalizationRatioDiffEpsilon || old < new-NormalizationRatioDiffEpsilon
}

// CPUBasicInfo describes the cpu basic features and status.
type CPUBasicInfo struct {
CPUModel string `json:"cpuModel,omitempty"`
Expand Down
32 changes: 32 additions & 0 deletions apis/extension/cpu_normalization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,35 @@ func TestSetCPUBasicInfo(t *testing.T) {
})
}
}

func TestCPUNormalizationRatioDifferent(t *testing.T) {
testCases := []struct {
old float64
new float64
expectedDiff bool
}{
{
old: 1.2,
new: 1.2,
expectedDiff: false,
},
{
old: 1.2,
new: 1.3,
expectedDiff: true,
},
{
old: 1.2,
new: 1.205,
expectedDiff: false,
},
{
old: 1.2,
new: 1.195,
expectedDiff: false,
},
}
for _, tc := range testCases {
assert.Equal(t, tc.expectedDiff, IsCPUNormalizationRatioDifferent(tc.old, tc.new))
}
}
29 changes: 4 additions & 25 deletions apis/extension/node_resource_amplification.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@ const (
// AnnotationNodeResourceAmplificationRatio denotes the resource amplification ratio of the node.
AnnotationNodeResourceAmplificationRatio = NodeDomainPrefix + "/resource-amplification-ratio"

// AnnotationNodeRawCapacity denotes the un-amplified raw capacity of the node.
AnnotationNodeRawCapacity = NodeDomainPrefix + "/raw-capacity"

// AnnotationNodeRawAllocatable denotes the un-amplified raw allocatable of the node.
AnnotationNodeRawAllocatable = NodeDomainPrefix + "/raw-allocatable"
)
Expand Down Expand Up @@ -106,28 +103,10 @@ func SetNodeResourceAmplificationRatio(node *corev1.Node, resource corev1.Resour
return true, nil
}

// GetNodeRawCapacity gets the raw capacity of node from annotations.
func GetNodeRawCapacity(annotations map[string]string) (corev1.ResourceList, error) {
s, ok := annotations[AnnotationNodeRawCapacity]
if !ok {
return nil, nil
}

var capacity corev1.ResourceList
if err := json.Unmarshal([]byte(s), &capacity); err != nil {
return nil, fmt.Errorf("failed to unmarshal node raw capacity: %w", err)
}

return capacity, nil
}

// SetNodeRawCapacity sets the node annotation according to the raw capacity.
func SetNodeRawCapacity(node *corev1.Node, capacity corev1.ResourceList) {
s, _ := json.Marshal(capacity)
if node.Annotations == nil {
node.Annotations = map[string]string{}
}
node.Annotations[AnnotationNodeRawCapacity] = string(s)
// HasNodeRawAllocatable checks if the node has raw allocatable annotation.
func HasNodeRawAllocatable(annotations map[string]string) bool {
_, ok := annotations[AnnotationNodeRawAllocatable]
return ok
}

// GetNodeRawAllocatable gets the raw allocatable of node from annotations.
Expand Down
120 changes: 0 additions & 120 deletions apis/extension/node_resource_amplification_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,126 +369,6 @@ func TestSetNodeResourceAmplificationRatio(t *testing.T) {
}
}

func TestGetNodeRawCapacity(t *testing.T) {
tests := []struct {
name string
arg *corev1.Node
want corev1.ResourceList
wantErr bool
}{
{
name: "node has no annotation",
arg: &corev1.Node{},
want: nil,
wantErr: false,
},
{
name: "node has no raw capacity annotation",
arg: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"xxx": "yyy",
},
},
},
want: nil,
wantErr: false,
},
{
name: "node has valid raw capacity annotation",
arg: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"xxx": "yyy",
AnnotationNodeRawCapacity: `{"cpu":"1"}`,
},
},
},
want: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1"),
},
wantErr: false,
},
{
name: "node has invalid raw capacity annotation",
arg: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
"xxx": "yyy",
AnnotationNodeRawCapacity: "invalid",
},
},
},
want: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, gotErr := GetNodeRawCapacity(tt.arg.Annotations)
assert.Equal(t, tt.want, got)
assert.Equal(t, tt.wantErr, gotErr != nil)
})
}
}

func TestSetNodeRawCapacity(t *testing.T) {
type args struct {
node *corev1.Node
capacity corev1.ResourceList
}
tests := []struct {
name string
args args
wantField *corev1.Node
}{
{
name: "set for node with no annotation",
args: args{
node: &corev1.Node{},
capacity: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1"),
},
},
wantField: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
AnnotationNodeRawCapacity: `{"cpu":"1"}`,
},
},
},
},
{
name: "set for node with old annotation",
args: args{
node: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
AnnotationNodeRawCapacity: `{"cpu":"2"}`,
},
},
},
capacity: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1"),
},
},
wantField: &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Annotations: map[string]string{
AnnotationNodeRawCapacity: `{"cpu":"1"}`,
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
SetNodeRawCapacity(tt.args.node, tt.args.capacity)
assert.Equal(t, tt.wantField, tt.args.node)
})
}
}

func TestGetNodeRawAllocatable(t *testing.T) {
tests := []struct {
name string
Expand Down
21 changes: 21 additions & 0 deletions config/webhook/manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,27 @@ webhooks:
resources:
- elasticquotas
sideEffects: None
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: webhook-service
namespace: system
path: /mutate-node-status
failurePolicy: Ignore
name: mnode-status.koordinator.sh
rules:
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- nodes/status
sideEffects: None
- admissionReviewVersions:
- v1
- v1beta1
Expand Down
Loading

0 comments on commit c62d869

Please sign in to comment.