Использование Terraform для создания Autoscaling Group (с двумя экземплярами) и Elastic Load Balancer (ELB) в AWS.
Экземпляры работают просто http-echo сервер написан на Go на порт 3000.
Когда DNS-имя Load Balancer посещается через браузер, запрос регистрируется в обоих экземплярах, а не в одном. Ожидаемое поведение должно заключаться в отправке запроса в один из экземпляров.
Журнал Instance1:
2019/01/23 05:03:53 <DNS Name of LB>
10.0.21.217:31904 "GET /favicon.ico HTTP/1.1" 200 58
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/71.0.3578.98 Safari/537.36" 9.018µs
Журнал Instance2:
2019/01/23 05:03:53 <DNS Name of LB>
10.0.21.217:47620 "GET / HTTP/1.1" 200 58
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/71.0.3578.98 Safari/537.36" 9.074µs
Но когда запрос отправляется через curl
на тот же адрес, балансировщик нагрузки работает должным образом и отправляет запрос только одному из экземпляров, а также циклически перебирает экземпляры при повторных запросах. Это желаемое поведение.
Журнал curl
запрос:
2019/01/23 05:43:15 <DNS Name of LB> 10.0.21.217:49364
"GET / HTTP/1.1" 200 58 "curl/7.47.0" 8.397µs
Оба экземпляра «исправны» и отвечают на запросы о работоспособности Load Balancer.
Конфигурация Load Balancer приведена ниже:
resource "aws_elb" "go_app" {
name = "terraform-asg-go-app"
security_groups = ["${aws_security_group.elastic_lb.id}"]
subnets = ["${aws_subnet.public.*.id}"]
listener {
lb_port = 80
lb_protocol = "http"
instance_port = 3000
instance_protocol = "http"
}
cross_zone_load_balancing = true
idle_timeout = 400
connection_draining = true
connection_draining_timeout = 400
}
В группа безопасности балансировщика нагрузки имел следующую конфигурацию:
resource "aws_security_group" "elastic_lb" {
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
В то время группа безопасности экземпляра была такая конфигурация:
resource "aws_security_group" "go_app" {
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 3000
to_port = 3000
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
Это ожидаемое поведение. Посмотрите на пути, которые выбираются в обоих случаях -
Instance1
10.0.21.217:31904 "GET /favicon.ico HTTP/1.1" 200 58
Instance2
10.0.21.217:47620 "GET / HTTP/1.1" 200 58
Второй извлекает саму страницу, а первый запрос извлекает фавикон страницы. Когда вы развертываете веб-приложение, браузер делает отдельный запросы на выборку всех ресурсов, связанных с вашим веб-приложением, одним из которых является значок favicon. Другими активами могут быть файлы css / js, изображения и т. Д. Все указанные ресурсы извлекаются отдельно и затем отображается на странице.
Когда браузер делает несколько запросов, они попадают в балансировщик нагрузки, который затем распределяет запрос между экземплярами, стоящими за ним, как правило, циклически, поэтому вы видите отдельные запросы на двух экземплярах.
curl
с другой стороны, просто получает HTML-страницу и не делает никаких дополнительных запросов.
Еще раз внимательно проверьте опубликованные выше журналы. Ваш Chrome делает два запроса:
GET / HTTP/1.1
GET /favicon.ico HTTP/1.1
И поскольку балансировщик нагрузки выполняет балансировку нагрузки, он отправляет по одному запросу на каждый узел, как и ожидалось.
Стандартное поведение современных настольных браузеров - запрашивать /favicon.ico
со всех веб-сайтов, чтобы они могли отображать значок сайта в закладках, вкладках и т. д. С другой стороны curl
не делает этого, поэтому вы видите только один запрос.
Надеюсь, это поможет :)