Running instance groups with auto scaling
In this tutorial, you will deploy an instance group with an automatic scaling policy applied if the permitted load is exceeded.
VM instances will be deployed in two availability zones and their load will be balanced with a Yandex Network Load Balancer network load balancer.
To create an instance group:
- Prepare your cloud.
- Prepare the environment.
- Create an instance group with auto scaling and network load balancer.
- Add a network load balancer with a target group.
- Test your instance group and network load balancer.
- Test auto scaling.
If you no longer need the resources you created, delete them.
You can also deploy an infrastructure for scaling your instance group via Terraform using a ready-made configuration file.
Prepare your cloud
Sign up for Yandex Cloud and create a billing account:
- Go to the management console
and log in to Yandex Cloud or create an account if you do not have one yet. - On the Yandex Cloud Billing
page, make sure you have a billing account linked and it has theACTIVE
orTRIAL_ACTIVE
status. If you do not have a billing account, create one.
If you have an active billing account, you can go to the cloud page
Learn more about clouds and folders.
-
If you don't have the Yandex Cloud command line interface yet, install it.
-
For the scripts from the tutorial to run correctly, download and install the jq
utility. -
To check auto scaling, install the wrk
benchmarking tool.
Prepare the environment
-
Create a service account named
for-autoscale
and assign it theeditor
role:Management consoleCLITerraformAPI- In the management console
, select a folder in which to create a service account. - At the top of the screen, go to the Service accounts tab.
- Click Create service account.
- In the window that opens:
- In the Name field, specify
for-autoscale
. - To assign the service account a role for the current folder, click
Add role and select theeditor
role. - Click Create.
- In the Name field, specify
-
Create a service account:
The folder specified in the CLI profile is used by default. You can specify a different folder using the
--folder-name
or--folder-id
parameter.yc iam service-account create --name for-autoscale
Result:
id: ajelabcde12f******** folder_id: b0g12ga82bcv******** created_at: "2020-11-30T14:32:18.900092Z" name: for-autoscale
-
Assign the role to the service account:
yc resource-manager folder add-access-binding b1g23ga82bcv******** \ --role editor \ --subject serviceAccount:ajelabcde12f********
Use the create REST API method for the ServiceAccount resource or the ServiceAccountService/Create gRPC API call.
- In the management console
-
Create a network named
yc-auto-network
and subnets in two availability zones:Management consoleCLITerraformAPI- In the management console
, select the folder where you want to create a network. - Select Virtual Private Cloud.
- Click Create network.
- In the Name field, enter
yc-auto-network
as the network name. - In the Advanced field, enable the Create subnets option.
- Click Create network.
-
Create a network:
yc vpc network create --name yc-auto-network
Result:
id: enpabce123hd******** folder_id: b0g12ga82bcv******** created_at: "2020-11-30T14:57:15Z" name: yc-auto-network
-
Create a subnet in the
ru-central1-a
availability zone:yc vpc subnet create \ --network-id enpabce123hd******** \ --range 192.168.1.0/24 \ --zone ru-central1-a
Result:
id: e1lnabc23r1c******** folder_id: b0g12ga82bcv******** created_at: "2020-11-30T16:23:12Z" network_id: enpabce123hd******** zone_id: ru-central1-a v4_cidr_blocks: - 192.168.1.0/24
-
Create a subnet in the
ru-central1-b
availability zone:yc vpc subnet create \ --network-id enpabce123hd******** \ --range 192.168.2.0/24 \ --zone ru-central1-b
Result:
id: b1csa2b3clid******** folder_id: b0g12ga82bcv******** created_at: "2020-11-30T16:25:02Z" network_id: enpabce123hd******** zone_id: ru-central1-b v4_cidr_blocks: - 192.168.2.0/24
-
Create a network.
Use the create REST API method for the Network resource or the NetworkService/Create gRPC API call.
-
Create subnets in the
ru-central1-a
andru-central1-b
availability zones.Use the create REST API method for the Subnet resource or the SubnetService/Create gRPC API call.
- In the management console
-
Create a security group:
Management consoleTerraform- In the management console
, select Virtual Private Cloud. - Open the Security groups tab.
- Create a security group for the load balancer:
-
Click Create group.
-
Enter the Name of the group:
sg-autoscale
. -
Select the Network:
yc-auto-network
. -
Under Rules, create rules using the instructions below the table:
Traffic
directionDescription Port
rangeProtocol Source/
destination typeSource /
destinationOutgoing any All Any CIDR 0.0.0.0/0 Incoming ext-http 80 TCP CIDR 0.0.0.0/0 Incoming healthchecks 80 TCP Load balancer health checks — - Select the Outgoing traffic or Incoming traffic tab.
- Click Add rule.
- In the Port range field of the window that opens, specify a single port or a range of ports that traffic will come to or from.
- In the Protocol field, specify the appropriate protocol or leave Any to allow traffic transmission over any protocol.
- In the Purpose or Source field, select the purpose of the rule:
- CIDR: Rule will apply to the range of IP addresses. In the CIDR blocks field, specify the CIDR and masks of subnets that traffic will come to or from. To add multiple CIDRs, click Add CIDR.
- Security group: Rule will apply to the VMs from the current group or the selected security group.
- Load balancer health checks: Rule allowing a load balancer to health check VMs.
- Click Save. Repeat the steps to create all the rules from the table.
-
Click Save.
-
- In the management console
Create an instance group with auto scaling and network load balancer
-
All instance groups are created from Container Optimized Image. Each instance contains a Docker container running a web server that emulates the service utilization.
Find out the ID of the latest version of the public Container Optimized Image.
A Container Optimized Image in a Container Registry registry may be updated and changed with new releases. This will not automatically update the VM image to the latest version. To create an instance group with the latest Container Optimized Image version, you need to check whether it is available yourself:
CLIYandex Cloud Marketplaceyc compute image get-latest-from-family container-optimized-image --folder-id standard-images
Result:
id: <ID_of_latest_COI_version> folder_id: standard-images ...
- Go to the Cloud Marketplace page and select the image with the configuration you need:
- Under Product IDs, copy the value of
image_id
.
-
Save the specification of the instance group with network load balancer to the file
specification.yaml
:name: auto-group service_account_id: <service_account_ID> scale_policy: auto_scale: min_zone_size: 1 max_size: 6 measurement_duration: 60s warmup_duration: 120s stabilization_duration: 60s initial_size: 2 cpu_utilization_rule: utilization_target: 40 deploy_policy: max_unavailable: 1 allocation_policy: zones: - zone_id: ru-central1-a - zone_id: ru-central1-b load_balancer_spec: target_group_spec: name: auto-group-tg instance_template: service_account_id: <service_account_ID> platform_id: standard-v3 resources_spec: memory: 2G cores: 2 core_fraction: 100 metadata: docker-container-declaration: |- spec: containers: - image: cr.yandex/yc/demo/web-app:v1 securityContext: privileged: false tty: false stdin: false boot_disk_spec: mode: READ_WRITE disk_spec: type_id: network-hdd size: 30G image_id: fd8iv792kira******** # Public Container Optimized Image ID. network_interface_specs: - network_id: <cloud_network_ID> primary_v4_address_spec: { one_to_one_nat_spec: { ip_version: IPV4 }}
-
In the
specification.yaml
file, replace the values in angle brackets for the real values you got in the previous steps. -
Create an instance group named
auto-group
using the specificationspecification.yaml
:CLITerraformAPIRun this command:
yc compute instance-group create --file=specification.yaml
Result:
done (2m45s) id: cl0hmabc1nd2******** folder_id: b0g12ga82bcv******** ... target_group_id: enpoi5jhfps3******** ... name: auto-group-tg service_account_id: ajelabcde12f******** status: ACTIVE
Use the CreateFromYaml method for the
InstanceGroup
resource. -
Make sure that the instance group was created:
Management consoleCLITerraformAPI- In the management console
, select the folder where you created the instance group. - Select Compute Cloud.
- In the left-hand panel, click
Instance groups. - Select the
auto-group
instance group.
yc compute instance-group list-instances auto-group
Result:
+----------------------+---------------------------+----------------+--------------+------------------------+----------------+ | INSTANCE ID | NAME | EXTERNAL IP | INTERNAL IP | STATUS | STATUS MESSAGE | +----------------------+---------------------------+----------------+--------------+------------------------+----------------+ | epdab0c1ji2a******** | cl0habce1nd2********-fned | 84.201.163.202 | 192.168.1.34 | RUNNING_ACTUAL [4m26s] | | | ef0uabc1s2fb******** | cl0habce1nd2********-craq | 130.193.56.102 | 192.168.2.19 | RUNNING_ACTUAL [4m14s] | | +----------------------+---------------------------+----------------+--------------+------------------------+----------------+
To view the list of created instance groups, use the list REST API method for the InstanceGroup resource or the InstanceGroupService/List gRPC API call.
- In the management console
Add a network load balancer with a target group
-
Create a network load balancer named
group-balancer
and connect it to the instance group you created:Management consoleCLITerraformAPI- In the management console
, select the folder where you want to create a load balancer. - Select Network Load Balancer.
- Click Create a network load balancer.
- Name it
group-balancer
. - In the Public address field, specify
Auto
. - Under Listeners, click Add listener. In the window that opens, specify:
- Name:
http
. - Port (the load balancer will use this port to accept incoming traffic):
80
. - Target port (the load balancer will redirect traffic to this port):
80
. - Click Add.
- Name:
- Under Target groups, click Add target group.
- In the Target group field, select the
auto-group-tg
instance group and click Configure. In the window that opens, specify:- Name:
tcp
- Type:
TCP
- Port:
80
- Click Apply.
- Name:
- Click Create.
yc load-balancer network-load-balancer create \ --listener external-ip-version=ipv4,name=http,port=80,protocol=tcp,target-port=80 \ --name group-balancer \ --target-group healthcheck-name=tcp,healthcheck-tcp-port=80,target-group-id=enpoi5jhfps3********
Result:
done (16s) id: b0rbabc1m2ed******** folder_id: b0g12ga82bcv******** ... healthy_threshold: "2" tcp_options: port: "80"
- Create a load balancer using the create REST API method for the NetworkLoadBalancer resource or the NetworkLoadBalancerService/Create gRPC API call.
- Add a listener to the load balancer using the addListener REST API method for the
NetworkLoadBalancer
resource or the NetworkLoadBalancerService/AddListener gRPC API call. - Attach the target group to the load balancer using the attachTargetGroup REST API method for the
NetworkLoadBalancer
resource or the NetworkLoadBalancerService/AttachTargetGroup gRPC API call. - Add the load balancer to the instance group using the addTargets REST API method for the TargetGroup resource or the TargetGroupService/AddTargets gRPC API call.
- In the management console
-
Make sure that the network load balancer
group-balancer
is created and attached to the instance group:Management consoleCLITerraformAPI- In the management console
, select the folder where you created the load balancer. - Select Network Load Balancer.
- Select
group-balancer
as your load balancer.
yc load-balancer network-load-balancer list
Result:
+----------------------+----------------+-------------+----------+----------------+------------------------+--------+ | ID | NAME | REGION ID | TYPE | LISTENER COUNT | ATTACHED TARGET GROUPS | STATUS | +----------------------+----------------+-------------+----------+----------------+------------------------+--------+ | b0rbabc1m2ed******** | group-balancer | ru-central1 | EXTERNAL | 1 | b0rdabckribe******** | ACTIVE | +----------------------+----------------+-----------------+----------+----------------+------------------------+--------+
Use the list REST API method for the NetworkLoadBalancer resource or the NetworkLoadBalancerService/List gRPC API call.
- In the management console
Test your instance group and network load balancer
-
Create a load on an instance.
To do this, save the script named
request.sh
in the home directory. The script will send a request to one of the instances through thegroup-balancer
load balancer. The request will utilize 100% CPU for 30 seconds.EXTERNAL_IP=$(yc load-balancer network-load-balancer get group-balancer --format=json | jq -r .listeners[0].address) curl "http://$EXTERNAL_IP/burn-cpu?time=30000&load=100"
-
Run the script:
CLIsh request.sh
Result:
projects/b0g12ga82bcv********/zones/ru-central1-b
-
View the instance utilization:
Management console-
In the management console
, select the folder where you created the instance group. -
Select Compute Cloud.
-
In the left-hand panel, click
Instance groups. -
Select the
auto-group
instance group. -
Go to the Monitoring tab.
The load balancer sent the request to an instance in the group. In the availability zone this instance belongs to, the average CPU utilization is higher than in other zones (see the Average CPU utilization in zone chart).
-
Test auto scaling
To test auto scaling for your instance group, increase the CPU utilization of each instance. In the specification.yaml
file, the scale_policy.auto_scale.cpu_utilization_rule.utilization_target
parameter has the value of 40
: it means that the target utilization level is 40% CPU. If you exceed the target utilization, the number of VMs in the group will increase.
-
Increase the utilization of the instance group.
To do this, save the script named
load.sh
in the home directory. The script sends requests to the instance group through 12 threads for 10 minutes. Each VM instance utilizes 20% CPU on each core that processes the request. The instance group utilization is 240% CPU at any given time. To be sure that requests are evenly distributed across the instances in the group, the script executes multiple parallel requests utilizing 20% CPU rather than one request utilizing 240% CPU.EXTERNAL_IP=$(yc load-balancer network-load-balancer get group-balancer --format=json | jq -r .listeners[0].address) wrk -H "Connection: close" -t12 -c12 -d10m "http://$EXTERNAL_IP/burn-cpu?time=5000&load=20"
-
Run the script:
CLIsh load.sh
Result:
Running 10m test @ http://130.193.56.111/burn-cpu?time=5000&load=20 12 threads and 12 connections Thread Stats Avg Stdev Max +/- Stdev ... Requests/sec: 15.04 Transfer/sec: 3.20KB
-
View the utilization levels:
Management console- In the management console
, select the folder where you created theauto-group
instance group. - Select Compute Cloud.
- In the left-hand panel, click
Instance groups. - Select the
auto-group
instance group. - Go to the Monitoring tab.
The chart Number of instances in zone shows how the number of instances changed in each availability zone. The chart Average CPU utilization in zone shows average CPU utilization in each availability zone. - Go to the Logs tab.
The page displays messages relating to auto scaling of the instance group.
The total utilization of 240% CPU was evenly distributed between two VMs in two availability zones and exceeded the target utilization of 40% CPU. Yandex Compute Cloud created one more VM in each availability zone to result in four VMs in the group. When the script stopped utilizing the CPU, Compute Cloud automatically decreased the number of instances in the group to two.
- In the management console
Delete the infrastructure
-
Delete the network load balancer:
Management consoleCLIAPI- In the management console
, select the folder where you created thegroup-balancer
load balancer. - Select Network Load Balancer.
- In the
group-balancer
line, click and select Delete. - In the window that opens, click Delete.
yc load-balancer network-load-balancer delete group-balancer
Result:
done (15s)
Use the delete REST API method for the NetworkLoadBalancer resource or the NetworkLoadBalancerService/Delete gRPC API call.
- In the management console
-
Delete the instance group:
Management consoleCLIAPI- In the management console
, select the folder where you created theauto-group
instance group. - Select Compute Cloud.
- In the left-hand panel, click
Instance groups. - In the
auto-group
instance group line, click and select Delete. - In the window that opens, click Delete.
yc compute instance-group delete auto-group
Result:
done (1m20s)
Use the delete REST API method for the InstanceGroup resource or the InstanceGroupService/Delete gRPC API call.
- In the management console
-
Delete the subnets:
Management consoleCLIAPI- In the management console
, select the folder where you created the subnets. - Open the Virtual Private Cloud section.
- Select the network with the appropriate subnets.
- In the line of the subnet you need, click
and select Delete. - In the window that opens, click Delete.
- Repeat the previous three steps to delete the remaining subnets.
-
Delete the subnet in the
ru-central1-a
availability zone:yc vpc subnet delete e1lnabc23r1c********
Result:
done (1s) id: e1lnabc23r1c******** folder_id: b0g12ga82bcv******** created_at: "2020-11-30T16:23:12Z" network_id: enpabce123hd******** zone_id: ru-central1-a v4_cidr_blocks: - 192.168.1.0/24
-
Delete the subnet in the
ru-central1-b
availability zone:yc vpc subnet delete b1csa2b3clid********
Result:
done (1s) id: b1csa2b3clid******** folder_id: b0g12ga82bcv******** created_at: "2020-11-30T16:25:02Z" network_id: enpabce123hd******** zone_id: ru-central1-b v4_cidr_blocks: - 192.168.2.0/24
Use the delete REST API method for the Subnet resource or the SubnetService/Delete gRPC API call.
- In the management console
-
Delete the network:
Management consoleCLIAPI- In the management console
, select the folder where you created the network. - Open the Virtual Private Cloud section.
- In the line of the network you need, click
and select Delete. - In the window that opens, click Delete.
yc vpc network delete yc-auto-network
Result:
id: enpabce123hd******** folder_id: b0g12ga82bcv******** created_at: "2020-11-30T14:57:15Z" name: yc-auto-network
Use the delete REST API method for the Network resource or the NetworkService/Delete gRPC API call.
- In the management console
-
Delete the service account:
Management consoleCLIAPI- In the management console
, select the folder the service account belongs to. - At the top of the screen, go to the Service accounts tab.
- In the line of the service account you need, click
and select Delete. - Confirm the deletion.
yc iam service-account delete for-autoscale
Result:
done (2s)
Use the delete REST API method for the ServiceAccount resource or the ServiceAccountService/Delete gRPC API call.
- In the management console
How to create an infrastructure using Terraform
Terraform
For more information about the provider resources, see the documentation on the Terraform
If you change the configuration files, Terraform automatically detects which part of your configuration is already deployed, and what should be added or removed.
To set up scaling for your instance group using Terraform:
-
Install Terraform and specify the source for installing the Yandex Cloud provider (see Configure a provider, step 1).
-
Prepare files with the infrastructure description:
Ready-made archiveManually-
Clone the repository with configuration files:
git clone https://github.com/yandex-cloud-examples/yc-vm-group-with-autoscale.git
-
Go to the directory with the repository. Make sure it contains the following files:
vm-autoscale.tf
: New infrastructure configuration.declaration.yaml
: Description of the Docker container with a web server that will be run on a VM to simulate the service load.config.tpl
: Description of VM user parameters.vm-autoscale.auto.tfvars
: User data.
- Create a directory for configuration files.
- In the directory, create:
-
The
vm-autoscale.tf
configuration file:vm-autoscale.tf
# Declaring variables for confidential parameters variable "folder_id" { type = string } variable "vm_user" { type = string } variable "ssh_key" { type = string sensitive = true } # Setting up the provider terraform { required_providers { yandex = { source = "yandex-cloud/yandex" version = ">= 0.47.0" } } } provider "yandex" { zone = "ru-central1-a" } # Creating a service account and assigning roles to it resource "yandex_iam_service_account" "for-autoscale" { name = "for-autoscale" } resource "yandex_resourcemanager_folder_iam_member" "vm-autoscale-sa-role-compute" { folder_id = var.folder_id role = "editor" member = "serviceAccount:${yandex_iam_service_account.for-autoscale.id}" } # Creating a cloud network and subnets resource "yandex_vpc_network" "vm-autoscale-network" { name = "vm-autoscale-network" } resource "yandex_vpc_subnet" "vm-autoscale-subnet-a" { name = "vm-autoscale-subnet-a" zone = "ru-central1-a" v4_cidr_blocks = ["192.168.1.0/24"] network_id = yandex_vpc_network.vm-autoscale-network.id } resource "yandex_vpc_subnet" "vm-autoscale-subnet-b" { name = "vm-autoscale-subnet-b" zone = "ru-central1-b" v4_cidr_blocks = ["192.168.2.0/24"] network_id = yandex_vpc_network.vm-autoscale-network.id } # Creating a security group resource "yandex_vpc_security_group" "sg-1" { name = "sg-autoscale" network_id = yandex_vpc_network.vm-autoscale-network.id egress { protocol = "ANY" description = "any" v4_cidr_blocks = ["0.0.0.0/0"] } ingress { protocol = "TCP" description = "ext-http" v4_cidr_blocks = ["0.0.0.0/0"] port = 80 } ingress { protocol = "TCP" description = "healthchecks" predefined_target = "loadbalancer_healthchecks" port = 80 } } # Specifying a ready-made VM image data "yandex_compute_image" "autoscale-image" { family = "container-optimized-image" } # Creating an instance group resource "yandex_compute_instance_group" "autoscale-group" { name = "autoscale-vm-ig" folder_id = var.folder_id service_account_id = yandex_iam_service_account.for-autoscale.id instance_template { platform_id = "standard-v3" resources { memory = 2 cores = 2 } boot_disk { mode = "READ_WRITE" initialize_params { image_id = data.yandex_compute_image.autoscale-image.id size = 30 } } network_interface { network_id = yandex_vpc_network.vm-autoscale-network.id subnet_ids = [ yandex_vpc_subnet.vm-autoscale-subnet-a.id, yandex_vpc_subnet.vm-autoscale-subnet-b.id ] security_group_ids = [ yandex_vpc_security_group.sg-1.id ] nat = true } metadata = { user-data = templatefile("config.tpl", { VM_USER = var.vm_user SSH_KEY = var.ssh_key }) docker-container-declaration = file("declaration.yaml") } } scale_policy { auto_scale { initial_size = 2 measurement_duration = 60 cpu_utilization_target = 40 min_zone_size = 1 max_size = 6 warmup_duration = 120 } } allocation_policy { zones = [ "ru-central1-a", "ru-central1-b" ] } deploy_policy { max_unavailable = 1 max_expansion = 0 } load_balancer { target_group_name = "auto-group-tg" target_group_description = "load balancer target group" } } # Creating a network load balancer resource "yandex_lb_network_load_balancer" "balancer" { name = "group-balancer" listener { name = "http" port = 80 target_port = 80 } attached_target_group { target_group_id = yandex_compute_instance_group.autoscale-group.load_balancer[0].target_group_id healthcheck { name = "tcp" tcp_options { port = 80 } } } }
-
The
declaration.yaml
file with a description of the Docker container with a web server that will be run on a VM instance to simulate the service load:declaration.yaml
spec: containers: - image: cr.yandex/yc/demo/web-app:v1 securityContext: privileged: false tty: false stdin: false
-
The
config.tpl
file with VM user parameters:config.tpl
users: - name: "${VM_USER}" groups: sudo shell: /bin/bash sudo: 'ALL=(ALL) NOPASSWD:ALL' ssh_authorized_keys: - "${SSH_KEY}"
-
vm-autoscale.auto.tfvars
user data file:vm-autoscale.auto.tfvars
folder_id = "<folder_ID>" vm_user = "<VM_username>" ssh_key = "<public_SSH_key_contents>"
-
For more information about the parameters of resources used in Terraform, see the provider documentation:
-
-
In the
vm-autoscale.auto.tfvars
file, set the user-defined parameters:folder_id
: Folder ID.vm_user
: VM username.ssh_key
: Contents of the file with a public SSH key to authenticate the user on the VM. For more information, see Creating an SSH key pair.
-
Create resources:
-
In the terminal, change to the folder where you edited the configuration file.
-
Make sure the configuration file is correct using the command:
terraform validate
If the configuration is correct, the following message is returned:
Success! The configuration is valid.
-
Run the command:
terraform plan
The terminal will display a list of resources with parameters. No changes are made at this step. If the configuration contains errors, Terraform will point them out.
-
Apply the configuration changes:
terraform apply
-
Confirm the changes: type
yes
in the terminal and press Enter.
-
- Management console, CLI, and API: Use the Yandex Cloud management console, CLI, or API to create your infrastructure step by step.
- Terraform: Streamline creating and managing your resources using the infrastructure as code (IaC) approach. Download a Terraform configuration example from the GitHub repository and then deploy the infrastructure using the Yandex Cloud Terraform provider
.