Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7764719
approval controller, metric collector controllers
Dec 6, 2025
fc87b21
minor fixes
Dec 10, 2025
f3ea6d5
minor fixes
Dec 10, 2025
3c8db43
address minor comments
Dec 10, 2025
e85a7a0
address minor comment
Dec 11, 2025
23ac827
address minor comment
Dec 11, 2025
018cacb
add birdeye view section
Dec 11, 2025
b8448b3
add context about kind-clusters
Dec 11, 2025
097e14a
fix image
Dec 11, 2025
164a25d
ensure script works for all clusters
Dec 11, 2025
cac604c
simplify metric-collector
Dec 12, 2025
69a8ed4
simplify approval controller
Dec 13, 2025
76de5f3
update README.md
Dec 13, 2025
16367ff
restructure dirs
Dec 15, 2025
538ae51
minor fixes
Dec 15, 2025
d937541
minor changes
Dec 15, 2025
d655a80
minor fixes
Dec 15, 2025
ab1e784
comments for workload health tracking
Dec 15, 2025
0f4a81c
update image, minor fixes
Dec 15, 2025
576dc2f
minor fixes
Dec 15, 2025
bd005d7
make commands for docker
Dec 15, 2025
7cbe0e5
minor update to README
Dec 15, 2025
fde0a44
minor fixes
Dec 15, 2025
ddc00e9
simplify hubconfig, runnning scripts
Dec 16, 2025
1578be0
address minor comments
Dec 16, 2025
0a68f88
minor fixes
Dec 16, 2025
9fa5010
account for workload kind
Dec 16, 2025
27f50e1
minor updates to readme
Dec 16, 2025
7c2bc78
fix README
Dec 16, 2025
aad7c4e
minor fixes
Dec 16, 2025
11b40af
minor fixes
Dec 16, 2025
ad798f4
minor readme update
Dec 16, 2025
d4a2b3e
minor fixes
Dec 17, 2025
2bb0a74
fix MetricCollectorReport cleanup
Dec 17, 2025
51a7da9
minor fix
Dec 17, 2025
6901556
address minor comments
Dec 17, 2025
4b3f709
address comments
Dec 17, 2025
cead734
address minor comments
Dec 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
625 changes: 625 additions & 0 deletions approval-controller-metric-collector/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Makefile for ApprovalRequest Controller

# Image settings
IMAGE_NAME ?= approval-request-controller
IMAGE_TAG ?= latest
REGISTRY ?=

# Build settings
GOOS ?= $(shell go env GOOS)
GOARCH ?= $(shell go env GOARCH)

# Tools
CONTROLLER_GEN_VERSION ?= v0.16.0
CONTROLLER_GEN = go run sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_GEN_VERSION)

.PHONY: help
help: ## Display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

##@ Code Generation

.PHONY: manifests
manifests: ## Generate CRD manifests
$(CONTROLLER_GEN) crd paths="./apis/..." output:crd:artifacts:config=config/crd/bases

.PHONY: generate
generate: ## Generate DeepCopy code
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./apis/..."

##@ Build

.PHONY: docker-build
docker-build: ## Build docker image
docker buildx build \
--file docker/approval-request-controller.Dockerfile \
--output=type=docker \
--platform=linux/$(GOARCH) \
--build-arg GOARCH=$(GOARCH) \
--tag $(IMAGE_NAME):$(IMAGE_TAG) \
--build-context kubefleet=.. \
..

.PHONY: docker-push
docker-push: ## Push docker image
docker push $(REGISTRY)$(IMAGE_NAME):$(IMAGE_TAG)

##@ Development

.PHONY: run
run: ## Run controller locally
cd .. && go run ./approval-request-controller/cmd/approvalrequestcontroller/main.go

##@ Deployment

.PHONY: install
install: ## Install helm chart
helm install approval-request-controller ./charts/approval-request-controller \
--namespace fleet-system \
--create-namespace \
--set image.repository=$(IMAGE_NAME) \
--set image.tag=$(IMAGE_TAG)

.PHONY: upgrade
upgrade: ## Upgrade helm chart
helm upgrade approval-request-controller ./charts/approval-request-controller \
--namespace fleet-system \
--set image.repository=$(IMAGE_NAME) \
--set image.tag=$(IMAGE_TAG)

.PHONY: uninstall
uninstall: ## Uninstall helm chart
helm uninstall approval-request-controller --namespace fleet-system

##@ Kind

.PHONY: kind-load
kind-load: docker-build ## Build and load image into kind cluster
kind load docker-image $(IMAGE_NAME):$(IMAGE_TAG) --name hub
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# ApprovalRequest Controller

The ApprovalRequest Controller is a standalone controller that runs on the **hub cluster** to automate approval decisions for staged updates based on workload health metrics.

## Overview

