Ansible Tower ile Kurumsal Deployment Yönetimi

Kurumsal ortamlarda onlarca, hatta yüzlerce sunucuya aynı anda deployment yapmak zorunda kaldığınızda, basit Ansible playbook’larının komut satırından çalıştırılması bir noktadan sonra yetersiz kalmaya başlar. Kim ne zaman hangi playbook’u çalıştırdı? Hangi sunucuda hata çıktı? Gece yarısı tetiklenen bir deployment’ı kim onayladı? Bu soruların cevabını vermek zorunda olduğunuzda Ansible Tower devreye girer.

Ansible Tower, Red Hat’in geliştirdiği ve AWX projesinin kurumsal versiyonu olan, Ansible’ın merkezi yönetim katmanıdır. Görsel arayüzü, rol tabanlı erişim kontrolü, job scheduling ve detaylı audit logları ile kurumsal deployment süreçlerini ciddi ölçüde kolaylaştırır. Bu yazıda gerçek dünya senaryoları üzerinden Ansible Tower kurulumundan production deployment pipeline’larına kadar kapsamlı bir rehber sunacağım.

Ansible Tower Neden Gerekli?

Küçük bir ekipte beş on sunucu yönetiyorsanız, ansible-playbook komutu yeterli olabilir. Ancak şu senaryoları düşünün:

  • 50 farklı sunucuya aynı anda uygulama güncellemesi yapılması gerekiyor
  • Geliştirici ekibi production’a erişim yetkisi olmadan deployment başlatmak istiyor
  • Compliance gereksinimleri gereği her deployment’ın kayıt altına alınması zorunlu
  • Farklı ortamlar (dev, staging, prod) için farklı credential set’leri kullanılması gerekiyor

Bu gereksinimlerin tamamını Ansible Tower karşılar. AWX, Tower’ın ücretsiz açık kaynak versiyonudur ve özellikler açısından büyük ölçüde örtüşür, ancak kurumsal destek ve bazı enterprise özellikler Tower’a özgüdür.

Kurulum ve İlk Yapılandırma

Tower kurulumu için minimum gereksinimler oldukça nettir. Tek node kurulum için en az 4 CPU, 8GB RAM ve 20GB disk alanı gerekmektedir. Production ortamları için bu değerlerin iki katını öneririm.

# Ansible Tower kurulum paketini indirme
wget https://releases.ansible.com/ansible-tower/setup/ansible-tower-setup-latest.tar.gz
tar xvzf ansible-tower-setup-latest.tar.gz
cd ansible-tower-setup-*/

# inventory dosyasını düzenleme
cat inventory

Kurulum öncesinde inventory dosyasını doğru yapılandırmak kritiktir:

# inventory dosyası içeriği
[tower]
localhost ansible_connection=local

[database]
# Harici veritabanı kullanıyorsanız buraya ekleyin
# db.example.com

[all:vars]
admin_password='GucluBirSifre123!'
pg_host=''
pg_port=''
pg_database='awx'
pg_username='awx'
pg_password='DBSifreniz'
pg_sslmode='prefer'

rabbitmq_port=5672
rabbitmq_vhost=tower
rabbitmq_username=tower
rabbitmq_password='RabbitSifreniz'
rabbitmq_cookie=cookiemonster

# Tower lisans türü
tower_package_name=ansible-tower
tower_package_version=3.8.0

Kurulumu başlatmak için:

# Kurulum scriptini çalıştırma
sudo ./setup.sh

# Kurulum tamamlandıktan sonra servis durumunu kontrol
sudo ansible-tower-service status

# Tower loglarını takip etme
sudo tail -f /var/log/tower/tower.log

Kurulum yaklaşık 15-20 dakika sürer. Tamamlandığında https://sunucu-ip-adresi adresinden arayüze ulaşabilirsiniz.

Tower CLI ile Otomasyon

Arayüz güzel ama gerçek güç, Tower’ı API ve CLI üzerinden kontrol ettiğinizde ortaya çıkar. awx CLI aracı bu iş için biçilmiş kaftandır:

# AWX CLI kurulumu
pip3 install awxkit

# Bağlantı ayarları
export TOWER_HOST=https://tower.sirketiniz.com
export TOWER_USERNAME=admin
export TOWER_PASSWORD=sifreniz
export TOWER_VERIFY_SSL=false

