Provisioning Azure Database for MySQL - Single Server from AKS
Published Sep 03 2021 02:17 PM 13.6K Views
Microsoft

To gain the benefits of using a MySQL database in a Kubernetes application, a common strategy is to provision the database in a container running in a pod. In doing so, the database will use the cluster resources. Accessing the database from other pods in the same AKS cluster running client apps is possible via Kubernetes networking. However, if for some reason cluster resources become unavailable, both the application and the database will be unavailable, as both rely on cluster health.

 

Important: Provisioning from Azure Kubernetes Service (AKS) using Azure Service Operator (ASO) is currently tested with the v1 alpha version, which only supports Azure Database for MySQL - Single Server. For information about provisioning Azure Database for MySQL - Flexible Server, see the blog post Using Azure Service Operator to provision Azure DB for MySQL- Flexible Server from within Kubernetes.

 

To address the issue of cluster resources being shared between the application and database, you can substitute the local database in AKS with Azure Database for MySQL, which separates the database from the AKS cluster. Thus, cluster resources will remain focused on delivering infrastructure required to run the app and database availability will not be impacted by AKS availability. By making this change, the architecture will be updated as shown in the following diagram.

 

AKS blog.png

 

You can provision Azure Database for MySQL programmatically using Terraform, or you can integrate it with the Kubernetes services. This post provides the steps for provisioning from Kubernetes using ASO, which allows dynamic deployment of Azure services directly from AKS. This makes the resources accessible from pods within the AKS cluster.

 

ASO runs as a collection of pods (controller and manager pods) in your AKS cluster and requires a certificate and a Service Principal (SP) to create resources in the subscription. In the following steps, you'll use Helm to add ASO. Helm is an open-source packaging tool that helps you install and manage the lifecycle of Kubernetes applications. Similar to Linux package managers like APT and Yum, Helm manages Kubernetes charts, which are packages of pre-configured Kubernetes resources.

 

Deployment of Azure MySQL Database is performed via a YAML file that serves as the basis for Kubernetes deployment and configuration of the pods. In the YAML file, the description of the service is provided, and the service deployment is performed via kubectl. kubectl is the Kubernetes command-line client, used to manage a Kubernetes cluster and is already installed if you use Azure Cloud Shell.

 

