Skip to content

Commit 36847bb

Browse files
author
Arvind Thirumurugan
committed
fixes
Signed-off-by: Arvind Thirumurugan <[email protected]>
1 parent 6bf80f8 commit 36847bb

File tree

13 files changed

+1175
-209
lines changed

13 files changed

+1175
-209
lines changed

approval-request-controller/README.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ The ApprovalRequest Controller is a standalone controller that runs on the **hub
44

55
## Overview
66

7-
This controller:
8-
- Watches `ApprovalRequest` and `ClusterApprovalRequest` resources
7+
This controller is designed to be a standalone component that can run independently from the main kubefleet repository. It:
8+
- Uses kubefleet v0.1.2 as an external dependency
9+
- Includes its own APIs for MetricCollectorReport and WorkloadTracker
10+
- Watches `ApprovalRequest` and `ClusterApprovalRequest` resources (from kubefleet)
911
- Creates `MetricCollector` resources on member clusters via ClusterResourcePlacement
1012
- Monitors workload health via `MetricCollectorReport` objects
1113
- Automatically approves requests when all tracked workloads are healthy
@@ -23,17 +25,19 @@ The controller is designed to run on the hub cluster and:
2325

2426
### Prerequisites
2527

26-
The following CRDs must be installed on the hub cluster:
28+
The following CRDs must be installed on the hub cluster (installed by kubefleet hub-agent):
2729
- `approvalrequests.placement.kubernetes-fleet.io`
2830
- `clusterapprovalrequests.placement.kubernetes-fleet.io`
29-
- `metriccollectors.placement.kubernetes-fleet.io`
30-
- `metriccollectorreports.placement.kubernetes-fleet.io` (installed by this chart)
31-
- `workloadtrackers.placement.kubernetes-fleet.io`
3231
- `clusterresourceplacements.placement.kubernetes-fleet.io`
3332
- `clusterresourceoverrides.placement.kubernetes-fleet.io`
3433
- `clusterstagedupdateruns.placement.kubernetes-fleet.io`
3534
- `stagedupdateruns.placement.kubernetes-fleet.io`
3635

36+
The following CRDs are installed by this chart:
37+
- `metriccollectors.placement.kubernetes-fleet.io`
38+
- `metriccollectorreports.placement.kubernetes-fleet.io`
39+
- `workloadtrackers.placement.kubernetes-fleet.io`
40+
3741
### Install via Helm
3842

