docs/content/v1.11/getting-started/provider-azure-part-2.md

32 KiB

title weight tocHidden
Azure Quickstart Part 2 120 true

{{< hint "important" >}} This guide is part 2 of a series. Follow [part 1]({{<ref "provider-azure" >}}) to install Crossplane and connect your Kubernetes cluster to Azure.

[Part 3]({{<ref "provider-azure-part-3">}}) covers patching CompositeResources and using Crossplane Packages. {{< /hint >}}

This section creates a Composition, CompositeResourceDefinition and a Claim to create a custom Kubernetes API to create Azure resources. This custom API is a composite resource (XR) API.

Prerequisites

  • Complete [quickstart part 1]({{<ref "provider-azure" >}}) connecting Kubernetes to Azure.
  • an Azure account with permissions to create an Azure Virtual Machine and Virtual Networking

{{<expand "Skip part 1 and just get started" >}}

  1. Add the Crossplane Helm repository and install Crossplane
helm repo add \
crossplane-stable https://charts.crossplane.io/stable
helm repo update
&&
helm install crossplane \
crossplane-stable/crossplane \
--namespace crossplane-system \
--create-namespace
  1. When the Crossplane pods finish installing and are ready, apply the Azure Provider
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: upbound-provider-azure
spec:
  package: xpkg.upbound.io/upbound/provider-azure:v0.32.0
EOF
  1. Use the Azure CLI to create a service principal and save the JSON output as azure-crednetials.json {{< editCode >}}
az ad sp create-for-rbac \
--sdk-auth \
--role Owner \
--scopes /subscriptions/$$<subscription_id>$$

{{</ editCode >}}

  1. Create a Kubernetes secret from the Azure JSON file.
kubectl create secret \
generic azure-secret \
-n crossplane-system \
--from-file=creds=./azure-credentials.json
  1. Create a ProviderConfig
cat <<EOF | kubectl apply -f -
apiVersion: azure.upbound.io/v1beta1
metadata:
  name: default
kind: ProviderConfig
spec:
  credentials:
    source: Secret
    secretRef:
      namespace: crossplane-system
      name: azure-secret
      key: creds
EOF

{{}}

Create a composition

[Part 1]({{<ref "provider-azure" >}}) created a single managed resource. A Composition is a template to create one or more managed resource at the same time.

This sample composition creates an Linux Virtual Machine and the required networking components.

Compositions have multiple components:

  • The individual managed resources.
  • The Composition kind and version.
  • A Composite type reference.

The following steps describe each of these components before applying the final Composition.

Define a virtual network

Define a virtualnetwork resource using the configuration from the previous section:

{{< hint "note" >}} Don't apply this configuration. This YAML is part of a larger definition. {{< /hint >}}

apiVersion: network.azure.upbound.io/v1beta1
kind: VirtualNetwork
metadata:
  name: crossplane-quickstart-network
spec:
  forProvider:
    addressSpace:
      - 10.0.0.0/16
    location: "Central US"
    resourceGroupName: <resource_group_name>

Define a subnet resource

Next, define a Subnet resource.

{{< hint "note" >}} Don't apply this configuration. This YAML is part of a larger definition. {{< /hint >}}

apiVersion: network.azure.upbound.io/v1beta1
kind: Subnet
metadata:
  name: crossplane-quickstart-subnet
spec:
  forProvider:
    addressPrefixes:
      - 10.0.1.0/24
    resourceGroupName: <resource_group_name>

Define a network interface

Define a network interface to attach to the virtual machine.

{{< hint "note" >}} Don't apply this configuration. This YAML is part of a larger definition. {{< /hint >}}

apiVersion: network.azure.upbound.io/v1beta1
kind: NetworkInterface
metadata:
  name: crossplane-quickstart-nic
spec:
  forProvider:
    ipConfiguration:
      - name: crossplane-quickstart-configuration
        privateIpAddressAllocation: Dynamic
    location: "Central US"
    resourceGroupName: <resource_group_name>

Define a virtual machine

Define the LinuxVirtualMachine with its settings.

{{< hint "note" >}} Don't apply this configuration. This YAML is part of a larger definition. {{< /hint >}}

apiVersion: compute.azure.upbound.io/v1beta1
kind: LinuxVirtualMachine
metadata:
  name: crossplane-quickstart-vm
