Terraform İle AWS Kullanımı ve EC2 Web Server Cluster Deploy
Terraform ile AWS iki adet EC2 Instance'dan oluşan bir web server cluster deploy etmek için neler yapmamız gerektiğini bu yazıda inceliyoruz.
Tek bir sunucu çalıştırmak iyi bir başlangıçtır, ancak gerçek dünyada tek bir sunucu tek bir başarısızlık noktasıdır. Bu sunucu çökerse veya çok fazla trafikten aşırı yüklenirse, kullanıcılar sitenize erişemez. Çözüm, bir sunucu kümesi çalıştırmak, azalan sunucular etrafında yönlendirme yapmak ve kümenin boyutunu trafiğe bağlı olarak yukarı veya aşağı doğru ayarlamaktır.
Böyle bir kümeyi manuel olarak yönetmek çok zor iştir. Neyse ki, Şekil 1'de gösterildiği gibi bir Auto Scaling Group (ASG) kullanarak AWS'nin bununla ilgilenmesine izin verebilirsiniz. Bir ASG, bir EC2 Instance kümesi (cluster) başlatmak, her bir Instance'ın durumunu izlemek, arızalı Instance'ları değiştirmek ve yüke göre kümenin boyutunu ayarlamak dahil olmak üzere birçok görevi sizin için tamamen otomatik olarak halleder.
Şimdi Terraform kısmına geçeceğiz fakat iki EC2 Instance'dan oluşan bir web server cluster deploy etmeden önce tek bir Ec2 Instance'dan oluşan web serveri nasıl deploy ettiğimizi hatırlamak adına şu yazımıza göz atabilirsiniz:
ASG oluşturmanın ilk adımı, ASG'deki her EC2 Instance'ın nasıl yapılandırılacağını belirten bir başlatma yapılandırması (launch configuration) oluşturmaktır. aws_launch_configuration
kaynağı, aws_instance
kaynağı ile neredeyse aynı parametreleri kullanır. Farklı olan parametreler şunlardır:
ami
: Artıkimage_id
olarak kullanacağız.vpc_security_group_ids
: Artıksecurity_groups
olarak kullanacağız.tags
: Desteklenmiyor. Bunuaws_autoscaling_group
kaynağında ele alacağız.
Son durumda aws_launch_configuration
kaynağımız şu şekilde olacaktır:
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
}
Trafiğe izin vermek için security_groups
ta referans aldığımız kaynağı da oluşturalım:
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"]
}
}
Artık aws_autoscaling_group
kaynağını kullanarak ASG'nin kendisini oluşturabilirsiniz:
resource "aws_autoscaling_group" "example" {
launch_configuration = aws_launch_configuration.example.name
min_size = 2
max_size = 10
tag {
key = "Name"
value = "terraform-asg-example"
propagate_at_launch = true
}
}
Bu ASG, her biri terraform-asg-example
adıyla etiketlenmiş 2 ila 10 EC2 Instance (ilk başlatma için varsayılan olarak 2'dir) arasında çalışır. ASG'nin launch_configuration
adını doldurmak için bir referans kullandığına dikkat edin. Bu bir soruna yol açar: launch configuration değişmezdir (immutable), bu nedenle launch configuration'ın herhangi bir parametresini değiştirirseniz, Terraform onu değiştirmeye çalışır. Normalde, bir kaynağı değiştirirken, Terraform önce eski kaynağı siler ve ardından onun yerine yenisini oluşturur, ancak ASG'niz (aws_autoscaling_group
) artık eski kaynağa bir referansa sahip olduğundan, Terraform onu silemez.
Bu sorunu çözmek için bir yaşam döngüsü ayarı kullanabilirsiniz. Her Terraform kaynağı, o kaynağın nasıl oluşturulduğunu, güncellendiğini ve/veya silindiğini yapılandıran birkaç yaşam döngüsü ayarını destekler. Özellikle yararlı bir yaşam döngüsü ayarı create_before_destroy
'dur. create_before_destroy
'u true
olarak ayarlarsanız, Terraform, kaynakları değiştirme sırasını tersine çevirir; ilk olarak yedek kaynağı oluşturur, eski kaynağa işaret eden tüm referansları bu yeni kaynakla günceller ve ardından eski kaynağı siler. aws_launch_configuration
'ınıza lifecycle
bloğunu aşağıdaki gibi ekleyin:
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
# auto scaling group ile launch configuration kullanırken gereklidir.
lifecycle {
create_before_destroy = true
}
}
Çalışması için ASG'nize eklemeniz gereken başka bir parametre daha var: subnet_ids
. Bu parametre, EC2 Instance'ların hangi VPC subnetlerde dağıtılması gerektiğini ASG'ye belirtir. Her subnet, yalıtılmış bir AWS AZ'de (yani yalıtılmış veri merkezinde) yaşar; bu nedenle, Instance'larınızı birden çok subnette dağıtarak, bazı veri merkezlerinde kesinti olsa bile hizmetinizin çalışmaya devam etmesini sağlarsınız. Subnetlerin listesini statik olarak kodlayabilirsiniz, ancak bu sürdürülemez veya taşınabilir olmayacaktır. Bu nedenle AWS hesabınızdaki subnetlerin listesini almak için data source kullanmak daha iyi bir seçenektir.
Bir data source, Terraform'u her çalıştırdığınızda sağlayıcıdan (bu durumda AWS) alınan bir salt okunur bilgiyi temsil eder. Terraform konfigürasyonlarınıza bir data source eklemek yeni bir şey yaratmaz; bu sadece sağlayıcının API'lerini veri için sorgulamanın ve bu verileri Terraform kodunuzun geri kalanı için kullanılabilir hale getirmenin bir yoludur. Her Terraform sağlayıcısı, çeşitli data source'lar sunar. Örneğin, AWS sağlayıcısı, VPC verilerini, subnet verilerini, AMI kimliklerini, IP adresi aralıklarını, mevcut kullanıcının kimliğini ve çok daha fazlasını aramak için veri kaynakları içerir.
Bir data source sözdizimi, bir kaynağın sözdizimine çok benzer:
data "<PROVIDER>_<TYPE>" "<NAME>" {
[CONFIG ...]
}
Burada;
-
PROVIDER
bir sağlayıcının adıdır (ör. aws), TYPE
kullanmak istediğiniz veri kaynağının türüdür (ör. vpc),NAME
, bu data source'a atıfta bulunmak için Terraform kodu boyunca kullanabileceğiniz bir tanımlayıcıdır,CONFIG
, o veri kaynağına özgü bir veya daha fazla bağımsız değişkenden oluşur.
Örneğin, Varsayılan VPC'nizin verilerini aramak için aws_vpc
data source'u şu şekilde kullanabilirsiniz:
data "aws_vpc" "default" {
default = true
}
Data source'larında, ilettiğiniz argümanların genellikle veri kaynağına hangi bilgiyi aradığınızı belirten arama filtreleri olduğunu unutmayın. aws_vpc
data source ile ihtiyacınız olan tek filtre default = true
olur ve bu, Terraform'u AWS hesabınızdaki default VPC'yi aramaya yönlendirir.
Verileri bir data source'dan çıkarmak için aşağıdaki attribute referans sözdizimini kullanırsınız:
data.<PROVIDER>_<TYPE>.<NAME>.<ATTRIBUTE>
Örneğin, aws_vpc
veri kaynağından VPC'nin kimliğini almak için aşağıdakileri kullanırsınız:
data.aws_vpc.default.id
Bu VPC içindeki subnetleri aramak için bunu başka bir data source olan aws_subnets
ile birleştirebilirsiniz:
data "aws_subnets" "default" {
filter {
name = "vpc-id"
values = [data.aws_vpc.default.id]
}
}
Son olarak, subnet kimliklerini aws_subnets
data source'dan çıkarabilir ve ASG'nize (biraz garip bir şekilde adlandırılmış) vpc_zone_identifier
argümanı aracılığıyla bu subnetleri kullanmasını söyleyebilirsiniz:
resource "aws_autoscaling_group" "example" {
launch_configuration = aws_launch_configuration.example.name
vpc_zone_identifier = data.aws_subnets.default.ids
min_size = 2
max_size = 10
tag {
key = "Name"
value = "terraform-asg-example"
propagate_at_launch = true
}
}
Şimdi tüm Terraform kodumuz hazır olduğuna göre sırasıyla terraform init
ve terraform apply
komutlarını çalıştırarak deploy işlemine başlayalım. Ardından EC2 Instance panelini ziyaret ettiğinizde 2 adet instance'ın çalıştığını göreceksiniz. Stres testi yaparak bu instance sayılarının arttığını da gözlemleyebilirsiniz.
NOT: terraform apply
komutu sonucu uzun sürüyorsa korkmayın. Yaklaşık 10dk sonra konsolunuzda bu problemin sebebini çıktı olarak göreceksiniz. Örneğin yeni bir AWS hesabı kullanıyorsanız şu hatayı almanız muhtemeldir:
{
StatusCode: "Failed",
StatusMessage: "You have requested more vCPU capacity than your current vCPU limit of 1 allows for the instance bucket that the specified instance type belongs to. Please visit http://aws.amazon.com/contact-us/ec2-request to request an adjustment to this limit. Launching EC2 instance failed."
}
Sorunun kaynağı hesabınıza tanımlanmış vCPU limitidir. Bu limiti EC2 panelindeki Limits sayfasından görebilirsiniz.
Sizin de gördüğünüz gibi izin verilen vCPU limiti 1 dir. Fakat deploy etmeye çalıştığımız t2.micro
instance'ın her biri 1 vCPU'a sahip olduğundan ikinci instance'ı deploy edemiyoruz. [Tablo Sayfası]
Hesap limitlerinizi "Service Quotas/AWS services/Amazon Elastic Compute Cloud (Amazon EC2)" sayfasına giderek artırabilir ve limitiniz arttıktan sonra terraform apply
komutunu tekrar çalıştırabilirsiniz.