3943
```bash
@@ -51,13 +55,13 @@ helm install approval-request-controller ./charts/approval-request-controller \
5155

5256
## Configuration
5357

54-
See `charts/approval-request-controller/values.yaml` for all configuration options.
55-
5658
Key settings:
5759
- `controller.logLevel`: Log verbosity (default: 2)
5860
- `controller.resources`: Resource requests and limits
5961
- `rbac.create`: Create RBAC resources (default: true)
60-
- `crds.install`: Install MetricCollectorReport CRD (default: true)
62+
- `crds.install`: Install MetricCollector, MetricCollectorReport, and WorkloadTracker CRDs (default: true)
63+
- `rbac.create`: Create RBAC resources (default: true)
64+
- `crds.install`: Install MetricCollector and MetricCollectorReport CRDs (default: true)
6165

6266
## Development
6367

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
/*
2+
Copyright 2025 The KubeFleet 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 v1beta1
18+
19+
import (
20+
"k8s.io/apimachinery/pkg/api/meta"
21+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22+
)
23+
24+
// +genclient
25+
// +genclient:nonNamespaced
26+
// +kubebuilder:object:root=true
27+
// +kubebuilder:resource:scope="Cluster",shortName=mc,categories={fleet,fleet-metrics}
28+
// +kubebuilder:subresource:status
29+
// +kubebuilder:storageversion
30+
// +kubebuilder:printcolumn:JSONPath=`.metadata.generation`,name="Gen",type=string
31+
// +kubebuilder:printcolumn:JSONPath=`.status.conditions[?(@.type=="MetricCollectorReady")].status`,name="Ready",type=string
32+
// +kubebuilder:printcolumn:JSONPath=`.status.workloadsMonitored`,name="Workloads",type=integer
33+
// +kubebuilder:printcolumn:JSONPath=`.status.lastCollectionTime`,name="Last-Collection",type=date
34+
// +kubebuilder:printcolumn:JSONPath=`.metadata.creationTimestamp`,name="Age",type=date
35+
36+
// MetricCollector is used by member-agent to scrape and collect metrics from workloads
37+
// running on the member cluster. It runs on each member cluster and collects metrics
38+
// from Prometheus-compatible endpoints.
39+
type MetricCollector struct {
40+
metav1.TypeMeta `json:",inline"`
41+
metav1.ObjectMeta `json:"metadata,omitempty"`
42+
43+
// The desired state of MetricCollector.
44+
// +required
45+
Spec MetricCollectorSpec `json:"spec"`
46+
47+
// The observed status of MetricCollector.
48+
// +optional
49+
Status MetricCollectorStatus `json:"status,omitempty"`
50+
}
51+
52+
// MetricCollectorSpec defines the desired state of MetricCollector.
53+
type MetricCollectorSpec struct {
54+
// PrometheusURL is the URL of the Prometheus server.
55+
// Example: http://prometheus.test-ns.svc.cluster.local:9090
56+
// +required
57+
// +kubebuilder:validation:Pattern=`^https?://.*$`
58+
PrometheusURL string `json:"prometheusUrl"`
59+
60+
// ReportNamespace is the namespace in the hub cluster where the MetricCollectorReport will be created.
61+
// This should be the fleet-member-{clusterName} namespace.
62+
// Example: fleet-member-cluster-1
63+
// +required
64+
ReportNamespace string `json:"reportNamespace"`
65+
}
66+
67+
// MetricsEndpointSpec defines how to access the metrics endpoint.ctor.
68+
type MetricCollectorStatus struct {
69+
// Conditions is an array of current observed conditions.
70+
// +optional
71+
Conditions []metav1.Condition `json:"conditions,omitempty"`
72+
73+
// ObservedGeneration is the generation most recently observed.
74+
// +optional
75+
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
76+
77+
// WorkloadsMonitored is the count of workloads being monitored.
78+
// +optional
79+
WorkloadsMonitored int32 `json:"workloadsMonitored,omitempty"`
80+
81+
// LastCollectionTime is when metrics were last collected.
82+
// +optional
83+
LastCollectionTime *metav1.Time `json:"lastCollectionTime,omitempty"`
84+
85+
// CollectedMetrics contains the most recent metrics from each workload.
86+
// +optional
87+
CollectedMetrics []WorkloadMetrics `json:"collectedMetrics,omitempty"`
88+
}
89+
90+
// WorkloadMetrics represents metrics collected from a single workload pod.
91+
type WorkloadMetrics struct {
92+
// Namespace is the namespace of the pod.
93+
// +required
94+
Namespace string `json:"namespace"`
95+
96+
// ClusterName from the workload_health metric label.
97+
// +required
98+
ClusterName string `json:"clusterName"`
99+
100+
// WorkloadName from the workload_health metric label (typically the deployment name).
101+
// +required
102+
WorkloadName string `json:"workloadName"`
103+
104+
// Health indicates if the workload is healthy (true=healthy, false=unhealthy).
105+
// +required
106+
Health bool `json:"health"`
107+
}
108+
109+
const (
110+
// MetricCollectorConditionTypeReady indicates the collector is ready.
111+
MetricCollectorConditionTypeReady string = "MetricCollectorReady"
112+
113+
// MetricCollectorConditionTypeCollecting indicates metrics are being collected.
114+
MetricCollectorConditionTypeCollecting string = "MetricsCollecting"
115+
116+
// MetricCollectorConditionTypeReported indicates metrics were successfully reported to hub.
117+
MetricCollectorConditionTypeReported string = "MetricsReported"
118+
)
119+
120+
// +kubebuilder:object:root=true
121+
122+
// MetricCollectorList contains a list of MetricCollector.
123+
type MetricCollectorList struct {
124+
metav1.TypeMeta `json:",inline"`
125+
metav1.ListMeta `json:"metadata,omitempty"`
126+
Items []MetricCollector `json:"items"`
127+
}
128+
129+
// GetConditions returns the conditions of the MetricCollector.
130+
func (m *MetricCollector) GetConditions() []metav1.Condition {
131+
return m.Status.Conditions
132+
}
133+
134+
// SetConditions sets the conditions of the MetricCollector.
135+
func (m *MetricCollector) SetConditions(conditions ...metav1.Condition) {
136+
m.Status.Conditions = conditions
137+
}
138+
139+
// GetCondition returns the condition of the given MetricCollector.
140+
func (m *MetricCollector) GetCondition(conditionType string) *metav1.Condition {
141+
return meta.FindStatusCondition(m.Status.Conditions, conditionType)
142+
}
143+
144+
func init() {
145+
SchemeBuilder.Register(&MetricCollector{}, &MetricCollectorList{})
146+
}