spec:
  forProvider:
    adminUsername: adminuser
    adminSshKey:
      - publicKey: ssh-rsa
          AAAAB3NzaC1yc2EAAAADAQABAAABAQC+wWK73dCr+jgQOAxNsHAnNNNMEMWOHYEccp6wJm2gotpr9katuF/ZAdou5AaW1C61slRkHRkpRRX9FA9CYBiitZgvCCz+3nWNN7l/Up54Zps/pHWGZLHNJZRYyAB6j5yVLMVHIHriY49d/GZTZVNB8GoJv9Gakwc/fuEZYYl4YDFiGMBP///TzlI4jhiJzjKnEvqPFki5p2ZRJqcbCiF4pJrxUQR/RXqVFQdbRLZgYfJ8xGB878RENq3yQ39d8dVOkq4edbkzwcUmwwwkYVPIoDGsYLaRHnG+To7FvMeyO7xDVQkMKzopTQV8AuKpyvpqu0a9pWOMaiCyDytO7GGN
          example@docs.crossplane.io
        username: adminuser
    location: "Central US"
    osDisk:
      - caching: ReadWrite
        storageAccountType: Standard_LRS
    size: Standard_B1ms	
    sourceImageReference:
      - offer: debian-11
        publisher: Debian
        sku: 11-backports-gen2
        version: latest
    resourceGroupName: <resource_group_name>

Create the composition object

The Composition combines all the managed resources into a single object.

A {{}}Composition{{</ hover>}} comes from the {{}}Crossplane{{</ hover>}} API resources.

Create any {{}}name{{</ hover>}} for this Composition.

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: crossplane-quickstart-vm-with-network

Add all the defined resources to the {{}}spec.resources{{</ hover>}} section of the Composition.

Give each resource a {{}}name{{</ hover>}} and put the resource definition under the {{}}base{{</ hover>}} key.

Add your {{}}resourceGroupName{{< /hover >}} for each resource in the Composition.

{{<hint "important" >}} The contents of the {{}}base{{</ hover>}} key doesn't include the metadata field from the managed resources. {{< /hint >}}

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: crossplane-quickstart-vm-with-network
spec:
  resources:
    - name: quickstart-subnet
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: Subnet
        spec:
          forProvider:
            addressPrefixes:
              - 10.0.1.0/24
            virtualNetworkNameSelector:
              matchControllerRef: true
            resourceGroupName: <resource_group_name>
# Removed for brevity

{{<hint "tip" >}} Crossplane provides the {{}}matchControllerRef{{}} value to automatically link resources created by the same Composition. {{}}

Compositions are a template for generating resources. A composite resource actually creates the resources.

A Composition defines what composite resources can use this template.

Compositions do this with the {{}}spec.compositeTypeRef{{</ hover>}} definition.

{{< hint "tip" >}} Crossplane recommends prefacing the kind with an X to show it's a Composition. {{< /hint >}}

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: crossplane-quickstart-vm-with-network
spec:
  compositeTypeRef:
    apiVersion: custom-api.example.org/v1alpha1
    kind: XVirtualMachine
  resources:
    # Removed for Brevity    

A composite resource is actually a custom Kubernetes API type you define. The platform team controls the kind, API endpoint and version.

With this {{}}spec.compositeTypeRef{{</ hover>}} Crossplane only allows composite resources from the API group {{}}custom-api.example.org{{</ hover>}} that are of {{}}kind: XVirtualMachine{{</ hover>}} to use this template to create resources.

Apply the composition

Apply the full Composition to your Kubernetes cluster.

{{<hint "important" >}} Add your {{}}resourceGroupName{{}} to each resource. {{< /hint >}}

{{< editCode >}}

cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: crossplane-quickstart-vm-with-network
spec:
  compositeTypeRef:
    apiVersion: custom-api.example.org/v1alpha1
    kind: XVirtualMachine
  resources:
    - name: quickstart-vm
      base:
        apiVersion: compute.azure.upbound.io/v1beta1
        kind: LinuxVirtualMachine
        spec:
          forProvider:
            adminUsername: adminuser
            adminSshKey:
              - publicKey: ssh-rsa
                  AAAAB3NzaC1yc2EAAAADAQABAAABAQC+wWK73dCr+jgQOAxNsHAnNNNMEMWOHYEccp6wJm2gotpr9katuF/ZAdou5AaW1C61slRkHRkpRRX9FA9CYBiitZgvCCz+3nWNN7l/Up54Zps/pHWGZLHNJZRYyAB6j5yVLMVHIHriY49d/GZTZVNB8GoJv9Gakwc/fuEZYYl4YDFiGMBP///TzlI4jhiJzjKnEvqPFki5p2ZRJqcbCiF4pJrxUQR/RXqVFQdbRLZgYfJ8xGB878RENq3yQ39d8dVOkq4edbkzwcUmwwwkYVPIoDGsYLaRHnG+To7FvMeyO7xDVQkMKzopTQV8AuKpyvpqu0a9pWOMaiCyDytO7GGN
                  example@docs.crossplane.io
                username: adminuser
            location: "Central US"
            osDisk:
              - caching: ReadWrite
                storageAccountType: Standard_LRS
            resourceGroupName: $$<resource_group_name>$$
            size: Standard_B1ms
            sourceImageReference:
              - offer: debian-11
                publisher: Debian
                sku: 11-backports-gen2
                version: latest
            networkInterfaceIdsSelector:
              matchControllerRef: true
    - name: quickstart-nic
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: NetworkInterface
        spec:
          forProvider:
            ipConfiguration:
              - name: crossplane-quickstart-configuration
                privateIpAddressAllocation: Dynamic
                subnetIdSelector:
                  matchControllerRef: true
            location: "Central US"
            resourceGroupName: $$<resource_group_name>$$
    - name: quickstart-subnet
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: Subnet
        spec:
          forProvider:
            addressPrefixes:
              - 10.0.1.0/24
            virtualNetworkNameSelector:
              matchControllerRef: true
            resourceGroupName: $$<resource_group_name>$$
    - name: quickstart-network
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: VirtualNetwork
        spec:
          forProvider:
            addressSpace:
              - 10.0.0.0/16
            location: "Central US"
            resourceGroupName: $$<resource_group_name>$$
EOF

{{< /editCode >}}

Confirm the Composition exists with kubectl get composition

kubectl get composition
NAME                                    XR-KIND           XR-APIVERSION                     AGE
crossplane-quickstart-vm-with-network   XVirtualMachine   custom-api.example.org/v1alpha1   5s

Again, the Composition is only a template. At this point, Crossplane hasn't created any resources inside of Azure.

Define a composite resource

The Composition that was just created limited which composite resources can use that template.

A composite resource is a custom API defined by the platform teams.
A CompositeResourceDefinition defines the schema for a composite resource.

A CompositeResourceDefinition installs the custom API type into Kubernetes and defines what spec keys and values are valid when calling this new custom API.

Before creating a composite resource Crossplane requires a CompositeResourceDefinition.

{{< hint "tip" >}} CompositeResourceDefinitions are also called XRDs for short. {{< /hint >}}

Just like a Composition the {{}}CompositeResourceDefinition{{}} is part of the {{}}Crossplane{{}} API group.

The XRD {{}}name{{}} is the new API endpoint.

{{< hint "tip" >}} Crossplane recommends using a plural name for the XRD {{}}name{{}}. {{< /hint >}}

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xvirtualmachines.custom-api.example.org

The XRD's {{}}spec{{}} defines the new custom API.

Define the API endpoint and kind

First, define the new API {{}}group{{}}.
Next, create the API {{}}kind{{}} and {{}}plural{{}}.

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xvirtualmachines.custom-api.example.org
spec:
  group: custom-api.example.org
  names:
    kind: XVirtualMachine
    plural: xvirtualmachines

{{<hint "note" >}} The XRD {{}}group{{}} matches the composition {{}}apiVersion{{}} and the XRD {{}}kind{{}} matches the composition {{}}compositeTypeRef.kind{{}}.

kind: Composition
# Removed for brevity
spec:
  compositeTypeRef:
    apiVersion: custom-api.example.org/v1alpha1
    kind: XVirtualMachine

{{< /hint >}}

Set the API version

In Kubernetes, all API endpoints have a version to show the stability of the API and track revisions.

Apply a version to the XRD with a {{}}versions.name{{}}. This matches the {{<hover label="noteComp"line="5">}}compositeTypeRef.apiVersion{{}}

XRDs require both {{}}versions.served{{}} and {{}}versions.referenceable{{}}.

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xvirtualmachines.custom-api.example.org
spec:
  group: custom-api.example.org
  names:
    kind: XVirtualMachine
    plural: xvirtualmachines
  versions:
  - name: v1alpha1
    served: true
    referenceable: true

{{<hint "note" >}} For more information on defining versions in Kubernetes read the API versioning section of the Kubernetes documentation. {{< /hint >}}

Create the API schema