# Mevcut inventory listesini görme
awx inventory list --all

# Job template listesi
awx job_templates list

# Belirli bir job'ı başlatma
awx job launch --job-template "Production Deploy" 
  --extra-vars '{"app_version": "2.1.0", "rollback": false}'

Organization, Team ve Kullanıcı Yapısı

Tower’ın en güçlü yanlarından biri rol tabanlı erişim kontrolüdür. Kurumsal bir yapı için şu hiyerarşiyi öneriyorum:

Organization: Şirket veya büyük birim düzeyinde. Örneğin “TechTeam”, “InfraTeam”.

Team: Organization altında gruplar. “Backend Developers”, “Ops Team”, “QA Team”.

User: Bireysel kullanıcılar, bir veya birden fazla team’e atanabilir.

Bu yapıyı Tower API üzerinden kurmak:

# Organization oluşturma
awx organizations create 
  --name "TechTeam" 
  --description "Teknoloji ekibi ana organizasyonu"

# Team oluşturma
awx teams create 
  --name "Backend Developers" 
  --organization "TechTeam"

# Kullanıcı oluşturma
awx users create 
  --username "ahmet.yilmaz" 
  --password "GeciciSifre!" 
  --email "[email protected]" 
  --first_name "Ahmet" 
  --last_name "Yılmaz"

# Kullanıcıyı team'e ekleme
awx teams associate 
  --name "Backend Developers" 
  --users "ahmet.yilmaz"

Inventory Yönetimi

Tower’da inventory yönetimi, dinamik ve statik olmak üzere iki şekilde çalışır. Üretim ortamlarında dinamik inventory kullanmanızı şiddetle tavsiye ederim. AWS, Azure, GCP veya VMware gibi platformlarla entegrasyon kurabilirsiniz.

Statik inventory için YAML formatı:

# production-inventory.yml
all:
  children:
    webservers:
      hosts:
        web01.prod.example.com:
          ansible_user: deploy
          ansible_port: 22
        web02.prod.example.com:
          ansible_user: deploy
          ansible_port: 22
      vars:
        app_root: /var/www/html
        nginx_worker_processes: 4
    
    databases:
      hosts:
        db01.prod.example.com:
          ansible_user: deploy
          pg_max_connections: 200
        db02.prod.example.com:
          ansible_user: deploy
          pg_max_connections: 200
      vars:
        pg_version: 14
    
    appservers:
      hosts:
        app01.prod.example.com:
          ansible_user: deploy
          java_heap_size: 4g
        app02.prod.example.com:
          ansible_user: deploy
          java_heap_size: 4g

AWS EC2 için dinamik inventory script:

# AWS dynamic inventory için gerekli paketler
pip3 install boto3 botocore

# Tower'da AWS Credential ekledikten sonra
# Inventory -> Sources -> Add Source -> Amazon EC2

# Test için komut satırından çekme
aws_ec2 --list --profile production | python3 -m json.tool

# Filtreleme ile sadece belirli tag'e sahip sunucuları alma
# Tower'daki Source Variables alanına şunu ekleyin:
# AWS EC2 dynamic inventory kaynak değişkenleri
filters:
  "tag:Environment": production
  "tag:Role": webserver
  instance-state-name: running
keyed_groups:
  - key: tags.Role
    prefix: role
  - key: placement.region
    prefix: aws_region
hostnames:
  - private-ip-address

Job Template ve Workflow Yapılandırması

Job Template, belirli bir playbook’u belirli bir inventory üzerinde çalıştırmak için yapılandırılmış şablondur. Gerçek bir örnek üzerinden gidelim:

# Job Template oluşturma (CLI ile)
awx job_templates create 
  --name "Production - Web Deploy" 
  --job_type "run" 
  --inventory "Production Inventory" 
  --project "WebApp Project" 
  --playbook "deploy/web-deploy.yml" 
  --credential "Production SSH Key" 
  --extra_vars '{"app_version": "", "force_restart": false}' 
  --ask_variables_on_launch true 
  --limit "webservers" 
  --verbosity 1 
  --timeout 300

Deployment playbook’unun kendisi:

