Elli sunucusu olan bir ortamda tek tek SSH ile bağlanıp paket güncellemek, er ya da geç bir sunucuda bir şeyi unutmanıza yol açar. Ansible bu sorunu ajansız çözer. Sunucularda hiçbir yazılım kurmaz, yalnızca SSH bağlantısı ve YAML dosyalarıyla tanımladığınız durumu tüm makinelere aynı şekilde uygular. Bu rehberde kurulumdan Ansible Vault'a kadar gerçek komutlarla ilerliyor, üretimde karşılaşacağınız tuzakları da ele alıyoruz.
Ansible Nedir ve Neden Agentsız Çalışır
Ansible, Red Hat'e ait açık kaynaklı bir otomasyon aracıdır. Puppet ve Chef gibi rakiplerinden farkı, yönetilen sunucuya herhangi bir ajan yazılımı kurmamasıdır; yalnızca Python ve SSH erişimi yeterlidir. Bu da kurulumu küçük ve orta ölçekli altyapılarda hızlı hale getirir, çünkü kurulum derdi control node adı verilen tek bir makinede kalır.
Control node, playbook'ları çalıştırdığınız makinedir; genelde kendi bilgisayarınız ya da bir CI sunucusudur. Yönetilen sunucular (managed nodes) ise sadece SSH anahtarınızı kabul eder, başka bir kurulum gerektirmez. Bu ayrımı netleştirmek önemlidir, çünkü Ansible'ı Puppet'ın ajan-master modeliyle karıştırmak kurulum aşamasında karışıklığa yol açar.
Ansible'ın modül kütüphanesi geniştir: apt, yum, copy, service, template, user gibi yüzlerce hazır modül gelir. Her modül belirli bir görevi yapar ve idempotent çalışacak şekilde tasarlanmıştır; aynı görevi on kez çalıştırsanız da sonuç değişmez. Resmi dokümantasyon (docs.ansible.com), yeni bir modülün parametrelerini kontrol ederken en güvenilir kaynaktır.
Ansible'ı Puppet ve Chef'ten ayıran bir başka özellik push tabanlı çalışma modelidir. Yönetilen sunucu sürekli bir ajanla merkezi sunucuyu yoklamaz; control node değişiklik göndermek istediğinde SSH üzerinden bağlanır, işini bitirir ve çıkar. Bu model ek bir arka plan servisi, ek bir açık port ya da ek bir güvenlik riski getirmez.
Kurulum ve Control Node Hazırlığı
Ansible'ı control node'a kurmak çoğu dağıtımda tek komutluk bir iştir. Debian ve Ubuntu tabanlı sistemlerde paket yöneticisinden, RHEL tabanlı sistemlerde ise EPEL deposu üzerinden kurulur. Kurulumdan sonra sürüm kontrolü yapmak, hangi Ansible ve Python sürümüyle çalıştığınızı doğrulamanızı sağlar.

# Debian/Ubuntu
sudo apt update && sudo apt install -y ansible
# RHEL/CentOS/Rocky (EPEL gerekli)
sudo dnf install -y epel-release
sudo dnf install -y ansible
# Kurulum ve sürüm doğrulama
ansible --version
Ansible Galaxy üzerinden topluluk rollerini de kurabilirsiniz; nginx kurulumu, Docker kurulumu veya PostgreSQL yapılandırması gibi yaygın görevler için hazır roller mevcuttur. ansible-galaxy install komutu bu rolleri ~/.ansible/roles dizinine indirir.
ansible-galaxy install geerlingguy.docker
ansible-galaxy install geerlingguy.postgresql
Yönetilen sunuculara SSH anahtarınızı önceden dağıtmanız gerekir; ssh-copy-id komutu bunu tek adımda halleder. Şifre ile SSH bağlantısı da mümkündür, ama anahtar tabanlı erişim hem daha hızlıdır hem de otomasyon sırasında parola istemi sorununu ortadan kaldırır.
Inventory Dosyası Nasıl Yazılır
Inventory, Ansible'ın hangi sunucuları yöneteceğini tanımlayan dosyadır; en basit hâliyle INI formatında yazılır, YAML formatı da desteklenir. Sunucuları gruplara ayırmak, görevleri yalnızca ilgili makinelere yönlendirmenizi sağlar. Aşağıdaki örnek web ve veritabanı sunucularını ayrı gruplarda tutuyor.
[webservers]
web1.example.com
web2.example.com ansible_host=10.0.1.12
[dbservers]
db1.example.com ansible_user=postgres
[webservers:vars]
http_port=80
[all:vars]
ansible_python_interpreter=/usr/bin/python3
Grup içinde grup tanımlamak da mümkündür; örneğin [production:children] altında webservers ve dbservers'ı toplayıp tek bir üst grup oluşturabilirsiniz. Büyük altyapılarda statik INI dosyası yerine dinamik inventory script'leri (AWS EC2 veya Azure gibi bulut sağlayıcılarından sunucu listesini otomatik çeken) tercih edilir. Inventory'nin doğruluğu tüm otomasyonun temelini oluşturur; yanlış gruba giden bir playbook, yanlış sunucuda servis yeniden başlatabilir.
Inventory dosyasını doğrulamak için ad-hoc komutlar kullanılır; tam bir playbook yazmadan tek bir modülü çalıştırmak istediğinizde bu yöntem işinizi görür.
# Tüm webservers grubuna ping at
ansible webservers -i inventory.ini -m ping
# dbservers grubunda disk kullanımını göster
ansible dbservers -i inventory.ini -a "df -h"
Playbook ve YAML Syntax'ı
Playbook, bir veya daha fazla "play" içeren YAML dosyasıdır; her play, belirli bir sunucu grubunda hangi görevlerin sırayla çalışacağını tanımlar. YAML girinti konusunda katıdır, tab karakteri yerine boşluk kullanmak zorunludur; aksi hâlde yaml.scanner.ScannerError hatasıyla karşılaşırsınız. Aşağıdaki örnek bir web sunucusuna nginx kurup servisi başlatıyor.