With an API endpoint named, now define the API schema, or what's allowed inside the spec of the new Kubernetes object.

{{< hint "note" >}} XRDs follow the Kubernetes CustomResourceDefinition rules for schemas. {{}}

Place the API {{< hover label="xrdSchema" line="8" >}}schema{{}} under the {{< hover label="xrdSchema" line="7" >}}version.name{{}}

The XRD type defines the next lines. They're always the same.

{{< hover label="xrdSchema" line="9" >}}openAPIV3Schema{{}} specifies how the schema gets validated.

Next, the entire API is an {{< hover label="xrdSchema" line="10" >}}object{{}} with a {{< hover label="xrdSchema" line="11" >}}property{{}} of {{< hover label="xrdSchema" line="12" >}}spec{{}}.

The {{< hover label="xrdSchema" line="12" >}}spec{{}} is also an {{< hover label="xrdSchema" line="13" >}}object{{}} with {{< hover label="xrdSchema" line="14" >}}properties{{}}.

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
# Removed for brevity
spec:
  # Removed for brevity
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:

{{< hint "tip" >}} For more information on the values allowed in a CompositeResourceDefinition view its schema with kubectl explain xrd {{< /hint >}}

Now, define the custom API. Your custom API continues under the last {{}}properties{{}} definition in the previous example.

This custom API has only one setting:

  • {{}}region{{}} - where to deploy the resources, a choice of "EU" or "US"

Users can't change any other settings of the VM or its network.

The{{}}region{{}} is a {{}}string{{}} and can match the regular expression that's {{}}oneOf{{}} {{}}EU{{}} or {{}}US{{}}.

This API requires the setting {{}}region{{}}.

# Removed for brevity
# schema.openAPIV3Schema.type.properties.spec
properties:
  region:
    type: string
    oneOf:
      - pattern: '^EU$'
      - pattern: '^US$'
required:
  - region

Enable claims to the API

Tell this XRD to offer a claim by defining the claim API endpoint under the XRD {{}}spec{{< /hover >}}.

{{< hint "tip" >}} Crossplane recommends a Claim {{}}kind{{</ hover>}} match the Composite Resource (XR) {{}}kind{{</ hover>}}, without the preceding X. {{< /hint >}}

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
# Removed for brevity
spec:
# Removed for brevity
  names:
    kind: XVirtualMachine
    plural: xvirtualmachines
  claimNames:
    kind: VirtualMachine
    plural: virtualmachines

{{<hint "note" >}} The Claims section later in this guide discusses claims. {{< /hint >}}

Apply the CompositeResourceDefinition

Apply the complete XRD to your Kubernetes cluster.

cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xvirtualmachines.custom-api.example.org
spec:
  group: custom-api.example.org
  names:
    kind: XVirtualMachine
    plural: xvirtualmachines
  versions:
  - name: v1alpha1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              region:
                type: string
                oneOf:
                  - pattern: '^EU$'
                  - pattern: '^US$'
            required:
              - region
  claimNames:
    kind: VirtualMachine
    plural: virtualmachines
EOF

Verify Kubernetes created the XRD with kubectl get xrd

kubectl get xrd
NAME                                      ESTABLISHED   OFFERED   AGE
xvirtualmachines.custom-api.example.org   True          True      4s

Create a composite resource

Creating an XRD allows the creation composite resources.

A composite resource uses the custom API created in the XRD.

The XRD maps the composite resource values to the Composition template and creates new managed resources.

Looking at part of the XRD:

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
# Removed for brevity
spec:
  group: custom-api.example.org
  names:
    kind: XVirtualMachine
# Removed for brevity
      spec:
        type: object
        properties:
          region:
            type: string
            oneOf:
              - pattern: '^EU$'
              - pattern: '^US$'

The XRD {{}}group{{}} becomes the composite resource {{}}apiVersion{{}}.

The XRD {{}}kind{{}} is the composite resource {{}}kind{{}}

The XRD API {{}}spec{{}} defines the composite resource {{}}spec{{}}.

The XRD {{}}properties{{}} section defines the options for the composite resource {{}}spec{{}}.

The one option is {{}}region{{}} and it can be either {{}}EU{{}} or {{}}US{{}}.

This composite resource uses {{}}region: US{{}}.

Apply the composite resource

Apply the composite resource to the Kubernetes cluster.

cat <<EOF | kubectl apply -f -
apiVersion: custom-api.example.org/v1alpha1
kind: XVirtualMachine
metadata:
  name: my-composite-resource
