docs/docs/master/stacks-guide-azure.md

16 KiB

title toc weight indent
Stacks Guide: Azure Setup true 540 true

Stacks Guide: Azure Setup

Table of Contents

Introduction

In this guide, we will set up an Azure provider in Crossplane so that we can install and use the WordPress sample stack, which depends on MySQL and Kubernetes!

Before we begin, you will need:

  • Everything from the Crossplane Stacks Guide before the cloud provider setup
    • The kubectl (v1.15+) tool installed and pointing to a Crossplane cluster
    • The Crossplane CLI installed
  • An account on Azure
  • The jq tool for interacting with some JSON

At the end, we will have:

  • A Crossplane cluster configured to use Azure
  • A typical Azure network configured to support secure connectivity between resources
  • Support in Crossplane cluster for satisfying MySQL and Kubernetes claims
  • A slightly better understanding of:
    • The way Azure is configured in Crossplane
    • The way dependencies for cloud-portable workloads are configured in Crossplane

We will not be covering the core concepts in this guide, but feel free to check out the Crossplane concepts document for that.

Install the Azure Stack

After Crossplane has been installed, it can be extended with more functionality by installing a Crossplane Stack! Let's install the stack for Microsoft Azure to add support for that cloud provider.

The namespace where we install the stack, is also the one in which the provider secret will reside. The name of this namespace is arbitrary, and we are calling it crossplane-system in this guide. Let's create it:

# namespace for Azure stack and provider secret
kubectl create namespace crossplane-system

Now we install the Azure stack using Crossplane CLI. Since this is an infrastructure stack, we need to specify that it's cluster-scoped by passing the --cluster flag.

kubectl crossplane stack generate-install --cluster 'crossplane/stack-azure:master' stack-azure | kubectl apply --namespace crossplane-system -f -

The rest of this guide assumes that the Azure stack is installed within crossplane-system namespace.

Validate the installation

To check to see whether our stack installed correctly, we can look at the status of our stack:

kubectl -n crossplane-system get stack

It should look something like:

NAME        READY   VERSION   AGE
stack-azure   True    0.0.2     45s

Configure Azure Account

We will make use of the following services on Azure:

  • Resource Group
  • Azure Kubernetes Service
  • Azure Database for MySQL
  • Virtual Network
  • Subnetwork
  • Virtual Network Rule

It is essential to make sure that the Azure user credentials are configured in Crossplane as a provider. Please follow the steps provider guide for more information.

Set Up Network Configuration

In this section we build a simple Azure virtual network configuration, by creating corresponding Crossplane managed resources. These resources are cluster scoped, so don't belong to a specific namespace. This network configuration enables resources in the WordPress stack to communicate securely. In this guide, we will use the sample Azure network configuration in the Crossplane repository. You can read more here about network secure connectivity configurations in Crossplane.

TL;DR

Apply the sample network configuration resources:

kubectl apply -k github.com/crossplane/crossplane//cluster/examples/workloads/kubernetes/wordpress/azure/network-config?ref=master

And you're done! You can check the status of the provisioning by running:

kubectl get -k github.com/crossplane/crossplane//cluster/examples/workloads/kubernetes/wordpress/azure/network-config?ref=master

When all resources have the Ready condition in True state, the provisioning is complete. You can now move on to the next section, or keep reading below for more details about the managed resources that we created.

Behind the scenes

In order to provision Azure resources, a Resource Group is needed to to logically group resources together. In addition, WordPress resources map to an AKS cluster and a SQLServer database instance. To make the database instance securely accessible from the cluster, they both need to live within the same Virtual Network. However, a Virtual Network is not the only Azure resource that is needed to provide inter-resource connectivity. In general, a Network Configuration which consists of a set of Virtual Networks, Subnets, VNet Rules and other resource is required for this purpose. For more information, see Azure resource connectivity design document.

To inspect the resources that we created above, let's run:

kubectl kustomize github.com/crossplane/crossplane//cluster/examples/workloads/kubernetes/wordpress/azure/network-config?ref=master > network-config.yaml

This will save the sample network configuration resources locally in network-config.yaml. Please note that the Azure parameters that are used in these resources (like addresPrefixes, location, etc...) are arbitrarily chosen in this solution and could be configured to implement other configurations.

Below we inspect each of these resources in more details.

  • ResourceGroup Represents an Azure Resource Group, that is used to logically group resources together.

    ---
    apiVersion: azure.crossplane.io/v1alpha3
    kind: ResourceGroup
    metadata:
      name: sample-rg
    spec:
      name: my-cool-rg
      location: Central US
      reclaimPolicy: Delete
      providerRef:
        name: azure-provider
    
  • VirtualNetwork Represents an Azure Virtual Network.

    ---
    apiVersion: network.azure.crossplane.io/v1alpha3
    kind: VirtualNetwork
    metadata:
      name: sample-vnet
    spec:
      name: my-cool-vnet
      resourceGroupNameRef:
        name: sample-rg
      location: Central US
      properties:
        addressSpace:
          addressPrefixes:
            - 10.2.0.0/16
      reclaimPolicy: Delete
      providerRef:
        name: azure-provider
    
  • Subnet Represents an Azure Subnet.

    ---
    apiVersion: network.azure.crossplane.io/v1alpha3
    kind: Subnet
    metadata:
      name: sample-subnet
    spec:
      name: my-cool-subnet
      resourceGroupNameRef:
        name: sample-rg
      virtualNetworkNameRef:
        name: sample-vnet
      properties:
        addressPrefix: 10.2.0.0/24
        serviceEndpoints:
          - service: Microsoft.Sql
      reclaimPolicy: Delete
      providerRef:
        name: azure-provider
    

As you probably have noticed, some resources are referencing other resources in their YAML representations. For instance for Subnet resource we have:

...
    virtualNetworkNameRef:
      name: sample-vnet
...

Such cross resource referencing is a Crossplane feature that enables managed resources to retrieve other resources attributes. This creates a blocking dependency, preventing the dependent resource from being created before the referred resource is ready. In the example above, Subnet will be blocked until the referred VirtualNetwork is created, and then it retrieves its name. For more information, see Cross Resource Referencing.

Configure Resource Classes

Once we have the network set up, we also need to tell Crossplane how to satisfy WordPress's claims (that will be created when we later install the WordPress stack) for a database and a Kubernetes cluster. The Resource Classes serve as templates for the corresponding resource claims.

In this guide, we will use the sample Azure resource classesin Crossplane repository.

TL;DR

Apply the sample Azure resource classes:

kubectl apply -k github.com/crossplane/crossplane//cluster/examples/workloads/kubernetes/wordpress/azure/resource-classes?ref=master

And you're done! Note that these resources do not immediately provision external Azure resources, as they only serve as template classes.

More Details

To inspect the resource classes that we created above, run:

kubectl kustomize github.com/crossplane/crossplane//cluster/examples/workloads/kubernetes/wordpress/azure/resource-classes?ref=master > resource-classes.yaml

This will save the sample resource classes YAML locally in resource-classes.yaml. As mentioned above, these resource classes serve as templates and could be configured depending on the specific needs that are needed from the underlying resources. For instance, in the sample resources the SQLServerClass has storageGB: 25, which will result in SQLServer databases of size 25 once a claim is submitted for this class. In addition, it's possible to have multiple classes defined for the same claim kind, but our sample has defined only one class for each resource type.

Below we inspect each of these resource classes in more details:

  • SQLServerClass Represents a resource that defines the blueprint for how a "standard" Azure MySQL Server should be dynamically provisioned

    ---
    apiVersion: database.azure.crossplane.io/v1beta1
    kind: SQLServerClass
    metadata:
      name: standard-mysql
      annotations:
        resourceclass.crossplane.io/is-default-class: "true"
    specTemplate:
      forProvider:
        administratorLogin: my-cool-login
        resourceGroupNameRef:
          name: sample-rg
        location: Central US
        sslEnforcement: Disabled
        version: "5.6"
        sku:
          tier: GeneralPurpose
          capacity: 2
          family: Gen5
        storageProfile:
          storageMB: 25600
      writeConnectionSecretsToNamespace: crossplane-system
      reclaimPolicy: Delete
      providerRef:
        name: azure-provider
    
  • AKSClusterClass Represents a resource that serves as a template to create an Azure Kubernetes Engine(AKS).

    ---
    apiVersion: compute.azure.crossplane.io/v1alpha3
    kind: AKSClusterClass
    metadata:
      name: standard-cluster
      annotations:
        resourceclass.crossplane.io/is-default-class: "true"
    specTemplate:
      writeConnectionSecretsToNamespace: crossplane-system
      resourceGroupNameRef:
        name: sample-rg
      vnetSubnetIDRef:
        name: sample-subnet
      location: Central US
      version: "1.12.8"
      nodeCount: 1
      nodeVMSize: Standard_B2s
      dnsNamePrefix: crossplane-aks
      disableRBAC: false
      writeServicePrincipalTo:
        name: akscluster-net
        namespace: crossplane-system
      reclaimPolicy: Delete
      providerRef:
        name: azure-provider
    

These resources will be the default resource classes for the corresponding claims (resourceclass.crossplane.io/is-default-class: "true" annotation). For more details about resource claims and how they work, see the documentation on resource claims, and resource class selection.

Post Stack Installation Network Configuration

After the WordPress stack is installed, we will need the AKS Cluster it provisions to be able to communicate with the MySQL database it provisions. In Azure, we can do so using a Virtual Network Rule. However, the rule cannot be created until after the MySQLInstance claim is created and satisfied, so we will start a short script to continually check if the database exists, and will create the rule if so.

cat > vnet-rule.yaml <<EOF
apiVersion: database.azure.crossplane.io/v1alpha3
kind: MySQLServerVirtualNetworkRule
metadata:
  name: sample-vnet-rule
spec:
  name: my-cool-vnet-rule
  serverName: MYSQL_NAME
  resourceGroupNameRef:
    name: sample-rg
  properties:
    virtualNetworkSubnetIdRef:
      name: sample-subnet
  reclaimPolicy: Delete
  providerRef:
    name: azure-provider
EOF

cat > vnetwatch.sh <<'EOF'
#!/usr/bin/env bash

set -e
trap 'exit 1' SIGINT

echo -n "waiting for mysql endpoint..." >&2
while kubectl get mysqlservers -o yaml | grep -q 'items: \[\]'; do
  echo -n "." >&2
  sleep 5
done
echo "done" >&2

export MYSQL_NAME=$(kubectl get mysqlservers -o=jsonpath='{.items[0].metadata.name}')

sed "s/MYSQL_NAME/$MYSQL_NAME/g" vnet-rule.yaml | kubectl apply -f -

EOF

chmod +x vnetwatch.sh && ./vnetwatch.sh

The script should be left running in the background while we go through the rest of the guide and install the WordPress stack.

Recap

To recap what we've set up now in our environment:

  • A Crossplane Provider resource for Azure
  • A Network Configuration to have secure connectivity between resources
  • An CloudSQLInstanceClass and an GKEClusterClass with the right configuration to use the mentioned networking setup.
  • A script that will create our Virtual Network Rule when our MySQL database name comes available.

Next Steps

Next we'll set up a Crossplane App Stack and use it! Head back over to the Stacks Guide document so we can pick up where we left off.