[Yandex Cloud documentation](../../../index.md) > [Yandex Network Load Balancer](../../index.md) > [Tutorials](../index.md) > [Fault-tolerant website with load balancing via a Network Load Balancer](index.md) > Terraform

# Fault-tolerant website with load balancing via Yandex Network Load Balancer using Terraform


To create a [fault-tolerant website with load balancing via Yandex Network Load Balancer](index.md) using Terraform:

1. [Get your cloud ready](#before-you-begin).
1. [Create your infrastructure](#deploy).
1. [Upload the website files](#upload-files).
1. [Test the fault tolerance](#test).

If you no longer need the resources you created, [delete them](#clear-out).

## Get your cloud ready {#before-you-begin}

Sign up for Yandex Cloud and create a [billing account](../../../billing/concepts/billing-account.md):
1. Navigate to the [management console](https://console.yandex.cloud) and log in to Yandex Cloud or create a new account.
1. On the **[Yandex Cloud Billing](https://center.yandex.cloud/billing/accounts)** page, make sure you have a billing account linked and it has the `ACTIVE` or `TRIAL_ACTIVE` [status](../../../billing/concepts/billing-account-statuses.md). If you do not have a billing account, [create one](../../../billing/quickstart/index.md) and [link](../../../billing/operations/pin-cloud.md) a cloud to it.

If you have an active billing account, you can create or select a [folder](../../../resource-manager/concepts/resources-hierarchy.md#folder) for your infrastructure on the [cloud page](https://console.yandex.cloud/cloud).

[Learn more about clouds and folders here](../../../resource-manager/concepts/resources-hierarchy.md).


### Required paid resources {#paid-resources}

The website support cost includes:

* Fee for [disks](../../../compute/concepts/disk.md) and continuously running [VMs](../../../compute/concepts/vm.md) (see [Yandex Compute Cloud pricing](../../../compute/pricing.md)).
* Fee for using dynamic or static [public IP addresses](../../../vpc/concepts/address.md#public-addresses) (see [Yandex Virtual Private Cloud pricing](../../../vpc/pricing.md)).
* Fee for a [network load balancer](../../concepts/index.md) and traffic balancing (see [Network Load Balancer pricing](../../pricing.md)).


## Create your infrastructure {#deploy}

With [Terraform](https://www.terraform.io/), you can quickly create a cloud infrastructure in Yandex Cloud and manage it using configuration files. These files store the infrastructure description written in HashiCorp Configuration Language (HCL). If you change the configuration files, Terraform automatically detects which part of your configuration is already deployed, and what should be added or removed.

Terraform is distributed under the [Business Source License](https://github.com/hashicorp/terraform/blob/main/LICENSE). The [Yandex Cloud provider for Terraform](https://github.com/yandex-cloud/terraform-provider-yandex) is distributed under the [MPL-2.0](https://www.mozilla.org/en-US/MPL/2.0/) license.

For more information about the provider resources, see the guides on the [Terraform](https://www.terraform.io/docs/providers/yandex/index.html) website or [its mirror](../../../terraform/index.md).

To create an infrastructure using Terraform:

1. [Install Terraform](../../../tutorials/infrastructure-management/terraform-quickstart.md#install-terraform), [get the credentials](../../../tutorials/infrastructure-management/terraform-quickstart.md#get-credentials), and specify the source for installing the Yandex Cloud provider (see [Configure your provider](../../../tutorials/infrastructure-management/terraform-quickstart.md#configure-provider), Step 1).
1. Set up your infrastructure description files:

    {% list tabs group=infrastructure_description %}

    - Ready-made configuration {#ready}

      1. Clone the repository with configuration files:

         ```bash
         git clone https://github.com/yandex-cloud-examples/yc-nlb-fault-tolerant-site.git
         ```

      1. Navigate to the repository directory. Make sure it now contains the `load-balancer.tf` file with the new infrastructure configuration.

    - Manually {#manual}

      1. Create a directory.
      1. In this directory, create the `load-balancer.tf` configuration file:

          {% cut "load-balancer.tf" %}

          ```hcl
          terraform {
            required_providers {
              yandex = {
                source  = "yandex-cloud/yandex"
                version = ">= 0.47.0"
              }
            }
          }
          
          provider "yandex" {
            zone = "ru-central1-a"
          }
          
          variable "folder_id" {
            description = "Yandex Cloud Folder ID where resources will be created"
            default     = "<folder_ID>"
          }
          
          resource "yandex_iam_service_account" "ig-sa" {
            name        = "ig-sa"
          }
          
          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_compute_instance_group" "ig-1" {
            name               = "nlb-vm-group"
            folder_id          = var.folder_id
            service_account_id = "${yandex_iam_service_account.ig-sa.id}"
            instance_template {
              platform_id = "standard-v3"
              resources {
                core_fraction = 20
                memory        = 1
                cores         = 2
              }
          
              boot_disk {
                mode = "READ_WRITE"
                initialize_params {
                  image_id = "<image_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}" ]
                nat        = true
              }
          
              metadata = {
                user-data = "#cloud-config\nusers:\n  - name: <username>\n    groups: sudo\n    shell: /bin/bash\n    sudo: 'ALL=(ALL) NOPASSWD:ALL'\n    ssh_authorized_keys:\n      - ${file("<path_to_public_SSH_key>")}"
              }
            }
          
            scale_policy {
              fixed_scale {
                size = 2
              }
            }
          
            allocation_policy {
              zones = ["ru-central1-a", "ru-central1-b"]
            }
          
            deploy_policy {
              max_unavailable = 1
              max_expansion   = 0
            }
          
            load_balancer {
              target_group_name = "nlb-tg"
            }
          }
          
          resource "yandex_lb_network_load_balancer" "foo" {
            name = "nlb-1"
            listener {
              name = "nlb-listener"
              port = 80
            }
            attached_target_group {
              target_group_id = "${yandex_compute_instance_group.ig-1.load_balancer.0.target_group_id}"
              healthcheck {
                name                = "health-check-1"
                unhealthy_threshold = 5
                healthy_threshold   = 5
                http_options {
                  port = 80
                }
              }
            }
          }
          
          resource "yandex_vpc_network" "network-1" {
            name = "network1"
          }
          
          resource "yandex_vpc_subnet" "subnet-1" {
            name           = "subnet1"
            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           = "subnet2"
            zone           = "ru-central1-b"
            network_id     = "${yandex_vpc_network.network-1.id}"
            v4_cidr_blocks = ["192.168.2.0/24"]
          }
          ```

          {% endcut %}

    {% endlist %}

    Learn more about the properties of Terraform resources in the relevant provider guides:

    * [Service account](../../../iam/concepts/users/service-accounts.md): [yandex_iam_service_account](../../../terraform/resources/iam_service_account.md).
    * [Role](../../../iam/concepts/access-control/roles.md): [yandex_resourcemanager_folder_iam_member](../../../terraform/resources/resourcemanager_folder_iam_member.md).
    * [Instance group](../../../compute/concepts/instance-groups/index.md): [yandex_compute_instance_group](../../../terraform/resources/compute_instance_group.md).
    * [Network load balancer](../../concepts/index.md): [yandex_lb_network_load_balancer](../../../terraform/resources/lb_network_load_balancer.md).
    * [Network](../../../vpc/concepts/network.md#network): [yandex_vpc_network](../../../terraform/resources/vpc_network.md).
    * [Subnets](../../../vpc/concepts/network.md#subnet): [yandex_vpc_subnet](../../../terraform/resources/vpc_subnet.md).


1. Under `variable`, specify `folder_id`, i.e., the ID of the folder for your resources.
1. Under `metadata`, specify the [metadata](../../../compute/concepts/vm-metadata.md) for creating a VM and the SSH key contents. Use this format for the key: `<any_name>:<SSH_key_contents>`. Regardless of the username you enter, the key is always assigned to the user set in the LAMP (LEMP) image configuration. Such users differ depending on the image. To learn more, see [Keys processed in public images Yandex Cloud](../../../compute/concepts/metadata/public-image-keys.md).

    You need to [create](../../../compute/operations/vm-connect/ssh.md) an SSH key pair on your own.

1. Under `boot_disk`, specify the ID of a VM [image](../../../compute/operations/images-with-pre-installed-software/get-list.md) with relevant components:

    * [LAMP](https://yandex.cloud/en/marketplace/products/yc/lamp) (Linux, Apache, MySQL®, PHP).
    * [LEMP](https://yandex.cloud/en/marketplace/products/yc/lemp) (Linux, Nginx, MySQL®, PHP).

1. Create the resources:

    1. In the terminal, navigate to the configuration file directory.
    1. Make sure the configuration is correct using this command:
    
       ```bash
       terraform validate
       ```
    
       If the configuration is valid, you will get this message:
    
       ```bash
       Success! The configuration is valid.
       ```
    
    1. Run this command:
    
       ```bash
       terraform plan
       ```
    
       You will see a list of resources and their properties. No changes will be made at this step. Terraform will show any errors in the configuration.
    1. Apply the configuration changes:
    
       ```bash
       terraform apply
       ```
    
    1. Type `yes` and press **Enter** to confirm the changes.

After creating the infrastructure, [upload the website files](#upload-files).


## Upload the website files {#upload-files}

To test the web server, upload the website files to each VM. You can use the `index.html` file from [this archive](https://storage.yandexcloud.net/doc-files/index.html.zip) as an example.

For each VM in the created group, do the following:

1. [Get](../../../compute/operations/vm-info/get-info.md) the VM public IP address.
1. [Connect](../../../compute/operations/vm-connect/ssh.md) to the VM via SSH.
1. Grant your user write permissions for the `/var/www/html` directory:

    ```bash
    sudo chown -R "$USER":www-data /var/www/html
    ```

1. Upload the website files to the VM via [SCP](https://en.wikipedia.org/wiki/Secure_copy_protocol).

    {% list tabs group=operating_system %}

    - Linux/macOS {#linux-macos}

      Use the `scp` command line utility:

      ```bash
      scp -r <path_to_directory_with_files> <VM_user_name>@<VM_IP_address>:/var/www/html
      ```

    - Windows {#windows}

      Use [WinSCP](https://winscp.net/eng/download.php) to copy the local file directory to `/var/www/html` on the VM.

    {% endlist %}

Once you upload all files, [test the fault tolerance](#test).


## Test the fault tolerance {#test}

1. [Get](../../../compute/operations/vm-info/get-info.md) the public IP address of any VM from the group you created.
1. [Connect](../../../compute/operations/vm-connect/ssh.md) to the VM via SSH.
1. Stop the web service to simulate a failure on the web server:

    {% list tabs %}

    - LAMP

      ```bash
      sudo service apache2 stop
      ```

    - LEMP

      ```bash
      sudo service nginx stop
      ```

    {% endlist %}

1. [Get](../../../compute/operations/vm-info/get-info.md) the listener IP address.
1. Open the website in the browser using the listener address.

    The connection should be successful, even though one of the web servers has failed.

1. When the check is complete, start the web service again:

    {% list tabs %}

    - LAMP

        ```bash
        sudo service apache2 start
        ```

    - LEMP

        ```bash
        sudo service nginx start
        ```

    {% endlist %}


## How to delete the resources you created {#clear-out}

To shut down the website and stop paying for the resources you created:

1. Open the `load-balancer.tf` configuration file and delete your infrastructure description from it.
1. Apply the changes:

    1. In the terminal, navigate to the configuration file directory.
    1. Make sure the configuration is correct using this command:
    
       ```bash
       terraform validate
       ```
    
       If the configuration is valid, you will get this message:
    
       ```bash
       Success! The configuration is valid.
       ```
    
    1. Run this command:
    
       ```bash
       terraform plan
       ```
    
       You will see a list of resources and their properties. No changes will be made at this step. Terraform will show any errors in the configuration.
    1. Apply the configuration changes:
    
       ```bash
       terraform apply
       ```
    
    1. Type `yes` and press **Enter** to confirm the changes.

#### See also {#see-also}

* [Fault-tolerant website with load balancing via Yandex Network Load Balancer using the management console](console.md)