# deploy/web-deploy.yml
---
- name: Web uygulaması deployment
  hosts: webservers
  serial: "{{ serial_percentage | default('50%') }}"
  max_fail_percentage: 20
  
  pre_tasks:
    - name: Deployment başlangıcını logla
      uri:
        url: "{{ slack_webhook_url }}"
        method: POST
        body_format: json
        body:
          text: "🚀 Deployment başlıyor: {{ inventory_hostname }} - Versiyon: {{ app_version }}"
      delegate_to: localhost
      when: slack_webhook_url is defined
    
    - name: Sunucuyu load balancer'dan çıkar
      uri:
        url: "http://{{ lb_host }}/api/servers/{{ inventory_hostname }}/disable"
        method: POST
        headers:
          Authorization: "Bearer {{ lb_api_token }}"
      delegate_to: localhost
      when: lb_host is defined

  roles:
    - role: app-deployment
      vars:
        version: "{{ app_version }}"
    
  post_tasks:
    - name: Health check
      uri:
        url: "http://{{ ansible_host }}:{{ app_port }}/health"
        status_code: 200
      retries: 5
      delay: 10
      register: health_result
    
    - name: Sunucuyu load balancer'a geri al
      uri:
        url: "http://{{ lb_host }}/api/servers/{{ inventory_hostname }}/enable"
        method: POST
        headers:
          Authorization: "Bearer {{ lb_api_token }}"
      delegate_to: localhost
      when: 
        - lb_host is defined
        - health_result.status == 200
    
    - name: Başarılı deployment bildirimi
      uri:
        url: "{{ slack_webhook_url }}"
        method: POST
        body_format: json
        body:
          text: "✅ Deployment tamamlandı: {{ inventory_hostname }}"
      delegate_to: localhost
      when: slack_webhook_url is defined

Workflow Template ile Çok Adımlı Pipeline

Workflow Template, birden fazla Job Template’i birbirine bağlayarak karmaşık pipeline’lar oluşturmanızı sağlar. Başarı/başarısızlık durumlarına göre farklı dallar izlenebilir.

Tipik bir production deployment workflow’u şöyle görünür:

  • Adım 1: Staging’e deploy
  • Adım 2 (Başarı durumunda): Integration testleri çalıştır
  • Adım 3 (Başarı durumunda): Manuel onay bekle (Approval node)
  • Adım 4 (Onay sonrası): Production’a deploy
  • Adım 5 (Başarısızlık durumunda): Rollback çalıştır ve bildirim gönder
# Workflow Template oluşturma
awx workflow_job_templates create 
  --name "Full Deployment Pipeline" 
  --organization "TechTeam" 
  --ask_variables_on_launch true 
  --extra_vars '{"app_version": "", "environment": "production"}'

# Workflow node'larını bağlamak için Tower UI kullanmak
# çok daha pratiktir, ancak API ile de yapılabilir:

# Workflow node ekleme
awx workflow_job_template_nodes create 
  --workflow_job_template "Full Deployment Pipeline" 
  --unified_job_template "Staging Deploy" 
  --extra_data '{"target_env": "staging"}'

Credential Yönetimi ve Güvenlik

Tower’ın en kritik özelliklerinden biri, credential’ları merkezi ve şifreli biçimde saklamasıdır. SSH anahtarları, API token’ları, veritabanı şifreleri hiçbir zaman açık metin olarak playbook’larda bulunmamalıdır.

Credential türleri:

  • Machine: SSH key veya şifre ile sunucu erişimi
  • Source Control: Git repo erişimi
  • Vault: Ansible Vault şifreleme anahtarı
  • Amazon Web Services: AWS access/secret key
  • Custom: Kendi credential tipinizi tanımlayabilirsiniz

Custom credential tipi örneği, internal API token yönetimi için:

# Custom Credential Type - Input Configuration
fields:
  - id: internal_api_token
    type: string
    label: Internal API Token
    secret: true
  - id: api_base_url
    type: string
    label: API Base URL

required:
  - internal_api_token
  - api_base_url
# Custom Credential Type - Injector Configuration
# Bu değerleri playbook'a environment variable olarak inject eder
env:
  INTERNAL_API_TOKEN: "{{ internal_api_token }}"
  API_BASE_URL: "{{ api_base_url }}"

