Crossplane can provision EKS clusters on demand, but it’s not just about calling an API; it’s about defining the desired end-state of your infrastructure and letting Crossplane reconcile it.

Let’s see it in action. Imagine you want to provision a new EKS cluster. Instead of manually creating IAM roles, VPCs, subnets, security groups, and finally the EKS cluster itself, you define a Cluster resource in Crossplane.

apiVersion: example.com/v1alpha1
kind: Cluster
metadata:
  name: my-new-eks-cluster
spec:
  compositionSelector:
    matchLabels:
      provider: aws
      type: eks
  parameters:
    region: us-east-1
    version: "1.28"
    nodeGroupSize: 3
    instanceType: t3.medium

When Crossplane sees this Cluster resource, it looks for a Composition that matches provider: aws and type: eks. This Composition then tells Crossplane how to build the EKS cluster from a set of underlying infrastructure managed by Crossplane’s providers (like the AWS provider).

The Composition itself is a Kubernetes custom resource that defines a template for provisioning infrastructure. It references Composed resources, which are the actual managed infrastructure objects.

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: eks.aws.example.com
  labels:
    provider: aws
    type: eks
spec:
  writeConnectionSecretToField:
    name: connectionSecretRef
  patchSets:
    - name: default
      patches:
        - fromFieldPath: spec.parameters.region
          toFieldPath: spec.forProvider.region
  resources:
    - name: vpc
      base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: VPC
        spec:
          forProvider:
            region: us-east-1
            cidrBlock: 10.0.0.0/16
      patches:
        - fromFieldPath: spec.parameters.region
          toFieldPath: spec.forProvider.region
    - name: subnet
      base:
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: Subnet
        spec:
          forProvider:
            region: us-east-1
            cidrBlock: 10.0.1.0/24
            availabilityZone: us-east-1a
            vpcIdRef:
              name: vpc
      patches:
        - fromFieldPath: spec.parameters.region
          toFieldPath: spec.forProvider.region
    - name: eks-cluster
      base:
        apiVersion: eks.aws.upbound.io/v1beta1
        kind: Cluster
        spec:
          forProvider:
            region: us-east-1
            version: "1.28"
            resourcesVpcConfig:
              subnetIds:
                - subnet
      patches:
        - fromFieldPath: spec.parameters.region
          toFieldPath: spec.forProvider.region
        - fromFieldPath: spec.parameters.version
          toFieldPath: spec.forProvider.version
        - fromFieldPath: spec.parameters.nodeGroupSize
          toFieldPath: spec.forProvider.nodeGroupConfig.0.scalingConfig.desiredSize
        - fromFieldPath: spec.parameters.instanceType
          toFieldPath: spec.forProvider.nodeGroupConfig.0.instanceTypes.0

The real magic is in the Composition’s resources section. Here, we define the building blocks: a VPC, a Subnet, and the EKS cluster itself. Notice how the subnet resource references vpc using vpcIdRef, and the eks-cluster references the subnet using subnetIds. Crossplane understands these dependencies and ensures resources are created in the correct order. The spec.parameters from your Cluster resource are then "patched" into the spec.forProvider of these underlying managed resources.

This abstraction allows teams to define higher-level constructs like "EKS Cluster" without needing to know the nitty-gritty details of VPC CIDRs, subnet configurations, or IAM policies. They just specify the desired state – region, Kubernetes version, node count, instance type – and Crossplane handles the rest.

The most surprising thing about Crossplane’s composition model is that the Composition and Composed resources are themselves Kubernetes Custom Resources. This means you can manage your infrastructure definitions, including how your abstract resources are composed into concrete cloud resources, using the same GitOps workflows and tools you use for your application code. You can version control your Compositions, review them in pull requests, and deploy them to your Crossplane control plane with kubectl apply.

The writeConnectionSecretToField in the Composition is crucial; once the EKS cluster is provisioned, Crossplane will automatically populate a Kubernetes secret with connection details like the cluster endpoint and certificate authority data, making it easy for your applications to connect.

Once your EKS cluster is up and running, the next logical step is to manage its add-ons or deploy applications onto it, which you can also do using Crossplane’s declarative approach.

Want structured learning?

Take the full Crossplane course →