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

25 KiB

title weight tocHidden
Azure Quickstart Part 3 120 true

{{< hint "important" >}} This guide is part 3 of a series.

Follow [part 1]({{<ref "provider-azure" >}}) to install Crossplane and connect your Kubernetes cluster to Azure.

Follow [part 2]({{<ref "provider-azure-part-2" >}}) to create a composition, custom resource definition and a claim. {{< /hint >}}

[Part 2]({{<ref "provider-azure-part-2" >}}) created a CompositeResourceDefinition to define the schema of the custom API. Users create a Claim to use the custom API and apply their options. Part 2 didn't show how the options set in a Claim change or get applied to the associated composite resources.

Prerequisites

  • Complete quickstart [part 1]({{<ref "provider-azure" >}}) and [part 2]({{<ref "provider-azure-part-2" >}}) to install Crossplane and the quickstart configurations.

{{<expand "Skip parts 1 and 2 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
  1. Create a composition {{< hint "tip" >}} Apply 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 >}}

  1. Create a CompositeResourceDefinition
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
  1. Create a new namespace
kubectl create namespace test

{{}}

Enable composition patches

In a Composition patches map fields in the custom API to fields inside the managed resources.

The example Composition has four managed resources. A {{}}LinuxVirtualMachine{{}}, {{}}NetworkInterface{{}}, {{}}Subnet{{}} and a {{}}VirtualNetwork{{}}.

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
resources:
    - name: quickstart-vm
      base:
        apiVersion: compute.azure.upbound.io/v1beta1
        kind: LinuxVirtualMachine
    - name: quickstart-nic
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: NetworkInterface
    - name: quickstart-subnet
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: Subnet
    - name: quickstart-network
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: VirtualNetwork    

The custom API defined a single option, {{}}region{{}}. A {{}}region{{}} can be either {{}}EU{{}} or {{}}US{{}}.

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$'

Creating a composition patch allows Crossplane to update the settings of the composite resource. Patches apply to the individual managed resources inside the Composition.

A {{}}patch{{}} has a {{}}fromField{{}} and a {{}}toField{{}} specifying which value from the custom API should apply to a field in the managed resource.
Patches can create a {{}}transform{{}} to change the from field before it's applied.

The transform {{}}type{{}} is what kind of change to make on the from field. Types of changes could include appending a string, preforming a math operation or mapping one value to another.

Applying a {{}}patch{{}} to the {{}}LinuxVirtualMachine{{}} uses the custom API {{}}region{{}} to use as the managed resource {{}}location{{}}.

The custom API value "EU" is {{}}mapped{{}} to the value "Sweden Central" and "US" is {{}}mapped{{}} to the value "Central US."

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
  resources:
    - name: quickstart-vm
      base:
        apiVersion: compute.azure.upbound.io/v1beta1
        kind: LinuxVirtualMachine
        spec:
          forProvider:
            location: "Central US"
            # Removed for Brevity
      patches:
        - fromFieldPath: "spec.region"
          toFieldPath: "spec.forProvider.location"
          transforms:
            - type: map
              map: 
                EU: "Sweden Central"
                US: "Central US"

Patching is a powerful tool enabling simpler or abstracted APIs. A developer isn't required to know the specific Azure location names, only the abstracted option of "EU" or "US."

Apply the updated composition

Apply the same patch to all other managed resource and apply the updated Composition.

{{< hint "tip" >}} Update each resourceGroupName with your Azure Resource Group. {{< /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
      patches:
        - fromFieldPath: "spec.region"
          toFieldPath: "spec.forProvider.location"
          transforms:
            - type: map
              map: 
                EU: "Sweden Central"
                US: "Central US"
    - 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>$$
      patches:
        - fromFieldPath: "spec.region"
          toFieldPath: "spec.forProvider.location"
          transforms:
            - type: map
              map: 
                EU: "Sweden Central"
                US: "Central US"
    - 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>$$
      patches:
        - fromFieldPath: "spec.region"
          toFieldPath: "spec.forProvider.location"
          transforms:
            - type: map
              map: 
                EU: "Sweden Central"
                US: "Central US"
    - name: quickstart-network
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: VirtualNetwork
        spec:
          forProvider:
            addressSpace:
              - 10.0.0.0/16
            location: "Sweden Central"
            resourceGroupName: $$<resource_group_name>$$
      patches:
        - fromFieldPath: "spec.region"
          toFieldPath: "spec.forProvider.location"
          transforms:
            - type: map
              map: 
                EU: "Sweden Central"
                US: "Central US"
EOF

{{< /editCode >}}

Create a claim

Create a new claim and set the {{}}region{{}} to "EU."

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

View the Claim with kubectl get claim

{{< hint "note" >}} It may take up to 10 minutes for the Claim to be READY. {{< /hint >}}

kubectl get claim -n test
NAME                        SYNCED   READY   CONNECTION-SECRET   AGE
claimed-eu-virtualmachine   True     True                        6m2s

The claim reports SYNCED and READY as True after Crossplane creates all the managed resources.

Describe the LinuxVirtualMachine resource to see the Azure location is Sweden Central.

kubectl describe linuxvirtualmachine | grep "At Provider\|Location"
    Location:                         Sweden Central
  At Provider:
    Location:                         swedencentral

Using {{}}region: "EU"{{}} patches the composite resource, updating the Azure location from Central US to Sweden Central. The developer creating the claim isn't required to know which specific Azure location or the location naming conventions. Using the abstract API options of "EU" or "US" the developer places their resources in the desired location.

Deleting the claim removes the managed resources.

{{<hint "note" >}} The managed resources take up to 5 minutes to delete. {{< /hint >}}

kubectl delete virtualmachine claimed-eu-virtualmachine -n test

Create a Crossplane configuration package

Crossplane configuration packages allow users to combine their CustomResourceDefinition and Composition files into a single OCI image.

{{< hint "note" >}} The Open Container Initiative defines the OCI image standard.
An OCI images is a standard way to package data. {{< /hint >}}

You can host configuration packages in image registries like Docker Hub or the Upbound Marketplace.

Crossplane can download and install configuration packages into a Kubernetes cluster.

Creating a configuration package makes your Crossplane custom APIs portable and versioned.

Building and installing configuration packages requires an OCI image compatible tool.

{{< hint "note" >}} You can use any software that builds OCI images. This includes Docker or Upbound's Up CLI. {{< /hint >}}

A configuration package includes at least three files:

  • crossplane.yaml defines the metadata of the package.
  • definition.yaml is the CompositeResourceDefinition for the package.
  • composition.yaml is the Composition template for the package.

Create a crossplane.yaml file

Configuration packages describe their contents and requirements with a crossplane.yaml file.

The crossplane.yaml file lists the required Crossplane Providers and their compatible versions as well as the required Crossplane version.

The Crossplane {{}}meta.pkg{{}} API defines the schema for a {{}}Configuration{{}}.

Inside the {{}}spec{{}} define the required Crossplane {{}}version{{}}.

The {{}}dependsOn{{}} section lists the dependencies for a package.

This package lists the Upbound {{}}provider-azure{{}} version {{}}0.32.0{{}} or later as a dependency.

{{<hint "tip" >}} Crossplane automatically installs dependencies. Dependencies can include other configuration packages. {{< /hint >}}

Create a new directory and save the crossplane.yaml file.

mkdir crossplane-azure-quickstart
cat <<EOF > crossplane-azure-quickstart/crossplane.yaml
apiVersion: meta.pkg.crossplane.io/v1
kind: Configuration
metadata:
  name: crossplane-azure-quickstart
spec:
  crossplane:
    version: ">=v1.11.0"
  dependsOn:
    - provider: xpkg.upbound.io/upbound/provider-azure
      version: ">=v0.32.0"
EOF

Create a definition.yaml file

A configuration package requires a CompositeResourceDefinition (XRD) to define the custom API.

Save the XRD as definition.yaml in the same directory as the crossplane.yaml file.

cat <<EOF > crossplane-azure-quickstart/definition.yaml
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

Create a composition.yaml file

The Composition template creates the managed resources and allows patches to customize the managed resources.

Copy the Composition into the composition.yaml file in the same directory as crossplane.yaml.

{{< hint "tip" >}} Update each resourceGroupName with your Azure Resource Group. {{< /hint >}}

{{< editCode >}}

cat <<EOF > crossplane-azure-quickstart/composition.yaml
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
      patches:
        - fromFieldPath: "spec.region"
          toFieldPath: "spec.forProvider.location"
          transforms:
            - type: map
              map: 
                EU: "Sweden Central"
                US: "Central US"
    - 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>$$
      patches:
        - fromFieldPath: "spec.region"
          toFieldPath: "spec.forProvider.location"
          transforms:
            - type: map
              map: 
                EU: "Sweden Central"
                US: "Central US"
    - 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>$$
      patches:
        - fromFieldPath: "spec.region"
          toFieldPath: "spec.forProvider.location"
          transforms:
            - type: map
              map: 
                EU: "Sweden Central"
                US: "Central US"
    - name: quickstart-network
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: VirtualNetwork
        spec:
          forProvider:
            addressSpace:
              - 10.0.0.0/16
            location: "Sweden Central"
            resourceGroupName: $$<resource_group_name>$$
      patches:
        - fromFieldPath: "spec.region"
          toFieldPath: "spec.forProvider.location"
          transforms:
            - type: map
              map: 
                EU: "Sweden Central"
                US: "Central US"
EOF

{{< /editCode >}}

Install the Crossplane command-line

To build a configuration package install the Crossplane Kubernetes command-line extension.

wget "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh"
chmod +x install.sh
./install.sh

Follow the directions and move the kubectl-crossplane binary to the correct directory.

Verify the Crossplane command-line installed with kubectl crossplane --help

kubectl crossplane --help
Usage: kubectl crossplane <command>

A command line tool for interacting with Crossplane.

Flags:
  -h, --help       Show context-sensitive help.
  -v, --version    Print version and quit.
      --verbose    Print verbose logging statements.
# Ouptut removed for brevity

Build a configuration package

Use the kubectl crossplane command to create an .xpkg file containing the custom APIs and Crossplane configuration.

kubectl crossplane build configuration -f crossplane-azure-quickstart/ --name="crossplane-azure-quickstart"

Now an .xpkg OCI image is inside the crossplane-azure-quickstart directory.

ls crossplane-azure-quickstart/
composition.yaml  crossplane-azure-quickstart.xpkg  crossplane.yaml  definition.yaml

Next steps

  • Explore Azure resources that Crossplane can configure in the Provider CRD reference.
  • Join the Crossplane Slack and connect with Crossplane users and contributors.
  • Read more about [Crossplane concepts]({{<ref "../concepts" >}})