Skip to content

Conversation

kahirokunn
Copy link

Problem
The linkerd-multicluster chart is intended to be reusable across clusters, but its controller values must be customized per cluster. This couples cluster-specific controller config with common components, making Argo CD diffs noisy, parameter management cumbersome, and IdP integrations (e.g., Backstage) harder when ownership boundaries are mixed.

Solution
Introduce a new chart, linkerd-multicluster-controller, that contains the controller templates split from linkerd-multicluster. The templates are intentionally duplicated (no functional changes) to preserve backward compatibility. We will release with both charts/templates coexisting; after a sufficient migration window, we’ll remove the duplication by either deleting the controller templates from linkerd-multicluster or merging the controller back via a single source of truth (e.g., library chart/unification step).

This split allows:

  • Per-cluster controller values without affecting the shared components
  • Clearer GitOps/Argo CD diffs and ownership boundaries
  • Simpler parameter management and IdP (e.g., Backstage) integration

Validation
Minimal workflow aligned with the docs’ “Link the clusters” step:

  1. Link the clusters (from east → west)
linkerd --context=east multicluster link-gen --cluster-name east \
  | kubectl --context=west apply -f -

(See Step 2: Link the clusters)

  1. Immediately install the per-cluster controller on the receiving cluster (west)
# minimal values for the controller that mirrors 'east'
cat > values-controller-east.yaml <<'EOF'
controllers:
  - link:
      ref:
        name: east
EOF

helm upgrade --install linkerd-multicluster-controller ./charts/linkerd-multicluster-controller \
  -n linkerd-multicluster --create-namespace \
  --kube-context west \
  -f values-controller-east.yaml
  1. Verify
linkerd multicluster check

Operational checks:

  • Templates render identically to the originals (no functional diffs)
  • Argo CD shows clean, separated diffs between common and controller releases

Fixes
Fixes #14385

DCO Sign off
Signed-off-by: kahirokunn [email protected]

Split controller templates from linkerd-multicluster to allow per-cluster controller values.
Copied templates/controller (intentional duplication; no functional changes).

Signed-off-by: kahirokunn <[email protected]>
@kahirokunn kahirokunn requested a review from a team as a code owner August 18, 2025 00:57
@olix0r
Copy link
Member

olix0r commented Aug 18, 2025

Hi @kahirokunn, thanks for submitting this!

Unfortunately, I think we are unlikely to merge this. Our plans are to merge the multicluster controller into the core control plane chart.

@kahirokunn kahirokunn marked this pull request as draft August 19, 2025 00:17
@kahirokunn kahirokunn force-pushed the feat/helm/linkerd-multicluster-controller branch from 985e5e3 to 7561569 Compare August 19, 2025 00:22
@kahirokunn
Copy link
Author

kahirokunn commented Aug 19, 2025

Hi @olix0r — thanks for your time! 😊 If you're open to it, may I ask a couple of questions to better understand the intended lifecycle for the multicluster service-mirror controller? 🤔 I may be misunderstanding some fundamentals, so any pointers would be appreciated. 🙏

My current intuition is that the controller behaves like a “link-scoped worker”: useful when a Link exists and unnecessary when it doesn’t. As a learning exercise (not a prescription), I tried publishing a standalone linkerd-multicluster-controller chart and using Projectsveltos to install/uninstall it dynamically based on Link objects:

---
apiVersion: lib.projectsveltos.io/v1beta1
kind: EventSource
metadata:
  name: install-linkerd-controller-by-link
spec:
  collectResources: true
  resourceSelectors:
  - group: multicluster.linkerd.io
    version: v1alpha3
    kind: Link
---
apiVersion: lib.projectsveltos.io/v1beta1
kind: EventTrigger
metadata:
  name: install-linkerd-controller-by-link
spec:
  sourceClusterSelector:
    matchLabels:
      installation.appthrust.com/linkerd: enabled
  eventSourceName: install-linkerd-controller-by-link
  oneForEvent: true
  helmCharts:
  - repositoryURL: oci://quay.io/appthrust/linkerd
    repositoryName: linkerd-multicluster-controller
    chartName: linkerd-multicluster-controller
    chartVersion: "0.1.0"
    releaseName: "linkerd-mc-{{ .Resource.metadata.name }}"
    releaseNamespace: "{{ .Resource.metadata.namespace }}"
    helmChartAction: Install
    values: |
      controllers:
        - link:
            ref:
              name: "{{ .Resource.metadata.name }}"
sequenceDiagram
autonumber
participant U as User/Automation
participant K as Kubernetes API
participant S as Sveltos (EventSource/Trigger)
participant H as Helm

U->>K: Create Link (multicluster.linkerd.io/v1alpha3)
K-->>S: Event: Link created
S->>H: Trigger Helm install (values: link.ref.name)
H->>K: helm install linkerd-mc-<linkname> -n <namespace>
Loading

With this, the controller is installed when a Link appears and removed when it’s deleted. From that perspective, I had a few questions:

  1. Auto-installation on Link presence — Is avoiding this primarily an engineering-bandwidth tradeoff, or is there an architectural reason (security posture, predictability, upgrade/rollback semantics, supportability) to keep the controller lifecycle decoupled from Link resources?

  2. Packaging shape — For components with different lifecycle/ownership boundaries, I had assumed they might be offered both (a) bundled for convenience and (b) as a separate chart for teams that manage them independently. Is there a design preference to ship the controller only within a single chart (now the control-plane), and if so, could you share the rationale?

  3. Standalone chart — If publishing a separate controller chart is not aligned with the project, is there a downside I should be aware of (user confusion, version skew, support expectations)? If it’s simply out of scope for upstream, that makes sense—just hoping to understand the reasoning.

  4. Longer-term operator approach — Would an operator-style pattern for link-scoped behavior ever be in scope, or is that class of automation something Linkerd prefers to avoid?

If there are docs, design notes, or prior discussions I should read, I’d be grateful for pointers. Thank you again for the guidance and for maintaining Linkerd.

Best regards
kahirokunn

@alpeb
Copy link
Member

alpeb commented Sep 5, 2025

Hi @kahirokunn ,

To expand on the previous reply, Linkerd multicluster so far has been designed as an extension. So only if you'd be interested in that, you'd install the controller that would then handle any Links you'd like to manage. This follows the typical controller/operator pattern. However we're planning on stepping back from this extension model and include it into core linkerd, mainly because the pervasiveness of multicluster setups and the simplicity this would offer. This would keep things in line with the operator model, but the packaging will change: there would no longer be need to install an additional helm chart to gain multicluster capabilities and the only config that users would need to provide would be the Link manifests.

@kahirokunn
Copy link
Author

kahirokunn commented Sep 6, 2025

Hi @alpeb! Thanks for the clear explanation!

Just to confirm my understanding: without installing the controller that manages Link resources, the Linkerd core will handle Link objects directly—so rather than integrating the controller’s Helm chart into the core chart, the core itself will process Link resources, and there will be no need to install that controller in the first place. Is that correct? 👀

Thanks again to you and the team for the continued focus on simplicity and UX!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Split multicluster Helm charts: separate common install and link controller into linkerd-multicluster-controller
3 participants