Skip to content

Commit 17fbfdd

Browse files
authored
Merge pull request #233 from wy-lucky/feat/not-collect-vnode-resource
feat(fcluster): do not collect resources related to virtual nodes.
2 parents cafc3db + 4ef5681 commit 17fbfdd

File tree

9 files changed

+134
-18
lines changed

9 files changed

+134
-18
lines changed

cmd/controller-manager/app/core.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ func startFederatedClusterController(
173173
controllerCtx.ComponentConfig.ClusterJoinTimeout,
174174
controllerCtx.WorkerCount,
175175
controllerCtx.FedSystemNamespace,
176+
controllerCtx.ComponentConfig.ResourceAggregationNodeFilter,
176177
)
177178
if err != nil {
178179
return nil, fmt.Errorf("error creating federate controller: %w", err)

cmd/controller-manager/app/options/options.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ type Options struct {
6262
PrometheusAddr string
6363
PrometheusPort uint16
6464
PrometheusQuantiles map[string]string
65+
66+
ResourceAggregationNodeFilter []string
6567
}
6668

6769
func NewOptions() *Options {
@@ -140,7 +142,16 @@ func (o *Options) AddFlags(flags *pflag.FlagSet, allControllers []string, disabl
140142
&o.PrometheusQuantiles,
141143
"prometheus-quantiles",
142144
map[string]string{"0.5": "0.01", "0.95": "0.01", "0.99": "0.002"},
143-
"prometheus summary objective quantiles",
145+
"Prometheus summary objective quantiles",
146+
)
147+
148+
flags.StringArrayVar(
149+
&o.ResourceAggregationNodeFilter,
150+
"resource-aggregation-node-filter",
151+
[]string{},
152+
"Nodes matching the provided label selector are excluded from resource aggregation. "+
153+
"If the flag is provided multiple times, "+
154+
"nodes are excluded as long as at least one of the selectors is matched.",
144155
)
145156
}
146157

cmd/controller-manager/app/util.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"time"
2424

2525
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/apimachinery/pkg/labels"
2627
"k8s.io/apimachinery/pkg/util/sets"
2728
"k8s.io/client-go/dynamic"
2829
"k8s.io/client-go/dynamic/dynamicinformer"
@@ -192,5 +193,15 @@ func getComponentConfig(opts *options.Options) (*controllercontext.ComponentConf
192193
componentConfig.NSAutoPropExcludeRegexp = nsAutoPropExcludeRegexp
193194
}
194195

196+
labelSelectors := make([]labels.Selector, len(opts.ResourceAggregationNodeFilter))
197+
for i, labelSelectorString := range opts.ResourceAggregationNodeFilter {
198+
labelSelector, err := labels.Parse(labelSelectorString)
199+
if err != nil {
200+
return nil, fmt.Errorf("failed to compile resource aggregation node filter: %w", err)
201+
}
202+
labelSelectors[i] = labelSelector
203+
}
204+
componentConfig.ResourceAggregationNodeFilter = labelSelectors
205+
195206
return componentConfig, nil
196207
}

pkg/controllers/context/context.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"regexp"
2222
"time"
2323

24+
"k8s.io/apimachinery/pkg/labels"
2425
dynamicclient "k8s.io/client-go/dynamic"
2526
"k8s.io/client-go/dynamic/dynamicinformer"
2627
kubeinformer "k8s.io/client-go/informers"
@@ -78,7 +79,8 @@ func (c *Context) StartFactories(ctx context.Context) {
7879
}
7980

8081
type ComponentConfig struct {
81-
NSAutoPropExcludeRegexp *regexp.Regexp
82-
ClusterJoinTimeout time.Duration
83-
MemberObjectEnqueueDelay time.Duration
82+
NSAutoPropExcludeRegexp *regexp.Regexp
83+
ClusterJoinTimeout time.Duration
84+
MemberObjectEnqueueDelay time.Duration
85+
ResourceAggregationNodeFilter []labels.Selector
8486
}