spec: 
  region: "US"
EOF

Verify the composite resource

Verify Crossplane created the composite resource with kubectl get xvirtualmachine

{{< hint "tip" >}} It may take up to 10 minutes for Azure to create the Virtual Machine resources. {{< /hint >}}

kubectl get xvirtualmachine
NAME                    SYNCED   READY   COMPOSITION                             AGE
my-composite-resource   True     True    crossplane-quickstart-vm-with-network   5m2s

{{<hint "tip" >}} Use kubectl get <kind> to view a specific kind of composite resource.
View all composite resources with kubectl get composite. {{< /hint >}}

Both SYNCED and READY are True when Crossplane created the Azure resources.

Now look at the linuxvirtualmachine and networkinterface managed resources with kubectl get linuxvirtualmachine and kubectl get networkinterface.

kubectl get linuxvirtualmachine
NAME                          READY   SYNCED   EXTERNAL-NAME                 AGE
my-composite-resource-w564c   True    True     my-composite-resource-w564c   8m33s
kubectl get networkinterface
NAME                          READY   SYNCED   EXTERNAL-NAME                 AGE
my-composite-resource-72ft8   True    True     my-composite-resource-72ft8   8m54s

The composite resource automatically generated the managed resources.

Using kubectl describe on a managed resource shows the Owner References is the composite resource.

 kubectl describe linuxvirtualmachine | grep "Owner References" -A5
  Owner References:
    API Version:           custom-api.example.org/v1alpha1
    Block Owner Deletion:  true
    Controller:            true
    Kind:                  XVirtualMachine
    Name:                  my-composite-resource

Each composite resource creates and owns a unique set of managed resources. If you create a second composite resource Crossplane creates a new LinuxVirtualMachine and new networking resources.

cat <<EOF | kubectl apply -f -
apiVersion: custom-api.example.org/v1alpha1
kind: XVirtualMachine
metadata:
  name: my-second-composite-resource
spec: 
  region: "US"
EOF

Again, use kubectl get xvirtualmachine to view both composite resources.

kubectl get xvirtualmachine
NAME                           SYNCED   READY   COMPOSITION                             AGE
my-composite-resource          True     True    crossplane-quickstart-vm-with-network   15m
my-second-composite-resource   True     True    crossplane-quickstart-vm-with-network   4m15s

And see there are two linuxvirtualmachine and two networkinterface managed resources.

kubectl get linuxvirtualmachine
NAME                                 READY   SYNCED   EXTERNAL-NAME                        AGE
my-composite-resource-w564c          True    True     my-composite-resource-w564c          16m
my-second-composite-resource-s92lw   True    True     my-second-composite-resource-s92lw   5m8s
kubectl get networkinterface
NAME                                 READY   SYNCED   EXTERNAL-NAME                        AGE
my-composite-resource-72ft8          True    True     my-composite-resource-72ft8          16m
my-second-composite-resource-wcnnv   True    True     my-second-composite-resource-wcnnv   5m21s

Delete the composite resources

Because the composite resource is the Owner of the managed resources, when Crossplane deletes the composite resource, it also deletes the managed resources automatically.

Delete the new composite resource with kubectl delete xvirtualmachine.

{{<hint "tip" >}} Delete a specific composite resource with kubectl delete <kind> or kubectl delete composite. {{< /hint >}}

Delete the second composition

kubectl delete xvirtualmachine my-second-composite-resource

{{<hint "note">}} It may take up to five minutes before Crossplane finishes deleting resources. {{}}

Now only one virtual machine and network interface exist.

kubectl get linuxvirtualmachines
NAME                          READY   SYNCED   EXTERNAL-NAME                 AGE
my-composite-resource-w564c   True    True     my-composite-resource-w564c   28m
kubectl get networkinterface
NAME                          READY   SYNCED   EXTERNAL-NAME                 AGE
my-composite-resource-72ft8   True    True     my-composite-resource-72ft8   29m

Delete the other composite resource to remove the last linuxvirtualmachines and networkinterface managed resources.

kubectl delete xvirtualmachine my-composite-resource

Composite resources are great for creating one or more related resources against a template, but all composite resources exist at the Kubernetes "cluster level." There's no isolation between composite resources. Crossplane uses Claims to create resources with namespace isolation.

Create a claim

Claims, just like composite resources use the custom API defined in the XRD. Unlike a composite resource, Crossplane can create Claims in a namespace.

Create a new Kubernetes namespace

Create a new namespace with kubectl create namespace.

