Setting Up Load Balancers Using Terraform

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
传统型负载均衡 CLB,每月750个小时 15LCU
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
简介: In this tutorial, we will learn how to set up Bolt on Alibaba Cloud ECS using Terraform load balancers and ApsaraDB for RDS.

By Alberto Roura, Alibaba Cloud Tech Share Author

In this tutorial, I will show you how to set up a CMS, in this case Bolt, on Alibaba Cloud using a Load Balancer and RDS with 3 ECS instances attached. We will be doing this based on a DevOps approach using Terraform and the official Alibaba Cloud (Alicloud) provider.

If you heard of the term "Load Balancer" but don't have a clear idea of the concept, sit tight, as I'm going to develop (pun intended) it a bit more.

What is Load Balancing?

Load balancing is a means to distribute workload across different resources. Let's say you own a very busy website; having a single server dealing with all queries will overload it. Instead, you can have an additional server to help cope with the requests.

The most common approach is to clone the web hosting server and put it behind a load balancer. The load balancer is just another server that distributes the load, sending the request from visitor to one server or another. Using load balancers also increases redundancy, so it's also handy to keep the data safe.

How Does a Load Balancer Distribute Load?

There are different scheduling methods to do it, and the most popular is Round Robin (RR), as it is very simple and effective. Another way to do it is using a similar approach called Weighted Round Robin (WRR), which is a fine-tuned version of RR.

Round-Robin Balancing (RR)

You might have heard the term Round Robin from sporting events, such as soccer tournaments. This technique name comes the original term meaning "signing petitions in circular order so that the leaders could not be identified". This leads to the current meaning in computing terms, where the load balancer rotates the attached servers, one at a time.

The biggest advantage is its simplicity. Load is also distributed evenly across all servers in a network. RR has one bad downside, however, as this algorithm doesn't care how different are servers between them and their capacity. That's why there is another version of this called Weighted Round-Robin.

Weighted Round-Robin (WRR)

This algorithm is based in the standard Round-Robin but with the difference of "having in mind" how different the resources are. In WRR, the resources are given priorities (weight) in the queue based on the capacity. For example, a 100GB server would be given a larger weight over a 20GB server. This approach gives the network admin more control in which servers should be used first and which ones later. WRR is better than RR for complex networks, such as in a hybrid cloud environment.

Weighted Least-Connections (WLC)

Similar to WRR, WLC is an approach that assigns different weights to the servers in a network. But unlike RR and WRR, WLC is dynamic. This scheduling algorithm sends the requests to the server with least active connections in a weighted resource list. This is handy when, apart from assigning a performance weight to each server, you want to control how busy, network-wise, a resource can get. The downside of this approach is that it requires more computations for it to work effectively.

Setting Up Terraform

With the Alibaba Cloud (Alicloud) official terraform provider we can choose between Weighted Round-Robin (WRR) and Weighted Least-Connections (WLC). It is completely up to you which one you use. In the example I provide, I have used WRR, but with no specific reasons.

Install Terraform

Terraform is very easy to install using Homebrew. If you do not have Homebrew already installed on your computer, please find install instructions here.

Run brew install terrafrom the below command in your terminal to install Terraform.

To verify Terraform installation type terraform version.

Install Alibaba Cloud Official provider

As Hashicorp is not actively updating the provider for us, Alibaba Cloud has a really good and active developed GitHub repository of its official provider, which is the one you should get and install. Go to the releases tab and get the latest one for your platform.

After downloading it, you should place the binary file in the plugins folder of terraform. On Windows, in the terraform.d/plugins beneath your user's "Application Data" directory. On all other systems, as Linux or Mac, in ~/.terraform.d/plugins in your user's home directory. Its also a good practice to version the binary, so you should rename it to terraform-provider-alicloud_v1.8.2, given that the version you downloaded is the 1.8.2, you should change that depending in which one you get.

Get Alibaba Cloud Access Keys

Once you log into your Alibaba Cloud console, go to the top Menu and click “accesskeys” located directly under your email address.

1

Once in the keys screen, copy the Access Key ID and the Access Key Secret into a safe place. To show the Secret Key to need to click on “Show“. Be careful where you save this data, as it is very sensitive. Also you should consider creating more limited keys using their policies.

Prepare the Terraform File

For this example, we will put all the config in one single file, but you are recommended to separate the different parts of the config in their own .tf files. This is a good practice that improves the maintainability and readability over time.