---
- name: Web sunucularini yapilandir
hosts: webservers
become: true
vars:
http_port: 80
tasks:
- name: Nginx paketini kur
apt:
name: nginx
state: present
update_cache: true
- name: Konfigurasyon dosyasini kopyala
copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
mode: '0644'
notify: nginx yeniden baslat
- name: Nginx servisinin calistigini garanti et
service:
name: nginx
state: started
enabled: true
handlers:
- name: nginx yeniden baslat
service:
name: nginx
state: restarted
RHEL tabanlı sunucularda apt yerine yum ya da dnf modülünü kullanmanız gerekir; paket adları da dağıtıma göre değişebilir. notify ve handlers çifti önemli bir detaydır: konfigürasyon dosyası değişmediyse servis yeniden başlamaz, yalnızca gerçek bir değişiklik olduğunda handler tetiklenir. Bu davranış, idempotency'nin pratikte nasıl işlediğini gösteren en net örnektir.
Playbook'u çalıştırmadan önce kuru çalıştırma (dry run) yapın; --check bayrağı hiçbir değişiklik uygulamadan neyin değişeceğini gösterir, --diff bayrağı ise dosya farklarını gösterir.
ansible-playbook -i inventory.ini playbook.yml --check --diff
# Sorun yoksa gercek calistirma
ansible-playbook -i inventory.ini playbook.yml
Ad-hoc komut ile playbook arasındaki fark çoğu yeni kullanıcının kafasını karıştırır. Aşağıdaki tablo ikisini ne zaman tercih etmeniz gerektiğini özetliyor.
| Özellik | Ad-hoc komut | Playbook |
|---|---|---|
| Kullanım amacı | Tek seferlik, hızlı kontrol | Tekrarlanabilir, kalıcı yapılandırma |
| Sürüm kontrolü | Yok, komut geçmişte kaybolur | Git ile takip edilebilir |
| Karmaşıklık | Tek modül, tek görev | Çoklu görev, koşullar, handler'lar |
| Örnek senaryo | "Şu an disk doluluğunu göster" | "Web sunucusu kurulumunu standardize et" |
Roller ile Organizasyon
Tek bir playbook dosyasına yüzlerce görev sıkıştırmak, altı ay sonra o dosyaya bakan herkes için anlaşılması zor hâle gelir. Roller, ilgili görevleri, değişkenleri, şablonları ve dosyaları standart bir dizin yapısında bir araya toplar. ansible-galaxy init komutu bu iskeleti otomatik oluşturur.

