
Работа с AWS NLB и Terraform в Unix/Linux
Network Load Balancer (NLB) работает на уровне подключения (уровень 4), он маршрутизирует подключения к целевым объектам – инстансам Amazon EC2, контейнерам и IP-адресам – на основе данных IP-протокола. Network Load Balancer идеально подходит для балансировки нагрузки трафика TCP, он способен обрабатывать миллионы запросов в секунду при обеспечении сверхнизких задержек. Network Load Balancer оптимизирован для обработки резких и внезапных изменений трафика, при этом на каждую зону доступности используется один статический IP-адрес. Сервис интегрирован с другими востребованными сервисами AWS, такими как Auto Scaling, Amazon EC2 Container Service (ECS) и Amazon CloudFormation.
Балансировка нагрузки на основе подключений
Можно балансировать нагрузку трафика TCP путем маршрутизации подключений к целевым объектам – инстансам Amazon EC2, микросервисам и контейнерам, а также IP-адресам.
Высокая доступность
Network Load Balancer обеспечивает высокую доступность. Он принимает входящий трафик от клиентов и распределяет этот трафик по целевым объектам в пределах одной и той же зоны доступности. Балансировщик нагрузки также контролирует работоспособность своих зарегистрированных целевых объектов и гарантирует, что он направляет трафик только на работоспособные целевые объекты. Когда балансировщик нагрузки обнаруживает неработоспособный целевой объект, он прекращает маршрутизацию на этот целевой объект и перенаправляет трафик на оставшиеся работоспособные целевые объекты. Если в зоне доступности нет ни одного работоспособного целевого объекта, но при этом есть целевые объекты в других зонах доступности, Network Load Balancer выполнит автоматическую обработку отказа и перенаправит трафик на работоспособные целевые объекты в других зонах доступности.
Высокая пропускная способность
Network Load Balancer предназначен для обработки трафика по мере его роста и может балансировать нагрузку объемом в миллионы запросов в секунду. Он также способен обрабатывать резко и внезапно меняющийся трафик.
Низкая задержка
Network Load Balancer обеспечивает чрезвычайно низкую задержку и хорошо подходит для приложений, чувствительных к задержкам.
Сохранение IP-адреса источника
Network Load Balancer сохраняет IP-адрес источника на стороне клиента, позволяя серверу видеть IP-адрес клиента. Этот IP-адрес может затем использоваться приложениями для дальнейшей обработки.
Поддержка статического IP-адреса
Network Load Balancer автоматически предоставляет статический IP-адрес для зоны доступности (подсети), который может использоваться приложениями в качестве IP-адреса внешнего интерфейса балансировщика нагрузки.
Поддержка эластичных IP-адресов
Network Load Balancer также позволяет назначать эластичный IP-адрес для зоны доступности (подсети), тем самым предоставляя клиенту собственный фиксированный IP-адрес.
Проверки работоспособности
Network Load Balancer поддерживает проверку работоспособности целевых объектов как для сети, так и для приложений. Работоспособность на уровне сети определяется по общей реакции целевого объекта на обычный трафик. Если целевой объект не реагирует на новые соединения или реагирует слишком медленно, балансировщик нагрузки помечает целевой объект как недоступный. Проверки работоспособности на уровне приложений также могут использоваться для получения более подробной информации. Периодически опрашивая определенный URL-адрес данного целевого объекта, можно сделать обобщенный вывод о фактической работоспособности приложения. Быстрая диагностика и высокоэффективная отладка обеспечиваются полностью наглядным представлением проверок работоспособности. Причины выявленной в результате проверок неработоспособности также доступны как «коды причин» в API Network Load Balancer и через метрики Amazon CloudWatch, связанные с проверками работоспособности целевых объектов.
Обработка отказа DNS
Если в Network Load Balancer не зарегистрированы работоспособные целевые объекты или если узлы Network Load Balancer в данной зоне неработоспособны, Amazon Route 53 будет направлять трафик на узлы балансировки нагрузки в других зонах доступности.
Интеграция с Amazon Route 53
В случае отказа Network Load Balancer интеграция с Route 53 обеспечит удаление недоступных IP-адресов балансировщика нагрузки и перенаправит запросы на альтернативный балансировщик нагрузки в другом регионе.
Интеграция с сервисами AWS
Network Load Balancer интегрирован с другими сервисами AWS, такими как Auto Scaling, Amazon EC2 Container Service (ECS), AWS CloudFormation, AWS CodeDeploy и AWS Config.
Долговременные TCP-подключения
Network Load Balancer поддерживает долговременные TCP-подключения, которые идеально подходят для приложений типа WebSocket.
Централизованная поддержка API
Network Load Balancer использует тот же API, что и Application Load Balancer. Это позволяет работать с целевыми группами, проверками работоспособности и балансировать нагрузку между несколькими портами в одном инстансе Amazon EC2 для поддержки контейнерных приложений.
Надежный мониторинг и проверка
Amazon CloudWatch предоставляет метрики Network Load Balancer. CloudWatch предоставляет такие метрики, как Active Flow Count, Healthy Host Count, New Flow Count, Processed Bytes и многие другие. Network Load Balancer интегрирован с AWS CloudTrail. CloudTrail отслеживает вызовы API к Network Load Balancer.
Расширенное ведение журнала
Можно использовать возможность Flow Logs для записи всех запросов, отправленных на балансировщик нагрузки. Flow Logs регистрирует информацию об IP-трафике, поступающем на сетевые интерфейсы в VPC и из них. Данные журнала потока сохраняются с помощью Amazon CloudWatch Logs.
Изолирование по зонам
Network Load Balancer предназначен для приложений с архитектурой, размещенной в одной зоне. Если в зоне доступности что-то выходит из строя, происходит автоматическая обработка отказа и переход в другие работоспособные зоны доступности. Хотя мы рекомендуем клиентам для достижения высокой доступности настраивать балансировщик нагрузки и целевые объекты в нескольких зонах доступности, Network Load Balancer можно использовать в одной зоне доступности для поддержки архитектур, требующих изолированной работы в зоне.
Балансировка нагрузки с использованием IP-адресов как целевых объектов
Применять балансировку нагрузки можно для любого приложения, размещенного в AWS или локально, если использовать в качестве целей IP-адреса серверной части приложения. Это позволяет обеспечить балансировку нагрузки на сервер приложения, размещенный на любом IP-адресе и в любом интерфейсе инстанса. Каждое приложение, размещенное на том же инстансе, может относиться к своей группе безопасности и использовать один и тот же порт. Можно также использовать IP-адреса в качестве целей для балансировки нагрузки на приложения, размещенные локально (через подключение с помощью Direct Connect) и на инстансах EC2-Classic (с использованием ClassicLink). Возможность балансировки нагрузки между AWS и локальными ресурсами упрощает миграцию в облако, расширение ресурсов в облако или использование облака для обеспечения отказоустойчивости.
Установка terraform в Unix/Linux
Установка крайне примитивная и я описал как это можно сделать тут:
Установка terraform в Unix/Linux
Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!
Чтобы получить помощь по использованию команд, выполните:
$ terraform Usage: terraform [--version] [--help] <command> [args] The available commands for execution are listed below. The most common, useful commands are shown first, followed by less common or more advanced commands. If you're just getting started with Terraform, stick with the common commands. For the other commands, please read the help and docs before usage. Common commands: apply Builds or changes infrastructure console Interactive console for Terraform interpolations destroy Destroy Terraform-managed infrastructure env Workspace management fmt Rewrites config files to canonical format get Download and install modules for the configuration graph Create a visual graph of Terraform resources import Import existing infrastructure into Terraform init Initialize a Terraform working directory output Read an output from a state file plan Generate and show an execution plan providers Prints a tree of the providers used in the configuration push Upload this Terraform module to Atlas to run refresh Update local state file against real resources show Inspect Terraform state or plan taint Manually mark a resource for recreation untaint Manually unmark a resource as tainted validate Validates the Terraform files version Prints the Terraform version workspace Workspace management All other commands: debug Debug output management (experimental) force-unlock Manually unlock the terraform state state Advanced state management
Приступим к использованию!
Работа с AWS NLB и Terraform в Unix/Linux
У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:
$ mkdir examples modules
В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.
Начнем писать модуль, но для этой задачи, я создам папку:
$ mkdir modules/nlb
Переходим в нее:
$ cd modules/nlb
Открываем файл:
$ vim nlb.tf
В данный файл, вставляем:
#--------------------------------------------------- # Create AWS NLB #--------------------------------------------------- resource "aws_lb" "lb" { #name_prefix = "${var.name_prefix}-" name = "${lower(var.name)}-nlb-${lower(var.environment)}" subnets = ["${var.subnets}"] internal = "${var.lb_internal}" enable_deletion_protection = "${var.enable_deletion_protection}" load_balancer_type = "${var.load_balancer_type}" idle_timeout = "${var.idle_timeout}" ip_address_type = "${var.ip_address_type}" timeouts { create = "${var.timeouts_create}" update = "${var.timeouts_update}" delete = "${var.timeouts_delete}" } lifecycle { create_before_destroy = true } tags { Name = "${lower(var.name)}-nlb-${lower(var.environment)}" Environment = "${var.environment}" Orchestration = "${var.orchestration}" Createdby = "${var.createdby}" } } #--------------------------------------------------- # Create AWS LB target group #--------------------------------------------------- resource "aws_lb_target_group" "lb_target_group" { name = "${lower(var.name)}-nlb-tg-${lower(var.environment)}" port = "${var.backend_port}" protocol = "${upper(var.backend_protocol)}" vpc_id = "${var.vpc_id}" target_type = "${var.target_type}" deregistration_delay = "${var.deregistration_delay}" tags { Name = "${lower(var.name)}-nlb-tg-${lower(var.environment)}" Environment = "${var.environment}" Orchestration = "${var.orchestration}" Createdby = "${var.createdby}" } health_check { interval = "${var.health_check_interval}" port = "${var.health_check_port}" healthy_threshold = "${var.health_check_healthy_threshold}" unhealthy_threshold = "${var.health_check_unhealthy_threshold}" protocol = "${var.backend_protocol}" } } #--------------------------------------------------- # Create AWS LB listeners #--------------------------------------------------- resource "aws_lb_listener" "frontend_tcp_80" { count = "${trimspace(element(split(",", var.alb_protocols), 1)) == "TCP" ? 1 : 0}" load_balancer_arn = "${aws_lb.lb.arn}" port = "80" protocol = "TCP" "default_action" { target_group_arn = "${aws_lb_target_group.lb_target_group.arn}" type = "forward" } depends_on = ["aws_lb.lb","aws_lb_target_group.lb_target_group"] } resource "aws_lb_listener" "frontend_tcp_443" { count = "${trimspace(element(split(",", var.alb_protocols), 1)) == "TCP" ? 1 : 0}" load_balancer_arn = "${aws_lb.lb.arn}" port = "443" protocol = "TCP" "default_action" { target_group_arn = "${aws_lb_target_group.lb_target_group.arn}" type = "forward" } depends_on = ["aws_lb.lb","aws_lb_target_group.lb_target_group"] } #--------------------------------------------------- # Create AWS LB target group attachment #--------------------------------------------------- resource "aws_lb_target_group_attachment" "lb_target_group_attachment" { count = "${length(var.target_ids) > 0 ? length(var.target_ids) : 0}" #availability_zone = "all" target_id = "${element(var.target_ids, count.index)}" port = "${var.backend_port}" target_group_arn = "${aws_lb_target_group.lb_target_group.arn}" depends_on = ["aws_lb_target_group.lb_target_group"] }
Открываем файл:
$ vim variables.tf
И прописываем:
#----------------------------------------------------------- # Global or/and default variables #----------------------------------------------------------- variable "name" { description = "Name to be used on all resources as prefix" default = "TEST-NLB" } variable "region" { description = "The region where to deploy this code (e.g. us-east-1)." default = "us-east-1" } variable "environment" { description = "Environment for service" default = "STAGE" } variable "orchestration" { description = "Type of orchestration" default = "Terraform" } variable "createdby" { description = "Created by" default = "Vitaliy Natarov" } variable "subnets" { description = "A list of subnet IDs to attach to the NLB" type = "list" default = [] } variable "lb_internal" { description = "If true, NLB will be an internal NLB" default = false } variable "name_prefix" { description = "Creates a unique name beginning with the specified prefix. Conflicts with name" default = "nlb" } variable "enable_deletion_protection" { description = "If true, deletion of the load balancer will be disabled via the AWS API. This will prevent Terraform from deleting the load balancer. Defaults to false." default = false } variable "load_balancer_type" { description = "The type of load balancer to create. Possible values are application or network. The default value is application." default = "network" } variable "idle_timeout" { description = "The time in seconds that the connection is allowed to be idle. Default: 60." default = "60" } variable "ip_address_type" { description = "The type of IP addresses used by the subnets for your load balancer. The possible values are ipv4 and dualstack" default = "ipv4" } variable "timeouts_create" { description = "Used for Creating LB. Default = 10mins" default = "10m" } variable "timeouts_update" { description = "Used for LB modifications. Default = 10mins" default = "10m" } variable "timeouts_delete" { description = "Used for LB destroying LB. Default = 10mins" default = "10m" } variable "vpc_id" { description = "Set VPC ID for ?LB" } variable "alb_protocols" { description = "A protocol the ALB accepts. (e.g.: TCP)" default = "TCP" } variable "target_type" { description = "The type of target that you must specify when registering targets with this target group. The possible values are instance (targets are specified by instance ID) or ip (targets are specified by IP address). The default is instance. Note that you can't specify targets for a target group using both instance IDs and IP addresses. If the target type is ip, specify IP addresses from the subnets of the virtual private cloud (VPC) for the target group, the RFC 1918 range (10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16), and the RFC 6598 range (100.64.0.0/10). You can't specify publicly routable IP addresses" default = "instance" } variable "deregistration_delay" { description = "The amount time for Elastic Load Balancing to wait before changing the state of a deregistering target from draining to unused. The range is 0-3600 seconds. The default value is 300 seconds." default = "300" } variable "backend_port" { description = "The port the service on the EC2 instances listen on." default = 80 } variable "backend_protocol" { description = "The protocol the backend service speaks. Options: HTTP, HTTPS, TCP, SSL (secure tcp)." default = "HTTP" } variable "target_ids" { description = "The ID of the target. This is the Instance ID for an instance, or the container ID for an ECS container. If the target type is ip, specify an IP address." type = "list" #default = "" } variable "certificate_arn" { description = "The ARN of the SSL Certificate. e.g. 'arn:aws:iam::XXXXXXXXXXX:server-certificate/ProdServerCert'" default = "" } variable "health_check_healthy_threshold" { description = "Number of consecutive positive health checks before a backend instance is considered healthy." default = 3 } variable "health_check_interval" { description = "Interval in seconds on which the health check against backend hosts is tried." default = 10 } variable "health_check_port" { description = "The port used by the health check if different from the traffic-port." default = "traffic-port" } variable "health_check_unhealthy_threshold" { description = "Number of consecutive positive health checks before a backend instance is considered unhealthy." default = 3 }
Собственно в этом файле храняться все переменные. Спасибо кэп!
Открываем последний файл:
$ vim outputs.tf
И в него вставить нужно следующие строки:
output "lb_name" { description = "" value = "${aws_lb.lb.name}" } output "lb_arn" { description = "ARN of the lb itself. Useful for debug output, for example when attaching a WAF." value = "${aws_lb.lb.arn}" } output "lb_arn_suffix" { description = "ARN suffix of our lb - can be used with CloudWatch" value = "${aws_lb.lb.arn_suffix}" } output "lb_dns_name" { description = "The DNS name of the lb presumably to be used with a friendlier CNAME." value = "${aws_lb.lb.dns_name}" } output "lb_id" { description = "The ID of the lb we created." value = "${aws_lb.lb.id}" } output "lb_zone_id" { description = "The zone_id of the lb to assist with creating DNS records." value = "${aws_lb.lb.zone_id}" } output "lb_listener_frontend_tcp_80_arn" { description = "The ARN of the HTTPS lb Listener we created." value = "${element(concat(aws_lb_listener.frontend_tcp_80.*.arn, list("")), 0)}" } output "lb_listener_frontend_tcp_443_arn" { description = "The ARN of the HTTP lb Listener we created." value = "${element(concat(aws_lb_listener.frontend_tcp_443.*.arn, list("")), 0)}" } output "lb_listener_frontend_tcp_80_id" { description = "The ID of the lb Listener we created." value = "${element(concat(aws_lb_listener.frontend_tcp_80.*.id, list("")), 0)}" } output "lb_listener_frontend_tcp_443_id" { description = "The ID of the lb Listener we created." value = "${element(concat(aws_lb_listener.frontend_tcp_443.*.id, list("")), 0)}" } output "target_group_arn" { description = "ARN of the target group. Useful for passing to your Auto Scaling group module." value = "${aws_lb_target_group.lb_target_group.arn}" }
Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:
$ mkdir nlb && cd $_
Внутри созданной папки открываем файл:
$ vim main.tf
И вставим в него следующий код:
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com" # terraform { required_version = "> 0.9.0" } provider "aws" { region = "us-east-1" shared_credentials_file = "${pathexpand("~/.aws/credentials")}" profile = "default" } module "iam" { source = "../../modules/iam" name = "My-Security" region = "us-east-1" environment = "PROD" aws_iam_role-principals = [ "ec2.amazonaws.com", ] aws_iam_policy-actions = [ "cloudwatch:GetMetricStatistics", "logs:DescribeLogStreams", "logs:GetLogEvents", "elasticache:Describe*", "rds:Describe*", "rds:ListTagsForResource", "ec2:DescribeAccountAttributes", "ec2:DescribeAvailabilityZones", "ec2:DescribeSecurityGroups", "ec2:DescribeVpcs", "ec2:Owner", ] } module "vpc" { source = "../../modules/vpc" name = "My" environment = "PROD" # VPC instance_tenancy = "default" enable_dns_support = "true" enable_dns_hostnames = "true" assign_generated_ipv6_cidr_block = "false" enable_classiclink = "false" vpc_cidr = "172.31.0.0/16" private_subnet_cidrs = ["172.31.32.0/20"] public_subnet_cidrs = ["172.31.0.0/20"] availability_zones = ["us-east-1b"] enable_all_egress_ports = "true" allowed_ports = ["8080", "3306", "443", "80"] map_public_ip_on_launch = "true" #Internet-GateWay enable_internet_gateway = "true" #NAT enable_nat_gateway = "false" single_nat_gateway = "true" #VPN enable_vpn_gateway = "false" #DHCP enable_dhcp_options = "false" # EIP enable_eip = "false" } module "ec2" { source = "../../modules/ec2" name = "TEST-Machine" region = "us-east-1" environment = "PROD" number_of_instances = 2 ec2_instance_type = "t2.micro" enable_associate_public_ip_address = "true" disk_size = "8" tenancy = "${module.vpc.instance_tenancy}" iam_instance_profile = "${module.iam.instance_profile_id}" subnet_id = "${element(module.vpc.vpc-publicsubnet-ids, 0)}" #subnet_id = "${element(module.vpc.vpc-privatesubnet-ids, 0)}" #subnet_id = ["${element(module.vpc.vpc-privatesubnet-ids)}"] vpc_security_group_ids = ["${module.vpc.security_group_id}"] monitoring = "true" } module "nlb" { source = "../../modules/nlb" name = "Load-Balancer" region = "us-east-1" environment = "PROD" subnets = ["${module.vpc.vpc-privatesubnet-ids}"] vpc_id = "${module.vpc.vpc_id}" enable_deletion_protection = false backend_protocol = "TCP" alb_protocols = "TCP" target_ids = ["${module.ec2.instance_ids}"] }
Еще полезности:
Работа с AWS IAM и Terraform в Unix/Linux
Работа с AWS VPC и Terraform в Unix/Linux
Работа с AWS S3 и Terraform в Unix/Linux
Работа с AWS EC2 и Terraform в Unix/Linux
Работа с AWS ASG(auto scaling group) и Terraform в Unix/Linux
Работа с AWS ELB и Terraform в Unix/Linux
Работа с AWS Route53 и Terraform в Unix/Linux
Работа с AWS RDS и Terraform в Unix/Linux
Работа с AWS SNS и Terraform в Unix/Linux
Работа с AWS SQS и Terraform в Unix/Linux
Работа с AWS KMS и Terraform в Unix/Linux
Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:
$ terraform init
Этим действием я инициализирую проект. Затем, подтягиваю модуль:
$ terraform get
PS: Для обновление изменений в самом модуле, можно выполнять:
$ terraform get -update
Проверим валидацию:
$ terraform validate
Запускем прогон:
$ terraform plan
Мне вывело что все у меня хорошо и можно запускать деплой:
$ terraform apply
Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:
$ terraform destroy
Весь материал аплоаджу в github аккаунт для удобства использования:
$ git clone https://github.com/SebastianUA/terraform.git
Вот и все на этом. Данная статья «Работа с AWS NLB и Terraform в Unix/Linux» завершена.