Fault-tolerant website with load balancing by Yandex Application Load Balancer
- Prepare your cloud
- Prepare the network infrastructure
- Create security groups
- Create an instance group
- Upload the website files
- Create a backend group
- Create an HTTP router
- Create an L7 load balancer
- Configure the DNS
- Test the fault tolerance
- How to delete the resources you created
- How to create an infrastructure using Terraform
Create and set up a website with load balancing by Application Load Balancer between three availability zones and fault tolerance in one zone.
- Prepare your cloud.
- Prepare the network infrastructure.
- Create security groups.
- Create an instance group.
- Upload the website files.
- Create a backend group.
- Create an HTTP router.
- Create an L7 load balancer.
- Configure the DNS.
- Test the fault tolerance.
If you no longer need the website, delete all its resources.
You can also deploy the infrastructure for hosting a website 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.
Required paid resources
The infrastructure support cost includes:
- Fee for continuously running VMs (see Yandex Compute Cloud pricing).
- Fee for using a dynamic external IP address (see Yandex Virtual Private Cloud pricing).
- Fee for load balancing (see Yandex Application Load Balancer pricing).
Prepare the network infrastructure
Before creating a VM:
-
Go to the Yandex Cloud management console
and select the folder where you will perform the operations. -
Make sure that the selected folder contains a network with subnets in the
ru-central1-a
,ru-central1-b
, andru-central1-c
availability zones. To do this, select Virtual Private Cloud on the folder page. If the subnets or network you need are not listed, create them.
Create security groups
Security groups include rules that let the load balancer receive incoming traffic and redirect it to the VMs so they can receive the traffic.
To create security groups for the load balancer and an instance group:
-
In the management console
, select Virtual Private Cloud. -
Open the Security groups tab.
-
Create a security group for the load balancer:
-
Click Create group.
-
Name the group, such as
alb-sg
. -
Select the network to assign the security group to.
-
Under Rules, create the following 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 ext-https 443 TCP CIDR 0.0.0.0/0 Incoming healthchecks 30080 TCP Load balancer health checks N/A - 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 desired 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 that allows a load balancer to check the health of VMs.
- Click Save. Repeat the steps to create all rules from the table.
-
Click Save.
-
-
Similarly, create a security group named
alb-vm-sg
for an instance group, with the same network and the following rules:Traffic
directionDescription Port
rangeProtocol Source type Source Incoming balancer 80 TCP Security group alb-sg
Incoming ssh 22 TCP CIDR 0.0.0.0/0
Create an instance group
Your application back ends will be deployed on the VM instance of the target group. The target group will be attached to the load balancer so that requests can be sent to the backend endpoints of your application.
To create an instance group with the minimum configuration:
-
In the management console
, select Compute Cloud. -
Open the Instance groups tab and click Create group.
-
Under Basic parameters:
- Name the instance group like
alb-vm-group
. - Select a service account from the list or create a new one. To be able to create, update, and delete group instances, assign the
editor
role to the service account. In Instance Groups, all operations are performed on behalf of a service account.
- Name the instance group like
-
Under Allocation, select three availability zones (
ru-central1-a
,ru-central1-b
andru-central1-c
) to ensure fault tolerance of your hosting. -
Under Instance template, click Define and set up the configuration for a basic instance:
- Under Basic parameters, enter the template Description:
- Under Image/boot disk selection, go to the Cloud Marketplace tab, select the LEMP product, and click Use.
- Under Disks, specify:
- Disk type: HDD.
- Size: 3 GB.
- Under Computing resources, specify:
- Platform: Intel Cascade Lake.
- vCPU: 2.
- Guaranteed vCPU share: 5%
- RAM: 1 GB.
- Under Network settings:
- Select a cloud network and its subnets.
- In the Public address field, select Auto.
- Select the
alb-vm-sg
security group.
- Under Access, specify the data required to access the VM:
- In the Service account field, select the service account to link the VM to.
- Enter the username in the Login field.
- In the SSH key field, paste the contents of the public key file.
To establish an SSH connection, you need to create a key pair. For more information, see Connecting to a Linux VM via SSH.
- Click Save.
-
Under Scaling, enter the Size of the instance group: 3.
-
Under Integration with Application Load Balancer, select Create target group and specify
alb-tg
as the group name. -
Click Create.
It may take several minutes to create an instance group. Once all VMs change their status to RUNNING
, you can upload the website files to them.
See also
Upload the website files
To test the web server, upload the website files to each VM. For example, you can use the index.html
file from this archive
Do the following for each VM instance in the created group:
-
On the Virtual machines tab, click on the name of the desired VM in the list. Under Network, find the VM's public IP address.
-
Connect to the VM via SSH.
-
Grant your user write access to the directory
/var/www/html
:sudo chown -R "$USER":www-data /var/www/html
-
Upload the website files to the VM via SCP
.Linux/macOSWindowsUse the
scp
command-line utility:scp -r <path to the file directory> <VM username>@<VM IP address>:/var/www/html
Use WinSCP
to copy the local file directory to/var/www/html
on the VM.
Create a backend group
You must link the target group created with the VM group to the backend group that defines traffic allocation settings.
For the backends, groups will implement health checks: the load balancer will periodically send health check requests to the VMs and expect a response after a certain delay.
To create a backend group:
-
Select Application Load Balancer in the folder where the instance group was created.
-
Open the Backend groups tab.
-
Click Create backend group.
-
Name the backend group, such as
alb-bg
. -
Under Backends, click Add.
-
Name the backend, such as
backend-1
. -
In the Target group field, select the previously created
alb-tg
target group. -
Specify the Port that the backend VMs will use to receive incoming traffic from the load balancer:
80
. -
Click Add health check.
-
Enter the Port that the backend VMs will use to accept health check connections from the load balancer:
80
. -
Enter the Path to be accessed by the load balancer's health checks:
/
. -
Click Create.
Create an HTTP router
The backend group should be linked to an HTTP router that defines HTTP routing rules.
To create an HTTP router and add a route to it:
-
Open the HTTP routers tab.
-
Click Create HTTP router.
-
Name the router, such as
alb-router
. -
Click Add virtual host.
-
Name the virtual host, such as
alb-host
. -
In the Authority field, specify the website's domain name:
alb-example.com
. -
Click Add route.
-
Name it like
route-1
. -
In the Backend group field, select the
alb-bg
group you created earlier. -
Leave all other settings as they are and click Create.
Create an L7 load balancer
To create a load balancer:
-
Open the Load balancers tab.
-
Click Create L7 load balancer.
-
Name the load balancer like
alb-1
. -
Under network settings, select the network that the instance group is connected to and the previously created
alb-sg
security group. -
Under Allocation, select the subnets for the load balancer's nodes in each availability zone and enable traffic.
-
Click Add listener under Listeners.
-
Name the listener, such as
alb-listener
. -
Under Public IP address settings, enable traffic.
-
Set the port to
80
. -
In the HTTP router field, select
alb-router
created earlier. -
Click Create.
Configure the DNS
You need to link the domain name you wish to use for your website to the load balancer's IP address. You can use Cloud DNS to manage your domain.
The instructions below describe how to configure DNS for the alb-example.com
domain name.
Add a zone
-
Select Cloud DNS in the folder where the instance group was created.
-
Click Create zone.
-
Specify the zone settings:
- Zone:
alb-example.com
. Specify your registered domain. - Type: Public.
- Name:
alb-zone
.
- Zone:
-
Click Create.
Add resource records
Create DNS records in the public zone:
-
Select Application Load Balancer. Find the IP address of the previously created
alb-1
load balancer in the list of load balancers. -
In Cloud DNS, select
alb-example.com.
. from the list. -
Create an A record:
- Click Create record.
- Set the record parameters:
- Name: Leave empty.
- Record type: Keep
A
as the value. - TTL (record time to live): Leave the default.
- Value: Enter the public IP address of
alb-1
.
- Click Create.
-
Create a CNAME record:
- Click Create record.
- Set the record parameters:
- Name:
www
. - Record type: Select
CNAME
as the value. - TTL (record time to live): Leave the default.
- Value: Enter
alb-example.com
.
- Name:
- Click Create.
Test the fault tolerance
-
In the management console
, select Compute Cloud. -
Go to the page of the VM from the previously created group. Under Network, find the VM's public IP address.
-
Connect to the VM via SSH.
-
Stop the web service to simulate a failure on the web server:
sudo service nginx stop
-
Connect to your website through a browser. The connection should be successful, even though one of the web servers has failed.
-
After the check is complete, restart the web service:
sudo service nginx start
How to delete the resources you created
To shut down the hosting and stop paying for the created resources:
-
Delete the Application Load Balancer components:
-
Delete the
alb-vm-group
instance group.
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 deploy an infrastructure to host a fault-tolerant load-balanced website in an instance group via Application Load Balancer using Terraform:
-
Install Terraform, get the authentication credentials, and specify the source for installing the Yandex Cloud provider (see Configure a provider, step 1).
-
Prepare files with the infrastructure description:
Ready-made archiveCreating files manually- Create a directory for files:
- Download the archive
(2 KB). - Unpack the archive to the directory. As a result, the
application-load-balancer.tf
configuration file should be added to it.
-
Create a directory for files:
-
Create a configuration file named
application-load-balancer.tf
in the directory:application-load-balancer.tf
# Declaring variables for confidential parameters variable "folder_id" { description = "ID of the folder where resources will be created" type = string } variable "vm_user" { type = string } variable "ssh_key_path" { type = string sensitive = true } variable "dns_zone" { type = string } variable "domain" { type = string } # Adding other variables locals { sa_name = "ig-sa" network_name = "network1" subnet_name1 = "subnet-1" subnet_name2 = "subnet-2" subnet_name3 = "subnet-3" } # Setting up the provider terraform { required_providers { yandex = { source = "yandex-cloud/yandex" version = ">= 0.47.0" } } } provider "yandex" { zone = "ru-central1-a" } resource "yandex_iam_service_account" "ig-sa" { name = local.sa_name } resource "yandex_resourcemanager_folder_iam_member" "editor" { folder_id = var.folder_id role = "editor" member = "serviceAccount:${yandex_iam_service_account.ig-sa.id}" } resource "yandex_vpc_network" "network-1" { name = local.network_name } resource "yandex_vpc_subnet" "subnet-1" { name = local.subnet_name1 zone = "ru-central1-a" network_id = yandex_vpc_network.network-1.id v4_cidr_blocks = ["192.168.1.0/24"] } resource "yandex_vpc_subnet" "subnet-2" { name = local.subnet_name2 zone = "ru-central1-b" network_id = yandex_vpc_network.network-1.id v4_cidr_blocks = ["192.168.2.0/24"] } resource "yandex_vpc_subnet" "subnet-3" { name = local.subnet_name3 zone = "ru-central1-d" network_id = yandex_vpc_network.network-1.id v4_cidr_blocks = ["192.168.3.0/24"] } resource "yandex_vpc_security_group" "alb-sg" { name = "alb-sg" network_id = yandex_vpc_network.network-1.id egress { protocol = "ANY" description = "any" v4_cidr_blocks = ["0.0.0.0/0"] from_port = 1 to_port = 65535 } ingress { protocol = "TCP" description = "ext-http" v4_cidr_blocks = ["0.0.0.0/0"] port = 80 } ingress { protocol = "TCP" description = "ext-https" v4_cidr_blocks = ["0.0.0.0/0"] port = 443 } ingress { protocol = "TCP" description = "healthchecks" predefined_target = "loadbalancer_healthchecks" port = 30080 } } resource "yandex_vpc_security_group" "alb-vm-sg" { name = "alb-vm-sg" network_id = yandex_vpc_network.network-1.id ingress { protocol = "TCP" description = "balancer" security_group_id = yandex_vpc_security_group.alb-sg.id port = 80 } ingress { protocol = "TCP" description = "ssh" v4_cidr_blocks = ["0.0.0.0/0"] port = 22 } } resource "yandex_compute_image" "lemp" { source_family = "lemp" } resource "yandex_compute_instance_group" "alb-vm-group" { name = "alb-vm-group" folder_id = var.folder_id service_account_id = yandex_iam_service_account.ig-sa.id instance_template { platform_id = "standard-v2" service_account_id = yandex_iam_service_account.ig-sa.id resources { core_fraction = 5 memory = 1 cores = 2 } boot_disk { mode = "READ_WRITE" initialize_params { image_id = yandex_compute_image.lemp.id type = "network-hdd" size = 3 } } network_interface { network_id = yandex_vpc_network.network-1.id subnet_ids = [yandex_vpc_subnet.subnet-1.id,yandex_vpc_subnet.subnet-2.id,yandex_vpc_subnet.subnet-3.id] nat = true security_group_ids = [yandex_vpc_security_group.alb-vm-sg.id] } metadata = { user-data = "#cloud-config\nusers:\n - name: ${var.vm_user}\n groups: sudo\n shell: /bin/bash\n sudo: ['ALL=(ALL) NOPASSWD:ALL']\n ssh-authorized-keys:\n - ${file("${var.ssh_key_path}")}" } } scale_policy { fixed_scale { size = 3 } } allocation_policy { zones = ["ru-central1-a", "ru-central1-b", "ru-central1-d"] } deploy_policy { max_unavailable = 1 max_expansion = 0 } application_load_balancer { target_group_name = "alb-tg" } } resource "yandex_alb_backend_group" "alb-bg" { name = "alb-bg" http_backend { name = "backend-1" port = 80 target_group_ids = [yandex_compute_instance_group.alb-vm-group.application_load_balancer.0.target_group_id] healthcheck { timeout = "10s" interval = "2s" healthcheck_port = 80 http_healthcheck { path = "/" } } } } resource "yandex_alb_http_router" "alb-router" { name = "alb-router" } resource "yandex_alb_virtual_host" "alb-host" { name = "alb-host" http_router_id = yandex_alb_http_router.alb-router.id authority = [var.domain, "www.${var.domain}"] route { name = "route-1" http_route { http_route_action { backend_group_id = yandex_alb_backend_group.alb-bg.id } } } } resource "yandex_alb_load_balancer" "alb-1" { name = "alb-1" network_id = yandex_vpc_network.network-1.id security_group_ids = [yandex_vpc_security_group.alb-sg.id] allocation_policy { location { zone_id = "ru-central1-a" subnet_id = yandex_vpc_subnet.subnet-1.id } location { zone_id = "ru-central1-b" subnet_id = yandex_vpc_subnet.subnet-2.id } location { zone_id = "ru-central1-d" subnet_id = yandex_vpc_subnet.subnet-3.id } } listener { name = "alb-listener" endpoint { address { external_ipv4_address { } } ports = [ 80 ] } http { handler { http_router_id = yandex_alb_http_router.alb-router.id } } } } resource "yandex_dns_zone" "alb-zone" { name = "alb-zone" description = "Public zone" zone = "${var.domain}." public = true } resource "yandex_dns_recordset" "rs-1" { zone_id = yandex_dns_zone.alb-zone.id name = "${var.domain}." ttl = 600 type = "A" data = [yandex_alb_load_balancer.alb-1.listener[0].endpoint[0].address[0].external_ipv4_address[0].address] } resource "yandex_dns_recordset" "rs-2" { zone_id = yandex_dns_zone.alb-zone.id name = "www" ttl = 600 type = "CNAME" data = [ var.domain ] }
For more information about the parameters of resources used in Terraform, see the provider documentation:
- yandex_iam_service_account
- yandex_resourcemanager_folder_iam_member
- yandex_vpc_network
- yandex_vpc_subnet
- yandex_vpc_security_group
- yandex_compute_image
- yandex_compute_instance_group
- yandex_alb_backend_group
- yandex_alb_http_router
- yandex_alb_virtual_host
- yandex_alb_load_balancer
- yandex_dns_zone
- yandex_dns_recordset
-
In the
variable
section, enter the value for thefolder_id
variable, that is, the ID of the folder where the resources are created. -
Under
metadata
, enter your username and the contents of your SSH key. For more information, see VM metadata. -
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.
-