What are Crossplane Configuration Packages?
Crossplane Configuration Packages are the high level of infrastructure reusability in the Crossplane ecosystem. Think of Crossplane Configuration Packages like Docker images for infrastructure. The configurations allow generated distributable packages that can be deployed consistently any environments.
So, for create configurations package is necessary create compositions and compositions resource definitions (xrd), if you have any doubts about these concepts, check this blog.

KCL + Crossplane: A Declarative Language for Deploying Complex Infrastructure on AWS with Kubernetes.
Javier Sepúlveda ・ Nov 19 ’24
#aws
#crossplane
#iac
Requirements for local test
- Kubernetes cluster (Minikube)
- Helm version v3.13.1 or later
- Crossplane
- programmatic access AWS
- Crossplane CLI
Link Repositoy

segoja7
/
configuration-crossplane-keycloak
This a repository for crossplane configuration package keycloak in AWS
Key Files
-
resources/compositions/infra/composition.k
: Main KCL composition defining all AWS resources -
resources/compositions/infra/crd.k
: Custom Resource Definition for the infrastructure -
resources/examples/claim.yaml
: Example claim to provision infrastructure -
configuration/crossplane.yaml
: Crossplane configuration metadata -
configuration/apis/infra/composition.yaml
: Render from resources/compositions/infra/composition.k -
configuration/apis/infra/crd.yaml
: Render from resources/compositions/infra/crd.k -
function.yaml
: Crossplane functions (KCL and auto-ready) -
install-configuration.yaml
: Crossplane configuration metadata for install configuration package in the cluster. -
provider.yaml
: AWS, Kubernetes and helm providers -
providerconfig.yaml
: Provider configuration
Architecture.
Step 1.
First, create a profile in minikube
minikube start -p crossplane
With minikube running is moment for install Helm and crossplane, check this link.
with the profile of minikube created and helm and crossplane running it is needed to create a txt file, for this case the document name is profile.txt
[default]
aws_access_key_id = <Your access key id>
aws_secret_access_key = <Your secret access key>
when the txt file is created it is necessary created a generic secret.
kubectl create secret generic aws-secret -n crossplane-system --from-file=creds=./profile.txt
Step 2.
Install functions.
The configuration have dependencies from this functions.
kubectl apply -f function.yaml
Step 3.
Installing a provider, in this case providers for aws, kubernetes and helm from community.
kubectl apply -f providers.yaml
Step 4.
Install providersconfig, it is using the key from secret with the name creds.
kubectl apply -f providerconfig.yaml
Step 5.
login in gihutb ghcr.io for push packages.
echo "<github token>" | docker login ghcr.io -u <user> --password-stdin
Step 6.
Create Gihub Secret in the cluster for pull packages from github and install configuration package.
kubectl create secret docker-registry ghcr-secret
--docker-server=ghcr.io
--docker-username=<username>
--docker-password=<token>
-n crossplane-system
Step 7.
Render compositions and XRD
These files are the result of the composition and crd created using kcl, any changes should be made from the .k files.
kcl run resources/compositions/infra/crd.k > configuration/apis/crd.yaml
kcl run resources/compositions/infra/composition.k > configuration/apis/composition.yaml
Step 8.
Build package configuration.
crossplane xpkg build --package-root=./configuration/ --package-file=segoja7-configuration-keycloack.xpkg
Step 9.
Push package configuration in the github account.
crossplane xpkg push ghcr.io/segoja7/segoja7-configuration-keycloack:v1.0.0 -f segoja7-configuration-keycloack.xpkg
Step 10.
Install-configuration.yaml allow install the configuration package in the cluster using the secret for authenticated and pull the OCI package configuration.
➜ kubectl apply -f install-configuration.yaml
configuration.pkg.crossplane.io/segoja7-configuration-keycloack created
Step 11.
Apply Claim is the end step, basically is create all resources abstracted and wait for her (status = True) for make probes.
➜ kubectl apply -f resources/examples/claim.yaml
multiazinfraclaim.segoja7.example/infra-claim created
Step 12.
Verify all resources created.
➜ kubectl get configuration.pkg
NAME INSTALLED HEALTHY PACKAGE AGE
segoja7-configuration-keycloack True True ghcr.io/segoja7/segoja7-configuration-keycloack:v1.0.0 3h15m
➜ kubectl get compositions
NAME XR-KIND XR-APIVERSION AGE
infra-composition XMultiAzInfra segoja7.example/v1alpha1 3h15m
➜ kubectl get managed
Warning: BucketPolicy has been deprecated. Use spec.forProvider.policy in Bucket instead.
NAME READY SYNCED AGE
dbsubnetgroup.database.aws.crossplane.io/backstage-subnet-group-idp True True 173m
NAME READY SYNCED STATE ENGINE VERSION AGE
rdsinstance.database.aws.crossplane.io/storedata-rds-idp True True available postgres 17.4 173m
NAME READY SYNCED ID IP AGE
address.ec2.aws.crossplane.io/eip-idp True True eipalloc-084d47829c9883e7f 54.146.16.193 173m
NAME READY SYNCED ID VPC AGE
internetgateway.ec2.aws.crossplane.io/igw-idp True True igw-0070a8d25d170cd90 vpc-0194aa72b31ff1d10 173m
NAME READY SYNCED ID VPC SUBNET ALLOCATION ID AGE
natgateway.ec2.aws.crossplane.io/ng-idp True True nat-023fe7472e37f1f37 vpc-0194aa72b31ff1d10 subnet-026e050150dc85f90 eipalloc-084d47829c9883e7f 173m
NAME READY SYNCED ID VPC AGE
routetable.ec2.aws.crossplane.io/rt-private-idp True True rtb-0b62322c0b2315bd6 vpc-0194aa72b31ff1d10 173m
routetable.ec2.aws.crossplane.io/rt-public-idp True True rtb-0aedc83d1aed5cdca vpc-0194aa72b31ff1d10 173m
NAME READY SYNCED ID VPC AGE
securitygroup.ec2.aws.crossplane.io/backstage-rds-sg-idp True True sg-071aed1f2a6d58405 vpc-0194aa72b31ff1d10 173m
NAME READY SYNCED ID VPC CIDR AGE
subnet.ec2.aws.crossplane.io/app-private-subnet-az1-idp True True subnet-0a5e735e87bccc368 vpc-0194aa72b31ff1d10 172.16.3.0/24 173m
subnet.ec2.aws.crossplane.io/app-private-subnet-az2-idp True True subnet-09b23d56234e463fe vpc-0194aa72b31ff1d10 172.16.4.0/24 173m
subnet.ec2.aws.crossplane.io/data-private-subnet-az1-idp True True subnet-07be7b51481002165 vpc-0194aa72b31ff1d10 172.16.1.0/24 173m
subnet.ec2.aws.crossplane.io/data-private-subnet-az2-idp True True subnet-0407ee651c0c58509 vpc-0194aa72b31ff1d10 172.16.2.0/24 173m
subnet.ec2.aws.crossplane.io/public-subnet-az1-idp True True subnet-026e050150dc85f90 vpc-0194aa72b31ff1d10 172.16.5.0/24 173m
subnet.ec2.aws.crossplane.io/public-subnet-az2-idp True True subnet-06404627395c08051 vpc-0194aa72b31ff1d10 172.16.6.0/24 173m
NAME READY SYNCED ID CIDR IPV6CIDR AGE
vpc.ec2.aws.crossplane.io/vpc-idp True True vpc-0194aa72b31ff1d10 172.16.0.0/16 173m
NAME READY SYNCED AGE
cluster.eks.aws.crossplane.io/cluster-idp True True 173m
NAME READY SYNCED EXTERNAL-NAME AGE
addon.eks.aws.crossplane.io/addon-coredns-idp True True arn:aws:eks:us-east-1:476114125818:addon/cluster-idp/coredns/4ccbf7c3-52dd-d8ca-bf02-ccdf71f63fae 173m
addon.eks.aws.crossplane.io/addon-eks-pod-identity-agent-idp True True arn:aws:eks:us-east-1:476114125818:addon/cluster-idp/eks-pod-identity-agent/c6cbf7c3-7123-3fae-d85d-bf0def5f9222 173m
addon.eks.aws.crossplane.io/addon-kube-proxy-idp True True arn:aws:eks:us-east-1:476114125818:addon/cluster-idp/kube-proxy/a8cbf7c3-537e-5279-faba-1c655083254d 173m
addon.eks.aws.crossplane.io/addon-vpc-cni-idp True True arn:aws:eks:us-east-1:476114125818:addon/cluster-idp/vpc-cni/40cbf7c3-7117-f2a4-05db-9fd138a12831 173m
NAME READY SYNCED CLUSTER AGE
nodegroup.eks.aws.crossplane.io/nodegroup-idp True True cluster-idp 173m
NAME CHART VERSION SYNCED READY STATE REVISION DESCRIPTION AGE
release.helm.crossplane.io/aws-load-balancer-controller-idp aws-load-balancer-controller 1.13.3 True True deployed 152 Upgrade complete 173m
release.helm.crossplane.io/cert-manageridp cert-manager v1.18.2 True False 173m
release.helm.crossplane.io/external-dnsidp external-dns 1.17.0 True True deployed 155 Upgrade complete 173m
release.helm.crossplane.io/ingress-nginxidp ingress-nginx 4.12.2 True True deployed 1 Install complete 173m
NAME READY SYNCED URL
openidconnectprovider.iam.aws.crossplane.io/eks-openid-idp True True https://oidc.eks.us-east-1.amazonaws.com/id/C9C33D016B220174E50834BA11189416
NAME ARN READY SYNCED AGE
policy.iam.aws.crossplane.io/awsloadbalancer-controller-idp arn:aws:iam::476114125818:policy/awsloadbalancer-controller-idp True True 173m
policy.iam.aws.crossplane.io/external-dns-idp arn:aws:iam::476114125818:policy/external-dns-idp True True 173m
NAME READY SYNCED ROLENAME POLICYARN AGE
rolepolicyattachment.iam.aws.crossplane.io/clusteradminrolepolicy-idp True True clusteradminrole-idp arn:aws:iam::aws:policy/AdministratorAccess 173m
rolepolicyattachment.iam.aws.crossplane.io/clusternoderolepolicy-idp-1 True True clusternoderole-idp arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy 173m
rolepolicyattachment.iam.aws.crossplane.io/clusternoderolepolicy-idp-2 True True clusternoderole-idp arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy 173m
rolepolicyattachment.iam.aws.crossplane.io/clusternoderolepolicy-idp-3 True True clusternoderole-idp arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly 173m
rolepolicyattachment.iam.aws.crossplane.io/clusternoderolepolicy-idp-4 True True clusternoderole-idp arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore 173m
rolepolicyattachment.iam.aws.crossplane.io/clusternoderolepolicy-idp-5 True True clusternoderole-idp arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly 173m
rolepolicyattachment.iam.aws.crossplane.io/clusterrolepolicy-idp True True clusterrole-idp arn:aws:iam::aws:policy/AmazonEKSClusterPolicy 173m
rolepolicyattachment.iam.aws.crossplane.io/sa-awsloadbalancer-controller-policy-idp True True sa-awsloadbalancer-controller-idp arn:aws:iam::476114125818:policy/awsloadbalancer-controller-idp 173m
rolepolicyattachment.iam.aws.crossplane.io/sa-cert-manager-policy-idp True True sa-cert-manager-idp arn:aws:iam::aws:policy/AmazonRoute53FullAccess 173m
rolepolicyattachment.iam.aws.crossplane.io/sa-external-dns-policy-idp True True sa-external-dns-idp arn:aws:iam::476114125818:policy/external-dns-idp 173m
NAME ARN READY SYNCED AGE
role.iam.aws.crossplane.io/clusteradminrole-idp arn:aws:iam::476114125818:role/clusteradminrole-idp True True 173m
role.iam.aws.crossplane.io/clusternoderole-idp arn:aws:iam::476114125818:role/clusternoderole-idp True True 173m
role.iam.aws.crossplane.io/clusterrole-idp arn:aws:iam::476114125818:role/clusterrole-idp True True 173m
role.iam.aws.crossplane.io/sa-awsloadbalancer-controller-idp arn:aws:iam::476114125818:role/sa-awsloadbalancer-controller-idp True True 173m
role.iam.aws.crossplane.io/sa-cert-manager-idp arn:aws:iam::476114125818:role/sa-cert-manager-idp True True 173m
role.iam.aws.crossplane.io/sa-external-dns-idp arn:aws:iam::476114125818:role/sa-external-dns-idp True True 173m
NAME KIND PROVIDERCONFIG SYNCED READY AGE
object.kubernetes.crossplane.io/cert-manager-certificate-idp Certificate provider-k8s-idp True True 173m
object.kubernetes.crossplane.io/cert-manager-clusterissuer-idp ClusterIssuer provider-k8s-idp True True 173m
object.kubernetes.crossplane.io/k8s-secret-idp Secret provider-k8s-idp True True 173m
object.kubernetes.crossplane.io/keycloak-deployment-idp Deployment provider-k8s-idp True True 173m
object.kubernetes.crossplane.io/keycloak-ingress-idp Ingress provider-k8s-idp True True 173m
object.kubernetes.crossplane.io/keycloak-service-idp Service provider-k8s-idp True True 173m
TESTING URL FOR KEYCLOAK
ROUTE 53 Configuration from external-DNS
CERTIFICATE FROM CERT-MANAGER
Step 13.
key points the claim
The claim receive the following important parameters:
- hostedZoneID: Is a hostzoneID created for route53, is used for cert-manager and external-dns.
- keycloakHostname: „idp.segoja7.com“ You need to change this parameter for a different url.
- domainNames: Is a list for create certificates and use in the keycloack deployment or ingress controller.
> Note: The configuration package create rds secret in the eks cluster, additional the password rds is the same for keycloack admin password.
CONCLUSION:
The configuration packages are:
- Composable: Combine multiple cloud resources into higher-level abstractions
- Reusable: Package once, deploy many times across teams and environments
- Versionable: Semantic versioning for infrastructure components
- Distributable: Share via OCI registries, just like container images.