Crossplane’s provider packages are the key to unlocking infrastructure from any cloud or API, but installing and upgrading them can feel like a black box.
Let’s peek behind the curtain and see what’s actually happening when you install or upgrade a provider. Imagine you have a Kubernetes cluster running Crossplane. When you install a provider, say for AWS, Crossplane doesn’t just magically know how to talk to AWS. Instead, it orchestrates a complex dance involving several Kubernetes resources.
Here’s a simplified view of that dance:
Providerresource: You create aProvidercustom resource (CR) in Kubernetes. This CR tells Crossplane, "Hey, I want to use the AWS provider." It specifies the package name (e.g.,xpkg.upbound.io/upbound/provider-aws:v0.40.0).ProviderConfigresource: You also create aProviderConfigCR. This is where you put the credentials and region information for your AWS account. This CR is linked to theProviderCR.Providercontroller: Crossplane’s coreProvidercontroller watches forProviderCRs. When it sees one, it checks if the specified package is already installed.- Package installation: If the package isn’t installed, Crossplane pulls the specified package image (e.g.,
us-docker.pkg.dev/upbound/provider-aws/provider-aws:v0.40.0) from a container registry. It then deploys this package as a new, dedicatedDeploymentin your Kubernetes cluster. This deployment is essentially a small, specialized controller that knows how to interact with AWS. ProviderRevisionresource: As part of the installation or upgrade process, aProviderRevisionCR is created. This CR represents a specific version of the provider’s controller binary. It holds information about the package image, its hash, and readiness status.Providercontroller (again): TheProvidercontroller then activates theProviderRevision, making the new provider controller ready to manage AWS resources. It also ensures that theProviderConfigis correctly associated with this active revision.
Let’s see this in action. Suppose you want to install the AWS provider.
First, you’d create a Provider CR:
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws
spec:
package: xpkg.upbound.io/upbound/provider-aws:v0.40.0
packagePullPolicy: IfNotPresent
Then, you’d create a ProviderConfig CR with your AWS credentials (this example uses environment variables for simplicity, but IAM roles are preferred for production):
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Environment
environmentCredentialsSecretRef:
name: aws-creds
namespace: crossplane-system
region: us-east-1
And in a separate Kubernetes Secret named aws-creds in the crossplane-system namespace, you’d have:
apiVersion: v1
kind: Secret
metadata:
name: aws-creds
namespace: crossplane-system
type: Opaque
data:
AWS_ACCESS_KEY_ID: <base64-encoded-access-key-id>
AWS_SECRET_ACCESS_KEY: <base64-encoded-secret-access-key>
After applying these, you can check the status:
kubectl get provider provider-aws -o yaml
You’ll see a Provider resource with a status indicating it’s healthy and a currentRevision pointing to a newly created ProviderRevision (e.g., provider-aws.v0.40.0-abcdef).
The ProviderRevision CR itself will show details about the deployed controller:
kubectl get providerrevision provider-aws.v0.40.0-abcdef -o yaml
Look for the status.controllerStatus.deploymentName field. This tells you the name of the Kubernetes Deployment running the AWS provider controller. You can then inspect that deployment:
kubectl get deployment <deployment-name> -n crossplane-system -o yaml
You’ll see a standard Kubernetes Deployment object, managing a ReplicaSet and Pods running the provider’s container image.
Upgrading is essentially the same process, but you’ll update the spec.package field in your Provider CR to point to a new version (e.g., xpkg.upbound.io/upbound/provider-aws:v0.41.0). Crossplane’s Provider controller will detect the change, pull the new package image, create a new ProviderRevision, and then gracefully terminate the old provider controller pods while starting the new ones. The Provider CR will then be updated to point to the new currentRevision.
Here’s a critical detail many overlook: when you upgrade a provider, Crossplane doesn’t just swap out the controller. It also manages the lifecycle of the ProviderRevision resources. Older, inactive ProviderRevision resources are garbage collected by default after a configurable period (controlled by the --provider-revisions-cleanup-interval flag on the Crossplane control plane, defaulting to 24 hours). This prevents your cluster from accumulating old, unused provider controller deployments and their associated Kubernetes objects.
The next hurdle you’ll likely encounter after successfully installing a provider is understanding how to configure specific cloud resources using the Custom Resource Definitions (CRDs) that the provider installs.