Having that clear, lets create a folder, and inside that folder a file called main.tf that we will edit in the next step.

main.tf

provider "alicloud" {
  access_key = "KEY"
  secret_key = "SECRET"
  region = "ap-southeast-2"
}

variable "vswitch" {
  type = "string"
  default = "vsw-xxxxxxxxx"
}

variable "sgroups" {
  type = "list"
  default = [
    "sg-xxxxxxxxxxx"
  ]
}

variable "app_name" {
  type = "string"
  default = "my_app"
}

variable "ecs_password" {
  type = "string"
  default = "Test1234!"
}

resource "alicloud_db_instance" "default" {
  engine = "MySQL"
  engine_version = "5.6"
  instance_type = "rds.mysql.t1.small"
  instance_storage = 5
  vswitch_id = "${var.vswitch}"
  security_ips = [
    "0.0.0.0/0"
  ]
}

resource "alicloud_db_database" "default" {
  instance_id = "${alicloud_db_instance.default.id}"
  name = "bolt_site"
  character_set = "utf8"
}

resource "alicloud_db_account" "default" {
  instance_id = "${alicloud_db_instance.default.id}"
  name = "bolt_user"
  password = "boltdb1234"
}

resource "alicloud_db_account_privilege" "default" {
  instance_id = "${alicloud_db_instance.default.id}"
  account_name = "${alicloud_db_account.default.name}"
  privilege = "ReadWrite"
  db_names = [
    "${alicloud_db_database.default.name}"
  ]
}

resource "alicloud_db_connection" "default" {
  instance_id = "${alicloud_db_instance.default.id}"
  connection_prefix = "bolt-app"
  port = "3306"
}

data "template_file" "user_data" {
  template = "${file("user-data.sh")}"
}

data "alicloud_images" "default" {
  name_regex = "^ubuntu_16.*_64"
}

data "alicloud_instance_types" "default" {
  instance_type_family = "ecs.xn4"
  cpu_core_count = 1
  memory_size = 1
}

resource "alicloud_instance" "app" {
  count = 3
  instance_name = "${var.app_name}-${count.index}"
  image_id = "${data.alicloud_images.default.images.0.image_id}"
  instance_type = "${data.alicloud_instance_types.default.instance_types.0.id}"

  vswitch_id = "${var.vswitch}"
  security_groups = "${var.sgroups}"
  internet_max_bandwidth_out = 100

  password = "${var.ecs_password}"

  user_data = "${data.template_file.user_data.template}"
}

resource "alicloud_slb" "default" {
  name = "${var.app_name}-slb"
  vswitch_id = "${var.vswitch}"
  internet = true
}

resource "alicloud_slb_listener" "http" {
  load_balancer_id = "${alicloud_slb.default.id}"
  backend_port = 80
  frontend_port = 80
  health_check_connect_port = 80
  bandwidth = -1
  protocol = "http"
  sticky_session = "on"
  sticky_session_type = "insert"
  cookie = "testslblistenercookie"
  cookie_timeout = 86400
}

resource "alicloud_slb_attachment" "default" {
  load_balancer_id = "${alicloud_slb.default.id}"
  instance_ids = [
    "${alicloud_instance.app.*.id}",
  ]
}

output "app_id" {
  value = "${alicloud_instance.app.*.public_ip}"
}


output "slb_ip" {
  value = "${alicloud_slb.default.address}"
}

output "rds_host" {
  value = "${alicloud_db_instance.default.connection_string}"
}

user-data.sh

In this example, we are going to rely in the cloud-init program that comes bundled in Ubuntu and runs whatever script to pass at the moment of resource creation. In this case, the script is going to install the needed software packages tu run Docker containers and to connect the app to the proper database. The file user-data.sh needs to be in the same path next to our main.tf. Be aware of the MYSQL_HOST variable, you'll need to adjust that to fit your database instance internet host.

#!/bin/bash -v

export MYSQL_HOST=bolt-app.mysql.australia.rds.aliyuncs.com

apt-get update && apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
apt-get update && apt-get install -y docker-ce docker-compose
curl -L https://github.com/docker/compose/releases/download/1.20.1/docker-compose-`uname -s`-`uname -m` -o /usr/bin/docker-compose

cd ~/
curl https://raw.githubusercontent.com/roura356a/bolt/master/with-mysql/docker-compose.yml -o docker-compose.yml
sed -i "s/=db/=$MYSQL_HOST/g" docker-compose.yml