This controller is designed to be a standalone component that can run independently from the main kubefleet repository. It:
- Uses kubefleet v0.1.2 as an external dependency
- Includes its own APIs for MetricCollectorReport and WorkloadTracker
- Watches `ApprovalRequest` and `ClusterApprovalRequest` resources (from kubefleet)
- Creates `MetricCollector` resources on member clusters via ClusterResourcePlacement
- Monitors workload health via `MetricCollectorReport` objects
- Automatically approves requests when all tracked workloads are healthy
- Runs every 15 seconds to check health status

## Architecture

The controller is designed to run on the hub cluster and:
1. Deploys MetricCollector instances to member clusters using CRP
2. Collects health metrics from MetricCollectorReports
3. Compares metrics against WorkloadTracker specifications
4. Approves ApprovalRequests when all workloads are healthy

## Installation

### Prerequisites

The following CRDs must be installed on the hub cluster (installed by kubefleet hub-agent):
- `approvalrequests.placement.kubernetes-fleet.io`
- `clusterapprovalrequests.placement.kubernetes-fleet.io`
- `clusterresourceplacements.placement.kubernetes-fleet.io`
- `clusterresourceoverrides.placement.kubernetes-fleet.io`
- `clusterstagedupdateruns.placement.kubernetes-fleet.io`
- `stagedupdateruns.placement.kubernetes-fleet.io`

The following CRDs are installed by this chart:
- `metriccollectors.metric.kubernetes-fleet.io`
- `metriccollectorreports.metric.kubernetes-fleet.io`
- `workloadtrackers.metric.kubernetes-fleet.io`

### Install via Helm

```bash
# Build the image
make docker-build IMAGE_NAME=approval-request-controller IMAGE_TAG=latest

# Load into kind (if using kind)
kind load docker-image approval-request-controller:latest --name hub

# Install the chart
helm install approval-request-controller ./charts/approval-request-controller \
--namespace fleet-system \
--create-namespace
```

## Configuration

The controller watches for:
- `ApprovalRequest` (namespaced)
- `ClusterApprovalRequest` (cluster-scoped)

Both resources from kubefleet are monitored, and the controller creates `MetricCollector` resources on appropriate member clusters based on the staged update configuration.

### Health Check Interval

The controller checks workload health every **15 seconds**. This interval is configurable via the `reconcileInterval` parameter in the Helm chart.

## API Reference

### WorkloadTracker

`WorkloadTracker` is a cluster-scoped custom resource that defines which workloads the approval controller should monitor for health metrics before auto-approving staged rollouts.

#### Example: Single Workload

```yaml
apiVersion: metric.kubernetes-fleet.io/v1beta1
kind: WorkloadTracker
metadata:
name: sample-workload-tracker
workloads:
- name: sample-metric-app
namespace: test-ns
```

#### Example: Multiple Workloads

```yaml
apiVersion: metric.kubernetes-fleet.io/v1beta1
kind: WorkloadTracker
metadata:
name: multi-workload-tracker
workloads:
- name: frontend
namespace: production
- name: backend-api
namespace: production
- name: worker-service
namespace: production
```

#### Usage Notes

- **Cluster-scoped:** WorkloadTracker is a cluster-scoped resource, not namespaced
- **Optional:** If no WorkloadTracker exists, the controller will skip health checks and won't auto-approve
- **Single instance:** The controller expects one WorkloadTracker per cluster and uses the first one found
- **Health criteria:** All workloads listed must report healthy (metric value = 1.0) before approval
- **Prometheus metrics:** Each workload should expose `workload_health` metrics that the MetricCollector can query

For a complete example, see: [`./examples/workloadtracker/workloadtracker.yaml`](./examples/workloadtracker/workloadtracker.yaml)

## Additional Resources

- **Main Tutorial:** See [`../README.md`](../README.md) for a complete end-to-end tutorial on setting up automated staged rollouts with approval automation
- **Metric Collector:** See [`../metric-collector/README.md`](../metric-collector/README.md) for details on the metric collection component that runs on member clusters
- **KubeFleet Documentation:** [Azure/fleet](https://github.com/Azure/fleet) - Multi-cluster orchestration platform
- **Example Configurations:**
- [`./examples/workloadtracker/`](./examples/workloadtracker/) - WorkloadTracker resource examples
- [`./examples/stagedupdaterun/`](./examples/stagedupdaterun/) - Staged update configuration examples
- [`./examples/prometheus/`](./examples/prometheus/) - Prometheus deployment and configuration for metric collection
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
Copyright 2025 The KubeFleet Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package v1alpha1 contains API Schema definitions for the placement v1beta1 API group
// +kubebuilder:object:generate=true
// +groupName=metric.kubernetes-fleet.io
package v1alpha1
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
Copyright 2025 The KubeFleet Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// +kubebuilder:object:generate=true
// +groupName=metric.kubernetes-fleet.io
package v1alpha1

import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)

var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "metric.kubernetes-fleet.io", Version: "v1alpha1"}

// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}

// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
Loading