ansible-galaxy init roles/nginx
Oluşan yapı şu klasörleri içerir:
tasks/main.yml- rolün asıl görevlerihandlers/main.yml- servis yeniden başlatma gibi tetiklenen eylemlertemplates/- Jinja2 şablonları (örneğinnginx.conf.j2)defaults/main.yml- varsayılan değişken değerlerivars/main.yml- override edilmemesi gereken sabit değişkenler
Bir playbook içinde rolü çağırmak tek satırdır, roles: [nginx, postgresql] gibi bir liste yeterlidir. Büyük altyapılarda rolleri ayrı bir Git deposunda tutup requirements.yml üzerinden ansible-galaxy install -r requirements.yml ile çekmek, ekipler arası paylaşımı kolaylaştırır. Ansible Galaxy'deki topluluk rollerini kullanmadan önce kaynak kodunu gözden geçirin; üretim sunucusunda çalışacak kod budur.
Rol bağımlılıklarını yönetmek için meta/main.yml dosyasına dikkat etmek gerekir; bir rol başka bir role bağımlıysa bunu burada tanımlarsınız, Ansible bağımlı rolü otomatik olarak önce çalıştırır. Değişken önceliği konusunda da dikkatli olun: defaults/main.yml en düşük önceliğe sahiptir ve inventory'deki bir değişken bunun üzerine kolayca yazar. Bu önceliği bilmemek, tanımladığınız değerin neden çalışmadığını uzun süre araştırmanıza yol açar.
Ansible Vault ile Gizli Bilgi Yönetimi
Veritabanı şifrelerini ve API anahtarlarını playbook içine düz metin yazıp Git'e göndermek yaygın bir güvenlik hatasıdır. Ansible Vault bu değerleri AES256 ile şifreleyip dosya içinde saklar; şifrelenmiş dosya Git'e güvenle commit edilebilir. ansible-vault encrypt_string komutu tek bir değişkeni şifreler, tüm dosyayı şifrelemenize gerek kalmaz.
# Tek bir degiskeni sifrele
ansible-vault encrypt_string 'GizliSifre123' --name 'db_password'
# Tum bir dosyayi sifrele
ansible-vault encrypt group_vars/production/secrets.yml
# Playbook calistirirken vault sifresini sor
ansible-playbook -i inventory.ini playbook.yml --ask-vault-pass
# Sifreyi bir dosyadan oku (CI/CD icin)
ansible-playbook -i inventory.ini playbook.yml --vault-password-file ~/.vault_pass.txt
Vault şifresini kod deposuna asla eklemeyin; --vault-password-file kullanıyorsanız o dosyayı .gitignore'a ekleyin ve dosya izinlerini 600 yapın. CI/CD ortamlarında bu şifre genelde bir secrets manager'dan (GitHub Actions secrets, GitLab CI variables gibi) çekilip geçici bir dosyaya yazılır. Vault kullanımına dair resmi rehber (docs.ansible.com/ansible/latest/vault_guide/index.html) şifre rotasyonu ve çoklu vault ID senaryolarını da kapsıyor.
Idempotency ve Gerçek Dünya Tuzakları
Idempotency teoride basit görünür ama pratikte shell veya command modülüyle sık sık bozulur. Bu iki modül idempotent değildir; dosya zaten var olsa bile her çalıştırmada komutu yeniden çalıştırır. Mümkün olduğunca copy, template, file, apt, service gibi durum tabanlı (state-based) modülleri tercih edin; shell yalnızca gerçekten başka bir seçenek kalmadığında kullanılmalıdır.
Bir diğer yaygın tuzak, shell kullanmak zorunda kaldığınızda creates veya changed_when parametrelerini atlamaktır. Bu parametreler olmadan Ansible her çalıştırmada görevi "changed" olarak işaretler; playbook'u tekrar çalıştırdığınızda gerçekte hiçbir şey değişmediği hâlde loglar kirlenir. Bir kurulum script'ini shell ile çalıştırıyorsanız creates: /opt/app/.installed eklemek, script zaten çalıştıysa görevi atlamasını sağlar.
Ansible'ı Puppet, Chef veya SaltStack ile karşılaştıranlar genelde hangisinin daha hızlı öğrenildiğini sorar. Aşağıdaki tablo genel eğilimi gösteriyor; kesin performans rakamları ortamdan ortama değişir.
| Araç | Mimari | Öğrenme eğrisi | Dil |
|---|---|---|---|
| Ansible | Agentsız, SSH tabanlı | Düşük-orta | YAML |
| Puppet | Ajan-master modeli | Orta-yüksek | Puppet DSL |
| Chef | Ajan-master modeli | Yüksek | Ruby DSL |
| SaltStack | Agentsız veya ajanlı (opsiyonel) | Orta | YAML |
Son bir uyarı: become: true ile root yetkisi alan görevleri test ortamında --check modunda çalıştırmadan üretime almayın. Bazı modüller check modunda gerçek durumu tam simüle edemez; özel shell komutları içeren görevlerde check modu "değişiklik yok" derken gerçek çalıştırmada beklenmedik bir şey kırılabilir. Küçük bir test sunucusunda gerçek çalıştırmayı doğrulamak, üretimde sürpriz yememenin en güvenilir yoludur.
Henüz yorum yok.
Sohbete katıl. Yorumlar yayınlanmadan önce moderasyondan geçer.