Skip to content

🌱 Upgrade FL controller Flower path to 1.26.x SuperLink/SuperNode architecture - #107

Merged
openshift-merge-bot[bot] merged 6 commits into
open-cluster-management-io:mainfrom
yanmxa:flower-controller-superlink-upgrade
Mar 13, 2026
Merged

🌱 Upgrade FL controller Flower path to 1.26.x SuperLink/SuperNode architecture#107
openshift-merge-bot[bot] merged 6 commits into
open-cluster-management-io:mainfrom
yanmxa:flower-controller-superlink-upgrade

Conversation

@yanmxa

@yanmxa yanmxa commented Mar 4, 2026

Copy link
Copy Markdown
Member

Related Jira Issue

https://issues.redhat.com/browse/ACM-30551

Summary

  • Upgrade the Flower path in the FederatedLearning controller from legacy Flower 1.x (server/client Jobs with own networking) to Flower 1.26.x SuperLink/SuperNode architecture
  • The controller now deploys only the application layer (SuperExec-ServerApp + SuperExec-ClientApp) on top of infrastructure pre-deployed by the Flower Addon
  • Replace per-cluster ManifestWork generation with a single ManifestWorkReplicaSet for automatic cluster management via OCM Placement

Changes

CRD: Added superlink (default: superlink.flower-system:9091) and supernode (default: flower-supernode.flower-addon:9094) endpoint fields to ServerSpec/ClientSpec

Controller: New reconcileFlower() path deploys:

  • SuperExec-ServerApp Deployment on hub (connects to SuperLink exec API)
  • SuperExec-ClientApp via ManifestWorkReplicaSet (connects to SuperNode ClientAppIO API)

Removed: Old Flower 1.x templates (server-job, service, route, client manifestwork) and associated param structs

Added: RBAC for apps/deployments and work.open-cluster-management.io/manifestworkreplicasets, workv1alpha1 scheme registration

Test plan

  • make generate && make manifests - CRD generation succeeds with new fields
  • make build - Go compilation passes
  • make test - All existing tests pass
  • Deploy to Kind cluster with OCM + Flower addon (cloud-user@10.0.11.238)
  • Verify SuperExec-ServerApp Deployment created on hub with correct args
  • Verify ManifestWorkReplicaSet created and ManifestWorks propagate to managed clusters
  • Verify SuperExec-ClientApp Deployments appear on managed clusters in correct namespace
  • Delete FederatedLearning CR and verify all resources cleaned up

🤖 Generated with Claude Code

@openshift-ci
openshift-ci Bot requested review from mikeshng and mrrr3d March 4, 2026 04:27
@openshift-ci

openshift-ci Bot commented Mar 4, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: yanmxa

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved label Mar 4, 2026
@yanmxa yanmxa changed the title Upgrade FL controller Flower path to 2.x SuperLink/SuperNode architecture 🌱 Upgrade FL controller Flower path to 2.x SuperLink/SuperNode architecture Mar 4, 2026
### Deploy a Federated Learning Instance (Flower)

#### 1. Deploy a Federated Learning Instance
#### 1. Create a FederatedLearning Resource

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#### 1. Create a FederatedLearning Resource
#### 1. Create a Federated Learning Resource

Should there be a space between FederatedLearning?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the resource name is FederatedLearning

ListenerPort int
CreateService bool
ObsSidecarImage string
// FlowerServerAppParams defines the parameters for a Flower 2.x SuperExec-ServerApp Deployment on hub.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean 1.2x instead of 2.x? The latest Flower version as of today is 1.26.1.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good Catch! You're right, the current Flower version is 1.26.x. I used "2.x" to conceptually distinguish the new SuperLink/SuperNode architecture from the old server/client model, but it's misleading. Will update all "2.x" references to reflect the actual version.

ObsSidecarImage string
// FlowerServerAppParams defines the parameters for a Flower 2.x SuperExec-ServerApp Deployment on hub.
type FlowerServerAppParams struct {
Namespace string // FL CR namespace (where Deployment is created)

@chongshenng chongshenng Mar 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use the full form of FL CR so that it's clear?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

// FlowerClientAppParams defines the parameters for a Flower 2.x SuperExec-ClientApp ManifestWorkReplicaSet.
type FlowerClientAppParams struct {
Name string // e.g., "<cr-name>-clientapp"
Namespace string // FL CR namespace (where MWRS is created)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

return nil
}

// pruneOpenFLClientResources cleans up OpenFL client resources (per-cluster ManifestWorks + Placement).

@chongshenng chongshenng Mar 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an alternate function used only for OpenFL (not Flower)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, exactly. pruneClientResources (line 226) dispatches by framework: Flower calls pruneFlowerClientResources, OpenFL calls pruneOpenFLClientResources. This split was needed because Flower now uses ManifestWorkReplicaSet while OpenFL uses per-cluster ManifestWorks — different resources require different cleanup logic.

return err
}

clientParams := &manifests.OpenFLClientParams{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be related to my comment above, is this part of the OpenFL function? If it doesn't impact the usage of Flower here, maybe this should go into another PR and focus only on the changes for Flower here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify further: the OpenFL code logic is unchanged — only the switch wrapper was removed since it had a single remaining case after extracting Flower. This is already isolated in commit 49a3955. Splitting it into a separate PR would introduce an awkward intermediate state (a single-case switch).

return ctrl.Result{}, nil
}

// reconcileFlower handles the Flower 2.x SuperLink/SuperNode architecture.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment above about Flower version.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update to 1.26.x.

}

