Claims (XRC)
Claims are namespace-scoped resources that request infrastructure from a Composition. While composite resources (XRs) are cluster-scoped and typically managed by platform teams, Claims let application teams request infrastructure within their own namespaces using standard Kubernetes RBAC.
# A dev team creates this Claim in their namespace
apiVersion: platform.example.com/v1alpha1
kind: Database
metadata:
name: orders-db
namespace: team-alpha
spec:
parameters:
engine: postgres
size: medium
region: us-east-1
compositionRef:
name: xdatabases.aws.platform.example.com
# Apply the claim in the team's namespace
kubectl apply -f claim-database.yaml -n team-alpha
# Check claim status
kubectl get database orders-db -n team-alpha
# NAME SYNCED READY CONNECTION-SECRET AGE
# orders-db True True orders-db-conn 5m
# The claim creates a cluster-scoped XDatabase composite
kubectl get xdatabase
# NAME SYNCED READY COMPOSITION AGE
# orders-db-xyz True True xdatabases.aws.platform.example.com 5m
# Connection details are stored in a Secret in the claim's namespace
kubectl get secret orders-db-conn -n team-alpha -o yaml
Self-Service Platform Pattern
The self-service pattern separates concerns: platform teams maintain Compositions and XRDs (the "what's possible"), while application teams create Claims (the "what I need"). RBAC controls who can create which Claims.
# RBAC: Allow team-alpha to create Database claims in their namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: database-claim-creator
namespace: team-alpha
subjects:
- kind: Group
name: team-alpha-devs
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: crossplane-database-claim-creator
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: crossplane-database-claim-creator
rules:
- apiGroups: ["platform.example.com"]
resources: ["databases"]
verbs: ["get", "list", "create", "update", "delete"]
GitOps with Flux
Flux treats Crossplane Claims like any other Kubernetes resource — it watches a Git repository and applies changes automatically. Infrastructure-as-code becomes infrastructure-as-Git-commits.
# Flux Kustomization watching the infra/ folder for Crossplane resources
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: crossplane-claims
namespace: flux-system
spec:
interval: 5m
sourceRef:
kind: GitRepository
name: platform-repo
path: ./infrastructure/claims
prune: true
healthChecks:
- apiVersion: platform.example.com/v1alpha1
kind: Database
name: orders-db
namespace: team-alpha
timeout: 10m
# Repository structure for GitOps-managed infrastructure
# platform-repo/
# ├── infrastructure/
# │ ├── definitions/ # XRDs (platform team manages)
# │ │ └── xrd-database.yaml
# │ ├── compositions/ # Compositions (platform team manages)
# │ │ └── composition-database-aws.yaml
# │ └── claims/ # Claims (dev teams add via PRs)
# │ ├── team-alpha/
# │ │ └── orders-db.yaml
# │ └── team-beta/
# │ └── analytics-db.yaml
# Dev team workflow:
# 1. Create a PR adding a claim YAML to infrastructure/claims/team-alpha/
# 2. Platform team reviews and approves
# 3. Flux detects the merge and applies the claim
# 4. Crossplane provisions the cloud resource
GitOps with ArgoCD
ArgoCD manages Crossplane resources through Applications that point to claim directories. Sync waves ensure XRDs and Compositions are applied before Claims:
# ArgoCD Application for Crossplane platform definitions
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: crossplane-platform
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "1"
spec:
project: infrastructure
source:
repoURL: https://github.com/org/platform-repo.git
targetRevision: main
path: infrastructure/definitions
destination:
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: true
selfHeal: true
---
# ArgoCD Application for team claims (depends on platform)
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: crossplane-claims
namespace: argocd
annotations:
argocd.argoproj.io/sync-wave: "2"
spec:
project: infrastructure
source:
repoURL: https://github.com/org/platform-repo.git
targetRevision: main
path: infrastructure/claims
destination:
server: https://kubernetes.default.svc
syncPolicy:
automated:
prune: true
selfHeal: true
Provider Lifecycle & Upgrades
Crossplane Providers are versioned packages. Managing upgrades safely requires understanding revision policies and runtime configurations:
# DeploymentRuntimeConfig for Provider resource limits
apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
metadata:
name: provider-aws-runtime
spec:
deploymentTemplate:
spec:
template:
spec:
containers:
- name: package-runtime
resources:
limits:
memory: 512Mi
cpu: 500m
requests:
memory: 256Mi
cpu: 100m
---
# Provider with pinned version and runtime config
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-s3
spec:
package: xpkg.upbound.io/upbound/provider-aws-s3:v1.7.0
revisionActivationPolicy: Automatic
revisionHistoryLimit: 3
runtimeConfigRef:
name: provider-aws-runtime
# Check Provider revision history
kubectl get providerrevisions.pkg.crossplane.io
# NAME HEALTHY REVISION IMAGE STATE
# provider-aws-s3-abc True 2 xpkg.upbound.io/.../v1.7.0 Active
# provider-aws-s3-xyz True 1 xpkg.upbound.io/.../v1.6.0 Inactive
# Upgrade a Provider (update the package version)
kubectl patch provider provider-aws-s3 \
--type merge \
-p '{"spec":{"package":"xpkg.upbound.io/upbound/provider-aws-s3:v1.8.0"}}'
# Monitor the upgrade
kubectl get providers.pkg.crossplane.io -w
Exercises
Database Claim in a namespace called team-alpha. Verify that it creates a cluster-scoped XDatabase composite, which in turn creates Managed Resources. Check that a connection Secret appears in the team-alpha namespace with endpoint and credentials.
infrastructure/claims/ path. Add a new claim YAML via a Git commit and verify that Flux applies it automatically within the reconciliation interval. Test deletion by removing the file and confirming Flux prunes the claim.
team-alpha can only create Database claims (not XDatabase composites or raw Managed Resources). Test by attempting to create a Managed Resource directly — it should be denied. Then create a Claim in the team namespace — it should succeed.
Key Takeaways
- Claims are namespace-scoped requests for infrastructure — the consumer-facing API
- The self-service pattern separates platform team (Compositions) from dev teams (Claims)
- Flux and ArgoCD treat Claims as standard K8s resources for GitOps reconciliation
- Sync waves in ArgoCD ensure XRDs/Compositions exist before Claims are applied
- Provider upgrades use revision history and activation policies for safe rollouts