pkg/controllers/federatedcluster/clusterstatus.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func (c *FederatedClusterController) collectIndividualClusterStatus(
107107

108108
// We skip updating cluster resources and api resources if cluster is not ready
109109
if readyStatus == corev1.ConditionTrue {
110-
if err := updateClusterResources(
110+
if err := c.updateClusterResources(
111111
ctx,
112112
&cluster.Status,
113113
podLister,
@@ -200,7 +200,7 @@ func checkReadyByHealthz(
200200
return corev1.ConditionFalse, clusterReadyStatus
201201
}
202202

203-
func updateClusterResources(
203+
func (c *FederatedClusterController) updateClusterResources(
204204
ctx context.Context,
205205
clusterStatus *fedcorev1a1.FederatedClusterStatus,
206206
podLister corev1listers.PodLister,
@@ -225,12 +225,12 @@ func updateClusterResources(
225225

226226
schedulableNodes := int64(0)
227227
for _, node := range nodes {
228-
if isNodeSchedulable(node) {
228+
if isNodeSchedulable(node) && !c.isNodeFiltered(node) {
229229
schedulableNodes++
230230
}
231231
}
232232

233-
allocatable, available := aggregateResources(nodes, pods)
233+
allocatable, available := c.aggregateResources(nodes, pods)
234234
clusterStatus.Resources = fedcorev1a1.Resources{
235235
SchedulableNodes: &schedulableNodes,
236236
Allocatable: allocatable,

pkg/controllers/federatedcluster/controller.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,10 @@ type FederatedClusterController struct {
7676
kubeClient kubeclient.Interface
7777
fedClient fedclient.Interface
7878

79-
fedSystemNamespace string
80-
clusterHealthCheckConfig *ClusterHealthCheckConfig
81-
clusterJoinTimeout time.Duration
79+
fedSystemNamespace string
80+
clusterHealthCheckConfig *ClusterHealthCheckConfig
81+
clusterJoinTimeout time.Duration
82+
resourceAggregationNodeFilter []labels.Selector
8283

8384
worker worker.ReconcileWorker[common.QualifiedName]
8485
statusCollectWorker worker.ReconcileWorker[common.QualifiedName]
@@ -98,6 +99,7 @@ func NewFederatedClusterController(
9899
clusterJoinTimeout time.Duration,
99100
workerCount int,
100101
fedSystemNamespace string,
102+
resourceAggregationNodeFilter []labels.Selector,
101103
) (*FederatedClusterController, error) {
102104
c := &FederatedClusterController{
103105
clusterInformer: clusterInformer,
@@ -109,9 +111,10 @@ func NewFederatedClusterController(
109111
// TODO: make health check period configurable
110112
Period: time.Second * 30,
111113
},
112-
clusterJoinTimeout: clusterJoinTimeout,
113-
metrics: metrics,
114-
logger: logger.WithValues("controller", FederatedClusterControllerName),
114+
clusterJoinTimeout: clusterJoinTimeout,
115+
resourceAggregationNodeFilter: resourceAggregationNodeFilter,
116+
metrics: metrics,
117+
logger: logger.WithValues("controller", FederatedClusterControllerName),
115118
}
116119

117120
broadcaster := record.NewBroadcaster()

pkg/controllers/federatedcluster/util.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package federatedcluster
1919
import (
2020
corev1 "k8s.io/api/core/v1"
2121
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22+
"k8s.io/apimachinery/pkg/labels"
2223

2324
fedcorev1a1 "github.com/kubewharf/kubeadmiral/pkg/apis/core/v1alpha1"
2425
"github.com/kubewharf/kubeadmiral/pkg/util/resource"
@@ -132,16 +133,32 @@ func isNodeSchedulable(node *corev1.Node) bool {
132133
return true
133134
}
134135

136+
// isNodeFiltered returns true if the node is filtered to aggregate resources, otherwise false.
137+
func (c *FederatedClusterController) isNodeFiltered(node *corev1.Node) bool {
138+
nodeLabels := node.GetLabels()
139+
if nodeLabels == nil {
140+
return false
141+
}
142+
143+
for _, labelSelector := range c.resourceAggregationNodeFilter {
144+
if labelSelector.Matches(labels.Set(nodeLabels)) {
145+
return true
146+
}
147+
}
148+
149+
return false
150+
}
151+
135152
// aggregateResources returns
136153
// - allocatable resources from the nodes and,
137154
// - available resources after considering allocations to the given pods.
138-
func aggregateResources(
155+
func (c *FederatedClusterController) aggregateResources(
139156
nodes []*corev1.Node,
140157
pods []*corev1.Pod,
141158
) (corev1.ResourceList, corev1.ResourceList) {
142159
allocatable := make(corev1.ResourceList)
143160
for _, node := range nodes {
144-
if !isNodeSchedulable(node) {
161+
if !isNodeSchedulable(node) || c.isNodeFiltered(node) {
145162
continue
146163
}
147164

pkg/controllers/federatedcluster/util_test.go

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222
"github.com/davecgh/go-spew/spew"
2323
corev1 "k8s.io/api/core/v1"
2424
"k8s.io/apimachinery/pkg/api/resource"
25+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/apimachinery/pkg/labels"
2527
)
2628

2729
func Test_aggregateResources(t *testing.T) {
@@ -256,11 +258,80 @@ func Test_aggregateResources(t *testing.T) {
256258
corev1.ResourceMemory: resource.MustParse("2Gi"),
257259
},
258260
},
261+
{
262+
name: "one container per pod, and filtering some nodes",
263+
nodes: []*corev1.Node{
264+
{
265+
Status: corev1.NodeStatus{
266+
Allocatable: corev1.ResourceList{
267+
corev1.ResourceCPU: resource.MustParse("1"),
268+
corev1.ResourceMemory: resource.MustParse("2Gi"),
269+
},
270+
},
271+
},
272+
{
273+
ObjectMeta: metav1.ObjectMeta{
274+
Labels: map[string]string{
275+
"type": "virtual-kubelet",
276+
},
277+
},
278+
Status: corev1.NodeStatus{
279+
Allocatable: corev1.ResourceList{
280+
corev1.ResourceCPU: resource.MustParse("1"),
281+
corev1.ResourceMemory: resource.MustParse("2Gi"),
282+
},
283+
},
284+
},
285+
},
286+
pods: []*corev1.Pod{
287+
{
288+
Spec: corev1.PodSpec{
289+
Containers: []corev1.Container{
290+
{
291+
Resources: corev1.ResourceRequirements{
292+
Requests: corev1.ResourceList{
293+
corev1.ResourceCPU: resource.MustParse("500m"),
294+
corev1.ResourceMemory: resource.MustParse("1Gi"),
295+
},
296+
},
297+
},
298+
},
299+
},
300+
},
301+
{
302+
Spec: corev1.PodSpec{
303+
Containers: []corev1.Container{
304+
{
305+
Resources: corev1.ResourceRequirements{
306+
Requests: corev1.ResourceList{
307+
corev1.ResourceCPU: resource.MustParse("500m"),
308+
corev1.ResourceMemory: resource.MustParse("1Gi"),
309+
},
310+
},
311+
},
312+
},
313+
},
314+
},
315+
},
316+
expectedAllocatable: corev1.ResourceList{
317+
corev1.ResourceCPU: resource.MustParse("1"),
318+
corev1.ResourceMemory: resource.MustParse("2Gi"),
319+
},
320+
expectedAvailable: corev1.ResourceList{
321+
corev1.ResourceCPU: resource.MustParse("0"),
322+
corev1.ResourceMemory: resource.MustParse("0Gi"),
323+
},
324+
},
259325
}
260326

261327
for _, tc := range testCases {
262328
t.Run(tc.name, func(t *testing.T) {
263-
allocatable, available := aggregateResources(tc.nodes, tc.pods)
329+
selector, _ := labels.Parse("type=virtual-kubelet")
330+
c := &FederatedClusterController{
331+
resourceAggregationNodeFilter: []labels.Selector{selector},
332+
}
333+
334+
allocatable, available := c.aggregateResources(tc.nodes, tc.pods)
264335
if len(allocatable) != len(tc.expectedAllocatable) {
265336
t.Fatalf("expected allocatable %s differs from actual allocatable %s", spew.Sdump(tc.expectedAllocatable), spew.Sdump(allocatable))
266337
}

pkg/util/cascadingdeletion/annotation.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
"github.com/kubewharf/kubeadmiral/pkg/controllers/common"
2222
)
2323

24-
// AnnotationCascadingDelete on a fedreated cluster means that
24+
// AnnotationCascadingDelete on a federated cluster means that
2525
// resources managed by KubeAdmiral in the cluster should be cleaned
2626
// up before deletion can occur.
2727
var AnnotationCascadingDelete = common.DefaultPrefix + "cascading-delete"

0 commit comments

Comments
 (0)