render, deployer := applier.NewRenderer(serverFS), applier.NewDeployer(r.Client)
serverParams := &manifests.OpenFLServerParams{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my comment above about maybe moving this to another PR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reasoning as the client file — see my reply here.

Comment thread federated-learning-controller/README.md Outdated

## Architecture

### Flower 2.x (SuperLink/SuperNode)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my earlier comment about the Flower version.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already updated to 1.26.x.

Comment thread federated-learning-controller/README.md Outdated
Comment on lines +258 to +259
--app <your-flower-app> \
--federation <superlink-address>

@chongshenng chongshenng Mar 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
--app <your-flower-app> \
--federation <superlink-address>
<your-flower-app> \
<superlink-connection>

You don't need to pass the --app or --federation flags. They are positional args.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, updated to positional args.

Comment thread federated-learning-controller/README.md Outdated
<summary><strong>Deploy a Federated Learning Instance (OpenFL)</strong></summary>

#### 2. Schedule the Federated Learning Clients into Managed Clusters
### OpenFL Path

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move the changes for OpenFL to another PR and keep this PR focused only for the Flower-related changes?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, split the OpenFL docs into #108.

@yanmxa yanmxa changed the title 🌱 Upgrade FL controller Flower path to 2.x SuperLink/SuperNode architecture 🌱 Upgrade FL controller Flower path to 1.26.x SuperLink/SuperNode architecture Mar 9, 2026
@yanmxa

yanmxa commented Mar 10, 2026

Copy link
Copy Markdown
Member Author

/retest

yanmxa and others added 6 commits March 12, 2026 15:05
…ture

Signed-off-by: Meng Yan <myan@redhat.com>
Remove unnecessary framework switch statements and embed.FS variables
since federatedLearningServer() and clusterWorkload() are now only
called for the OpenFL path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Meng Yan <myan@redhat.com>
The new template files were missed in the initial commit because
git add -u only tracks modified/deleted files, not new untracked ones.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Meng Yan <myan@redhat.com>
…R abbreviation, fix flwr run syntax, split OpenFL docs to separate PR

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Meng Yan <myan@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Meng Yan <myan@redhat.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Meng Yan <myan@redhat.com>
@yanmxa
yanmxa force-pushed the flower-controller-superlink-upgrade branch from b312554 to 9abaeda Compare March 12, 2026 08:38
@yanmxa
yanmxa requested review from chongshenng March 12, 2026 09:49
@ldpliu

ldpliu commented Mar 13, 2026

Copy link
Copy Markdown

/lgtm

@openshift-ci openshift-ci Bot added the lgtm label Mar 13, 2026
@openshift-merge-bot
openshift-merge-bot Bot merged commit fcd1224 into open-cluster-management-io:main Mar 13, 2026
10 checks passed
@yanmxa
yanmxa deleted the flower-controller-superlink-upgrade branch March 17, 2026 02:03
openshift-merge-bot Bot pushed a commit that referenced this pull request May 14, 2026
* 🌱 Migrate Flower app-torch example to SuperExec architecture

The Flower path in the FederatedLearning controller was upgraded to the
1.26.x SuperLink/SuperNode/SuperExec architecture in #107, but
examples/flower/app-torch/ was left on the legacy Flower 1.x
`server`/`client` entrypoint. The manifests produced by the controller
launch the container with SuperExec args (`--insecure`,
`--appio-api-address=<addr>`, `--plugin-type=<serverapp|clientapp>`),
which the old entrypoint.sh rejected with `Unsupported command
'--insecure'` (see #116).

This rewrites the example to match the SuperExec contract used by the
flower-addon's cifar10 reference app:

- server_app.py / client_app.py now expose `ServerApp` / `ClientApp`
  objects via `@app.main()` / `@app.train()` / `@app.evaluate()`.
- task.py loads MNIST via `flwr_datasets.FederatedDataset` with an
  `IidPartitioner`; partition-id is derived from the `cluster-name` /
  `num-partitions` node_config injected by the flower-addon SuperNode.
- pyproject.toml pins `flwr>=1.26.1` and registers the new
  `[tool.flwr.app.components]` entry points.
- Dockerfile switches the base image to `flwr/superexec:1.26.1` and
  bakes PyTorch / Flower deps in at build time. ENTRYPOINT is now
  `flower-superexec`. This also resolves the slow-startup feedback in
  issue #116 where the previous image re-downloaded ~2GB of deps on
  every pod start.
- entrypoint.sh and app_torch/utils.py are removed (obsolete with
  SuperExec).

README updates:

- Add a step to enable the `ManifestWorkReplicaSet` feature gate on the
  hub (disabled by default in OCM v1.2.x, per the original report).
- Point the sample `FederatedLearning` CR at
  `quay.io/open-cluster-management/federated-learning-application:flower-mnist-latest`
  (the legacy `flower-app:cifar10-v1.0.0` image referenced in main is
  unavailable on quay.io and is incompatible with the SuperExec args).
- Clarify the SuperExec image contract and update the `APP_NAME`
  example to `flower-mnist`.

Fixes #116

Signed-off-by: Meng Yan <myan@redhat.com>

* Address CodeRabbit review feedback

- client_app.py: replace process-randomized `hash()` with `hashlib.sha256`
  so the cluster-name -> partition-id mapping is stable across pod
  restarts.
- server_app.py: make the final-model save path configurable via the
  `FLOWER_MODEL_OUTPUT_PATH` env var; skip the save when it's unset
  (the hub ServerApp Deployment has no PVC by default, so writing to
  /app was effectively a no-op).
- task.py: cache the centralized MNIST DataLoader across rounds and
  drop the redundant `with_format("torch")` (overridden by
  `with_transform`).
- pyproject.toml: cap `flwr` at `<2` to guard against future breaking
  major releases.

Signed-off-by: Meng Yan <myan@redhat.com>

---------

Signed-off-by: Meng Yan <myan@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants