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

feat: use new property name for node count property + specify the core properties (node count, total/allocatable/available CPU/memory) #810

Merged
Merged
18 changes: 18 additions & 0 deletions apis/cluster/v1/commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ const (
ClusterStateLeave ClusterState = "Leave"
)

const (
// A list of property names that should be supported by every property provider and
// is available out of the box in Fleet without any property provider configuration.

// The non-resource properties.
// NodeCountProperty is a property that describes the number of nodes in the cluster.
NodeCountProperty = "kubernetes-fleet.io/node-count"

// The resource properties.
// Total and allocatable CPU resource properties.
TotalCPUCapacityProperty = "resources.kubernetes-fleet.io/total-cpu"
AllocatableCPUCapacityProperty = "resources.kubernetes-fleet.io/allocatable-cpu"

// Total and allocatable memory resource properties.
TotalMemoryCapacityProperty = "resources.kubernetes-fleet.io/total-memory"
AllocatableMemoryCapacityProperty = "resources.kubernetes-fleet.io/allocatable-memory"
)

michaelawyu marked this conversation as resolved.
Show resolved Hide resolved
// ResourceUsage contains the observed resource usage of a member cluster.
type ResourceUsage struct {
// Capacity represents the total resource capacity of all the nodes on a member cluster.
Expand Down
1 change: 0 additions & 1 deletion apis/cluster/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions apis/cluster/v1beta1/commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ const (
ClusterStateLeave ClusterState = "Leave"
)

const (
// A list of property names that should be supported by every property provider and
// is available out of the box in Fleet without any property provider configuration.

// The non-resource properties.
// NodeCountProperty is a property that describes the number of nodes in the cluster.
NodeCountProperty = "kubernetes-fleet.io/node-count"

// The resource properties.
// Total and allocatable CPU resource properties.
TotalCPUCapacityProperty = "resources.kubernetes-fleet.io/total-cpu"
AllocatableCPUCapacityProperty = "resources.kubernetes-fleet.io/allocatable-cpu"

// Total and allocatable memory resource properties.
TotalMemoryCapacityProperty = "resources.kubernetes-fleet.io/total-memory"
AllocatableMemoryCapacityProperty = "resources.kubernetes-fleet.io/allocatable-memory"
)

// ResourceUsage contains the observed resource usage of a member cluster.
type ResourceUsage struct {
// Capacity represents the total resource capacity of all the nodes on a member cluster.
Expand Down
1 change: 0 additions & 1 deletion apis/cluster/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion apis/placement/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion apis/placement/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion apis/placement/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion apis/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 16 additions & 4 deletions docs/concepts/PropertyProviderAndClusterProperties/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ in the form of Kubernetes conditions.

The Fleet member agent can run with or without a property provider. If a provider is not set up, or
the given provider fails to start properly, the agent will collect limited properties about
the cluster on its own, specifically the total and allocatable CPU and memory capacities of
the host member cluster.
the cluster on its own, specifically the node count, plus the total/allocatable
CPU and memory capacities of the host member cluster.

## Cluster properties

Expand All @@ -75,7 +75,7 @@ such as `cpu` and `memory`, and the usage information should consist of:
* Non-resource property: a metric about a member cluster, in the form of a key/value
pair; the key should be in the format of
[a Kubernetes label key](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set),
such as `kubernetes.azure.com/node-count`, and the value at this moment should be a sortable
such as `kubernetes-fleet.io/node-count`, and the value at this moment should be a sortable
numeric that can be parsed as
[a Kubernetes quantity](https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/quantity/).

Expand All @@ -92,7 +92,7 @@ status:
agentStatus: ...
conditions: ...
properties:
kubernetes.azure.com/node-count:
kubernetes-fleet.io/node-count:
observationTime: "2024-04-30T14:54:24Z"
value: "2"
...
Expand All @@ -111,3 +111,15 @@ status:
Note that conditions reported by the property provider (if any), would be available in the
`.status.conditions` array as well.

All property providers should support the following set of properties:

* Non-resource properties:
* `kubernetes-fleet.io/node-count`: the number of nodes in the cluster
* Resource properties
* The total and allocatable capacities of CPU (`cpu`) and memory (`memory`) resources in the cluster.

### Reserved domain for property names

Fleet reserves the domain, `kubernetes-fleet.io`, for property names. Except for the properties
explicitly listed above, which should be supported by all property providers, any custom property added
by a property provider should not use the reserved domain.
6 changes: 3 additions & 3 deletions docs/howtos/property-based-scheduling.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ spec:
clusterSelectorTerms:
- propertySelector:
matchExpressions:
- name: "kubernetes.azure.com/node-count"
- name: "kubernetes-fleet.io/node-count"
operator: Ge
values:
- "5"
Expand Down Expand Up @@ -130,7 +130,7 @@ spec:
region: east
propertySelector:
matchExpressions:
- name: "kubernetes.azure.com/node-count"
- name: "kubernetes-fleet.io/node-count"
operator: Ge
values:
- "5"
Expand Down Expand Up @@ -225,7 +225,7 @@ spec:
- weight: 20
preference:
metricSorter:
name: kubernetes.azure.com/node-count
name: kubernetes-fleet.io/node-count
sortOrder: Descending
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,12 @@ func (r *Reconciler) updateResourceStats(ctx context.Context, imc *clusterv1beta
allocatableMemory.Add(*(node.Status.Allocatable.Memory()))
}

imc.Status.Properties = map[clusterv1beta1.PropertyName]clusterv1beta1.PropertyValue{
clusterv1beta1.NodeCountProperty: {
Value: fmt.Sprintf("%d", len(nodes.Items)),
ObservationTime: metav1.Now(),
},
}
imc.Status.ResourceUsage.Capacity = corev1.ResourceList{
corev1.ResourceCPU: capacityCPU,
corev1.ResourceMemory: capacityMemory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ var _ = Describe("Test Internal Member Cluster Controller", Serial, func() {
Expect(updatedHealthCond.Reason).To(Equal(EventReasonInternalMemberClusterHealthy))

By("checking updated member cluster usage")
Expect(imc.Status.Properties[clusterv1beta1.NodeCountProperty].Value).ShouldNot(BeEmpty())
Expect(imc.Status.ResourceUsage.Allocatable).ShouldNot(BeNil())
Expect(imc.Status.ResourceUsage.Capacity).ShouldNot(BeNil())
Expect(imc.Status.ResourceUsage.ObservationTime).ToNot(Equal(metav1.Now()))
Expand Down
17 changes: 6 additions & 11 deletions pkg/propertyprovider/aks/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ import (
)

const (
// A list of properties that the AKS property provider collects.
// A list of properties that the AKS property provider collects in addition to the
michaelawyu marked this conversation as resolved.
Show resolved Hide resolved
// Fleet required ones.

// NodeCountProperty is a property that describes the number of nodes in the cluster.
NodeCountProperty = "kubernetes.azure.com/node-count"
// PerCPUCoreCostProperty is a property that describes the average hourly cost of a CPU core in
// a Kubernetes cluster.
PerCPUCoreCostProperty = "kubernetes.azure.com/per-cpu-core-cost"
Expand All @@ -41,13 +40,9 @@ const (
PerGBMemoryCostProperty = "kubernetes.azure.com/per-gb-memory-cost"

// The resource properties.
TotalCPUCapacityProperty = "resources.kubernetes-fleet.io/total-cpu"
AllocatableCPUCapacityProperty = "resources.kubernetes-fleet.io/allocatable-cpu"
AvailableCPUCapacityProperty = "resources.kubernetes-fleet.io/available-cpu"

TotalMemoryCapacityProperty = "resources.kubernetes-fleet.io/total-memory"
AllocatableMemoryCapacityProperty = "resources.kubernetes-fleet.io/allocatable-memory"
AvailableMemoryCapacityProperty = "resources.kubernetes-fleet.io/available-memory"
// Available CPU and memory resource properties.
AvailableCPUCapacityProperty = "resources.kubernetes-fleet.io/available-cpu"
michaelawyu marked this conversation as resolved.
Show resolved Hide resolved
AvailableMemoryCapacityProperty = "resources.kubernetes-fleet.io/available-memory"

CostPrecisionTemplate = "%.3f"
)
Expand Down Expand Up @@ -197,7 +192,7 @@ func (p *PropertyProvider) Collect(_ context.Context) propertyprovider.PropertyC

// Collect the non-resource properties.
properties := make(map[clusterv1beta1.PropertyName]clusterv1beta1.PropertyValue)
properties[NodeCountProperty] = clusterv1beta1.PropertyValue{
properties[clusterv1beta1.NodeCountProperty] = clusterv1beta1.PropertyValue{
Value: fmt.Sprintf("%d", p.nodeTracker.NodeCount()),
ObservationTime: metav1.Now(),
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/propertyprovider/aks/provider_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ var (

expectedRes := propertyprovider.PropertyCollectionResponse{
Properties: map[clusterv1beta1.PropertyName]clusterv1beta1.PropertyValue{
NodeCountProperty: {
clusterv1beta1.NodeCountProperty: {
Value: fmt.Sprintf("%d", len(nodes)),
},
PerCPUCoreCostProperty: {
Expand Down
4 changes: 2 additions & 2 deletions pkg/propertyprovider/aks/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func TestCollect(t *testing.T) {
},
wantMetricCollectionResponse: propertyprovider.PropertyCollectionResponse{
Properties: map[clusterv1beta1.PropertyName]clusterv1beta1.PropertyValue{
NodeCountProperty: {
clusterv1beta1.NodeCountProperty: {
Value: "2",
},
PerCPUCoreCostProperty: {
Expand Down Expand Up @@ -294,7 +294,7 @@ func TestCollect(t *testing.T) {
},
wantMetricCollectionResponse: propertyprovider.PropertyCollectionResponse{
Properties: map[clusterv1beta1.PropertyName]clusterv1beta1.PropertyValue{
NodeCountProperty: {
clusterv1beta1.NodeCountProperty: {
Value: "2",
},
PerCPUCoreCostProperty: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const (
envLabelName = "env"
envLabelValue1 = "prod"

nodeCountPropertyName = "kubernetes.azure.com/node-count"
nodeCountPropertyName = "kubernetes-fleet.io/node-count"
ryanzhang-oss marked this conversation as resolved.
Show resolved Hide resolved
nodeCountPropertyValue1 = "3"

availableCPUPropertyName = "resources.kubernetes-fleet.io/available-cpu"
michaelawyu marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
25 changes: 13 additions & 12 deletions test/e2e/placement_pickall_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/ptr"

clusterv1beta1 "go.goms.io/fleet/apis/cluster/v1beta1"
placementv1beta1 "go.goms.io/fleet/apis/placement/v1beta1"
"go.goms.io/fleet/pkg/propertyprovider/aks"
"go.goms.io/fleet/test/e2e/framework"
Expand Down Expand Up @@ -388,7 +389,7 @@ var _ = Describe("placing resources using a CRP of PickAll placement type", func
PropertySelector: &placementv1beta1.PropertySelector{
MatchExpressions: []placementv1beta1.PropertySelectorRequirement{
{
Name: aks.NodeCountProperty,
Name: clusterv1beta1.NodeCountProperty,
Operator: placementv1beta1.PropertySelectorGreaterThanOrEqualTo,
Values: []string{
"3",
Expand Down Expand Up @@ -462,14 +463,14 @@ var _ = Describe("placing resources using a CRP of PickAll placement type", func
PropertySelector: &placementv1beta1.PropertySelector{
MatchExpressions: []placementv1beta1.PropertySelectorRequirement{
{
Name: aks.NodeCountProperty,
Name: clusterv1beta1.NodeCountProperty,
Operator: placementv1beta1.PropertySelectorGreaterThanOrEqualTo,
Values: []string{
"3",
},
},
{
Name: aks.TotalCPUCapacityProperty,
Name: clusterv1beta1.TotalCPUCapacityProperty,
Operator: placementv1beta1.PropertySelectorLessThan,
Values: []string{
"10000",
Expand Down Expand Up @@ -522,14 +523,14 @@ var _ = Describe("placing resources using a CRP of PickAll placement type", func
PropertySelector: &placementv1beta1.PropertySelector{
MatchExpressions: []placementv1beta1.PropertySelectorRequirement{
{
Name: aks.NodeCountProperty,
Name: clusterv1beta1.NodeCountProperty,
Operator: placementv1beta1.PropertySelectorGreaterThanOrEqualTo,
Values: []string{
"3",
},
},
{
Name: aks.TotalCPUCapacityProperty,
Name: clusterv1beta1.TotalCPUCapacityProperty,
Operator: placementv1beta1.PropertySelectorLessThan,
Values: []string{
"10000",
Expand All @@ -542,7 +543,7 @@ var _ = Describe("placing resources using a CRP of PickAll placement type", func
PropertySelector: &placementv1beta1.PropertySelector{
MatchExpressions: []placementv1beta1.PropertySelectorRequirement{
{
Name: aks.NodeCountProperty,
Name: clusterv1beta1.NodeCountProperty,
Operator: placementv1beta1.PropertySelectorEqualTo,
Values: []string{
"4",
Expand Down Expand Up @@ -622,7 +623,7 @@ var _ = Describe("placing resources using a CRP of PickAll placement type", func
},
},
{
Name: aks.AllocatableCPUCapacityProperty,
Name: clusterv1beta1.AllocatableCPUCapacityProperty,
Operator: placementv1beta1.PropertySelectorGreaterThan,
Values: []string{
"10000",
Expand Down Expand Up @@ -695,7 +696,7 @@ var _ = Describe("placing resources using a CRP of PickAll placement type", func
PropertySelector: &placementv1beta1.PropertySelector{
MatchExpressions: []placementv1beta1.PropertySelectorRequirement{
{
Name: aks.NodeCountProperty,
Name: clusterv1beta1.NodeCountProperty,
Operator: placementv1beta1.PropertySelectorGreaterThanOrEqualTo,
Values: []string{
"3",
Expand Down Expand Up @@ -771,7 +772,7 @@ var _ = Describe("placing resources using a CRP of PickAll placement type", func
PropertySelector: &placementv1beta1.PropertySelector{
MatchExpressions: []placementv1beta1.PropertySelectorRequirement{
{
Name: aks.AllocatableCPUCapacityProperty,
Name: clusterv1beta1.AllocatableCPUCapacityProperty,
Operator: placementv1beta1.PropertySelectorLessThanOrEqualTo,
Values: []string{
"10000",
Expand Down Expand Up @@ -840,7 +841,7 @@ var _ = Describe("placing resources using a CRP of PickAll placement type", func
PropertySelector: &placementv1beta1.PropertySelector{
MatchExpressions: []placementv1beta1.PropertySelectorRequirement{
{
Name: aks.AllocatableMemoryCapacityProperty,
Name: clusterv1beta1.AllocatableMemoryCapacityProperty,
Operator: placementv1beta1.PropertySelectorLessThan,
Values: []string{
"1Ki",
Expand Down Expand Up @@ -871,14 +872,14 @@ var _ = Describe("placing resources using a CRP of PickAll placement type", func
PropertySelector: &placementv1beta1.PropertySelector{
MatchExpressions: []placementv1beta1.PropertySelectorRequirement{
{
Name: aks.NodeCountProperty,
Name: clusterv1beta1.NodeCountProperty,
Operator: placementv1beta1.PropertySelectorEqualTo,
Values: []string{
"2",
},
},
{
Name: aks.TotalMemoryCapacityProperty,
Name: clusterv1beta1.TotalMemoryCapacityProperty,
Operator: placementv1beta1.PropertySelectorGreaterThanOrEqualTo,
Values: []string{
"1Ki",
Expand Down
Loading
Loading