Architecture, Azure, Cloud, DevOps, IaC, technology, Uncategorized

Becoming a Cloud Architect, Part 2 – Building and Deploying Azure Cloud Infrastructure using Terraform

One of the hardest parts of a Cloud Architect’s job is not to deploy highly scalable infrastructures or troubleshooting cryptic cloud service...

Written by Freddy Ayala · 3 min read >

One of the hardest parts of a Cloud Architect’s job is not to deploy highly scalable infrastructures or troubleshooting cryptic cloud service provider errors but to understand what really the client needs.

In the first part of this series of articles we have worked together with the client and a product owner in order to better define the client’s requirement.

In this article we are not going to go into detail of waterfall vs agile but you should be aware than it is impossible to totally define the client requirement in paper, most of the time trying to go to far into the requirements analysis is a waste of time because clients do not know what they want until they see something.

In our case our client has asked us to deploy their blog on Azure, but hasn’t told us what technologies to use or which are the security requirements. So it is our job to guide the client and help him discover his need through a series of workshops.

Once the requirement is better understood we should capture and document it using any kind of tool that we have at our disposal, we have chosen to use a backlog and architecture diagrams to do it.

So with our architecture ready we will do a first iteration of the project where we will test all our hypothesis and provide something tangible at the end of the iteration so we can discuss with the client and validate if it is what they really need, as the iterations advances the requirement will become more and more clear, this is the “agile” way of doing things.

Nevertheless, as a rule of thumb we should keep things simple and don’t do more than what’s necessary to provide a solution, in our case we have decided to use wordpress, but we could have also coded our blog from scratch but of course that would have been pure madness.

So let’s remember our architecture:

Since we have decided to use terraform, first of all the as the cloud architect we will connect to the Azure Portal and create two resources: A Resource Group and a Storage Account:

Inside the storage account we will create a new container called tf-state and copy the storage account key that we will use to store the remote terraform state.

Now we will use visual studio code and create the following files:

First of all we will define our remote terraform state file using the parameters we got from our storage account:

backend.tfvars

# storage account settings
storage_account_name = "stcloudarchitect"
container_name       = "tf-state"
key                  = "<Storage Account Key>"
resource_group_name  = "rg-cloudarchitect-blog-prod-01"

Now we will define the variables that we are going to use inside our terraform configuration scripts, the variables database and app-service are in fact object that will have more values inside.

variables.tfvars

variable "location" {}
variable "resource_group" {}
variable "database" {}
variable "app-service" {}

And now is the moment to provide the values that we are going to use inside our scripts inside the terraform.tfvars, we might have to modify some values after deployment in order to update them, like the connection string.

terraform.tfvars

location       = "francecentral"
resource_group = "rg-cloudarchitect-blog-prod-01"
app-service = {
  backup_storage_account_url = "https://stcloudarchitect.blob.core.windows.net/backups?..."
  connection_string          = "Server=db...."
}
database = {
  administrator_login          = ".."
  administrator_login_password = "...."
}

Next step is to add our resources to the main.tf file, we begin with our database, we will check the azurerm_mysql_server terraform azurerm_mysql_server (https://www.terraform.io/docs/providers/azurerm/r/mysql_server.html) and create our resource accordingly:

resource "azurerm_mysql_server" "db-cloudarchitect" {


  location            = var.location
  name                = "db-cloudarchitect"
  resource_group_name = var.resource_group
  sku_name            = "B_Gen5_1"
  ssl_enforcement     = "Disabled"
  tags                = {}
  version             = "5.7"

  storage_profile {
    auto_grow             = "Enabled"
    backup_retention_days = 7
    geo_redundant_backup  = "Disabled"
    storage_mb            = 51200
  }
  administrator_login          = var.database.administrator_login
  administrator_login_password = var.database.administrator_login_password
  timeouts {}
}

And now we will create our app service plan and web application

resource "azurerm_app_service" "cloud-architect" {
  app_service_plan_id     = azurerm_app_service_plan.asp-cloudarchitectblog.id
  app_settings            = {}
  client_affinity_enabled = false
  client_cert_enabled     = false
  enabled                 = true
  https_only              = true
  location                = var.location
  name                    = "cloud-architect"
  resource_group_name     = var.resource_group


  tags = {}

  auth_settings {
    additional_login_params        = {}
    allowed_external_redirect_urls = []
    enabled                        = false
    token_refresh_extension_hours  = 0
    token_store_enabled            = false
  }

  backup {
    enabled             = true
    name                = "cloud-architect"
    storage_account_url = var.app-service.backup_storage_account_url

    schedule {
      frequency_interval       = 1
      frequency_unit           = "Day"
      keep_at_least_one_backup = true
      retention_period_in_days = 30
      start_time               = "2020-08-20T12:05:25Z"
    }
  }

  connection_string {
    name  = "wordpress"
    type  = "MySql"
    value = var.app-service.connection_string
  }

  logs {
    application_logs {
    }

    http_logs {
    }
  }

  site_config {
    always_on = false
    default_documents = [
      "Default.htm",
      "Default.html",
      "Default.asp",
      "index.htm",
      "index.html",
      "iisstart.htm",
      "default.aspx",
      "index.php",
      "hostingstart.html",
    ]
    dotnet_framework_version  = "v4.0"
    ftps_state                = "AllAllowed"
    http2_enabled             = false
    ip_restriction            = []
    linux_fx_version          = "PHP|7.3"
    local_mysql_enabled       = false
    managed_pipeline_mode     = "Integrated"
    min_tls_version           = "1.2"
    remote_debugging_enabled  = false
    remote_debugging_version  = "VS2017"
    scm_type                  = "None"
    use_32_bit_worker_process = true
    websockets_enabled        = false
  }

  timeouts {}
}

So our next step is to launch the terraform trifecta init, plan and then apply if everything goes well:

terraform init -backend-config=backend.tfvars
terraform plan -var-file=terraform.tfvars
terraform apply -var-file=terraform.tfvars

And voila! our infrastructure has been deployed!

Once the infrastructure deployed we have to do the following tasks to finish our deployment:

  • Download the latest version of wordpress and upload the code to our app service using either git or ftp.
  • Copy the database connection string into the terraform.tf file connection_string parameter and then relaunch terraform apply to modify the connection string.
  • The product owner will connect to the wordpress instance install a wordpress theme and then create some posts to make a demo to the client.

So after all these steps we have deployed our blog and we are ready to show it to the client.

In the next blog post we will analyse the reaction of our client and plan our next iteration.

Stay tunned!

Leave a Reply

Your email address will not be published. Required fields are marked *