kubectl create namespace test

Look at the XRD to see the parameters for the Claim. A Claim uses the same {{}}group{{}} a composite resource uses but a different {{}}kind{{}}.

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
# Removed for brevity
spec:
# Removed for brevity
  group: custom-api.example.org
  claimNames:
    kind: VirtualMachine
    plural: virtualmachines

Like the composite resource, create a new object with the {{}}custom-api.example.org{{}} API endpoint.

The XRD {{}}claimNames.kind{{}} defines the {{}}kind{{}}.

The {{}}spec{{}} uses the same API options as the composite resource.

Apply the claim

Apply the claim to your Kubernetes cluster.

cat <<EOF | kubectl apply -f -
apiVersion: custom-api.example.org/v1alpha1
kind: VirtualMachine
metadata:
  name: claimed-virtualmachine
  namespace: test
spec:
  region: "US"
EOF

Verify the claim

Verify Crossplane created the claim with kubectl get virtualmachine in the test namespace.

{{<hint "tip" >}} View claims with kubectl get <kind> or use kubectl get claim to view all Claims. {{}}

kubectl get virtualmachine -n test
NAME                     SYNCED   READY   CONNECTION-SECRET   AGE
claimed-virtualmachine   True     True                        3m40s

When Crossplane creates a Claim, a unique composite resource is also created. View the new composite resource with kubectl get xvirtualmachine.

kubectl get xvirtualmachine
NAME                           SYNCED   READY   COMPOSITION                             AGE
claimed-virtualmachine-cw6cv   True     True    crossplane-quickstart-vm-with-network   3m57s

The composite resource exists at the "cluster scope" while the Claim exists at the "namespace scope."

Create a second namespace and a second claim.

kubectl create namespace test2
cat <<EOF | kubectl apply -f -
apiVersion: custom-api.example.org/v1alpha1
kind: VirtualMachine
metadata:
  name: claimed-virtualmachine
  namespace: test2
spec:
  region: "US"
EOF

View the claims in all namespaces with kubectl get virtualmachine -A

kubectl get virtualmachine -A
NAMESPACE   NAME                     SYNCED   READY   CONNECTION-SECRET   AGE
test        claimed-virtualmachine   True     True                        12m
test2       claimed-virtualmachine   True     True                        7m35s

Now look at the composite resources at the cluster scope.

kubectl get xvirtualmachine
NAME                           SYNCED   READY   COMPOSITION                             AGE
claimed-virtualmachine-7jth5   True     True    crossplane-quickstart-vm-with-network   7m53s
claimed-virtualmachine-cw6cv   True     True    crossplane-quickstart-vm-with-network   12m

Crossplane created a second composite resource for the second Claim.

Looking at the virtual machines and network interfaces shows two of each resource, one for each claim.

kubectl get linuxvirtualmachines
NAME                                 READY   SYNCED   EXTERNAL-NAME                        AGE
claimed-virtualmachine-7jth5-v2gsh   True    True     claimed-virtualmachine-7jth5-v2gsh   8m10s
claimed-virtualmachine-cw6cv-w8v65   True    True     claimed-virtualmachine-cw6cv-w8v65   13m
kubectl get networkinterface
NAME                                 READY   SYNCED   EXTERNAL-NAME                        AGE
claimed-virtualmachine-7jth5-hj657   True    True     claimed-virtualmachine-7jth5-hj657   8m44s
claimed-virtualmachine-cw6cv-f9z4f   True    True     claimed-virtualmachine-cw6cv-f9z4f   13m

Delete the claims

Removing the claims removes the composite resources and the associated managed resources.

kubectl delete virtualmachine claimed-virtualmachine -n test
kubectl delete virtualmachine claimed-virtualmachine -n test2

Verify Crossplane removed all the managed resources.

kubectl get linuxvirtualmachines
No resources found
kubectl get networkinterface
No resources found

Claims are powerful tools to give users resources in their own isolated namespace. But these examples haven't shown how the custom API can change the settings defined in the Composition. This composition patching applies the API settings when creating resources. [Part 3]({{< ref "provider-azure-part-3">}}) of this guide covers composition patches and making all this configuration portable in Crossplane Packages.

Next steps

  • [Continue to part 3]({{< ref "provider-azure-part-3">}}) to learn about patching resources and creating Crossplane Packages.
  • Explore Azure resources that Crossplane can configure in the Provider CRD reference.
  • Join the Crossplane Slack and connect with Crossplane users and contributors.