Integrating an L7 load balancer with Cloud CDN and Object Storage using Terraform
Note
To implement this solution, you will need a domain. We will use the example.com domain name as an example.
To create an infrastructure to integrate an L7 load balancer with Yandex Cloud CDN and Yandex Object Storage using Terraform:
- Get your cloud ready.
- Deploy the infrastructure for integration of an L7 load balancer with Cloud CDN and Object Storage.
- Test the solution.
If you no longer need the resources you created, delete them.
Get your cloud ready
Sign up for Yandex Cloud and create a billing account:
- Navigate to the management console
and log in to Yandex Cloud or create a new account. - On the Yandex Cloud Billing
page, make sure you have a billing account linked and it has theACTIVEorTRIAL_ACTIVEstatus. If you do not have a billing account, create one and link a cloud to it.
If you have an active billing account, you can navigate to the cloud page
Learn more about clouds and folders here.
Required paid resources
The infrastructure support costs include:
- Fee for data storage in Object Storage, data operations, and outbound traffic (see Object Storage pricing).
- Fee for using the L7 load balancer’s computing resources (see Application Load Balancer pricing).
- A fee for outgoing traffic from CDN servers (see Cloud CDN pricing).
- Fee for public DNS requests and DNS zones if using Yandex Cloud DNS (see Cloud DNS pricing).
Deploying the infrastructure for integration of an L7 load balancer with Cloud CDN and Object Storage
With Terraform
Terraform is distributed under the Business Source License
For more information about the provider resources, see the relevant documentation on the Terraform
To create an infrastructure using Terraform:
-
Install Terraform, get the credentials, and specify the source for installing Yandex Cloud (see Configure your provider, step 1).
-
Set up your infrastructure description files:
Ready-made configurationManually-
Clone the repository with configuration files:
git clone https://github.com/yandex-cloud-examples/cdn-storage-integration-config -
Navigate to the repository directory. It should now contain the following files:
cdn-storage-integration-config.tf: New infrastructure configuration file.cdn-storage-integration.auto.tfvars: File with the values of user-defined variables.index.html: Test file of your service, used to health-check the solution.
-
Create a folder for configuration files. In this folder:
-
Create a file named
index.htmlwith the following contents:<!DOCTYPE html> <html> <head> <title>My service</title> </head> <body> <p>The service is working</p> </body> </html> -
Create a configuration file named
cdn-storage-integration-config.tf:cdn-storage-integration-config.tf
# Declaring variables variable "folder_id" { type = string } variable "domain_name" { type = string } variable "bucket_name" { type = string } variable "index_file_path" { type = string } locals { network_name = "example-network" subneta_name = "example-subnet-ru-central1-a" subnetb_name = "example-subnet-ru-central1-b" subnetd_name = "example-subnet-ru-central1-d" sg_name = "example-sg" object_key = "index.html" domain_zone_name = "my-domain-zone" cert_name = "mymanagedcert" origin_gp_name = "example-origin-group" bg_name = "example-bg" backend_name = "example-backend" router_name = "example-router" vh_name = "example-vh" route_name = "example-route" alb_name = "example-balancer" listener_name = "example-listener" } # Configuring the provider terraform { required_providers { yandex = { source = "yandex-cloud/yandex" } } required_version = ">= 0.13" } provider "yandex" { folder_id = var.folder_id } # Creating a public DNS zone resource "yandex_dns_zone" "my-domain-zone" { name = local.domain_zone_name zone = "${var.domain_name}." public = true } # Adding a Let's Encrypt certificate resource "yandex_cm_certificate" "le-certificate" { name = local.cert_name domains = [var.domain_name] managed { challenge_type = "DNS_CNAME" challenge_count = 1 } } # Creating a CNAME record for domain validation when issuing a certificate resource "yandex_dns_recordset" "validation-record" { count = yandex_cm_certificate.le-certificate.managed[0].challenge_count zone_id = yandex_dns_zone.my-domain-zone.id name = yandex_cm_certificate.le-certificate.challenges[count.index].dns_name type = yandex_cm_certificate.le-certificate.challenges[count.index].dns_type ttl = 600 data = [yandex_cm_certificate.le-certificate.challenges[count.index].dns_value] } # Waiting for domain validation and the issue of a Let's Encrypt certificate data "yandex_cm_certificate" "example-com" { depends_on = [yandex_dns_recordset.validation-record] certificate_id = yandex_cm_certificate.le-certificate.id wait_validation = true } # Creating a network resource "yandex_vpc_network" "my-network" { name = local.network_name } # Creating subnets resource "yandex_vpc_subnet" "my-subnet-a" { name = local.subneta_name zone = "ru-central1-a" network_id = yandex_vpc_network.my-network.id v4_cidr_blocks = ["192.168.1.0/24"] } resource "yandex_vpc_subnet" "my-subnet-b" { name = local.subnetb_name zone = "ru-central1-b" network_id = yandex_vpc_network.my-network.id v4_cidr_blocks = ["192.168.2.0/24"] } resource "yandex_vpc_subnet" "my-subnet-d" { name = local.subnetd_name zone = "ru-central1-d" network_id = yandex_vpc_network.my-network.id v4_cidr_blocks = ["192.168.3.0/24"] } # Creating a security group resource "yandex_vpc_security_group" "my-sg" { name = local.sg_name network_id = yandex_vpc_network.my-network.id ingress { protocol = "TCP" description = "http" v4_cidr_blocks = ["0.0.0.0/0"] port = 80 } ingress { protocol = "TCP" description = "https" v4_cidr_blocks = ["0.0.0.0/0"] port = 443 } ingress { protocol = "TCP" description = "healthchecks" predefined_target = "loadbalancer_healthchecks" port = 30080 } egress { protocol = "ANY" description = "any" v4_cidr_blocks = ["0.0.0.0/0"] from_port = 0 to_port = 65535 } } # Creating a bucket resource "yandex_storage_bucket" "cdn-source-bucket" { bucket = var.bucket_name folder_id = var.folder_id anonymous_access_flags { read = true list = true } } # Uploading the main page of the test service to the bucket resource "yandex_storage_object" "index-object" { bucket = yandex_storage_bucket.cdn-source-bucket.bucket key = local.object_key source = var.index_file_path content_type = "text/html" } # Creating a backend group resource "yandex_alb_backend_group" "test-backend-group" { name = local.bg_name http_backend { name = local.backend_name weight = 100 port = 80 storage_bucket = var.bucket_name } } # Creating an HTTP router resource "yandex_alb_http_router" "my-router" { name = local.router_name } # Creating a virtual host resource "yandex_alb_virtual_host" "my-virtual-host" { name = local.vh_name http_router_id = yandex_alb_http_router.my-router.id route { name = local.route_name http_route { http_match { http_method = ["GET"] path { prefix = "/" } } http_route_action { backend_group_id = yandex_alb_backend_group.test-backend-group.id } } } authority = [var.domain_name] } # Creating an L7 load balancer resource "yandex_alb_load_balancer" "my-balancer" { name = local.alb_name network_id = yandex_vpc_network.my-network.id security_group_ids = [yandex_vpc_security_group.my-sg.id] allocation_policy { location { zone_id = "ru-central1-a" subnet_id = yandex_vpc_subnet.my-subnet-a.id } location { zone_id = "ru-central1-b" subnet_id = yandex_vpc_subnet.my-subnet-b.id } location { zone_id = "ru-central1-d" subnet_id = yandex_vpc_subnet.my-subnet-d.id } } listener { name = local.listener_name endpoint { address { external_ipv4_address { } } ports = [80] } http { handler { http_router_id = yandex_alb_http_router.my-router.id } } } } # Creating a CDN origin group resource "yandex_cdn_origin_group" "my-origin-group" { name = local.origin_gp_name origin { source = yandex_alb_load_balancer.my-balancer.listener[0].endpoint[0].address[0].external_ipv4_address[0].address } } # Creating a CDN resource resource "yandex_cdn_resource" "my-resource" { cname = var.domain_name active = true origin_protocol = "http" origin_group_id = yandex_cdn_origin_group.my-origin-group.id ssl_certificate { type = "certificate_manager" certificate_manager_id = data.yandex_cm_certificate.example-com.id } options { redirect_http_to_https = true forward_host_header = true } } # Creating a CNAME record for the CDN resource resource "yandex_dns_recordset" "cdn-cname" { zone_id = yandex_dns_zone.my-domain-zone.id name = "${var.domain_name}." type = "CNAME" ttl = 600 data = [yandex_cdn_resource.my-resource.provider_cname] } -
Create a file with user data named
cdn-storage-integration.auto.tfvars:cdn-storage-integration.auto.tfvars
folder_id = "<folder_ID>" bucket_name = "<bucket_name>" domain_name = "<domain_name>" index_file_path = "<local_filepath_to_index.html>"
-
Learn more about the properties of Terraform resources in the relevant provider guides:
- Network: yandex_vpc_network.
- Subnet: yandex_vpc_subnet.
- Security group: yandex_vpc_security_group.
- DNS zone: yandex_dns_zone.
- DNS resource record: yandex_dns_recordset.
- TLS certificate: yandex_cm_certificate.
- Bucket: yandex_storage_bucket.
- Object: yandex_storage_object.
- Origin group: yandex_cdn_origin_group.
- CDN resource: yandex_cdn_resource.
- Backend group: yandex_alb_backend_group.
- HTTP router: yandex_alb_http_router.
- Virtual host: yandex_alb_virtual_host.
- L7 load balancer: yandex_alb_load_balancer.
-
-
In the
cdn-storage-integration.auto.tfvarsfile, set the values of the user-defined variables:-
folder_id: Folder ID. -
bucket_name: Bucket name consistent with the naming conventions. -
domain_name: Name of the domain to host the test service.To use domain names in the public DNS zone, you need to delegate it to authoritative name servers. Specify the addresses of the
ns1.yandexcloud.netandns2.yandexcloud.netservers in your account on your domain name registrar's website. -
index_file_path: Local path to theindex.htmlfile that contains your test service contents, e.g.,/Users/MyUser/Repos/cdn-storage-integration/index.html.
-
-
Create the resources:
-
In the terminal, go to the directory where you edited the configuration file.
-
Make sure the configuration file is correct using this command:
terraform validateIf the configuration is correct, you will get this message:
Success! The configuration is valid. -
Run this command:
terraform planYou will see a detailed list of resources. No changes will be made at this step. If the configuration contains any errors, Terraform will show them.
-
Apply the changes:
terraform apply -
Type
yesand press Enter to confirm the changes.
-
This will create and configure all the required infrastructure in the folder you selected.
Test the solution
To test the service, open https://example.com/index.html in your browser (with your domain name in place of example.com). If everything is configured correctly, you should see a page with the following content:
<!DOCTYPE html>
<html>
<head>
<title>My service</title>
</head>
<body>
<p>The service is working</p>
</body>
</html>
How to delete the resources you created
Warning
Before deleting the infrastructure, delete all objects in the created bucket.
To stop paying for the resources you created:
-
Open the
cdn-storage-integration-config.tffile and delete your infrastructure description from it. -
Apply the changes:
-
In the terminal, go to the directory where you edited the configuration file.
-
Make sure the configuration file is correct using this command:
terraform validateIf the configuration is correct, you will get this message:
Success! The configuration is valid. -
Run this command:
terraform planYou will see a detailed list of resources. No changes will be made at this step. If the configuration contains any errors, Terraform will show them.
-
Apply the changes:
terraform apply -
Type
yesand press Enter to confirm the changes.
-