pagopa / dx

Devex repository for shared tools and pipelines.
https://pagopa.github.io/dx/docs/
1 stars 0 forks source link

[DEVEX-134] Add Autoscaler module for App Service and Function App #42

Closed Krusty93 closed 2 months ago

Krusty93 commented 3 months ago

List of changes

Add autoscaler module for both App Service and Function App hosted by App Service Plan

Motivation and context

Simplify autoscaler management

Minimal usage:

module "autoscaler" {
  source = "../azure_app_service_plan_autoscaler"

  environment = {
    prefix          = "io"
    env_short       = "d"
    location        = "italynorth"
    domain          = "test"
    app_name        = "autoscaler"
    instance_number = "01"
  }

  resource_group_name = "dev-andreag"
  app_service_plan_id = "/subscriptions/a4e96bcd-59dc-4d66-b2f7-5547ad157c12/resourceGroups/dev-andreag/providers/Microsoft.Web/serverfarms/io-d-test-autoscaler-asp-01"
  app_service_id      = "/subscriptions/a4e96bcd-59dc-4d66-b2f7-5547ad157c12/resourcegroups/dev-andreag/providers/Microsoft.Web/sites/io-d-test-autoscaler-app-01"

  scheduler = {
    normal_load = {
      default = 2
      minimum = 1
      maximum = 5
    }
  }

  tags = {
    Test = "autoscale"
  }
}

Set one recurrent profile for low load

module "autoscaler" {
  source = "../azure_app_service_plan_autoscaler"

  scheduler = {
    normal_load = {
      default = 2
      minimum = 1
      maximum = 5
    }
    low_load = {
      default = 1
      minimum = 1
      maximum = 2
      start = {
        hour = 18
        minutes = 30
      }
      end = {
        hour = 19
        minutes = 45
      }
      name = "low"
    }
  }
}

Set two profiles for low and high load

module "autoscaler" {
  source = "../azure_app_service_plan_autoscaler"

  scheduler = {
    normal_load = {
      default = 2
      minimum = 1
      maximum = 5
    }
    low_load = {
      default = 1
      minimum = 1
      maximum = 2
      start = {
        hour = 18
        minutes = 30
      }
      end = {
        hour = 19
        minutes = 45
      }
      name = "low"
    }
    high_load = {
      default = 3
      minimum = 3
      maximum = 8
      start = {
        hour = 04
        minutes = 30
      }
      end = {
        hour = 05
        minutes = 45
      }
      name = "high"
    }
  }
}

Set custom metrics over requests

module "autoscaler" {
  source = "../azure_app_service_plan_autoscaler"

  scheduler = {
    normal_load = {
      default = 2
      minimum = 1
      maximum = 5
    }
  }

  scale_metrics = {
    requests = {
      upper_threshold = 1000
      lower_threshold = 100
      increase_by     = 1
      decrease_by     = 1
    }
  }
}

Set custom metrics overriding default values (CPU and memory are mandatory, if not set default values are used)

module "autoscaler" {
  source = "../azure_app_service_plan_autoscaler"

  scheduler = {
    normal_load = {
      default = 2
      minimum = 1
      maximum = 5
    }
  }

  scale_metrics = {
    cpu = {
      upper_threshold = 50
      lower_threshold = 5
      increase_by     = 1
      decrease_by     = 1
    }
  }
}

Type of changes

Does this introduce a change to production resources with possible user impact?

Other information

gunzip commented 3 months ago
  1. can we have some presets with default values (ie. low, standard, high) ? I mean, other modules that use this one but setup some defaults
  2. since the autoscaler is tied to one app service, can we populate all the environment values automatically from the app service resource ones? ie. accepting some parameters for a data resource. same for resource_group_name (or viceveversa, computing app_service_plan_id and app_service_id from environment values?)
Krusty93 commented 3 months ago
  1. can we have some presets with default values (ie. low, standard, high) ? I mean, other modules that use this one but setup some defaults

Not sure, it's difficult to estimate the number of requests a workload should support and their thresholds. Values can vary a lot. It's the same reason why I set defaults on CPU and memory (percentage values) but not on number of requests.

Any suggestion?

According to this logic, I tried to set a maximum of 3 recurrent schedules (normal, low and high) trying to abstract lot of details

  1. since the autoscaler is tied to one app service, can we populate all the environment values automatically from the app service resource ones? ie. accepting some parameters for a data resource. same for resource_group_name (or viceveversa, computing app_service_plan_id and app_service_id from environment values?)

No because we don't know if the id is about an App Service or a Function App, so we don't know which resource type use for the data block

gunzip commented 3 months ago

About

No because we don't know if the id is about an App Service or a Function App, so we don't know which resource type use for the data block

Can we provide a variable for the type (either function or app service) or use two different parameters?

The goal is to avoid to specify the whole environment section here which can be extracted from appservice / function module outputs:

environment = {
    prefix          = "io"
    env_short       = "d"
    location        = "italynorth"
    domain          = "test"
    app_name        = "autoscaler"
    instance_number = "01"
  }

  resource_group_name = "dev-andreag"
  app_service_plan_id = "/subscriptions/a4e96bcd-59dc-4d66-b2f7-5547ad157c12/resourceGroups/dev-andreag/providers/Microsoft.Web/serverfarms/io-d-test-autoscaler-asp-01"
  app_service_id      = "/subscriptions/a4e96bcd-59dc-4d66-b2f7-5547ad157c12/resourcegroups/dev-andreag/providers/Microsoft.Web/sites/io-d-test-autoscaler-app-01"

Ideally this configuration should be reduced to only one parameter, either:

app_service_id = module.some_app_service.outputs.id or function_app_id = module.some_function_app.outputs.id and everything else computed from some data source.

I don't know if it's possibile.