Skip to main content

Crossplane Ep 2: Providers and Credentials

Rachmat Hidayat
Author
Rachmat Hidayat
Learn & sharing insights on TypeScript, Go, Kubernetes, DevOps, DevSecOps, SRE, Platform Engineering, AI/ML Engineering, and MLOps.
crossplane - This article is part of a series.
Part 2: This Article
If you look at an empty Crossplane installation, it knows nothing about S3 Buckets or VPCs. To teach Kubernetes about cloud resources, we must install a Provider. Providers serve two purposes: they inject Custom Resource Definitions (CRDs) into the cluster, and they contain the Go code necessary to communicate with the cloud vendor’s REST API.

1. Installing the AWS Provider
#

We will be using the official AWS Provider maintained by Upbound (the creators of Crossplane). Because AWS is massive (over 1000 different resources), Upbound split the AWS Provider into smaller “Families” to save memory in your cluster.

For this series, we will install the provider-aws-s3 and provider-aws-ec2 packages.

To install a provider, you write a standard Kubernetes YAML file targeting the Provider CRD (which was installed in Episode 1).

Create a file named provider-aws.yaml:

apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-s3
spec:
  # This points to the official Upbound OCI registry
  package: xpkg.upbound.io/upbound/provider-aws-s3:v1.14.0
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-ec2
spec:
  package: xpkg.upbound.io/upbound/provider-aws-ec2:v1.14.0

Apply this to your cluster:

kubectl apply -f provider-aws.yaml

Verifying the Provider Installation
#

It takes a few minutes for Crossplane to download the package, unpack the binary, and inject the hundreds of CRDs into the cluster.

You can check the status of the providers:

kubectl get providers

Expected Terminal Output:

NAME               INSTALLED   HEALTHY   PACKAGE                                           AGE
provider-aws-ec2   True        True      xpkg.upbound.io/upbound/provider-aws-ec2:v1.14.0  2m
provider-aws-s3    True        True      xpkg.upbound.io/upbound/provider-aws-s3:v1.14.0   2m

Once INSTALLED and HEALTHY are both True, the cluster has learned how to speak AWS! You can verify this by checking if the bucket CRD exists:

kubectl get crds | grep bucket

You should see buckets.s3.aws.upbound.io listed.


2. Managing Credentials
#

The Provider knows how to talk to AWS, but it doesn’t have permission to do so. We must provide it with AWS IAM credentials.

Caution

Never hardcode AWS keys into plain text YAML files. We will use native Kubernetes Secrets to store the credentials securely.

Step 1: Create an aws-credentials.txt file
#

Create a temporary text file on your laptop containing your AWS Access Keys. Format it like a standard ~/.aws/credentials file:

# aws-credentials.txt
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

Step 2: Inject the text file into a Kubernetes Secret
#

Run the following command to create a Kubernetes Secret in the crossplane-system namespace. We are passing the file contents into the credentials key of the Secret.

kubectl create secret generic aws-secret \
  -n crossplane-system \
  --from-file=credentials=./aws-credentials.txt

(You can now delete the aws-credentials.txt file from your laptop).


3. The ProviderConfig
#

Now we have a Provider, and we have a Secret. We must link them together. We do this using a ProviderConfig.

A ProviderConfig acts as the authentication configuration for a specific cloud environment. You can create multiple ProviderConfigs (e.g., default, aws-dev-account, aws-prod-account) to manage multiple AWS accounts from a single Crossplane cluster.

Create a file named provider-config.yaml:

apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
  # We name this 'default'. If we don't explicitly specify a ProviderConfig 
  # on a resource, it will look for this one.
  name: default
spec:
  credentials:
    # Tell Crossplane to look for a Kubernetes Secret
    source: Secret
    secretRef:
      namespace: crossplane-system
      name: aws-secret
      key: credentials

Apply the config:

kubectl apply -f provider-config.yaml

4. Alternatives to Static Credentials (IRSA)
#

In a real production environment (like AWS EKS), managing static Access Keys is a security risk. They don’t expire, and they must be manually rotated.

If you are running Crossplane on AWS EKS, you should use IAM Roles for Service Accounts (IRSA) instead of a Kubernetes Secret.

With IRSA, you attach an AWS IAM Role directly to the Kubernetes ServiceAccount that the Crossplane Provider Pod uses. The Provider Pod will automatically request short-lived temporary tokens from the AWS Metadata service.

To configure a ProviderConfig for IRSA (or EC2 Instance Metadata), you change the source to InjectedIdentity:

# Example IRSA Configuration (Do not apply if using local kind cluster)
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
  name: default
spec:
  credentials:
    source: InjectedIdentity

Troubleshooting & Common Errors
#

  1. Provider HEALTHY is False

    • Root Cause: The provider Pod is crashing. This often happens in local kind clusters if you run out of Docker memory, or if the Kubernetes cluster cannot reach the Upbound registry.
    • Solution: Run kubectl get pods -n crossplane-system and look for pods prefixed with provider-aws-*. Check their logs using kubectl logs <pod-name>.
  2. cannot create resource "providerconfigs"

    • Root Cause: You tried to apply the ProviderConfig YAML before the Provider was fully installed and HEALTHY. The ProviderConfig CRD is injected by the Provider itself!
    • Solution: Wait for kubectl get providers to show True for both columns, then re-apply the ProviderConfig.

Conclusion & Next Steps
#

Your Kubernetes cluster is now fully weaponized. It has the Crossplane engine, the AWS Provider schemas, and the IAM credentials required to modify physical cloud infrastructure.

In Episode 3: Managed Resources (MR), we will write our first infrastructure YAML file, provision a physical AWS S3 bucket directly via kubectl, and witness the true power of the continuous reconciliation loop.

crossplane - This article is part of a series.
Part 2: This Article