docker-compose up -d    

Launch Terraform

terraform init

We are ready to take off! Type the init command for Terraform to get the project ready to apply.

terraform init

terraform plan

In order to verify that everything is fine, it is good practice to run the plan command, so you can get an overview of the job without actually applying it.

terraform plan

terraform apply

Seatbelts on. We are now deploying our machine! Run the apply command and wait until it finishes. It will take about 3 to 5 minutes depending on the Internet connection and the conditions of the datacenter you are connecting to.

terraform apply

After the job finishes, you will get a message in the terminal confirming the IP address of your new ECS instances, RDS host and Load Balancer IP:

Apply complete! Resources: 11 added, 0 changed, 0 destroyed.

Outputs:

app_id = [
    xx.xx.xx.xx,
    xx.xx.xx.xx,
    xx.xx.xx.xx
]
rds_host = rm-xxxxxxxxxxx.mysql.australia.rds.aliyuncs.com
slb_ip = xx.xx.xx.xxx

If the security group you selected has the port 80 opened, you can now type the IP of the balancer in your browser and see how Bolt web-based installation comes up to customize your new website.

Conclusion

You have now successfully set up Bolt on Alibaba Cloud ECS using Load Balancers and RDS. Go and do something fun with them! Because this is a fresh Bolt installation, you'll need to manually visit one of the instances (not the slb) and create the first user, so this way the health check will pass in the 3 backend servers. After that, visiting the SLB IP directly or thought a domain should be enough to make it work.

Enjoy you newly-created SLB-backed Bolt web application!

相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
2月前
|
数据中心
【Azure Service Bus】创建 ServiceBus 的Terraform脚本报错GetAuthorizationRule: Invalid input
为了最佳的体验,需要确保使用最新 Terraform azurerm 组件!
|
3月前
|
C++ Windows
vs2019 This application failed to start because it could not find or load the QT platform plugin
这篇文章介绍了在VS2019中解决QT程序运行时出现的“无法找到或加载QT平台插件”错误的步骤,通过将必要的DLL文件和插件目录复制到项目解决方案中解决了问题。
|
3月前
ESLint—— Failed to load config "standard" to extend from
ESLint—— Failed to load config "standard" to extend from
78 0
|
JSON 监控 数据格式
Grafana导入 json 文件的 dashboard 错误 Templating Failed to upgrade legacy queries Datasource xxx not found
Grafana导入 json 文件的 dashboard 错误 Templating Failed to upgrade legacy queries Datasource xxx not found
405 0
|
安全 Python
YAML+PyYAML笔记 8 | PyYAML源码之full_load(),full_load_all(),safe_load(),unsafe_load(),unsafe_load_all()
YAML+PyYAML笔记 8 | PyYAML源码之full_load(),full_load_all(),safe_load(),unsafe_load(),unsafe_load_all()
130 1
|
6月前
|
JavaScript 前端开发
ESLint—— Failed to load config “standard“ to extend from
ESLint—— Failed to load config “standard“ to extend from
186 0
|
6月前
error: no configuration has been provided, try setting KUBERNETES_MASTER environment variable
error: no configuration has been provided, try setting KUBERNETES_MASTER environment variable
133 0
|
6月前
|
Kubernetes 容器
k8s-error execution phase upload-config/kubelet: Error writing Crisocket...
k8s-error execution phase upload-config/kubelet: Error writing Crisocket...
188 0
|
C++ iOS开发
报错解决:Could not build wheels for soxr, which is required to install pyproject.toml-based projects(可用)
链接如下:【金山文档】 1-Microsoft Visual C++ Build Tools。找了好久,才找到正确的解决方案,网上一大堆升级setuptools的方法只对少数人管用。注意,虽然我的这个报错内容有点长,但是我感觉和其它的。如果网页提示登录,可以不用登录,直接下载即可。然后打开镜像ios文件(双击即可)错误是一样的解决方案。文件,打开后安装即可。
2670 1
报错解决:Could not build wheels for soxr, which is required to install pyproject.toml-based projects(可用)
|
Android开发
【错误记录】Gradle 配置 productFlavors 报错 ( All flavors must now belong to a named flavor dimension. )
【错误记录】Gradle 配置 productFlavors 报错 ( All flavors must now belong to a named flavor dimension. )
407 0