AWS Elastic Beanstalk ile Uygulama Dağıtımı
Yıllardır sunucu kurup uygulama deploy etmekle uğraştıysanız, bir noktada şunu düşünmüşsünüzdür: “Bu işin daha az acı veren bir yolu olmalı.” İşte tam bu noktada AWS Elastic Beanstalk devreye giriyor. PaaS (Platform as a Service) kategorisinde yer alan bu servis, altyapı detaylarıyla boğuşmadan uygulamanızı hızlıca ayağa kaldırmanızı sağlıyor. Ama “kolaylık” kelimesine aldanmayın; Beanstalk’ı doğru kullanmak için altında ne döndüğünü anlamak şart. Bu yazıda hem temel kavramları hem de gerçek dünya senaryolarını ele alacağız.
Elastic Beanstalk Nedir ve Neden Kullanılır?
Elastic Beanstalk, kodunuzu yüklediğinizde otomatik olarak EC2 instance’ları, Load Balancer, Auto Scaling grupları, güvenlik grupları ve S3 bucket’larını sizin yerinize oluşturup yönetir. Siz sadece uygulamanızı ve konfigürasyonunuzu sağlarsınız.
Peki kimler için ideal?
- Küçük-orta ölçekli ekipler: DevOps mühendisi olmayan ekipler için ciddi zaman tasarrufu sağlar.
- Hızlı prototipleme: MVP’yi hızla ayağa kaldırmak isteyenler için biçilmiş kaftan.
- Mevcut AWS altyapısıyla entegrasyon: RDS, ElastiCache, SQS gibi servislerle kolay entegre olur.
Desteklenen platformlar arasında Python, Node.js, Java, .NET, PHP, Ruby, Go ve Docker bulunuyor. Docker desteği sayesinde neredeyse her stack’i çalıştırabilirsiniz.
Temel Kavramlar
Beanstalk’ı anlamak için şu kavramları iyi kavramanız gerekiyor:
- Application: En üst seviyedeki mantıksal container. Birden fazla environment içerebilir.
- Environment: Uygulamanın çalıştığı gerçek altyapı. Web server veya worker tipi olabilir.
- Environment Tier: Web Server Tier HTTP isteklerini karşılar, Worker Tier ise arka plan işleri için SQS’ten mesaj tüketir.
- Application Version: Deploy ettiğiniz her kod paketi bir versiyondur, S3’te saklanır.
- Configuration Template: Ortam ayarlarını tekrar kullanmak için şablon oluşturmanızı sağlar.
- Platform: Çalışma zamanı ortamı (örneğin Python 3.11 running on Amazon Linux 2023).
AWS CLI ve EB CLI Kurulumu
Beanstalk ile çalışmak için iki araç şart: AWS CLI ve EB CLI. Şimdi bunları kuralım.
# AWS CLI kurulumu (Linux)
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# AWS CLI konfigürasyonu
aws configure
# AWS Access Key ID: AKIAIOSFODNN7EXAMPLE
# AWS Secret Access Key: wJalrXUtn...
# Default region name: eu-west-1
# Default output format: json
# EB CLI kurulumu
pip install awsebcli --upgrade --user
# PATH'e ekleyelim (bash kullanıcıları için)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
# Versiyon kontrolü
eb --version
# EB CLI 3.20.x (Python 3.x)
İlk Uygulamanızı Deploy Etmek
Senaryo: Bir Flask uygulamasını Beanstalk’a deploy edeceğiz. Basit ama gerçek dünyada en sık karşılaşılan senaryo bu.
Önce uygulama dosyalarını hazırlayalım:
# Proje dizini oluşturalım
mkdir flask-beanstalk-demo && cd flask-beanstalk-demo
# Virtual environment
python3 -m venv venv
source venv/bin/activate
# Bağımlılıkları kuralım
pip install flask gunicorn
# requirements.txt oluştur
pip freeze > requirements.txt
# Basit Flask uygulaması
cat > application.py << 'EOF'
from flask import Flask, jsonify
import os
application = Flask(__name__)
@application.route('/')
def index():
return jsonify({
"status": "ok",
"environment": os.environ.get("APP_ENV", "development"),
"version": os.environ.get("APP_VERSION", "1.0.0")
})
@application.route('/health')
def health():
return jsonify({"status": "healthy"}), 200
if __name__ == '__main__':
application.run(debug=False, port=5000)
EOF
Önemli not: Beanstalk, Python uygulamalarında dosya adının application.py ve WSGI nesnesinin application olmasını bekler. Buna uymayan uygulamalarda deploy sonrası 502 hatası alırsınız, bu klasik bir tuzak.
Şimdi Beanstalk’ı initialize edelim:
# EB CLI ile projeyi başlat
eb init flask-beanstalk-demo
--platform "Python 3.11 running on 64bit Amazon Linux 2023"
--region eu-west-1
# Environment oluştur ve deploy et
eb create production
--instance-type t3.small
--min-instances 2
--max-instances 4
--elb-type application
--tags Environment=production,Team=backend
# Deploy durumunu izle
eb status
eb logs
.ebextensions ile Gelişmiş Konfigürasyon
Beanstalk’ın gerçek gücü .ebextensions klasöründe saklı. Bu klasör içindeki YAML dosyaları ile instance konfigürasyonu, ortam değişkenleri, paket kurulumu ve çok daha fazlasını yönetebilirsiniz.
mkdir -p .ebextensions
# Ortam değişkenleri ve instance ayarları
cat > .ebextensions/01_environment.config << 'EOF'
option_settings:
aws:elasticbeanstalk:application:environment:
APP_ENV: production
LOG_LEVEL: WARNING
DATABASE_URL: "{{resolve:ssm:/myapp/production/database_url}}"
aws:elasticbeanstalk:environment:proxy:staticfiles:
/static: static
aws:autoscaling:launchconfiguration:
InstanceType: t3.small
IamInstanceProfile: aws-elasticbeanstalk-ec2-role
aws:autoscaling:asg:
MinSize: 2
MaxSize: 6
aws:elasticbeanstalk:cloudwatch:logs:
StreamLogs: true
DeleteOnTerminate: false
RetentionInDays: 30
EOF
# Sistem paketleri ve özel komutlar
cat > .ebextensions/02_packages.config << 'EOF'
packages:
yum:
htop: []
postgresql-devel: []
commands:
01_upgrade_pip:
command: "/var/app/venv/staging-LQM1lest/bin/pip install --upgrade pip"
ignoreErrors: false
container_commands:
01_migrate:
command: "source /var/app/venv/staging-LQM1lest/bin/activate && python manage.py migrate"
leader_only: true
02_collectstatic:
command: "source /var/app/venv/staging-LQM1lest/bin/activate && python manage.py collectstatic --noinput"
EOF
container_commands ile commands arasındaki farka dikkat edin. container_commands uygulama kodu deploy edildikten sonra, commands ise daha önce çalışır. leader_only: true ayarı ise migration gibi sadece bir kez çalışması gereken komutlar için kritik öneme sahiptir.
Procfile ve Gunicorn Konfigürasyonu
Production ortamında Flask’ın built-in sunucusu kesinlikle kullanılmamalı. Gunicorn ile çalıştıralım:
# Procfile oluştur
cat > Procfile << 'EOF'
web: gunicorn --workers=3 --threads=2 --timeout=60 --bind=0.0.0.0:8000 --access-logfile=- --error-logfile=- application:application
EOF
# Alternatif olarak .platform/nginx/conf.d/ ile Nginx'i özelleştirebilirsiniz
mkdir -p .platform/nginx/conf.d
cat > .platform/nginx/conf.d/custom.conf << 'EOF'
client_max_body_size 20M;
keepalive_timeout 75;
upstream gunicorn {
server 127.0.0.1:8000;
keepalive 32;
}
EOF
Multi-Environment Yönetimi
Gerçek dünyada staging ve production ortamlarını ayrı tutmak şart. Beanstalk’ta bu oldukça temiz bir şekilde yönetilebilir.
# Staging environment oluştur
eb create staging
--instance-type t3.micro
--min-instances 1
--max-instances 2
--elb-type application
--tags Environment=staging,Team=backend
# Staging'e deploy
eb deploy staging
# Production'a deploy
eb deploy production
# Environment'lar arası geçiş
eb use staging
eb status
eb use production
eb status
# Staging'i production ile swap et (Blue/Green deployment)
eb swap staging --destination_name production
eb swap komutu, Beanstalk’ın en güçlü özelliklerinden biridir. DNS seviyesinde iki environment’ı birbirleriyle takas eder, bu sayede sıfır downtime deployment yapabilirsiniz. Swap sonrasında eski production, staging olarak kalır ve bir şeyler ters giderse aynı komutla geri alabilirsiniz.
CloudFormation ile Beanstalk Altyapısını Kod Olarak Yönetmek
Beanstalk ortamlarını manuel oluşturmak yerine Infrastructure as Code yaklaşımını benimseyelim. AWS CloudFormation ile Beanstalk kaynaklarını tanımlayabiliriz:
# cfn-template.yaml oluştur
cat > cfn-template.yaml << 'EOF'
AWSTemplateFormatVersion: '2010-09-09'
Description: Elastic Beanstalk Production Environment
Parameters:
ApplicationName:
Type: String
Default: flask-beanstalk-demo
EnvironmentName:
Type: String
Default: production
SolutionStackName:
Type: String
Default: "64bit Amazon Linux 2023 v4.0.0 running Python 3.11"
Resources:
BeanstalkApplication:
Type: AWS::ElasticBeanstalk::Application
Properties:
ApplicationName: !Ref ApplicationName
Description: Flask Demo Application
BeanstalkEnvironment:
Type: AWS::ElasticBeanstalk::Environment
Properties:
ApplicationName: !Ref BeanstalkApplication
EnvironmentName: !Ref EnvironmentName
SolutionStackName: !Ref SolutionStackName
OptionSettings:
- Namespace: aws:autoscaling:asg
OptionName: MinSize
Value: '2'
- Namespace: aws:autoscaling:asg
OptionName: MaxSize
Value: '6'
- Namespace: aws:elasticbeanstalk:environment
OptionName: EnvironmentType
Value: LoadBalanced
- Namespace: aws:elasticbeanstalk:cloudwatch:logs
OptionName: StreamLogs
Value: 'true'
- Namespace: aws:elasticbeanstalk:cloudwatch:logs
OptionName: RetentionInDays
Value: '30'
Outputs:
EnvironmentURL:
Description: Beanstalk Environment URL
Value: !GetAtt BeanstalkEnvironment.EndpointURL
EOF
# Stack'i deploy et
aws cloudformation create-stack
--stack-name beanstalk-production
--template-body file://cfn-template.yaml
--capabilities CAPABILITY_IAM
--region eu-west-1
# Stack durumunu izle
aws cloudformation wait stack-create-complete
--stack-name beanstalk-production
--region eu-west-1
CI/CD Pipeline ile Otomatik Deploy
Manuel deploy yapmak hata yaratır. GitHub Actions ile otomatik bir pipeline kuralım:
# .github/workflows/deploy.yml
mkdir -p .github/workflows
cat > .github/workflows/deploy.yml << 'EOF'
name: Deploy to Elastic Beanstalk
on:
push:
branches:
- main
- staging
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: python -m pytest tests/ -v
deploy-staging:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/staging'
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1
- name: Deploy to Staging
run: |
pip install awsebcli
eb init flask-beanstalk-demo --region eu-west-1 --platform "Python 3.11 running on 64bit Amazon Linux 2023"
eb deploy staging --timeout 20
eb status staging
deploy-production:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1
- name: Deploy to Production
run: |
pip install awsebcli
eb init flask-beanstalk-demo --region eu-west-1 --platform "Python 3.11 running on 64bit Amazon Linux 2023"
eb deploy production --timeout 20
EOF
Yaygın Sorunlar ve Çözümleri
Beanstalk ile çalışırken mutlaka karşılaşacağınız sorunlar ve çözümleri:
502 Bad Gateway hatası: En sık karşılaşılan sorun. Neden olabilir?
- WSGI nesnesinin adı
applicationdeğil - Gunicorn port numarası Nginx ile uyuşmuyor
- Uygulama exception fırlatıyor ve başlamıyor
# Logları hemen kontrol et
eb logs --all
# Sadece uygulama loglarını çek
eb logs --log-group /aws/elasticbeanstalk/production/var/log/web.stdout.log
# Instance'a doğrudan bağlan
eb ssh production
# Bağlandıktan sonra logları kontrol et
sudo tail -f /var/log/web.stdout.log
sudo tail -f /var/log/nginx/error.log
sudo systemctl status web
Deployment timeout sorunları: Büyük uygulamalarda veya yavaş migration’larda deployment timeout alabilirsiniz.
# Timeout süresini artır
eb deploy production --timeout 30
# .ebextensions ile de ayarlanabilir
cat > .ebextensions/03_timeout.config << 'EOF'
option_settings:
aws:elasticbeanstalk:command:
DeploymentPolicy: RollingWithAdditionalBatch
BatchSizeType: Percentage
BatchSize: 25
Timeout: 1800
HealthCheckSuccessThreshold: Ok
EOF
Health check başarısızlıkları: Load Balancer health check’i başarısız olduğunda instance’lar sürekli terminate edilip yeniden başlatılır.
# Health check path'ini özelleştir
cat > .ebextensions/04_healthcheck.config << 'EOF'
option_settings:
aws:elasticbeanstalk:environment:process:default:
HealthCheckPath: /health
MatcherHTTPCode: 200
Port: 80
Protocol: HTTP
HealthCheckInterval: 30
HealthCheckTimeout: 5
HealthyThresholdCount: 2
UnhealthyThresholdCount: 5
EOF
Maliyet Optimizasyonu
Beanstalk kullanırken maliyeti kontrol altında tutmak için birkaç kritik nokta:
- Scheduled Scaling: Test ortamları için gece saatlerinde instance sayısını sıfıra indirin.
- Spot Instance kullanımı: Non-production ortamlarda Spot Instance’lar ile %70’e kadar tasarruf mümkün.
- Environment saat dilimi yönetimi: Staging environment’ı hafta sonları terminate edip Pazartesi sabahı yeniden oluşturun.
# Auto Scaling scheduled action ile gece kapatma
aws autoscaling put-scheduled-update-group-action
--auto-scaling-group-name "awseb-e-xxxxxxxx-stack-AWSEBAutoScalingGroup"
--scheduled-action-name "scale-down-night"
--recurrence "0 22 * * 1-5"
--min-size 0
--max-size 0
--desired-capacity 0
# Sabah tekrar açma
aws autoscaling put-scheduled-update-group-action
--auto-scaling-group-name "awseb-e-xxxxxxxx-stack-AWSEBAutoScalingGroup"
--scheduled-action-name "scale-up-morning"
--recurrence "0 8 * * 1-5"
--min-size 1
--max-size 4
--desired-capacity 2
Beanstalk’ın Sınırları ve Ne Zaman Bırakmalısınız?
Beanstalk her senaryoya uygun değil. Şu durumlarda Beanstalk’tan ECS, EKS veya başka bir çözüme geçmeyi düşünün:
- Microservice mimarisine geçiş: Onlarca servisi Beanstalk’ta yönetmek karmaşıklaşır, ECS Fargate daha uygun olur.
- Gelişmiş deployment stratejileri: Canary deployment veya feature flag tabanlı rollout için Beanstalk yetersiz kalır.
- Altyapı üzerinde tam kontrol ihtiyacı: Beanstalk bazı altyapı değişikliklerini zorlaştırır veya imkansız kılar.
- Çok kiracılı (multi-tenant) uygulamalar: Her müşteri için ayrı environment açmak hem maliyetli hem yönetimi güç olur.
Beanstalk’ın oluşturduğu EC2 instance’lara, güvenlik gruplarına ve Auto Scaling gruplarına konsol üzerinden müdahale etmekten kaçının. Beanstalk bu kaynakları yeniden deploy sırasında sıfırlayabilir, yaptığınız değişiklikler kaybolur.
Sonuç
Elastic Beanstalk, doğru kullanıldığında gerçekten hayat kurtarır. Altyapı yönetimiyle vakit kaybetmek yerine uygulama geliştirmeye odaklanmanızı sağlar. Ancak “sihirli bir çözüm” değil; altında ne döndüğünü anlamadan kullanmak, sorunlar çıktığında sizi çıkmaza sokabilir.
Bu yazıda anlattıklarımı özetlersek:
.ebextensionsklasörünü etkin kullanmak, tekrar edilebilir ve öngörülebilir deployment’lar için zorunlu.eb swapkomutu ile Blue/Green deployment yaparak sıfır downtime hedefleyin.- Log’ları gerçek zamanlı izleyin, sorun çıktığında ilk bakacağınız yer burası.
- CI/CD pipeline olmadan production deploy etmeyin, manuel müdahaleler hata kaynağı.
- Maliyeti unutmayın, küçük ayarlarla ciddi tasarruf yapılabilir.
Beanstalk ile başlayıp zamanla Kubernetes’e geçmek çok yaygın bir yolculuk. Beanstalk, bu yolculuğun ilk adımı için mükemmel bir başlangıç noktası. Umarım bu yazı hem başlamanıza hem de daha verimli kullanmanıza yardımcı olur.
