What Is Crossplane
Crossplane is an open source, CNCF project built on the foundation of Kubernetes to orchestrate anything.
Its basically the kubernetes native approach to solve similar issues and challenges that tools like Terraform, Pulumi and IDEM are trying to solve.
Tanzu Application Platform makes use of Crossplane to power a number of capabilities, such as dynamic provisioning of services instances with Services Toolkit as well as the out of the box Bitnami Services.
What Is Dynamic Service Provisioning
One of the strong capabilities in TAP, is the ability to easily bind a workload to backing services like databases or message brokers.
The issue that has existed till now in TAP, is that the provisioning of these services was a manual process, where there was no self service element in play.
This required the Service Operators such as DBAs or dedicated experts in specific services, to be involved in the process of deploying a service, before the application operator could then claim that service, and then, the developer could utilize that claim in their own workload.
While the APIs have been there for the developer to easily bind to a service, all of the manual steps needed to get to that point, was a major stumbling block for many, causing delays in development, and made it so our developers were not truly self sufficient.
Now it is important to note, this is not a trivial issue to solve, and nearly all platforms on the market have this the of issue, and now as of TAP 1.5, VMware have added in some amazing features, which allow us to easily and securely offer self service capabilities to our end users, to provision and lifecycle manage their applications backing services, without needing all of the manual toil.
The idea with dynamic service provisioning, is that a service operator, can define via a Crossplane XRD and composition (just a bunch of YAML), a service they want to provide. they can define what fields a user can change, and which ones they can’t change. they can set validations on values, and really any constraints that they want, which are defined in a simple OpenAPIv3 Schema within the service definition.
Once the service operator has defined these services they want to offer in the cluster to the end users, a developer can simply claim a new instance of that service, and provide the parameters he wants to set (which the service operator defined for him), and the platform will automatically provision a new instance of that service, and create the needed configurations for the TAP workloads to seamlessly bind to the services, just like they would till TAP 1.5, using the Service Bindings for Kubernetes Spec.
Out of the box, TAP 1.5 comes with a few very common services packaged as Crossplane compositions and XRDs, for Bitnami helm charts.
The included services are:
While this in it of itself is great, VMware have taken it a step further, and via a few values in your TAP values file, you can configure these compositions to instead of deploying the OSS Bitnami helm charts, deploy VMware Application Catalog based helm charts, as long as you have a VAC subscription and that you provide the needed credentials to make it work.
These services, are probably the most common backing services today in the kubernetes ecosystem, and as such it is great to see them being included out of the box in TAP!
Building Your Own Services
Building your own services based on Crossplane can seem quite overwhelming at the beginning, but once you get a hold of it, its truly easy to do.
Similar to all tools in this area, such as Helm, YTT, Terraform etc., the learning curve is indeed a hurdle one must cross, but once you do, the options are endless, and the value is huge!
Another great feature in TAP 1.5 is the GitOps installation flow, and you can see in my Sample GitOps Repo where I defined my entire TAP installation, I have put together a few examples of custom services including:
- RabbitMQ Operator based cluster
- VMware PostgreSQL Operator based clusters
- VMware MySQL Operator based clusters
- MongoDB using the Bitnami OSS Helm chart
- Kafka using the Bitnami OSS Helm chart
- Microsoft SQL Server using raw kubernetes YAML and the official SQL Server image from Microsoft.
What does the new experience look like for a developer
The first step they would do is see what classes of services are available to them:
$ tanzu services classes list
This will return an output similar to:
NAME DESCRIPTION kafka-unmanaged Kafka by Bitnami mongodb-unmanaged MongoDB by Bitnami mysql MySQL mysql-unmanaged MySQL by Bitnami postgresql PostgreSQL postgresql-unmanaged PostgreSQL by Bitnami rabbitmq RabbitMQ rabbitmq-unmanaged RabbitMQ by Bitnami redis-unmanaged Redis by Bitnami sqlserver-unmanaged SQL Server by TeraSky
Then the developer can see what parameters were exposed to him for a specific service for example:
$ tanzu services classes get postgresql-unmanaged
Which will return output like the following:
NAME: postgresql-unmanaged DESCRIPTION: PostgreSQL by Bitnami READY: true PARAMETERS: KEY DESCRIPTION TYPE DEFAULT REQUIRED storageGB The desired storage capacity in GB. integer 1 false
As we can see, one parameter has been exposed to the developer, where they can set the amount of storage they want allocated to the database.
If the developer wants to now deploy a database with 20 GB of storage for example he simply runs a command like the following:
$ tanzu services class-claim create my-db --class postgresql-unmanaged \ --parameter storageGB=20
which will return output similar to the following:
Creating claim 'my-db' in namespace 'test-01'. Please run `tanzu services class-claims get my-db --namespace test-01` to see the progress of create.
And now if the developer runs the command suggested in the output they can see the status of the provisioning, which will look similar to:
Name: my-db Namespace: test-01 Claim Reference: services.apps.tanzu.vmware.com/v1alpha1:ClassClaim:my-db Class Reference: Name: postgresql-unmanaged Status: Ready: True Claimed Resource: Name: 98ec8a57-7c2a-405e-82fc-9102dc6c0717 Namespace: test-01 Group: Version: v1 Kind: Secret
This shows them all the needed info in order to simply now bind this service to there workload either via the CLI using the –service-ref flag or by adding in a serviceClaims section to their workload YAML pointing at the class claim resource that was created. An example of the imperative command mechanism would look like:
$ tanzu apps workload create -f config/workload.yaml --service-ref db=services.apps.tanzu.vmware.com/v1alpha1:ClassClaim:my-db
And the declarative YAML configuration would look like:
spec: serviceClaims: - name: db ref: apiVersion: services.apps.tanzu.vmware.com/v1alpha1 kind: ClassClaim name: my-db
This simple user experience, is extremely powerful, and provides an unprecedented UX for developers, while finding the right balance between developer autonomy and platform and operational needs and concerns.
The new dynamic provisioning functionality is a true game changer in terms of Developer experience, and helps platform teams truly meet their goal of being enablers for the business and not being stumbling blocks in the way to production.
The integration with crossplane is a great choice in my opinion, and I am truly excited to see how this integration deepens and grows over future releases.