Terraform İle AWS Kullanımı ve Load Balancer Deploy
Terraform ile AWS kullanarak yüksek düzeyde kullanılabilir ve ölçeklenebilir bir Load Balancer deploy edebilirsiniz. AWS Load Balancer deploy etmek için neler yapmamız gerektiğini bu yazıda inceliyeceğiz.
Önceki yazımız "Terraform İle AWS Kullanımı ve EC2 Web Server Cluster Deploy" da ASG'mizi deploy etmiştik. Ancak küçük bir sorunumuz var: Artık her biri kendi IP adresine sahip birden çok sunucunuz var, fakat genellikle son kullanıcılarınıza kullanmaları için yalnızca tek bir IP vermeniz gerekir. Bu sorunu çözmenin bir yolu, trafiği sunucularınız arasında dağıtmak için bir yük dengeleyici (load balancer) dağıtmak ve tüm kullanıcılarınıza yük dengeleyicinin IP'sini (aslında DNS adı) vermektir. Yüksek düzeyde kullanılabilir ve ölçeklenebilir bir yük dengeleyici oluşturmak çok fazla iş yüküdür. Bir kez daha, Şekil 1'de gösterildiği gibi Amazon'un Elastic Load Balancer (ELB) hizmetini kullanarak AWS'nin bu işi sizin için halletmesine izin verebilirsiniz.
Asıl konuya geçmeden önce EC2 Instance cluster'ı nasıl deploy ettiğimizi hatırlamak isterseniz aşağıdaki bağlantıyı kullanabilirsiniz.
AWS, üç farklı load balancer türü sunar:
- Application Load Balancer (ALB): HTTP ve HTTPS trafiğinin yük dengelemesi için en uygunudur. OSI modelinin uygulama katmanında (Katman 7) çalışır.
- Network Load Balancer (NLB): TCP, UDP ve TLS trafiğinin yük dengelemesi için en uygunudur. ALB'den daha hızlı yüklenmeye yanıt olarak yukarı ve aşağı ölçeklenebilir (NLB, saniyede on milyonlarca isteğe ölçeklenecek şekilde tasarlanmıştır). OSI modelinin taşıma katmanında (Katman 4) çalışır.
- Classic Load Balancer (CLB): Bu, hem ALB'den hem de NLB'den önce gelen "legacy" yük dengeleyicidir. HTTP, HTTPS, TCP ve TLS trafiğini işleyebilir, ancak ALB veya NLB'den çok daha az özelliğe sahiptir. OSI modelinin hem uygulama katmanında (L7) hem de taşıma katmanında (L4) çalışır.
Bugünlerde çoğu uygulama ALB veya NLB kullanmalıdır. Üzerinde çalıştığınız basit web sunucusu örneği, aşırı performans gereksinimleri olmayan bir HTTP uygulaması olduğundan, ALB en uygunu olacaktır.
ALB, Şekil 2'de gösterildiği gibi birkaç parçadan oluşur:
- Listener: Belirli bir bağlantı noktasını (ör. 80) ve protokolü (ör. HTTP) dinler.
- Listener rule: Bir listener'a gelen istekleri alır ve belirli yollarla (örneğin,
/foo
ve/bar
) veya ana bilgisayar adlarıyla (örneğin,foo.example.com
vebar.example.com
) eşleşenleri belirli hedef gruplara gönderir. - Target groups: Yük dengeleyiciden istek alan bir veya daha fazla sunucu. Hedef grup ayrıca bu sunucularda sağlık kontrolleri gerçekleştirir ve yalnızca sağlıklı node'lara istek gönderir.
Terraform kısmına geçersek, ilk adım, kullanacağımız provider'ı eklemek olacaktır.
provider "aws" {
region = "us-east-2"
}
Ardından aws_lb
kaynağını kullanarak ALB'nin kendisini oluşturmaktır:
resource "aws_lb" "example" {
name = "terraform-asg-example"
load_balancer_type = "application"
subnets = data.aws_subnets.default.ids
}
Sayfanın başında verdiğimiz önceki yazıda data konusunu anlatmıştık. Burada hızlıca subnet bilgisini alacak data
referansı ekleyelim.
data "aws_vpc" "default" {
default = true
}
data "aws_subnets" "default" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default.id]
}
}
subnets
parametresinin, aws_subnets
veri kaynağını kullanarak default
VPC'nizdeki tüm subnetleri kullanacak şekilde load balancer'ı yapılandırdığını unutmayın. AWS yük dengeleyicileri tek bir sunucudan değil, ayrı subnetlerde (ve dolayısıyla , ayrı veri merkezlerinde) çalışabilen birden çok sunucudan oluşur. AWS, load balancer sunucuların sayısını trafiğe göre otomatik olarak yukarı ve aşağı ölçeklendirir ve bu sunuculardan biri arızalanırsa yük devretmeyi yönetir. Böylece kutudan çıkar çıkmaz ölçeklenebilirlik ve yüksek kullanılabilirlik elde edersiniz.
Sonraki adım, aws_lb_listener
kaynağını kullanarak bu ALB için bir listener tanımlamaktır:
resource "aws_lb_listener" "http" {
load_balancer_arn = aws_lb.example.arn
port = 80
protocol = "HTTP"
# By default, return a simple 404 page
default_action {
type = "fixed-response"
fixed_response {
content_type = "text/plain"
message_body = "404: page not found"
status_code = 404
}
}
}
Bu listener, ALB'yi; varsayılan HTTP port olan 80 numaralı portu dinleyecek, protokol olarak HTTP kullanacak ve herhangi bir listener rule ile eşleşmeyen istekler için varsayılan response olarak basit bir 404 sayfası gönderecek şekilde yapılandırır.
Varsayılan olarak, ALB'ler dahil tüm AWS kaynaklarının gelen veya giden trafiğe izin vermediğini, dolayısıyla özellikle ALB için yeni bir güvenlik grubu oluşturmanız gerektiğini unutmayın. Bu güvenlik grubu, HTTP üzerinden load balancer'a erişebilmeniz için 80 numaralı portu gelen isteklere ve load balancer'ın sağlık kontrollerini gerçekleştirebilmesi için tüm portlara giden isteklere izin vermelidir:
resource "aws_security_group" "alb" {
name = "terraform-example-alb"
# Allow inbound HTTP requests
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
# Allow all outbound requests
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
aws_lb
kaynağına, security_groups
değişkeni aracılığıyla bu güvenlik grubunu kullanmasını söylemeniz gerekir:
resource "aws_lb" "example" {
name = "terraform-asg-example"
load_balancer_type = "application"
subnets = data.aws_subnets.default.ids
security_groups = [aws_security_group.alb.id]
}
Ardından, aws_lb_target_group
kaynağını kullanarak ASG'niz için bir hedef grup oluşturmanız gerekir:
resource "aws_lb_target_group" "asg" {
name = "terraform-asg-example"
port = 8080
protocol = "HTTP"
vpc_id = data.aws_vpc.default.id
health_check {
path = "/"
protocol = "HTTP"
matcher = "200"
interval = 15
timeout = 3
healthy_threshold = 2
unhealthy_threshold = 2
}
}
Bu hedef grup, her bir Instance için periyodik olarak bir HTTP isteği göndererek Instance'ların durumunu kontrol edecek ve Instance'ın yalnızca yapılandırılmış matcher
ile eşleşen bir yanıt döndürmesi durumunda (ör. 200
) o Instance'ı sağlıklı olarak işaretleyecek. Bir Instance bozulduğu veya aşırı yüklendiği için yanıt vermezse, "sağlıksız" olarak işaretlenir ve hedef grup, kullanıcılarınızın kesintiye uğramasını en aza indirmek için otomatik olarak ona trafik göndermeyi durdurur.
Hedef grup, hangi EC2 Instance'lara istek göndereceğini nasıl biliyor? aws_lb_target_group_attachment
kaynağını kullanarak hedef gruba statik bir EC2 Instance listesi ekleyebilirsiniz, ancak bir ASG ile Instance'lar herhangi bir zamanda başlatılabilir veya sonlandırılabilir, bu nedenle statik bir liste çalışmaz. Bunun yerine, ASG ve ALB arasındaki birinci sınıf bir entegrasyondan yararlanabilirsiniz. aws_autoscaling_group
kaynağına ekleyin ve target_group_arns
bağımsız değişkenini yeni hedef grubunuza işaret edecek şekilde ayarlayın:
Lauch configuration kaynağını ve güvenlik grubunu ekleyelim.
resource "aws_launch_configuration" "example" {
image_id = "ami-0fb653ca2d3203ac1"
instance_type = "t2.micro"
security_groups = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p 8080 &
EOF
}
resource "aws_security_group" "instance" {
name = "terraform-example-instance"
ingress {
from_port = 8080
to_port = 8080
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Ardından ASG kaynağını ekleyelim.
resource "aws_autoscaling_group" "example" {
launch_configuration = aws_launch_configuration.example.name
vpc_zone_identifier = data.aws_subnets.default.ids
target_group_arns = [aws_lb_target_group.asg.arn]
health_check_type = "ELB"
min_size = 2
max_size = 10
tag {
key = "Name"
value = "terraform-asg-example"
propagate_at_launch = true
}
}
health_check_type
'ı da "ELB
" olarak güncellemelisiniz. Varsayılan health_check_type
tipi "EC2
" dir. EC2
tipi, yalnızca AWS hipervizörü sanal makinenin tamamen kapalı veya erişilemez olduğunu söylediğinde bir Instance'ı sağlıksız olarak değerlendiren minimum bir durum denetimidir. "ELB
" durum denetimi daha sağlamdır, çünkü ASG'ye bir Instance'ın sağlıklı olup olmadığını belirlemek için hedef grubun durum denetimini kullanma ve hedef grup bunları sağlıksız olarak bildirirse Instance'ları otomatik olarak değiştirme talimatı verir. Bu şekilde, Instance'lar yalnızca tamamen kapalı olduklarında değil, örneğin bellekleri tükendiği veya kritik bir işlem çöktüğü için isteklere cevap vermeyi durdurduklarında da değiştirilir.
Son olarak, aws_lb_listener_rule
kaynağını kullanarak listener rule'ları oluşturup tüm bu parçaları birbirine bağlamanın zamanı geldi:
resource "aws_lb_listener_rule" "asg" {
listener_arn = aws_lb_listener.http.arn
priority = 100
condition {
path_pattern {
values = ["*"]
}
}
action {
type = "forward"
target_group_arn = aws_lb_target_group.asg.arn
}
}
Önceki kod, ASG'nizi içeren hedef gruba herhangi bir yolla (*
) eşleşen istekler gönderen bir listener rule ekler.
Load balancer'ı dağıtmadan önce yapmanız gereken son bir şey var: Daha önce sahip olduğunuz tek EC2 Instance'ın eski public_ip
çıktısını ALB'nin DNS adını gösteren bir çıktıyla değiştirmek:
output "alb_dns_name" {
value = aws_lb.example.dns_name
description = "The domain name of the load balancer"
}
Şimdi terraform init
ve terraform plan
komutlarını çalıştırın ve plan
komutu çıktısını okuyun. Orijinal tek EC2 Instance'ınızın kaldırıldığını ve onun yerine Terraform'un bir launch configuration, ASG, ALB ve bir güvenlik grubu oluşturacağını görmelisiniz. Plan iyi görünüyorsa, yes yazın ve Enter'a basın. Uygulama tamamlandığında, alb_dns_name
çıktısını görmelisiniz:
Outputs:
alb_dns_name = "terraform-asg-example-123.us-east-2.elb.amazonaws.com"
Bu URL'yi kopyalayın. EC2 Instance'ların önyüklenmesi ve ALB'de sağlıklı görünmesi birkaç dakika sürer. Bu arada, ne dağıttığınızı inceleyebilirsiniz. EC2 konsolunun ASG bölümünü açın ve Şekil 3'te gösterildiği gibi ASG'nin oluşturulduğunu görmelisiniz.
Instances sekmesine geçerseniz, Şekil 4'te gösterildiği gibi iki EC2 Instance'ın başlatıldığını görürsünüz.
Eğer Load Balancers sekmesini tıklarsanız, Şekil 5'te gösterildiği gibi ALB'nizi görürsünüz.
Son olarak, Target Groups sekmesine tıklarsanız, Şekil 6'da gösterildiği gibi hedef grubunuzu ve detaylarını bulabilirsiniz.
Target Groups sayfasında ekranın alt yarısında Targets sekmesini bulursanız, Instance'larınızın hedef gruba kaydolduğunu ve sağlık kontrollerinden geçtiğini görebilirsiniz. Durum göstergesinin her ikisi için de "healthy" olduğunu göstermesini bekleyin. Bu genellikle bir ila iki dakika sürer. Gördüğünüzde de, daha önce kopyaladığınız alb_dns_name
adresine gidip sayfanızı test edin:
Tebrikler! ALB, trafiği EC2 Instance'larınıza yönlendiriyor. URL'ye her eriştiğinizde, isteği işlemek için farklı bir Instance seçecektir. Artık tamamen çalışan bir web sunucuları kümeniz var!
Artık bu noktada, kümenizin yeni Instance'ları başlatmaya veya eskilerini kapatmaya nasıl tepki verdiğini görebilirsiniz. Örneğin, Instance sekmesine gidin ve onay kutusunu seçip üstteki Eylemler düğmesini tıklatarak ve ardından Instance Durumu'nu Sonlandır olarak ayarlayarak Instance'lardan birini terminate edin. ALB URL'sini test etmeye devam edin ve bir Instance'ı sonlandırırken bile her istek için 200 OK almanız gerekir, çünkü ALB, Instance'ın kapalı olduğunu otomatik olarak algılayacak ve ona yönlendirmeyi durduracaktır. Daha da ilginç olanı, Instance kapandıktan kısa bir süre sonra ASG, ikiden az Bulut Sunucusunun çalıştığını algılayacak ve yerine yenisini otomatik olarak başlatacaktır (kendi kendini iyileştiren!). Ayrıca, Terraform kodunuza desired_capacity
parametresini ekleyerek ve uygulamayı yeniden çalıştırarak ASG'nin kendisini nasıl yeniden boyutlandırdığını görebilirsiniz.