PLEASE NOTE: This document applies to v0.13 version and not to the latest release v1.1
Documentation for other releases can be found by using the version selector in the top right of any doc page.In a previous section we learned that Crossplane can be configured with new composite resources (XRs) that are composed of other resources, allowing you to define and offer resources that group and abstract infrastructure primitives. We use two special Crossplane resources to define and configure new XRs and XRCs:
CompositeResourceDefinition
(XRD) defines a new kind of composite
resource, including its schema. An XRD may optionally offer a claim.Composition
specifies which resources a composite resource will be
composed of, and how they should be configured. You can create multiple
Composition
options for each composite resource.XRDs and Compositions may be packaged as a configuration, that may easily be
installed to Crossplane by creating a declarative Configuration
resource, or
by using kubectl crossplane install configuration
. In the examples below we
will build and push a configuration that defines a new
CompositePostgreSQLInstance
XR that takes a single storageGB
parameter, and
creates a connection Secret
with keys for username
, password
, and
endpoint
.
Our configuration will consist of three files:
crossplane.yaml
- Metadata about the configuration.definition.yaml
- The XRD.composition.yaml
- The Composition.Crossplane can create a configuration from any directory with a valid
crossplane.yaml
metadata file at its root, and one or more XRDs or
Compositions. The directory structure does not matter, as long as the
crossplane.yaml
file is at the root. Note that a configuration need not
contain one XRD and one composition - it could include only an XRD, only a
composition, several compositions, or any combination thereof.
Before we go any further, we must create a directory in which to build our configuration:
mkdir crossplane-config
cd crossplane-config
We’ll create the aforementioned three files in this directory, then build them into a package.
First we’ll create a CompositeResourceDefinition
(XRD) to define the schema of
our CompositePostgreSQLInstance
and its PostgreSQLInstance
resource claim.
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: CompositeResourceDefinition
metadata:
name: compositepostgresqlinstances.database.example.org
spec:
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
connectionSecretKeys:
- username
- password
- endpoint
- port
crdSpecTemplate:
group: database.example.org
version: v1alpha1
names:
kind: CompositePostgreSQLInstance
plural: compositepostgresqlinstances
validation:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
required:
- storageGB
required:
- parameters
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/definition.yaml
You might notice that the XRD we created specifies both “names” and “claim names”. This is because the composite resource it defines offers a composite resource claim (XRC).
Now we’ll specify which managed resources our CompositePostgreSQLInstance
XR
and its claim could be composed of, and how they should be configured. We do
this by defining a Composition
that can satisfy the XR we defined above. In
this case, our Composition
will specify how to provision a public PostgreSQL
instance on the chosen provider.
Note that this Composition will create an RDS instance using your default VPC, which may or may not allow connections from the internet depending on how it is configured. Select the AWS (New VPC) Composition if you wish to create an RDS instance that will allow traffic from the internet.
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: Composition
metadata:
name: compositepostgresqlinstances.aws.database.example.org
labels:
provider: aws
guide: quickstart
vpc: default
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: CompositePostgreSQLInstance
resources:
- base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
spec:
forProvider:
region: us-east-1
dbInstanceClass: db.t2.small
masterUsername: masteruser
engine: postgres
engineVersion: "9.6"
skipFinalSnapshotBeforeDeletion: true
publiclyAccessible: true
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.allocatedStorage"
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- fromConnectionSecretKey: port
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/aws/composition.yaml
Note: this
Composition
for AWS also includes several networking managed resources that are required to provision a publicly available PostgreSQL instance. Composition enables scenarios such as this, as well as far more complex ones. See the composition documentation for more information.
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: Composition
metadata:
name: vpcpostgresqlinstances.aws.database.example.org
labels:
provider: aws
guide: quickstart
vpc: new
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: CompositePostgreSQLInstance
resources:
- base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: VPC
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.0.0/16
enableDnsSupport: true
enableDnsHostNames: true
- base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: Subnet
metadata:
labels:
zone: us-east-1a
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.64.0/18
vpcIdSelector:
matchControllerRef: true
availabilityZone: us-east-1a
- base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: Subnet
metadata:
labels:
zone: us-east-1b
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.128.0/18
vpcIdSelector:
matchControllerRef: true
availabilityZone: us-east-1b
- base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: Subnet
metadata:
labels:
zone: us-east-1c
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.192.0/18
vpcIdSelector:
matchControllerRef: true
availabilityZone: us-east-1c
- base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: DBSubnetGroup
spec:
forProvider:
region: us-east-1
description: An excellent formation of subnetworks.
subnetIdSelector:
matchControllerRef: true
- base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: InternetGateway
spec:
forProvider:
region: us-east-1
vpcIdSelector:
matchControllerRef: true
- base:
apiVersion: ec2.aws.crossplane.io/v1alpha4
kind: RouteTable
spec:
forProvider:
region: us-east-1
vpcIdSelector:
matchControllerRef: true
routes:
- destinationCidrBlock: 0.0.0.0/0
gatewayIdSelector:
matchControllerRef: true
associations:
- subnetIdSelector:
matchLabels:
zone: us-east-1a
- subnetIdSelector:
matchLabels:
zone: us-east-1b
- subnetIdSelector:
matchLabels:
zone: us-east-1c
- base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: SecurityGroup
spec:
forProvider:
region: us-east-1
vpcIdSelector:
matchControllerRef: true
groupName: crossplane-getting-started
description: Allow access to PostgreSQL
ingress:
- fromPort: 5432
toPort: 5432
ipProtocol: tcp
ipRanges:
- cidrIp: 0.0.0.0/0
description: Everywhere
- base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
spec:
forProvider:
region: us-east-1
dbSubnetGroupNameSelector:
matchControllerRef: true
vpcSecurityGroupIDSelector:
matchControllerRef: true
dbInstanceClass: db.t2.small
masterUsername: masteruser
engine: postgres
engineVersion: "9.6"
skipFinalSnapshotBeforeDeletion: true
publiclyAccessible: true
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.allocatedStorage"
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- fromConnectionSecretKey: port
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/aws-with-vpc/composition.yaml
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: Composition
metadata:
name: compositepostgresqlinstances.gcp.database.example.org
labels:
provider: gcp
guide: quickstart
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: CompositePostgreSQLInstance
resources:
- base:
apiVersion: database.gcp.crossplane.io/v1beta1
kind: CloudSQLInstance
spec:
forProvider:
databaseVersion: POSTGRES_9_6
region: us-central1
settings:
tier: db-custom-1-3840
dataDiskType: PD_SSD
ipConfiguration:
ipv4Enabled: true
authorizedNetworks:
- value: "0.0.0.0/0"
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.settings.dataDiskSizeGb"
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- name: port
value: "5432"
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/gcp/composition.yaml
Note: the
Composition
for Azure also includes aResourceGroup
andPostgreSQLServerFirewallRule
that are required to provision a publicly available PostgreSQL instance on Azure. Composition enables scenarios such as this, as well as far more complex ones. See the composition documentation for more information.
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: Composition
metadata:
name: compositepostgresqlinstances.azure.database.example.org
labels:
provider: azure
guide: quickstart
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: CompositePostgreSQLInstance
resources:
- base:
apiVersion: azure.crossplane.io/v1alpha3
kind: ResourceGroup
spec:
location: West US 2
- base:
apiVersion: database.azure.crossplane.io/v1beta1
kind: PostgreSQLServer
spec:
forProvider:
administratorLogin: myadmin
resourceGroupNameSelector:
matchControllerRef: true
location: West US 2
sslEnforcement: Disabled
version: "9.6"
sku:
tier: GeneralPurpose
capacity: 2
family: Gen5
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.storageProfile.storageMB"
transforms:
- type: math
math:
multiply: 1024
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- name: port
value: "5432"
- base:
apiVersion: database.azure.crossplane.io/v1alpha3
kind: PostgreSQLServerFirewallRule
spec:
forProvider:
serverNameSelector:
matchControllerRef: true
resourceGroupNameSelector:
matchControllerRef: true
properties:
startIpAddress: 0.0.0.0
endIpAddress: 255.255.255.254
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/azure/composition.yaml
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: Composition
metadata:
name: compositepostgresqlinstances.alibaba.database.example.org
labels:
provider: alibaba
guide: quickstart
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: CompositePostgreSQLInstance
resources:
- base:
apiVersion: database.alibaba.crossplane.io/v1alpha1
kind: RDSInstance
spec:
forProvider:
engine: PostgreSQL
engineVersion: "9.4"
dbInstanceClass: rds.pg.s1.small
securityIPList: "0.0.0.0/0"
masterUsername: "myuser"
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.dbInstanceStorageInGB"
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- fromConnectionSecretKey: port
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/alibaba/composition.yaml
Finally, we’ll author our metadata file then build and push our configuration so that Crossplane users may install it.
Note that Crossplane pushes packages to an OCI registry - currently Docker Hub by default. You may need to run
docker login
before you are able to push a package.
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: getting-started-with-aws
annotations:
guide: quickstart
provider: aws
vpc: default
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/aws/crossplane.yaml
# Set this to the Docker Hub username or OCI registry you wish to use.
REG=my-package-repo
kubectl crossplane build configuration
kubectl crossplane push configuration ${REG}/getting-started-with-aws:v0.13
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: getting-started-with-aws-with-vpc
annotations:
guide: quickstart
provider: aws
vpc: new
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/aws-with-vpc/crossplane.yaml
# Set this to the Docker Hub username or OCI registry you wish to use.
REG=my-package-repo
kubectl crossplane build configuration
kubectl crossplane push configuration ${REG}/getting-started-with-aws-with-vpc:v0.13
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: getting-started-with-gcp
annotations:
guide: quickstart
provider: gcp
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/gcp/crossplane.yaml
# Set this to the Docker Hub username or OCI registry you wish to use.
REG=my-package-repo
kubectl crossplane build configuration
kubectl crossplane push configuration ${REG}/getting-started-with-gcp:v0.13
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: getting-started-with-azure
annotations:
guide: quickstart
provider: azure
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/azure/crossplane.yaml
# Set this to the Docker Hub username or OCI registry you wish to use.
REG=my-package-repo
kubectl crossplane build configuration
kubectl crossplane push configuration ${REG}/getting-started-with-azure:v0.13
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: getting-started-with-alibaba
annotations:
guide: quickstart
provider: alibaba
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-0.13/docs/snippets/package/alibaba/crossplane.yaml
# Set this to the Docker Hub username or OCI registry you wish to use.
REG=my-package-repo
kubectl crossplane build configuration
kubectl crossplane push configuration ${REG}/getting-started-with-alibaba:v0.13
That’s it! You’ve now built and pushed your package. Take a look at the Crossplane packages documentation for more information about installing and working with packages.
To clean up, you can simply delete your package directory:
cd ..
rm -rf crossplane-config