docs snapshot for crossplane version `master`

This commit is contained in:
Crossplane 2020-05-18 02:05:48 +00:00
parent 847b92ff83
commit a28ede29e7
3 changed files with 890 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

890
docs/master/composition.md Normal file
View File

@ -0,0 +1,890 @@
---
title: Publishing Infrastructure
toc: true
weight: 400
indent: true
---
# Publishing Infrastructure
Crossplane allows infrastructure operators to define and compose new kinds of
infrastructure resources then publish them for the application operators they
support to use, all without writing any code.
Infrastructure providers extend Crossplane, enabling it to manage a wide array
of infrastructure resources like Azure SQL servers and AWS ElastiCache clusters.
Infrastructure composition allows infrastructure operators to define, share, and
reuse new kinds of infrastructure resources that are _composed_ of these
infrastructure resources. Infrastructure operators may configure one or more
compositions of any defined resource, and may publish any defined resource to
their application operators, who may then declare that their application
requires that kind of resource.
Composition can be used to build a catalogue of kinds and configuration classes
of infrastructure that fit the needs and opinions of your organisation. As an
infrastructure operator you might define your own `MySQLInstance` resource. This
resource would allow your application operators to configure only the settings
that _your_ organisation needs - perhaps engine version and storage size. All
other settings are deferred to a selectable composition representing a
configuration class like "production" or "staging". Compositions can hide
infrastructure complexity and include policy guardrails so that applications can
easily and safely consume the infrastructure they need, while conforming to your
organisational best-practices.
> Note that composition is an **experimental** feature of Crossplane. Refer to
> [Current Limitations] for information on functionality that is planned but not
> yet implemented.
## Concepts
![Infrastructure Composition Concepts]
A _Composite_ infrastructure resource is composed of other resources. Its
configuration schema is user-defined. The `MySQLInstance` resources in the above
diagram are composite infrastructure resources.
A `Composition` specifies how Crossplane should reconcile a composite
infrastructure resource - i.e. what infrastructure resources it should compose.
For example the Azure `Composition` configures Crossplane to reconcile a
`MySQLInstance` with an Azure `MySQLServer` and a `MySQLServerFirewallRule`.
A _Requirement_ for an infrastructure resource declares that an application
requires a particular kind of composite infrastructure resource, as well as
specifying how to configure that resource. The `MySQLInstanceRequirement`
resources in the above diagram declare that the application pods each require a
`MySQLInstance`.
An `InfrastructureDefinition` defines a new kind of composite infrastructure
resource. The `InfrastructureDefinition` in the above diagram defines the
existence and schema of the `MySQLInstance` composite infrastructure resource.
An `InfrastructurePublication` publishes a defined composite infrastructure
resource, allowing application operators to declare a requirement for it. The
`InfrastructurePublication` in the above diagram allows application operators to
author a `MySQLInstanceRequirement`.
> Note that composite resources and compositions are _cluster scoped_ - they
> exist outside of any Kubernetes namespace. A requirement is a namespaced proxy
> for a composite resource. This enables an RBAC model under which application
> operators may only interact with infrastructure via requirements.
## Defining and Publishing Infrastructure
New kinds of infrastructure resource are typically defined and published by an
infrastructure operator. There are three steps to this process:
1. Define your resource and its schema.
1. Specify one or more possible ways your resource may be composed.
1. Optionally, publish your resource so that applications may require it.
### Define your Infrastructure Resource
Infrastructure resources are defined by an `InfrastructureDefinition`:
```yaml
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: InfrastructureDefinition
metadata:
# InfrastructureDefinitions follow the constraints of CustomResourceDefinition
# names. They must be named <plural>.<group>, per the plural and group names
# configured by the crdSpecTemplate below.
name: mysqlinstances.example.org
spec:
# Composite infrastructure resources may optionally expose a connection secret
# - a Kubernetes Secret containing all of the details a pod might need to
# connect to the infrastructure resource. Resources that wish to expose a
# connection secret must declare what keys they support. These keys form a
# 'contract' - any composition that intends to be compatible with this
# infrastructure resource must compose resources that supply these connection
# secret keys.
connectionSecretKeys:
- username
- password
- hostname
# A template for the spec of a CustomResourceDefinition. Only the group,
# version, names, validation, and additionalPrinterColumns fields of a CRD
# spec are supported.
crdSpecTemplate:
group: example.org
version: v1alpha1
names:
kind: MySQLInstance
listKind: MySQLInstanceList
plural: mysqlinstances
singular: mysqlinstance
validation:
# This schema defines the configuration fields that the composite resource
# supports. It uses the same structural OpenAPI schema as a Kubernetes CRD
# - for example, this resource supports a spec.parameters.version enum.
# The following fields are reserved for Crossplane's use, and will be
# overwritten if included in this validation schema:
#
# - soec.resourceRef
# - spec.resourceRefs
# - spec.requirementRef
# - spec.writeConnectionSecretToRef
# - spec.reclaimPolicy
# - status.conditions
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
version:
description: MySQL engine version
type: string
enum: ["5.6", "5.7"]
storageGB:
type: integer
location:
description: Geographic location of this MySQL server.
type: string
required:
- version
- storageGB
- location
required:
- parameters
```
Refer to the Kubernetes documentation on [structural schemas] for full details
on how to configure the `openAPIV3Schema` for your composite resource.
`kubectl describe` can be used to confirm that a new composite infrastructure
resource was successfully defined. Note the `Established` condition and events,
which indicate the process was successful.
```console
$ kubectl describe infrastructuredefinition mysqlinstances.example.org
Name: mysqlinstances.example.org
Namespace:
Labels: <none>
Annotations: API Version: apiextensions.crossplane.io/v1alpha1
Kind: InfrastructureDefinition
Metadata:
Creation Timestamp: 2020-05-15T05:30:44Z
Finalizers:
finalizer.apiextensions.crossplane.io
published.apiextensions.crossplane.io
Generation: 1
Resource Version: 1418120
Self Link: /apis/apiextensions.crossplane.io/v1alpha1/infrastructuredefinitions/mysqlinstances.example.org
UID: f8fedfaf-4dfd-4b8a-8228-6af0f4abd7a0
Spec:
Connection Secret Keys:
username
password
hostname
Crd Spec Template:
Group: example.org
Names:
Kind: MySQLInstance
List Kind: MySQLInstanceList
Plural: mysqlinstances
Singular: mysqlinstance
Validation:
openAPIV3Schema:
Properties:
Spec:
Parameters:
Properties:
Location:
Description: Geographic location of this MySQL server.
Type: string
Storage GB:
Type: integer
Version:
Description: MySQL engine version
Enum:
5.6
5.7
Type: string
Required:
version
storageGB
location
Type: object
Required:
parameters
Type: object
Type: object
Version: v1alpha1
Status:
Conditions:
Last Transition Time: 2020-05-15T05:30:45Z
Reason: Successfully reconciled resource
Status: True
Type: Synced
Last Transition Time: 2020-05-15T05:30:45Z
Reason: Created CRD and started controller
Status: True
Type: Established
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ApplyInfrastructureDefinition 4m10s apiextensions/infrastructuredefinition.apiextensions.crossplane.io waiting for CustomResourceDefinition to be established
Normal RenderCustomResourceDefinition 55s (x8 over 4m10s) apiextensions/infrastructuredefinition.apiextensions.crossplane.io Rendered CustomResourceDefinition
Normal ApplyInfrastructureDefinition 55s (x7 over 4m9s) apiextensions/infrastructuredefinition.apiextensions.crossplane.io Applied CustomResourceDefinition and (re)started composite controller
```
### Specify How Your Resource May Be Composed
Once a new kind of infrastructure resource is defined Crossplane must be
instructed how to reconcile that kind of infrastructure resource. This is done
by authoring a `Composition`.
A `Composition`:
* Declares one kind of composite infrastructure resource that it satisfies.
* Specifies a "base" configuration for one or more infrastructure resources.
* Specifies "patches" that overlay configuration values from an instance of the
composite infrastructure resource onto each "base".
Multiple compositions may satisfy a particular kind of composite infrastructure
resource, and the author of a composite resource (or resource requirement) may
select which composition will be used. This allows an infrastructure operator to
offer their application operators a choice between multiple opinionated classes
of infrastructure, allowing them to explicitly specify only some configuration.
An infrastructure operator may offer their application operators the choice
between an "Azure" and a "GCP" composition when creating a `MySQLInstance` for
example, Or they may offer a choice between a "production" and a "staging"
`MySQLInstance` composition. In either case the application operator may
configure any value supported by the composite infrastructure resource's schema,
with all other values being deferred to the composition.
> Note that per [Current Limitations] it is not currently possible to specify a
> default or an enforced composition for a particular kind of infrastructure
> resource, but these options will be added in a future release of Crossplane.
> In the meantime composite resource and/or resource requirement authors must
> specify a composition for their resource to use.
The below `Composition` satisfies the `MySQLInstance` defined in the previous
section by composing an Azure SQL server, firewall rule, and resource group:
```yaml
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: Composition
metadata:
name: example-azure
labels:
purpose: example
provider: azure
spec:
# This Composition declares that it satisfies the MySQLInstance composite
# resource defined above - i.e. it patches "from" a MySQLInstance.
from:
apiVersion: example.org/v1alpha1
kind: MySQLInstance
# This Composition reconciles an instance of a MySQLInstance by patching from
# the MySQLInstance "to" new instances of the infrastructure resources below.
# These resources may be the managed resources of an infrastructure provider
# such as provider-azure, or other composite infrastructure resources.
to:
# A MySQLInstance that uses this Composition will be composed of an Azure
# ResourceGroup. The "base" for this ResourceGroup specifies the base
# configuration that may be extended or mutated by the patches below.
- base:
apiVersion: azure.crossplane.io/v1alpha3
kind: ResourceGroup
spec:
reclaimPolicy: Delete
providerRef:
name: example
# Patches copy or "overlay" the value of a field path within the composite
# resource (the MySQLInstance) to a field path within the composed resource
# (the ResourceGroup). In the below example any labels and annotations will
# be propagated from the MySQLInstance to the ResourceGroup, as will the
# location.
patches:
- fromFieldPath: "metadata.labels"
toFieldPath: "metadata.labels"
- fromFieldPath: "metadata.annotations"
toFieldPath: "metadata.annotations"
- fromFieldPath: "spec.parameters.location"
toFieldPath: "spec.location"
# Sometimes it is necessary to "transform" the value from the composite
# resource into a value suitable for the composed resource, for example an
# Azure based composition may represent geographical locations differently
# from a GCP based composition that satisfies the same composite resource.
# This can be done by providing an optional array of transforms, such as
# the below that will transform the MySQLInstance spec.parameters.location
# value "us-west" into the ResourceGroup spec.location value "West US".
transforms:
- type: map
map:
us-west: West US
us-east: East US
au-east: Australia East
# A MySQLInstance that uses this Composition will also be composed of an
# Azure MySQLServer.
- base:
apiVersion: database.azure.crossplane.io/v1beta1
kind: MySQLServer
spec:
forProvider:
# When this MySQLServer is created it must specify a ResourceGroup in
# which it will exist. The below resourceGroupNameSelector corresponds
# to the spec.forProvider.resourceGroupName field of the MySQLServer.
# It selects a ResourceGroup with a matching controller reference.
# Two resources that are part of the same composite resource will have
# matching controller references, so this MySQLServer will always
# select the ResourceGroup above. If this Composition included more
# than one ResourceGroup they could be differentiated by matchLabels.
resourceGroupNameSelector:
matchControllerRef: true
administratorLogin: notadmin
sslEnforcement: Disabled
sku:
tier: GeneralPurpose
capacity: 8
family: Gen5
storageProfile:
backupRetentionDays: 7
geoRedundantBackup: Disabled
providerRef:
name: example
writeConnectionSecretToRef:
namespace: crossplane-system
reclaimPolicy: Delete
patches:
- fromFieldPath: "metadata.labels"
toFieldPath: "metadata.labels"
- fromFieldPath: "metadata.annotations"
toFieldPath: "metadata.annotations"
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
# Transform the value from the MySQLInstance using Go string formatting.
# This can be used to prefix or suffix a string, or to convert a number
# to a string. See https://golang.org/pkg/fmt/ for more detail.
- type: string
string:
fmt: "%s-mysqlserver"
- fromFieldPath: "spec.parameters.version"
toFieldPath: "spec.forProvider.version"
- fromFieldPath: "spec.parameters.location"
toFieldPath: "spec.forProvider.location"
transforms:
- type: map
map:
us-west: West US
us-east: East US
au-east: Australia East
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.storageProfile.storageMB"
# Transform the value from the MySQLInstance by multiplying it by 1024 to
# convert Gigabytes to Megabytes.
transforms:
- type: math
math:
multiply: 1024
# In addition to a base and patches, this composed MySQLServer declares that
# it can fulfil the connectionSecretKeys contract required by the definition
# of the MySQLInstance. This MySQLServer writes a connection secret with a
# username, password, and endpoint that may be used to connect to it. These
# connection details will also be exposed via the composite resource's
# connection secret. Exactly one composed resource must provide each secret
# key, but different composed resources may provide different keys.
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
# The name of the required MySQLInstance connection secret key can be
# supplied if it is different from the connection secret key exposed by
# the MySQLServer.
- name: hostname
fromConnectionSecretKey: endpoint
# A MySQLInstance that uses this Composition will also be composed of an
# Azure MySQLServerFirewallRule.
- base:
apiVersion: database.azure.crossplane.io/v1alpha3
kind: MySQLServerFirewallRule
spec:
forProvider:
resourceGroupNameSelector:
matchControllerRef: true
serverNameSelector:
matchControllerRef: true
properties:
startIpAddress: 10.10.0.0
endIpAddress: 10.10.255.254
virtualNetworkSubnetIdSelector:
name: sample-subnet
providerRef:
name: example
reclaimPolicy: Delete
patches:
- fromFieldPath: "metadata.labels"
toFieldPath: "metadata.labels"
- fromFieldPath: "metadata.annotations"
toFieldPath: "metadata.annotations"
# Some composite resources may be "dynamically provisioned" - i.e. provisioned
# on-demand to satisfy an application's requirement for infrastructure. The
# writeConnectionSecretsToNamespace and reclaimPolicy fields configure default
# values used when dynamically provisioning a composite resource; they are
# explained in more detail below.
writeConnectionSecretsToNamespace: crossplane-system
reclaimPolicy: Delete
```
Field paths reference a field within a Kubernetes object via a simple string.
API conventions describe the syntax as "standard JavaScript syntax for accessing
that field, assuming the JSON object was transformed into a JavaScript object,
without the leading dot, such as metadata.name". Array indices are specified via
square braces while object fields may be specified via a period or via square
braces.Kubernetes field paths do not support advanced features of JSON paths,
such as `@`, `$`, or `*`. For example given the below `Pod`:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: example-pod
annotations:
example.org/a: example-annotation
spec:
containers:
- name: example-container
image: example:latest
command: [example]
args: ["--debug", "--example"]
```
* `metadata.name` would contain "example-pod"
* `metadata.annotations['example.org/a']` would contain "example-annotation"
* `spec.containers[0].name` would contain "example-container"
* `spec.containers[0].args[1]` would contain "--example"
> Note that Compositions provide _intentionally_ limited functionality when
> compared to powerful templating and composition tools like Helm or Kustomize.
> This allows a Composition to be a schemafied Kubernetes-native resource that
> can be stored in and validated by the Kubernetes API server at authoring time
> rather than invocation time.
### Publish Your Infrastructure Resource
An infrastructure operator may choose to publish any defined kind of composite
infrastructure resource to their application operators. Doing so is optional -
a kind of resource that is defined but not published may still be created at the
cluster scope, but application operators may not create a namespaced requirement
for that kind of resource.
Infrastructure is published by an `InfrastructurePublication`:
```yaml
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: InfrastructurePublication
metadata:
# InfrastructurePublications must use the same name as the
# InfrastructureDefinition that defines the resource they publish.
name: mysqlinstances.example.org
spec:
infrastructureDefinitionRef:
name: mysqlinstances.example.org
```
`kubectl describe` can be used to confirm that a composite infrastructure
resource was successfully published. Note the `Established` condition and
events, which indicate the process was successful.
```console
$ kubectl describe infrastructurepublication mysqlinstances.example.org
Name: mysqlinstances.example.org
Namespace:
Labels: <none>
Annotations: API Version: apiextensions.crossplane.io/v1alpha1
Kind: InfrastructurePublication
Metadata:
Creation Timestamp: 2020-05-15T05:30:44Z
Finalizers:
published.apiextensions.crossplane.io
Generation: 1
Resource Version: 1418122
Self Link: /apis/apiextensions.crossplane.io/v1alpha1/infrastructurepublications/mysqlinstances.example.org
UID: 534c5151-2adc-4b4b-9248-fa30740e6b32
Spec:
Infrastructure Definition Ref:
Name: mysqlinstances.example.or
Status:
Conditions:
Last Transition Time: 2020-05-15T05:30:46Z
Reason: Successfully reconciled resource
Status: True
Type: Synced
Last Transition Time: 2020-05-15T05:30:46Z
Reason: Created CRD and started controller
Status: True
Type: Established
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ApplyInfrastructurePublication 7m35s apiextensions/infrastructurepublication.apiextensions.crossplane.io waiting for CustomResourceDefinition to be established
Normal GetInfrastructureDefinition 7m32s (x7 over 7m36s) apiextensions/infrastructurepublication.apiextensions.crossplane.io Got published InfrastructureDefinition
Normal RenderCustomResourceDefinition 7m32s (x7 over 7m36s) apiextensions/infrastructurepublication.apiextensions.crossplane.io Rendered CustomResourceDefinition
Normal ApplyInfrastructurePublication 7m32s (x5 over 7m34s) apiextensions/infrastructurepublication.apiextensions.crossplane.io Applied CustomResourceDefinition and (re)started requirement controller
```
### Permit Crossplane to Reconcile Your Infrastructure Resource
Typically Crossplane runs using a service account that does not have access to
reconcile arbitrary kinds of resource. A `ClusterRole` can grant Crossplane
permission to reconcile your newly defined and published resource:
```yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: mysqlinstances.example.org
labels:
rbac.crossplane.io/aggregate-to-crossplane: "true"
rules:
- apiGroups:
- example.org
resources:
- mysqlinstances
- mysqlinstances/status
- mysqlinstancerequirements
- mysqlinstancerequirements/status
verbs:
- "*"
```
## Using Infrastructure
![Infrastructure Composition Provisioning]
Crossplane offers several ways for both infrastructure operators and application
operators to use the composite infrastructure they've defined and published:
1. Only infrastructure operators can create or manage infrastructure of a kind
that is not published to application operators.
1. Infrastructure operators can create infrastructure of a published kind. This
allows an application operator to create a requirement that specifically
requires the resource the infrastructure operator created.
1. Application operators can create a requirement for infrastructure of a kind
that has been published, and it will be provisioned on-demand.
Options one and two are frequently referred to as "static provisioning", while
option three is known as "dynamic provisioning".
> Note that infrastructure operator focused Crossplane concepts are cluster
> scoped - they exist outside any namespace. Crossplane assumes infrastructure
> operators will have similar RBAC permissions to cluster administrators, and
> will thus be permitted to manage cluster scoped resources. Application
> operator focused Crossplane concepts are namespaced. Crossplane assumes
> application operators will be permitted access to the namespace(s) in which
> their applications run, and not to cluster scoped resources.
### Creating and Managing Composite Infrastructure
An infrastructure operator may wish to author a composite resource of a kind
that is published - i.e. a resource kind that has an `InfrastructurePublication`
as well as an `InfrastructureDefinition` - so that an application operator may
later author a requirement for that exact resource. This pattern is useful for
infrastructure resources that may take several minutes to provision - the
infrastructure operator can keep a pool of resources available in advance in
order to ensure application requirements may be instantly satisfied.
In some cases an infrastructure operator may wish to use Crossplane to model
composite infrastructure that they do not wish to allow application operators to
provision. Consider a `VPCNetwork` composite resource that creates an AWS VPC
network with an internet gateway, route table, and several subnets. Defining
this resource as a composite allows the infrastructure operator to easily reuse
their configuration, but it does not make sense in their organisation to allow
application operators to create "supporting infrastructure" like a VPC network.
In both of the above scenarios the infrastructure operator may statically
provision a composite resource; i.e. author it directly rather than via its
corresponding requirement. The `MySQLInstance` composite infrastructure resource
defined above could be authored as follows:
```yaml
apiVersion: example.org/v1alpha1
kind: MySQLInstance
metadata:
# Composite resources are cluster scoped, so there's no need for a namespace.
name: example
spec:
# The schema of the spec.parameters object is defined by the earlier example
# of an InfrastructureDefinition. The location, storageGB, and version fields
# are patched onto the ResourceGroup, MySQLServer, and MySQLServerFirewallRule
# that this MySQLInstance composes.
parameters:
location: au-east
storageGB: 20
version: "5.7"
# Support for a compositionRef is automatically injected into the schema of
# all defined composite infrastructure resources. This allows the resource
# author to explicitly reference a Composition that this composite resource
# should use - in this case the earlier example-azure Composition. Note that
# it is also possible to select a composition by labels - see the below
# MySQLInstanceRequirement for an example of this approach.
compositionRef:
name: example-azure
# Support for a writeConnectionSecretToRef is automatically injected into the
# schema of all defined composite infrastructure resources. This allows the
# resource to write a connection secret containing any details required to
# connect to it - in this case the hostname, username, and password. Composite
# resource authors may omit this reference if they do not need or wish to
# write these details.
writeConnectionSecretToRef:
namespace: infra-secrets
name: example-mysqlinstance
# Support for a reclaimPolicy is automatically injected into the schema of all
# defined composite infrastructure resources. The reclaim policy applies only
# to published kinds of infrastructure - it controls whether the resource is
# deleted or retained when its corresponding Requirement is deleted. If an
# application authored a MySQLInstanceRequirement for this MySQLInstance then
# later deleted their MySQLInstanceRequirement this MySQLInstance and all of
# the resources it composes would be deleted. If the policy were instead set
# to 'Retain' the MySQLInstance would be retained, for example to allow an
# infrastructure operator to perform manual cleanup.
reclaimPolicy: Delete
```
Any updates to the `MySQLInstance` composite infrastructure resource will be
immediately reconciled with the resources it composes. For example if more
storage were needed an update to the `spec.parameters.storageGB` field would
immediately be propagated to the `spec.forProvider.storageProfile.storageMB`
field of the composed `MySQLServer` due to the relationship established between
these two fields by the patches configured in the `example-azure` `Composition`.
`kubectl describe` may be used to examine a composite infrastructure resource.
Note the `Synced` and `Ready` conditions below. The former indicates that
Crossplane is successfully reconciling the composite resource by updating the
composed resources. The latter indicates that all composed resources are also
indicating that they are in condition `Ready`, and therefore the composite
resource should be online and ready to use. More detail about the health and
configuration of the composite resource can be determined by describing each
composite resource. The kinds and names of each composed resource are exposed as
"Resource Refs" - for example `kubectl describe mysqlserver example-zrpgr` will
describe the detailed state of the composed Azure `MySQLServer`.
```console
$ kubectl describe mysqlinstance.example.org
Name: example
Namespace:
Labels: <none>
Annotations: API Version: example.org/v1alpha1
Kind: MySQLInstance
Metadata:
Creation Timestamp: 2020-05-15T06:53:16Z
Generation: 4
Resource Version: 1425809
Self Link: /apis/example.org/v1alpha1/mysqlinstances/example
UID: f654dd52-fe0e-47c8-aa9b-235c77505674
Spec:
Composition Ref:
Name: example-azure
Parameters:
Location: au-east
Storage GB: 20
Version: 5.7
Reclaim Policy: Delete
Resource Refs:
API Version: azure.crossplane.io/v1alpha3
Kind: ResourceGroup
Name: example-wspmk
UID: 4909ab46-95ef-4ba7-8f7a-e1d9ee1a6b23
API Version: database.azure.crossplane.io/v1beta1
Kind: MySQLServer
Name: example-zrpgr
UID: 3afb903e-32db-4834-a6e7-31249212dca0
API Version: database.azure.crossplane.io/v1alpha3
Kind: MySQLServerFirewallRule
Name: example-h4zjn
UID: 602c8412-7c33-4338-a3af-78166c17b1a0
Write Connection Secret To Ref:
Name: example-mysqlinstance
Namespace: infra-secrets
Status:
Conditions:
Last Transition Time: 2020-05-15T06:56:46Z
Reason: Resource is available for use
Status: True
Type: Ready
Last Transition Time: 2020-05-15T06:53:16Z
Reason: Successfully reconciled resource
Status: True
Type: Synced
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SelectComposition 10s (x7 over 3m40s) composite/mysqlinstances.example.org Successfully selected composition
Normal PublishConnectionSecret 10s (x7 over 3m40s) composite/mysqlinstances.example.org Successfully published connection details
Normal ComposeResources 10s (x7 over 3m40s) composite/mysqlinstances.example.org Successfully composed resources
```
### Creating an Infrastructure Requirement
Infrastructure requirements represent an application's requirement for a defined
kind of infrastructure, for example the above `MySQLInstance`. Requirements are
a proxy for the kind of resource they require, allowing application operators to
provision and consume infrastructure. An infrastructure requirement may require
pre-existing, statically provisioned infrastructure or it may dynamically
provision infrastructure on-demand. A requirement for a defined kind of
composite infrastructure resource is always suffixed with `Requirement`. A
requirement for a composite infrastructure resource of kind `MySQLInstance` is,
for example, of kind `MySQLInstanceRequirement`.
The below requirement explicitly requires the `MySQLInstance` authored in the
previous example:
```yaml
# The MySQLInstanceRequirement always has the same API group and version as the
# resource it requires. Its kind is always suffixed with Requirement.
apiVersion: example.org/v1alpha1
kind: MySQLInstanceRequirement
metadata:
# Infrastructure requirements are namespaced.
namespace: default
name: example
spec:
# The schema of the spec.parameters object is defined by the earlier example
# of an InfrastructureDefinition. The location, storageGB, and version fields
# are patched onto the ResourceGroup, MySQLServer, and MySQLServerFirewallRule
# composed by the required MySQLInstance.
parameters:
location: au-east
storageGB: 20
version: "5.7"
# Support for a resourceRef is automatically injected into the schema of all
# published infrastructure requirement resources. The resourceRef specifies
# the explicit MySQLInstance that is required.
resourceRef:
name: example
# Support for a writeConnectionSecretToRef is automatically injected into the
# schema of all published infrastructure requirement resources. This allows
# the resource to write a connection secret containing any details required to
# connect to it - in this case the hostname, username, and password.
writeConnectionSecretToRef:
name: example-mysqlinstance
```
A requirement may omit the `resourceRef` and instead include a `compositionRef`
(as in the previous `MySQLInstance` example) or a `compositionSelector` in order
to trigger dynamic provisioning. A requirement that does not include a reference
to an existing composite infrastructure resource will have a suitable composite
resource provisioned on demand:
```yaml
apiVersion: example.org/v1alpha1
kind: MySQLInstanceRequirement
metadata:
namespace: default
name: example
spec:
parameters:
location: au-east
storageGB: 20
version: "5.7"
# Support for a compositionSelector is automatically injected into the schema
# of all published infrastructure requirement resources. This selector selects
# the example-azure composition by its labels.
compositionSelector:
matchLabels:
purpose: example
provider: azure
writeConnectionSecretToRef:
name: example-mysqlinstance
```
> Note that compositionSelector labels can form a shared language between the
> infrastructure operators who define compositions and the application operators
> who require composite resources. Compositions could be labelled by zone, size,
> or purpose in order to allow application operators to request a class of
> composite resource by describing their needs such as "east coast, production".
Like composite resources, requirements can be examined using `kubectl describe`.
The `Synced` and `Ready` conditions have the same meaning as the `MySQLInstance`
above. The "Resource Ref" indicates the name of the composite resource that was
either explicitly required, or in the case of the below requirement dynamically
provisioned.
```console
$ kubectl describe mysqlinstancerequirement.example.org example
Name: example
Namespace: default
Labels: <none>
Annotations: API Version: example.org/v1alpha1
Kind: MySQLInstanceRequirement
Metadata:
Creation Timestamp: 2020-05-15T07:08:11Z
Finalizers:
finalizer.apiextensions.crossplane.io
Generation: 3
Resource Version: 1428420
Self Link: /apis/example.org/v1alpha1/namespaces/default/mysqlinstancerequirements/example
UID: d87e9580-9d2e-41a7-a198-a39851815840
Spec:
Composition Selector:
Match Labels:
Provider: azure
Purpose: example
Parameters:
Location: au-east
Storage GB: 20
Version: 5.7
Resource Ref:
Name: default-example-8t4tb
Write Connection Secret To Ref:
Name: example-mysqlinstance
Status:
Conditions:
Last Transition Time: 2020-05-15T07:26:49Z
Reason: Resource is available for use
Status: True
Type: Ready
Last Transition Time: 2020-05-15T07:08:11Z
Reason: Successfully reconciled resource
Status: True
Type: Synced
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ConfigureCompositeResource 8m23s requirement/mysqlinstances.example.org Successfully configured composite resource
Normal BindCompositeResource 8m23s (x7 over 8m23s) requirement/mysqlinstances.example.org Composite resource is not yet ready
Normal BindCompositeResource 4m53s (x4 over 23m) requirement/mysqlinstances.example.org Successfully bound composite resource
Normal PropagateConnectionSecret 4m53s (x4 over 23m) requirement/mysqlinstances.example.org Successfully propagated connection details from composite resource
```
## Current Limitations
Defining and publishing composite infrastructure resources is an experimental
feature of Crossplane. At present the below functionality is planned but not yet
implemented:
* Updates to a composite infrastructure resource are immediately applied to the
resources it composes, but updates to a requirement are not yet applied to the
composite resource that was allocated to satisfy the requirement. In a future
release of Crossplane updating a requirement will update its allocated
composite infrastructure resource.
* A composite infrastructure resource (or dynamically provisioned requirement)
must specify a composition reference or selector. In a future Crossplane
release it will be possible to configure a default composition for resources
that provide no information about what composition they desire, and to
configure a single composition that will be enforced for all resources.
* Only three transforms are currently supported - string format, multiplication,
and map. Crossplane intends to limit the set of supported transforms, and will
add more as clear use cases appear.
* Compositions are mutable, and updating a composition causes all composite
resources that use that composition to be updated accordingly. A future
release of Crossplane may alter this behaviour.
* Composite resources that are retained when the requirement they were allocated
to is deleted become available for allocation to another requirement. This may
not be the desired behaviour, for example if the application that previously
required the composite infrastructure resource wrote sensitive data to it. A
future release of Crossplane may alter the reclaim policy options.
[Current Limitations]: #current-limitations
[Infrastructure Composition Concepts]: composition-concepts.png
[structural schemas]: https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#specifying-a-structural-schema
[Infrastructure Composition Provisioning]: composition-provisioning.png