Alright, let’s talk about the elephant in the room, the one wearing a “Kick Me” sign that says “DEPRECATED” on its back: KubeFed. You’ve heard the term “Kubernetes Federation” and your first Google search probably led you here. Buckle up, because this is a story of good intentions, architectural reality checks, and why the community ultimately decided to take a different path. We’ll cover what it was, why it’s being shelved, and what you should be looking at instead.

The Grand, Flawed Promise of KubeFed

KubeFed’s goal was noble: to present a single, unified API to control resources across multiple clusters. The dream was you’d kubectl apply -f my-app.yaml once, and KubeFed would be the clever middle-manager figuring out how to distribute those resources (Deployments, Services, etc.) to all your registered clusters based on policies you defined.

It did this by installing its own control plane (the KubeFed Controller Manager) in a host cluster. This host cluster didn’t run your workloads; it was just the brains of the operation. You’d then register your other member clusters by providing their kubeconfigs. KubeFed would watch for resources with special annotations and then use the kubeconfigs to create copies of them in the target member clusters.

Here’s a taste of what that configuration looked like. First, you’d define where to deploy something with a FederatedDeploymentPlacement (yes, the names are as verbose as the architecture):

apiVersion: scheduling.kubefed.io/v1alpha1
kind: FederatedDeploymentPlacement
metadata:
  name: my-app-placement
  namespace: my-namespace
spec:
  clusterNames:
    - cluster-us-west1
    - cluster-eu-central1

And then you’d define what to deploy and how it should be overridden per-cluster using a FederatedDeployment:

apiVersion: types.kubefed.io/v1alpha1
kind: FederatedDeployment
metadata:
  name: my-app
  namespace: my-namespace
spec:
  template:
    metadata:
      labels:
        app: my-app
    spec:
      replicas: 3
      containers:
      - name: app
        image: my-registry/my-app:latest
  placement:
    clusterNames:
      - cluster-us-west1
      - cluster-eu-central1
  overrides:
  - clusterName: cluster-us-west1
    clusterOverrides:
      - path: "/spec/replicas"
        value: 5 # Because US West traffic is bigger, obviously.

The idea is compelling on a whiteboard. The reality, as we all discovered, was a messy divorce from standard Kubernetes tooling and philosophy.

Why KubeFed Got Shown the Door

The deprecation announcement wasn’t a surprise to most of us who tried to use it seriously. The problems were fundamental:

  1. It Fought the Kubernetes API, Instead of Embracing It: KubeFed didn’t extend the Kubernetes API; it created a parallel, incompatible universe of Federated* CRDs. Your existing GitOps workflows, Helm charts, and ArgoCD applications knew nothing about FederatedDeployment. You had to rewrite all your manifests for the federation layer, creating a nasty abstraction that leaked like a sieve. It was a classic case of “what if we reinvent the wheel, but make it square?”

  2. The Complexity Bomb: You now had to manage, secure, and give network access to a whole new control plane. The host cluster became a single point of failure and a massive security liability—whoever controlled it had god-like access to every member cluster. Debugging was a nightmare. Was the problem in your app? In your cluster? Or in the KubeFed controller that’s silently failing to propagate a change? Enjoy the three-hour debugging session.

  3. It Solved the Easy Problems: KubeFed was decent at propagating simple resources like Deployments and ConfigMaps. But the moment you stepped into advanced networking (e.g., federating Ingresses across cloud providers) or stateful workloads, it fell apart. These are the hard problems we actually need solved, and KubeFed’s generic propagation model wasn’t the right tool for the job.

The maintainers themselves rightly concluded that a generic, one-size-fits-all federation framework was the wrong approach. The community was already solving specific multi-cluster problems (like networking and discovery) with better, more focused tools.

The Heirs to the (Unfinished) Throne

So if not KubeFed, then what? We’ve moved to a composable world. Instead of a monolithic framework, you pick best-in-class tools for each specific job. KubeFed’s successors aren’t direct replacements; they’re a whole new philosophy.

  1. Cluster API (CAPI): This is the biggest conceptual shift. KubeFed managed workload deployment. CAPI manages the clusters themselves. It’s the infrastructure-as-code paradigm for your Kubernetes clusters. Need a new cluster in AWS and one in Azure as part of your fleet? Define them in a manifest and let CAPI handle the provisioning. It solves the problem of lifecycle management, which is a far more foundational need than mere resource propagation.

  2. Service Mesh and DNS-based Federation: For the “how do I access services across clusters?” problem, service meshes like Linkerd and Istio are the de facto standard. You use them to create a unified network identity, and they handle the secure east-west traffic between clusters. Pair this with a global DNS provider (like external-dns with a cloud DNS service) or a purpose-built tool like Admiralty.io’s Multiclusteringress, and you have a robust, standards-compliant way to do cross-cluster discovery and routing. This approach uses vanilla Kubernetes resources (Services, Ingress) that all your existing tools understand.

  3. GitOps and Propagation: For deploying the workloads themselves, you don’t need a fancy federated API. You need a robust GitOps tool like ArgoCD or Flux. You define your applications in a git repo, and point your ArgoCD instances in each cluster to it. A change to the repo is synced to all clusters. It’s simple, explicit, and leverages the tools you’re already using for single-cluster CD. For advanced placement logic (e.g., “this app only goes to clusters labeled ’edge’”), you’d use ArgoCD’s ApplicationSet generator with cluster filters.

Here’s a more modern, GitOps-centric approach to achieving what the KubeFed example above did, using an ArgoCD ApplicationSet:

# applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: my-app
spec:
  generators:
  - clusters:
      selector:
        matchLabels:
          environment: production # Select clusters based on labels
  template:
    spec:
      project: default
      source:
        repoURL: 'https://git.mycompany.com/apps/my-app.git'
        targetRevision: main
        path: kustomize/overlays/production # Different overlays per cluster? Easy.
      destination:
        server: '{{server}}'
        namespace: my-namespace
      syncPolicy:
        automated: {}

This is clearer, more debuggable, and doesn’t require a dedicated, fragile control plane.

The lesson from the KubeFed experiment is this: embrace the Kubernetes API and ecosystem, don’t abstract it away. Use focused tools for focused jobs. Your multi-cluster architecture will be far more stable, secure, and understandable for it.