Skip to content

Latest commit

 

History

History
352 lines (308 loc) · 13 KB

day.82.deploying.postgres.in.azure.using.arm.md

File metadata and controls

352 lines (308 loc) · 13 KB

Day 82 - Deploying PostgreSQL in Azure using ARM

Today we will cover how to deploy a PostgreSQL Server and a Web Application in Azure using ARM and how to automatically connect the two.


In today's article we will cover the following scenarios when troubleshooting your Kubernetes Applications using kubectl.

Deploy a new Resource Group
Create the ARM Template File
Deploy the ARM Template
Things to Consider
Conclusion


SPONSOR: Need to stop and start your development VMs on a schedule? The Azure Resource Scheduler let's you schedule up to 10 Azure VMs for FREE! Learn more HERE


Deploy a new Resource Group

Using Azure CLI, run the following command to create a new Resource Group.

az group create \
--name 100days-postgres \
--location westeurope

You should get back the following output:

{
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/100days-postgres",
  "location": "westeurope",
  "managedBy": null,
  "name": "100days-postgres",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": null,
  "type": "Microsoft.Resources/resourceGroups"
}

Create the ARM Template File

Below is the ARM Template File that we will be using to deploy the PostgreSQL Server, a database, and an Azure Web App that will automatically be connected to the database.

Copy the contents below into a file called azuredeploy.json.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "siteName": {
            "type": "string",
            "defaultValue": "100dayspostgre",
            "metadata": {
                "description": "Name of azure web app"
            }
        },
        "administratorLogin": {
            "type": "string",
            "defaultValue": "pgadmin",
            "minLength": 1,
            "metadata": {
                "description": "Database administrator login name"
            }
        },
        "administratorLoginPassword": {
            "type": "securestring",
            "defaultValue": "[guid(resourceGroup().id, deployment().name)]",
            "minLength": 8,
            "maxLength": 128,
            "metadata": {
                "description": "Database administrator password"
            }
        },
        "databaseSkuCapacity": {
            "type": "int",
            "defaultValue": 2,
            "allowedValues": [
                2,
                4,
                8,
                16,
                32
            ],
            "metadata": {
                "description": "Azure database for PostgreSQL compute capacity in vCores (2,4,8,16,32)"
            }
        },
        "databaseSkuName": {
            "type": "string",
            "defaultValue": "GP_Gen5_2",
            "allowedValues": [
                "GP_Gen5_2",
                "GP_Gen5_4",
                "GP_Gen5_8",
                "GP_Gen5_16",
                "GP_Gen5_32",
                "MO_Gen5_2",
                "MO_Gen5_4",
                "MO_Gen5_8",
                "MO_Gen5_16",
                "MO_Gen5_32",
                "B_Gen5_1",
                "B_Gen5_2"
            ],
            "metadata": {
                "description": "Azure database for PostgreSQL sku name "
            }
        },
        "databaseSkuSizeMB": {
            "type": "int",
            "defaultValue": 51200,
            "allowedValues": [
                102400,
                51200
            ],
            "metadata": {
                "description": "Azure database for PostgreSQL Sku Size "
            }
        },
        "databaseSkuTier": {
            "type": "string",
            "defaultValue": "GeneralPurpose",
            "allowedValues": [
                "GeneralPurpose",
                "MemoryOptimized",
                "Basic"
            ],
            "metadata": {
                "description": "Azure database for PostgreSQL pricing tier"
            }
        },
        "postgresqlVersion": {
            "type": "string",
            "defaultValue": "11",
            "metadata": {
                "description": "PostgreSQL version"
            }
        },
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]",
            "metadata": {
                "description": "Location for all resources."
            }
        },
        "databaseskuFamily": {
            "type": "string",
            "defaultValue": "Gen5",
            "metadata": {
                "description": "Azure database for PostgreSQL sku family"
            }
        }
    },
    "variables": {
        "databaseName": "[concat('primary_', parameters('siteName'), 'db')]",
        "serverName": "[concat(parameters('siteName'), 'srv')]",
        "hostingPlanName": "[concat(parameters('siteName'), 'serviceplan')]"
    },
    "resources": [
        {
            "apiVersion": "2018-02-01",
            "name": "[variables('hostingPlanName')]",
            "type": "Microsoft.Web/serverfarms",
            "location": "[parameters('location')]",
            "properties": {
                "name": "[variables('hostingPlanName')]",
                "workerSize": "1",
                "numberOfWorkers": 0
            },
            "sku": {
                "Tier": "Standard",
                "Name": "S1"
            }
        },
        {
            "apiVersion": "2018-02-01",
            "name": "[parameters('siteName')]",
            "type": "Microsoft.Web/sites",
            "location": "[parameters('location')]",
            "dependsOn": [
                "[concat('Microsoft.Web/serverfarms/', variables('hostingPlanName'))]"
            ],
            "properties": {
                "name": "[parameters('siteName')]",
                "serverFarmId": "[variables('hostingPlanName')]"
                },
            "resources": [
                {
                    "apiVersion": "2018-02-01",
                    "name": "connectionstrings",
                    "type": "config",
                    "dependsOn": [
                        "[concat('Microsoft.Web/sites/', parameters('siteName'))]"
                    ],
                    "properties": {
                        "defaultConnection": {
                            "value": "[concat('Database=', variables('databaseName'), ';Server=', reference(resourceId('Microsoft.DBforPostgreSQL/servers',variables('serverName'))).fullyQualifiedDomainName, ';User Id=', parameters('administratorLogin'),'@', variables('serverName'),';Password=', parameters('administratorLoginPassword'))]",
                            "type": "PostgreSQL"
                        }
                    }
                }
            ]
        },
        {
            "apiVersion": "2017-12-01",
            "type": "Microsoft.DBforPostgreSQL/servers",
            "location": "[parameters('location')]",
            "name": "[variables('serverName')]",
            "sku": {
                "name": "[parameters('databaseSkuName')]",
                "tier": "[parameters('databaseSkuTier')]",
                "capacity": "[parameters('databaseSkucapacity')]",
                "size": "[parameters('databaseSkuSizeMB')]",
                "family": "[parameters('databaseskuFamily')]"
            },
            "properties": {
                "version": "[parameters('postgresqlVersion')]",
                "administratorLogin": "[parameters('administratorLogin')]",
                "administratorLoginPassword": "[parameters('administratorLoginPassword')]",
                "storageMB": "[parameters('databaseSkuSizeMB')]"
            },
            "resources": [
                {
                    "type": "firewallrules",
                    "apiVersion": "2017-12-01",
                    "dependsOn": [
                        "[concat('Microsoft.DBforPostgreSQL/servers/', variables('serverName'))]"
                    ],
                    "location": "[parameters('location')]",
                    "name": "[concat(variables('serverName'),'firewall')]",
                    "properties": {
                        "startIpAddress": "0.0.0.0",
                        "endIpAddress": "255.255.255.255"
                    }
                },
                {
                    "name": "[variables('databaseName')]",
                    "type": "databases",
                    "apiVersion": "2017-12-01",
                    "properties": {
                        "charset": "utf8",
                        "collation": "English_United States.1252"
                    },
                    "dependsOn": [
                        "[concat('Microsoft.DBforPostgreSQL/servers/', variables('serverName'))]"
                    ]
                }
            ]
        }
    ]
}

