Fault-tolerant website with load balancing with 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 with 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.
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 public IP address (see Yandex Virtual Private Cloud pricing).
- Fee for traffic balancing (see Application Load Balancer pricing).
Prepare the network infrastructure
Before creating a VM:
- Go to the Yandex Cloud management console
and select the folder to perform your steps in. - Make sure 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 allow the load balancer to 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, e.g.,
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 — - 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.
-
-
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 backends will be deployed on the VM 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, e.g.,
alb-vm-group
. - Select a service account from the list or create a new one. To be able to create, update, and delete instances in the instance group, assign the
editor
role to the service account. By default, all operations with security groups are performed on behalf of the service account.
- Name the instance group, e.g.,
- 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 information 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 a few minutes to create an instance group. As soon as 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
For each VM in the created group, do the following:
-
On the Virtual machines tab, click the name of the 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
/var/www/html
directory: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 <file_directory_path> <VM_user_name>@<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, e.g.,
alb-bg
. - Under Backends, click Add.
- Name the backend, e.g.,
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, e.g.,
alb-router
. - Click Add virtual host.
- Name the virtual host, e.g.,
alb-host
. - In the Authority field, specify the website's domain name:
alb-example.com
. - Click Add route.
- Name the route, e.g.,
route-1
. - In the Backend group field, select the
alb-bg
group you created earlier. - Leave all other settings unchanged 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, e.g.,
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, e.g.,
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 want to use for your website to the load balancer's IP address. You can use Cloud DNS to manage your domain.
Below you will find 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): Keep the default value.
- Value: Enter the public IP address of the
alb-1
load balancer.
- 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): Keep the default value.
- 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
-
Open your website in the browser. The website should open, 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
VM 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 host a fault-tolerant website in a VM group with load balancing with 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 configurationManually-
Clone the repository with configuration files.
git clone https://github.com/yandex-cloud-examples/yc-website-high-availability-with-alb.git
-
Go to the directory with the repository. Make sure it contains the following files:
application-load-balancer-website.tf
: New infrastructure configuration.application-load-balancer-website.auto.tfvars
: File with user data.
- Create a directory for configuration files.
- In the directory, create:
-
application-load-balancer-website.tf
configuration file:application-load-balancer-website.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 ] }
-
application-load-balancer-website.auto.tfvars
file with user data:application-load-balancer-website.auto.tfvars
folder_id = "<folder_ID>" vm_user = "<VM_username>" ssh_key_path = "<path_to_public_SSH_key>" domain = "<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
application-load-balancer-website.auto.tfvars
file, set the user-defined parameters:folder_id
: Folder ID.vm_user
: VM username.ssh_key_path
: Path to the file with a public SSH key to authenticate the user on the VM. For more information, see Creating an SSH key pair.domain
: Domain name, e.g.,alb-example.com
.
-
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.
-