Docker, tek bir uygulamayı paketlemenin sorununu çözer; ama gerçek bir altyapıda onlarca sunucunun her birine Docker’ı kurmak, güvenlik ayarlarını yapmak, kullanıcıları oluşturmak ve container’ları dağıtmak gibi tekrarlayan işler de vardır. Bunları elle, sunucu sunucu SSH’layarak yapmak hem yorucu hem hataya açıktır. Ansible, bu tür sunucu ve altyapı otomasyonunu YAML ile tarif edilen, tekrar çalıştırıldığında hep aynı sonucu veren (idempotent) “playbook”lar üzerinden çözer.
Ansible’ı farklı kılan ne?
Chef, Puppet gibi diğer otomasyon araçlarının aksine Ansible’ın iki temel özelliği onu özellikle yeni başlayanlar için erişilebilir kılar:
- Agentless (ajansız): Yönettiğiniz sunuculara herhangi bir yazılım kurmanıza gerek yok. Ansible, standart SSH üzerinden bağlanır ve komutları çalıştırır; sadece kontrol makinenizde (Ansible’ın çalıştığı bilgisayar) Python ve Ansible kurulu olması yeterlidir.
- Deklaratif YAML: “Şu adımları çalıştır” yerine “sunucunun son hali şöyle olsun” dersiniz — Docker’ın kurulu olması, belirli bir kullanıcının var olması gibi. Ansible, o son duruma zaten ulaşılmışsa hiçbir şey değiştirmez (idempotency) — playbook’u güvenle defalarca çalıştırabilirsiniz.
Kurulum ve inventory (envanter) dosyası
# Kontrol makinenize (yönetilen sunuculara değil!) kurulum
pip install ansible --break-system-packages
ansible --version
Ansible’a hangi sunucuları yöneteceğinizi bir inventory dosyasıyla söylersiniz:
# inventory.ini
[web]
web1.ornek.com
web2.ornek.com
[db]
db1.ornek.com ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/prod.pem
[web:vars]
ortam=production
# Tüm sunuculara SSH ile erişebildiğinizi doğrulayın
ansible all -i inventory.ini -m ping
-m ping, Ansible’ın “modül” (module) çalıştırma mantığının en basit örneğidir: her komut aslında bir modülü (ping, apt, copy, docker_container gibi) belirttiğiniz sunucularda çalıştırır.
İlk playbook: sunuculara Docker kurmak
# docker-kur.yml
---
- name: Docker Engine'i kur ve yapılandır
hosts: web
become: true # sudo ile çalıştır
tasks:
- name: Gerekli paketleri kur
apt:
name:
- ca-certificates
- curl
- gnupg
state: present
update_cache: true
- name: Docker'ın resmi kurulum betiğini indir
get_url:
url: https://get.docker.com
dest: /tmp/get-docker.sh
mode: '0755'
- name: Docker'ı kur
command: sh /tmp/get-docker.sh
args:
creates: /usr/bin/docker # zaten kuruluysa tekrar çalıştırma
- name: Kullanıcıyı docker grubuna ekle
user:
name: "{{ ansible_user }}"
groups: docker
append: true
- name: Docker servisinin açılışta başladığından emin ol
systemd:
name: docker
enabled: true
state: started
ansible-playbook -i inventory.ini docker-kur.yml
Bu playbook’u web grubundaki iki sunucuya karşı çalıştırdığınızda, Ansible her görevi (task) sırayla uygular ve zaten o durumda olan bir sunucuda hiçbir değişiklik yapmaz — çıktıda changed yerine ok görürsünüz. Bu, playbook’u üçüncü, dördüncü kez çalıştırmaktan çekinmemenizi sağlar.
creates: /usr/bin/docker satırı idempotency’nin somut bir örneği: Ansible bu dosya zaten varsa komutu atlar. Elle yazdığınız command/shell görevlerinde bu tür bir koruma eklemek, playbook’un güvenle tekrar çalıştırılabilir kalmasını sağlar.
community.docker koleksiyonuyla container dağıtmak
Ansible’ın resmi community.docker koleksiyonu, docker_container ve docker_compose_v2 gibi modüllerle container’ları da doğrudan yönetmenizi sağlar — sunucu kurulumuyla container dağıtımını tek bir playbook’ta birleştirebilirsiniz:
ansible-galaxy collection install community.docker
# container-dagit.yml
---
- name: Uygulama container'ını dağıt
hosts: web
become: true
tasks:
- name: En güncel imajı çek
community.docker.docker_image:
name: kullanici-adi/benim-api
tag: latest
source: pull
force_source: true
- name: Container'ı (yoksa) oluştur, (varsa) günceltilmiş imajla yeniden başlat
community.docker.docker_container:
name: benim-api
image: kullanici-adi/benim-api:latest
state: started
restart_policy: unless-stopped
recreate: true
ports:
- "8080:8080"
env:
DATABASE_URL: "{{ vault_database_url }}"
Buradaki vault_database_url değişkeni, gizli bilgilerin playbook’a açık metin olarak yazılmasını önlemek için Ansible Vault ile şifrelenmiş bir dosyadan gelir (ansible-vault create secrets.yml) — tıpkı Docker’da secret’ları imaja gömmemek gerektiği gibi, Ansible playbook’larında da parolalar asla düz metin tutulmamalıdır.
Roller: playbook’ları yeniden kullanılabilir hale getirmek
Playbook’lar büyüdükçe, ilgili görevleri, dosyaları ve varsayılan değişkenleri bir arada tutan role (rol) yapısına geçilir — tıpkı bir Docker imajını farklı projelerde yeniden kullanmak gibi, bir Ansible rolünü de (örneğin “docker-kurulumu” rolü) farklı projelerde tekrar tekrar kullanabilirsiniz:
ansible-galaxy init roles/docker-kurulumu
roles/
docker-kurulumu/
tasks/main.yml # yukarıdaki görevler buraya taşınır
handlers/main.yml # örn. "docker'ı yeniden başlat" gibi tetiklenen eylemler
defaults/main.yml # varsayılan değişkenler
templates/ # Jinja2 şablonları (örn. daemon.json)
# site.yml — rolleri birleştiren ana playbook
---
- hosts: web
become: true
roles:
- docker-kurulumu
- uygulama-dagitimi
Ansible, Docker Compose ve Kubernetes ile nasıl bir arada durur?
| Araç | Hangi katmanı yönetir? |
|---|---|
| Dockerfile | Tek bir imajın içeriği |
| Docker Compose | Tek sunucuda birden fazla container’ın birlikte çalışması |
| Ansible | Sunucuların kendisi: paket kurulumu, kullanıcılar, güvenlik ayarları, birden fazla sunucuya tutarlı dağıtım |
| Kubernetes | Container’ların bir kümede orkestrasyonu, ölçekleme, self-healing |
Bu araçlar birbirini dışlamaz, farklı sorunları çözer. Yaygın bir gerçek dünya deseni: Ansible ile sunucuları (veya Kubernetes node’larının kendisini) hazırlamak, Docker Compose veya Kubernetes ile üzerlerindeki uygulamaları çalıştırmak.
Sunucularınız artık kod olarak, tutarlı ve tekrarlanabilir şekilde yapılandırılıyor. Bir adım daha geriye gidip, bu sunucuların kendisinin (bulut sağlayıcıda bir VM, ağ, güvenlik grubu) nasıl otomatik olarak oluşturulacağını ele almak için sırada Terraform ile altyapıyı kodlama var.