In order to automatically connect the Web Application being deployed to the PostgreSQL Server, the connectionString is automatically populated with the databaseName, administratorLogin, and administratorLoginPassword Parameters of the PostgreSQL Server at runtime.

"properties": {
    "defaultConnection": {
        "value": "[concat('Database=', variables('databaseName'), ';Server=', reference(resourceId('Microsoft.DBforPostgreSQLvariables('serverName'))).fullyQualifiedDomainName, ';User Id=', parameters('administratorLogin'),'@', variables('servePassword=', parameters('administratorLoginPassword'))]",
        "type": "PostgreSQL"
    }
}

Below is a table of the Parameter Values that will be passed to the ARM Template at runtime.

Name Type Default Value Description
siteName String 100dayspostgre Name of the Azure Web App
administratorLogin String pgadmin PostgreSQL Server Admin Login User
administratorLoginPassword secureString ARM Template guid Function PostgreSQL Server Admin Login Password
databaseSkuCapacity Integer 2 Number of vCores to assign to the PostgreSQL Server
databaseSkuName String GP_Gen5_2 PostgreSQL Server SKU to use
databaseSkuSizeMB Integer 51200 PostgreSQL Server Database Size in MB
databaseSkuTier String GeneralPurpose PostgreSQL Server SKU Pricing Tier
postgresqlVersion String 11 PostgreSQL Server Version
location String Resource Group Location Azure Location to Use

Deploy the ARM Template

Run the following command to deploy the ARM Template using the Azure CLI

az group deployment create \
--resource-group 100days-postgres \
--template-file azuredeploy.json \
--output table

The deployment should run for a few minutes and should output the following when it's completed.

Name         ResourceGroup     State      Timestamp                         Mode
-----------  ----------------  ---------  --------------------------------  -----------
azuredeploy  100days-postgres  Succeeded  2020-01-20T15:20:53.896948+00:00  Incremental

If you would like to retrieve the PostgreSQL Server Database Administrator Password that is generated with the ARM Template guid Function, you have some options.


Option 1: Add output to the ARM Template to display the Password.


Option 2: In the Azure Portal, retrieve the Password from the defaultConnection String in the Application Settings of the Web Application.


Option 3: Run the following command below from the Azure CLI.

az webapp config connection-string list \
--name 100dayspostgre \
--resource-group 100days-postgres \
--query [].value.value \
--output tsv

You should get back the connection string currently in use for the Web App to connect to the PostgreSQL Server.

Database=primary_100dayspostgredb;Server=100dayspostgresrv.postgres.database.azure.com;User Id=pgadmin@100dayspostgresrv;Password=602f2e38-3d43-547e-87e4-274cca70db33

Things to Consider

The PostgreSQL Database name must be 63 or fewer characters and must start with a letter or an underscore. The rest of the string can contain letters, digits, and underscores.

If you need to use virtual network rules for your PostgreSQL Server, you need to use General Purpose or Memory Optimized servers. Virtual network rules are not available to Basic servers.


Conclusion

In today's article we covered how to deploy a PostgreSQL Server in Azure using ARM and how to make it automatically connect to a newly deployed Web Application. If there's a specific scenario that you wish to be covered in future articles, please create a New Issue in the starkfell/100DaysOfIaC GitHub repository.