Deploy with ACM and GitOps
This guide explains how Red Hat ACM primitives cooperate with OpenShift GitOps (Argo CD) to drive hub-spoke deployment from Git.
ManagedClusterSet
A ManagedClusterSet groups clusters for RBAC and placement. Typical patterns:
- One set for all fleet clusters.
- Separate sets for production vs non-production.
Cluster membership in a set is what downstream objects reference—not individual cluster names embedded in static YAML.
Placement
Placement selects clusters from a ManagedClusterSet using label selectors or predicates. ACM computes intent continuously as clusters join, leave, or change labels.
Example concerns:
- Select
region=eastfor east-only workloads. - Require feature labels such as
environment=prod.
PlacementDecision
ACM publishes PlacementDecision objects listing concrete cluster names that satisfied a Placement at a given time. GitOps integrations watch these decisions to know where to apply manifests without hardcoding kube-apiserver URLs in Git.
GitOpsCluster
A GitOpsCluster resource associates Argo CD (spec.argocd) with clusters chosen by placement. It bridges ACM’s fleet selection with Argo CD’s cluster secrets and Application destinations.
Together, Placement → PlacementDecision → GitOpsCluster avoids brittle per-cluster Application YAML checked into Git.
ApplicationSet with clusterDecisionResource
The ApplicationSet uses a clusterDecisionResource generator that reads ACM PlacementDecision objects. For each cluster selected by the Placement, the ApplicationSet creates an Application that deploys the cluster’s dedicated Helm chart folder to the remote spoke.
The ApplicationSet template uses two dynamic variables from the PlacementDecision:
- `` — cluster name (e.g.
east,west), used as both the repositorypathand thedestination.name - `` — cluster API server URL (available but not used directly;
destination.nameresolves via cluster secrets)
This means adding a new spoke with correct labels and a matching folder in the repository automatically generates a new Application.
Remote deployment model
Each cluster has its own Argo CD instance. The hub’s ApplicationSet pushes the per-cluster chart to each spoke’s openshift-gitops namespace. The spoke’s Argo CD then manages the child Applications locally.
Hub ArgoCD → ApplicationSet
→ east-spoke-components (source: east/, destination: east cluster)
→ east/templates/ generates child Application CRs
→ East ArgoCD syncs child apps locally
→ west-spoke-components (source: west/, destination: west cluster)
→ west/templates/ generates child Application CRs
→ West ArgoCD syncs child apps locally
Industrial Edge components exist ONLY in spoke charts. The hub chart never includes them.
Troubleshooting: fleet-spoke-push shows no Applications
The OpenShift / ACM UI may report no Argo applications when any link in this chain is missing:
- Managed clusters are Imported / Available (
oc get managedcluster). - Each spoke must be named
eastandwest(matching the folder names in the repository), and registered as Argo CD cluster secrets. ManagedClusterSetBindingglobalexists inopenshift-gitopsand clusters carrycluster.open-cluster-management.io/clusterset: global(see chart templates).-
Placementhub-spoke-placementselects your spokes (regionineastwestby default). -
PlacementDecisionobjects exist inopenshift-gitopswith decisions listing those cluster names:oc get placementdecisions.cluster.open-cluster-management.io -n openshift-gitops \ -l cluster.open-cluster-management.io/placement=hub-spoke-placement -o yaml GitOpsClusterhub-spoke-gitopsis reconciled so Argo registers the same clusters (Settings → Clusters in Argo CD).- RBAC: Role
applicationset-placementdecisionsbindsopenshift-gitops-applicationset-controllerso the clusterDecisionResource generator can listplacementdecisions. - Region paths exist:
charts/region/east/andcharts/region/west/must contain bootstrapChart.yaml,values.yaml, andtemplates/(same layout as hub).
Step-by-step deployment
- Install OpenShift GitOps on the hub (subscription stable channel) if not already present.
- Install ACM hub components and verify
MultiClusterHubis healthy. - Create ManagedClusterSet and bind hub + spokes.
- Label spokes for placement (
region,environment, etc.). - Define Placement and verify generated PlacementDecision objects show expected clusters.
- Create GitOpsCluster referencing your Argo CD namespace (
openshift-gitopsby convention). - Apply ApplicationSet manifests (often shipped via this repo’s
acm-hub-spokechart path) so Applications appear under the Argo CD project. - ACM console labels: the ApplicationSet metadata must include
cluster.open-cluster-management.io/placement: hub-spoke-placement(same value as the Placement label). Without it, ACM Search → ApplicationSet → Details may show no Argo applications even wheneast-spoke-components/west-spoke-componentsexist inopenshift-gitops. - Observe sync waves — lower waves (namespaces, operators) complete before application workloads.
- Camel Dashboard (spokes): after wave 3, verify
camel-dashboard-openshift-all-{east,west}and enable the console plugin — see Getting Started — Camel Dashboard and Troubleshooting.
If east-spoke-components or west-spoke-components is missing on the hub, re-sync acm-hub-spoke. The ApplicationSet fleet-spoke-push is a persistent resource in charts/all/acm-hub-spoke/templates/applicationset.yaml (sync-wave 4). Do not delete parent apps with prune: true unless you intend to recreate them.
For a full YAML walkthrough of each layer, see GitOps deployment chain.
Verify from CLI (source of truth):
oc get applicationset fleet-spoke-push -n openshift-gitops -o jsonpath='{.status.resourcesCount}{"\n"}'
oc get applications -n openshift-gitops | grep spoke
References
Next → Scaffolding to deploy Industrial Edge instances from Developer Hub, or Getting Started for the full bootstrap walk-through.