approval-request-controller/apis/placement/v1beta1/metriccollectorreport_types.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -72,25 +72,6 @@ type MetricCollectorReport struct {
7272
LastReportTime *metav1.Time `json:"lastReportTime,omitempty"`
7373
}
7474

75-
// WorkloadMetrics represents metrics collected from a single workload pod.
76-
type WorkloadMetrics struct {
77-
// Namespace is the namespace of the pod.
78-
// +required
79-
Namespace string `json:"namespace"`
80-
81-
// ClusterName from the workload_health metric label.
82-
// +required
83-
ClusterName string `json:"clusterName"`
84-
85-
// WorkloadName from the workload_health metric label (typically the deployment name).
86-
// +required
87-
WorkloadName string `json:"workloadName"`
88-
89-
// Health indicates if the workload is healthy (true=healthy, false=unhealthy).
90-
// +required
91-
Health bool `json:"health"`
92-
}
93-
9475
// +kubebuilder:object:root=true
9576

9677
// MetricCollectorReportList contains a list of MetricCollectorReport.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
Copyright 2025 The KubeFleet 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 v1beta1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
)
22+
23+
// WorkloadReference represents a workload to be tracked
24+
type WorkloadReference struct {
25+
// Name is the name of the workload
26+
// +required
27+
Name string `json:"name"`
28+
29+
// Namespace is the namespace of the workload
30+
// +required
31+
Namespace string `json:"namespace"`
32+
}
33+
34+
// +genclient
35+
// +genclient:nonNamespaced
36+
// +kubebuilder:object:root=true
37+
// +kubebuilder:resource:scope="Cluster",categories={fleet,fleet-placement}
38+
// +kubebuilder:storageversion
39+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
40+
41+
// WorkloadTracker expresses user intent to track certain workloads
42+
type WorkloadTracker struct {
43+
metav1.TypeMeta `json:",inline"`
44+
metav1.ObjectMeta `json:"metadata,omitempty"`
45+
46+
// Workloads is a list of workloads to track
47+
// +optional
48+
Workloads []WorkloadReference `json:"workloads,omitempty"`
49+
}
50+
51+
// +kubebuilder:object:root=true
52+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
53+
54+
// WorkloadTrackerList contains a list of WorkloadTracker
55+
type WorkloadTrackerList struct {
56+
metav1.TypeMeta `json:",inline"`
57+
metav1.ListMeta `json:"metadata,omitempty"`
58+
Items []WorkloadTracker `json:"items"`
59+
}
60+
61+
func init() {
62+
SchemeBuilder.Register(&WorkloadTracker{}, &WorkloadTrackerList{})
63+
}

0 commit comments

Comments
 (0)