# Veya extra_vars olarak:
extra_vars:
  api_token: "{{ internal_api_token }}"
  api_url: "{{ api_base_url }}"

Notification ve Alerting Entegrasyonu

Deployment süreçlerinde bildirimler hayat kurtarır. Tower, Slack, email, PagerDuty, webhook gibi pek çok notification backend’i destekler.

Slack notification yapılandırması:

# Slack Notification Template oluşturma
awx notification_templates create 
  --name "Slack Deployment Alerts" 
  --organization "TechTeam" 
  --notification_type "slack" 
  --notification_configuration '{
    "token": "xoxb-your-bot-token",
    "channels": ["#deployments", "#ops-alerts"]
  }' 
  --messages '{
    "started": {
      "message": "Deployment başladı: {{ job.name }} - Başlatan: {{ job.created_by }}"
    },
    "success": {
      "message": "✅ Başarılı: {{ job.name }} - Süre: {{ job.elapsed }} saniye"
    },
    "error": {
      "message": "❌ HATA: {{ job.name }} - Detay: {{ job.result_traceback }}"
    }
  }'

Scheduling ve Maintenance Windows

Planlı bakım pencereleri için Tower’ın scheduling özelliği çok işe yarar. Gece yarısı security patch’lerini otomatik uygulamak ya da haftalık backup job’larını zamanlamak için kullanabilirsiniz.

# Periyodik schedule oluşturma
awx schedules create 
  --name "Haftalık Security Patch - Pazar 03:00" 
  --unified_job_template "Security Patching" 
  --rrule "DTSTART:20240101T000000Z RRULE:FREQ=WEEKLY;BYDAY=SU;BYHOUR=3;BYMINUTE=0;BYSECOND=0" 
  --enabled true

# Aylık veritabanı bakımı
awx schedules create 
  --name "Aylık DB Maintenance" 
  --unified_job_template "Database Maintenance" 
  --rrule "DTSTART:20240101T220000Z RRULE:FREQ=MONTHLY;BYMONTHDAY=1;BYHOUR=22;BYMINUTE=0" 
  --enabled true 
  --extra_data '{"maintenance_type": "vacuum_analyze", "notify_dba": true}'

Gerçek Dünya Senaryosu: Blue-Green Deployment

E-ticaret platformu deployment’larında sıfır downtime kritik önem taşır. Tower ile blue-green deployment nasıl yapılır:

# blue-green-deploy.yml
---
- name: Blue-Green Deployment Orchestration
  hosts: localhost
  gather_facts: false
  
  vars:
    lb_api: "https://haproxy-api.internal"
    
  tasks:
    - name: Mevcut aktif ortamı belirle
      uri:
        url: "{{ lb_api }}/active-slot"
        headers:
          Authorization: "Bearer {{ lb_token }}"
      register: current_slot
    
    - name: Hedef ortamı belirle
      set_fact:
        active_slot: "{{ current_slot.json.slot }}"
        target_slot: "{{ 'green' if current_slot.json.slot == 'blue' else 'blue' }}"
    
    - name: Deployment bilgisini logla
      debug:
        msg: "Aktif: {{ active_slot }} -> Hedef: {{ target_slot }}"

- name: Hedef slot'a deploy et
  hosts: "{{ target_slot }}_servers"
  serial: 1
  
  roles:
    - role: app-deployment
  
  post_tasks:
    - name: Smoke test
      uri:
        url: "http://{{ ansible_host }}:8080/api/health"
        status_code: 200
      retries: 3
      delay: 5

- name: Traffic'i yeni slot'a yönlendir
  hosts: localhost
  gather_facts: false
  
  tasks:
    - name: Load balancer'ı güncelle
      uri:
        url: "{{ lb_api }}/switch"
        method: POST
        body_format: json
        body:
          slot: "{{ target_slot }}"
        headers:
          Authorization: "Bearer {{ lb_token }}"
    
    - name: Eski slot'u standby'a al
      uri:
        url: "{{ lb_api }}/standby/{{ active_slot }}"
        method: POST
        headers:
          Authorization: "Bearer {{ lb_token }}"

Tower’da Audit ve Compliance

Kurumsal ortamlarda her işlemin kayıt altında olması zorunludur. Tower bu konuda oldukça kapsamlı log altyapısına sahiptir.

# Tüm job geçmişini görüntüleme
awx jobs list --all --order_by "-created" 
  --format json | jq '.results[] | {id, name, status, created, elapsed}'

# Belirli kullanıcının aktivitelerini sorgulama
awx activity_stream list 
  --actor "ahmet.yilmaz" 
  --timestamp__gte "2024-01-01T00:00:00Z"

# Splunk veya ELK'a log göndermek için
# Tower Settings -> Logging -> Log Aggregator Type
# Elasticsearch endpoint ve token'ı buraya girilir

# Başarısız job detaylarını export etme
awx jobs list --status "failed" 
  --created__gte "2024-01-01T00:00:00Z" 
  --format json > failed-jobs-report.json

Performance Tuning ve Ölçeklendirme

Yüzlerce sunucuya paralel deployment yapıyorsanız Tower’ın varsayılan ayarları yetersiz kalabilir. İnce ayarlar için:

# Tower job kapasitesini artırma
# /etc/tower/conf.d/custom.py dosyasına ekle:
AWX_TASK_ENV = {
    'ANSIBLE_FORKS': '50',
    'ANSIBLE_TIMEOUT': '30',
}

# Aynı anda çalışabilecek job sayısı
# Tower Settings -> Jobs -> Maximum Scheduled Jobs: 10

# Inventory refresh paralleliği
AWX_INVENTORY_UPDATE_BATCH_SIZE = 100
ANSIBLE_CALLBACKS_ENABLED = "profile_tasks"

Cluster yapısı için birden fazla Tower node kullanımı:

# Multi-node cluster inventory
[tower]
tower1.example.com
tower2.example.com
tower3.example.com

[database]
db.example.com

[all:vars]
admin_password='SifresinizBuraya'
pg_host='db.example.com'
pg_database='tower'
pg_username='tower'
pg_password='DBSifresi'

GitOps Entegrasyonu

Tower’ı Git workflow’unuzla entegre etmek, deployment süreçlerini kaynak kod yönetimiyle birleştirmenin en temiz yoludur.

Webhook ile otomatik tetikleme:

# GitHub/GitLab webhook'unu Tower'a bağlama
# Job Template -> Options -> Enable Webhook
# Webhook URL: https://tower.sirket.com/api/v2/job_templates/42/github/
# Webhook Key: Tower'ın ürettiği secret key

# Projeyi webhook ile güncellemek için
# Project -> Options -> SCM Update on Launch: true

# Branch bazlı deployment için extra_vars kullanımı
# Playbook içinde:
- name: Git branch'ine göre ortam belirle
  set_fact:
    deploy_environment: >-
      {{ 'production' if tower_job_template_extra_vars.branch == 'main'
         else 'staging' if tower_job_template_extra_vars.branch == 'develop'
         else 'feature' }}

Sonuç

Ansible Tower, sadece bir GUI değil, kurumsal deployment operasyonlarının merkezi sinir sistemidir. Rol tabanlı erişim kontrolüyle geliştiriciler production’a doğrudan erişmeden deployment başlatabilir, audit logları ile her değişiklik takip edilebilir, notification sistemiyle ekip her gelişmeden anında haberdar olur.

Pratik tavsiyelerim şöyle sıralanabilir: Önce küçük başlayın, birkaç kritik playbook’u Tower’a taşıyın ve ekibinizi sürece alıştırın. Credential yönetimini ilk günden doğru kurun, sonradan değiştirmek zahmetli olur. Dynamic inventory kullanın, statik inventory liste bakımı zamanla baş ağrısına dönüşür. Workflow Template’leri erken öğrenin çünkü gerçek değer tek başına Job Template’lerde değil, birbirine bağlı pipeline’larda ortaya çıkar.

AWX ile başlamanızı da öneririm. Ücretsiz, açık kaynak ve Tower ile büyük ölçüde uyumludur. Ekibinizi ve süreçlerinizi AWX’e adapte ettikten sonra kurumsal destek veya enterprise özellikler gerektiğinde Tower’a geçiş oldukça sorunsuz olur.

Deployment kaosu her ekibin kabusu, Tower ise bu kaosu düzene sokan pratik çözümdür.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir