HomeBlogAnsible ile Konfigürasyon Yönetimi: Sıfırdan Production'a
Infrastructure as Code

Ansible ile Konfigürasyon Yönetimi: Sıfırdan Production'a

April 12, 202612 dkArticle
ansible konfiguerasyon-yoenetimi iac otomasyon

Ansible ile Konfigürasyon Yönetimi: Sıfırdan Production'a

Sunucu sayınız arttıkça manuel konfigürasyon sürdürülemez hale gelir. "Bu sunucuya hangi paketler kuruluydu?", "Nginx config'i hangi sunucuda farklıydı?" gibi sorular operasyonel kabus yaratır. Ansible, agentless mimarisi ve idempotent yapısıyla bu sorunu kökünden çözer.

Neden Ansible?

Terraform ve Pulumi altyapıyı oluşturur (VM, network, storage), Ansible ise oluşan altyapıyı konfigüre eder. İkisi rakip değil, tamamlayıcıdır:

| Özellik | Ansible | Chef/Puppet | |---------|---------|-------------| | Mimari | Agentless (SSH) | Agent gerektirir | | Dil | YAML (deklaratif) | Ruby DSL | | Öğrenme eğrisi | Düşük | Yüksek | | Push/Pull | Push-based | Pull-based | | İlk kurulum | Sadece control node | Server + agent kurulumu |

Ansible'ın en büyük avantajı: hedef sunuculara hiçbir şey kurmanız gerekmez. SSH erişimi ve Python yeterlidir.

Kurulum

# macOS
brew install ansible

# Ubuntu/Debian
sudo apt update && sudo apt install -y ansible

# pip ile (tüm platformlar)
pip install ansible

# Versiyon kontrolü
ansible --version

Inventory: Sunucularınızı Tanımlayın

Inventory dosyası Ansible'a hangi sunuculara bağlanacağını söyler. INI veya YAML formatında yazılabilir:

# inventory/hosts.ini

[webservers]
web1.example.com ansible_host=192.168.1.10
web2.example.com ansible_host=192.168.1.11

[dbservers]
db1.example.com ansible_host=192.168.1.20

[monitoring]
monitor.example.com ansible_host=192.168.1.30

[production:children]
webservers
dbservers
monitoring

[production:vars]
ansible_user=deploy
ansible_ssh_private_key_file=~/.ssh/deploy_key
ansible_python_interpreter=/usr/bin/python3

Daha karmaşık ortamlar için dynamic inventory kullanılır. AWS, GCP, Azure gibi cloud provider'lar için hazır inventory plugin'leri mevcuttur:

# inventory/aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
  - eu-west-1
keyed_groups:
  - key: tags.Environment
    prefix: env
  - key: tags.Role
    prefix: role
filters:
  tag:ManagedBy: ansible

İlk Playbook: Ad-Hoc Komutlardan Playbook'a

Önce ad-hoc komutlarla başlayalım:

# Tüm sunuculara ping at
ansible all -i inventory/hosts.ini -m ping

# Web sunucularının uptime bilgisini al
ansible webservers -i inventory/hosts.ini -m command -a "uptime"

# Bir paket kur
ansible webservers -i inventory/hosts.ini -m apt -a "name=nginx state=present" --become

Ancak gerçek dünyada playbook kullanırsınız. İşte bir web sunucu kurulum playbook'u:

# playbooks/setup-webserver.yml
---
- name: Web sunucu konfigürasyonu
  hosts: webservers
  become: true
  vars:
    nginx_worker_processes: auto
    nginx_worker_connections: 1024
    app_port: 3000

  tasks:
    - name: Sistem paketlerini güncelle
      apt:
        update_cache: true
        cache_valid_time: 3600

    - name: Gerekli paketleri kur
      apt:
        name:
          - nginx
          - certbot
          - python3-certbot-nginx
          - ufw
        state: present

    - name: Nginx konfigürasyon dosyasını deploy et
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/app
        owner: root
        group: root
        mode: "0644"
      notify: Nginx'i yeniden yükle

    - name: Site'ı aktif et
      file:
        src: /etc/nginx/sites-available/app
        dest: /etc/nginx/sites-enabled/app
        state: link

    - name: Default site'ı kaldır
      file:
        path: /etc/nginx/sites-enabled/default
        state: absent
      notify: Nginx'i yeniden yükle

    - name: UFW ile HTTP/HTTPS portlarını aç
      ufw:
        rule: allow
        port: "{{ item }}"
        proto: tcp
      loop:
        - "80"
        - "443"
        - "22"

    - name: UFW'yi aktif et
      ufw:
        state: enabled
        default: deny

    - name: Nginx servisinin çalıştığından emin ol
      service:
        name: nginx
        state: started
        enabled: true

  handlers:
    - name: Nginx'i yeniden yükle
      service:
        name: nginx
        state: reloaded

İlgili Jinja2 template:

{# templates/nginx.conf.j2 #}
upstream app_backend {
    server 127.0.0.1:{{ app_port }};
}

server {
    listen 80;
    server_name {{ inventory_hostname }};

    location / {
        proxy_pass http://app_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /health {
        access_log off;
        return 200 "OK";
    }
}

Playbook'u çalıştırın:

# Dry-run (değişiklikleri göster ama uygulama)
ansible-playbook -i inventory/hosts.ini playbooks/setup-webserver.yml --check --diff

# Gerçek çalıştırma
ansible-playbook -i inventory/hosts.ini playbooks/setup-webserver.yml

# Belirli bir tag ile sadece ilgili task'ları çalıştır
ansible-playbook -i inventory/hosts.ini playbooks/setup-webserver.yml --tags "nginx"

Role Yapısı: Playbook'ları Modüler Hale Getirin

Playbook'lar büyüdükçe yönetilemez hale gelir. Ansible Role yapısı kodunuzu yeniden kullanılabilir modüllere böler:

# Role iskeletini oluştur
ansible-galaxy init roles/nginx

# Ortaya çıkan yapı:
roles/nginx/
├── defaults/
│   └── main.yml      # Varsayılan değişkenler (override edilebilir)
├── handlers/
│   └── main.yml      # Handler tanımları
├── tasks/
│   └── main.yml      # Ana task listesi
├── templates/
│   └── nginx.conf.j2 # Jinja2 template'leri
├── files/             # Statik dosyalar
├── vars/
│   └── main.yml      # Role-specific değişkenler
└── meta/
    └── main.yml       # Bağımlılıklar ve metadata

Role'ün task dosyası:

# roles/nginx/tasks/main.yml
---
- name: Nginx'i kur
  apt:
    name: nginx
    state: present
  tags: [nginx, install]

- name: Nginx konfigürasyonunu deploy et
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/sites-available/{{ nginx_site_name }}
    mode: "0644"
    validate: nginx -t -c %s
  notify: reload nginx
  tags: [nginx, config]

- name: Site'ı aktif et
  file:
    src: /etc/nginx/sites-available/{{ nginx_site_name }}
    dest: /etc/nginx/sites-enabled/{{ nginx_site_name }}
    state: link
  notify: reload nginx
  tags: [nginx, config]

Varsayılan değişkenler:

# roles/nginx/defaults/main.yml
---
nginx_site_name: default
nginx_worker_processes: auto
nginx_worker_connections: 1024
nginx_client_max_body_size: 10m
nginx_proxy_read_timeout: 60

Ana playbook artık çok daha temiz:

# playbooks/site.yml
---
- name: Web sunucularını konfigüre et
  hosts: webservers
  become: true
  roles:
    - role: common
    - role: nginx
      vars:
        nginx_site_name: myapp
        nginx_client_max_body_size: 50m
    - role: certbot
    - role: node_exporter

Ansible Vault: Secret Yönetimi

Şifreleri, API anahtarlarını ve sertifikaları Vault ile şifreleyin:

# Yeni bir vault dosyası oluştur
ansible-vault create group_vars/production/vault.yml

# Mevcut dosyayı şifrele
ansible-vault encrypt group_vars/production/secrets.yml

# Dosyayı düzenle
ansible-vault edit group_vars/production/vault.yml

# Playbook'u vault password ile çalıştır
ansible-playbook site.yml --ask-vault-pass

# Veya password dosyasından oku
ansible-playbook site.yml --vault-password-file ~/.vault_pass

Best practice olarak vault değişkenlerini prefix ile kullanın:

# group_vars/production/vault.yml (şifreli)
vault_db_password: "gizli-sifre-123"
vault_api_key: "sk-abc..."

# group_vars/production/vars.yml (açık)
db_password: "{{ vault_db_password }}"
api_key: "{{ vault_api_key }}"

Production Best Practice'leri

1. ansible.cfg ile Merkezi Konfigürasyon

# ansible.cfg
[defaults]
inventory = inventory/
roles_path = roles/
retry_files_enabled = false
host_key_checking = false
forks = 20
timeout = 30
stdout_callback = yaml

[privilege_escalation]
become = true
become_method = sudo

[ssh_connection]
pipelining = true
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

pipelining = true ayarı SSH bağlantı sayısını azaltarak performansı önemli ölçüde artırır.

2. Idempotency Kuralına Uy

Her task idempotent olmalı — kaç kez çalıştırırsanız çalıştırın aynı sonucu vermeli:

# KÖTÜ: Her çalıştırmada tekrar eklenir
- name: Satır ekle
  shell: echo "export APP_ENV=production" >> /etc/environment

# İYİ: Sadece yoksa ekler
- name: Environment değişkenini ayarla
  lineinfile:
    path: /etc/environment
    line: "export APP_ENV=production"
    state: present

3. Test ve CI Entegrasyonu

Ansible playbook'larınızı CI pipeline'ında test edin:

# .github/workflows/ansible-lint.yml
name: Ansible Lint
on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Ansible Lint
        uses: ansible/ansible-lint@v24
        with:
          targets: playbooks/

Molecule ile role testleri yazın:

# Molecule test ortamını başlat
pip install molecule molecule-docker
cd roles/nginx
molecule init scenario --driver-name docker
molecule test

4. Proje Dizin Yapısı

Production-ready bir Ansible projesi şöyle organize edilir:

ansible-project/
├── ansible.cfg
├── inventory/
│   ├── production/
│   │   ├── hosts.yml
│   │   └── group_vars/
│   │       ├── all.yml
│   │       └── webservers.yml
│   └── staging/
│       ├── hosts.yml
│       └── group_vars/
├── playbooks/
│   ├── site.yml
│   ├── deploy.yml
│   └── rollback.yml
├── roles/
│   ├── common/
│   ├── nginx/
│   └── app/
└── requirements.yml

Sonraki Adımlar

Ansible temellerini öğrendikten sonra şu konulara bakmanızı öneriyorum:

  • Ansible AWX/Tower: Web arayüzü, RBAC ve scheduled job'lar
  • Ansible Collections: Galaxy'den hazır collection'ları kullanma
  • Terraform + Ansible: Terraform ile altyapıyı oluştur, Ansible ile konfigüre et
  • Molecule: Role'leriniz için otomatik test yazma

Ansible, Infrastructure as Code yolculuğunuzda Terraform'un doğal tamamlayıcısıdır. Terraform altyapıyı provision eder, Ansible onu konfigüre eder. Bu ikiliyi birlikte kullanarak sunucu konfigürasyonlarınızı tamamen kod olarak yönetebilir, tekrarlanabilir ve denetlenebilir hale getirebilirsiniz.

Weekly DevOps Newsletter

Get new tool reviews, comparisons and DevOps trends delivered to your inbox weekly.