To provision, perform the following steps.

 

  1.  Open the Cloud Shell, and then connect to your AKS cluster by running the following command:
    az aks get-credentials --resource-group RGNAME --name CLUSTERNAME​
  2.  Add cert-manager to the cluster by running the following command:
    kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.5.3/cert-manager.yaml​
  3.  Create a Helm repository and charts for ASO by running the following command:
    helm repo add aso https://raw.githubusercontent.com/Azure/azure-service-operator/master/charts​
  4.  Create an Azure service principal by running the following command:
    az ad sp create-for-rbac --name "azure-service-operator" --role contributor --scopes /subscriptions/<AZURE_SUBSCRIPTION_ID>​
    Output:
    {
      "appId": "2c0e1d61-1ac7-4710-9f60-d4844c47dd21",
      "displayName": "azure-service-operator",
      "name": "2c0e1d61-1ac7-4710-9f60-d4844c47dd21",
      "password": "iBW-RKtsq.ScrVdUp2_4SSKgI0P_eMFbh-",
      "tenant": "72f988bf-86f1-41af-91ab-2d7cd011db47"
    }
  5.  Install ASO on your Kubernetes cluster by running the following command:
    helm upgrade --install aso aso/azure-service-operator \
    --create-namespace \
    --namespace=azureoperator-system \
    --set azureSubscriptionID=<AZURE_SUBSCRIPTION_ID> \
    --set azureTenantID=<TENANT> \
    --set azureClientID=<APPID> \
    --set azureClientSecret=<PASSWORD>
  6.  Verify that the ASO is operating properly by running the following command:
    kubectl get pods -n azureoperator-system​
    The results will appear as shown in the following diagram.

    image3.PNG

  7. Create a YAML file named myfile.yml by running the following command:
    code myfile.yml​
  8. In the newly created myfile.yml, insert the desired configuration for the MySQL server and databases, along with the server firewall rule to allow access to the server after deployment. Sample contents of the file myfile.yml are shown in the following diagram. The content sample of YAML file can also be accessed at this repository. Save the YAML configuration file.
    # Azure Database for MySQL deployment
    
    apiVersion: azure.microsoft.com/v1alpha2
    kind: MySQLServer
    metadata:
         name: mysqlappdbserver
         labels: # Provide tags to add to the KeyVault as labels
         tag1: value1
         tag2: value2
    spec:
         location: eastus
         resourceGroup: MyResourceGroup
         serverVersion: "5.7" # could also be 8.0
         sslEnforcement: Enabled
         createMode: Default # Possible values include: Default, Replica, PointInTimeRestore (not implemented), GeoRestore (not implemented)
         # Optional admin secret name. If the admin secret is specified the `username` and `password` fields of the secret will be used to set
         # the administrator username and password. If adminSecret is not provided, ASO will generate an administrator account
         # and password.
         # adminSecret: my-admin-secret
         sku:
              name: GP_Gen5_4
              tier: GeneralPurpose # possible values - 'Basic', 'GeneralPurpose', 'MemoryOptimized'
              family: Gen5
              size: "51200"
              capacity: 4
              # Optional Backup Retention Config
              # storageProfile:
              # backupRetentionDays: 10
              # geoRedundantBackup: Enabled # Disabled or Enabled
              # storageMB: 5120 # max storage - minimum of 5120 MB and additional increments of 1024 MB up to maximum of 16777216 MB
              # storageAutogrow: Enabled # Disabled or Enabled
    ---
    apiVersion: azure.microsoft.com/v1alpha1
    kind: MySQLFirewallRule
    metadata:
         name: mysqlfirewallrule-azureservices
    spec:
         resourceGroup: MyResourceGroup
         server: mysqlappdbserver
         startIpAddress: 0.0.0.0
         endIpAddress: 0.0.0.0
    ---
    apiVersion: azure.microsoft.com/v1alpha1
    kind: MySQLDatabase
    metadata:
         name: mydatabasename
    spec:
         resourceGroup: MyResourceGroup
         server: mysqlappdbserver
  9.  Deploy MySQL server by running the following command:
    kubectl appy -f myfile.yml​
  10.  Check the deployment status by running the following command:
    kubectl get MySqlServer​

    The results will appear as shown in the following diagram.
    image4.PNG
    The server is now accessible via the Azure portal as well.

Note: You can explicitly provide the username and password in the YAML config file, or you can use them as environmental variables to connect your application to the server. The server name, username, and password are stored as keys in the secret generated by Kubernetes. To view the encoded keys run the following command:

 

 

 

 

 

 

 

 

 

kubectl describe secrets mysqlserver-mysqlappdbserver

 

 

 

 

 

 

 

 

 

A similar output will appear:

image5.PNG

You can reference the secret inside the YAML file for a pod that configures an app that needs to connect to the service in a deployment. The following example retrieves the values of the fullyQualifiedServerName, fullyQualifiedUsername, and password keys, and makes them available as environment variables inside a pod.

 

 

 

 

 

 

 

 

 

apiVersion: apps/v1
kind: Deployment
metadata:
    name: mysqlapp
spec:
    replicas: 4
    selector: 
 …
    template: 
	 …
    	spec: 
		…
         containers: 
		…
         env:
	   - name: MYSQL_USER
		valueFrom:
		  secretKeyRef:
			name: mysqlserver-mysqlappdbserver
			key:	fullyQualifiedUsername
         - name: MYSQL_PASSWORD
		valueFrom:
		  secretKeyRef:
			name: mysqlserver-mysqlappdbserver
			key:	password
         - name: MYSQL_SERVICE_HOST
		valueFrom:
		  secretKeyRef:
			name: mysqlserver-mysqlappdbserver
			key:	fullyQualifiedServerName
         - name: MYSQL_SERVICE_PORT
		value: '3306'

 

 

 

 

 

 

 

 

 

The application will retrieve environmental variables above and use them to construct a connector to the database server. The advantage of this approach is that connection credentials are not exposed to the app, reducing the chances of accidental disclosure.

 

Supportability note: This approach is also supported for Azure Database for PostgreSQL, Azure SQL Database, and Azure Cosmos DB. For more details and YAML code examples, please check the following repository. A list of ASO supported resources can be found here.

Co-Authors
Version history
Last update:
‎Jan 13 2022 05:38 PM
Updated by: