#!/bin/bash
# Kurulacak paketin adı (örnek: htop, curl, nginx, vs)
PAKET_ADI="htop"
# Ansible komutu
ansible all -i hosts -m apt -a "name=$PAKET_ADI state=present" --become
Böylece kurmak istediğim farklı paketler olduğunda içerisine girip paket adını güncellemem yeterli olabilir.
Dosyaya çalıştırma izni vermeyi de unutmuyoruz:
chmod +x paket_kur.sh
Şimdi ise ilk Playbook'umuzu deneyelim, birden fazla paket kurulumunu bir yml dosyası ile host'larımıza gönderelim.
vi package_install.yml dosyasını oluşturdum ve aşağıdaki bilgileri ekledim:
---
- name: Paket kurulumları
hosts: all
become: yes
tasks:
- name: htop kur
apt:
name: htop
state: present
- name: curl kur
apt:
name: curl
state: present
- name: git kur
apt:
name: git
state: present
Ardından playbook dosyamı koşmak için bu komutu kullanıyorum:
ansible-playbook -i hosts package_install.yml
Ve böylece tek bir yml dosyasını çalıştırarak ansible sayesinde tüm hosts makinelerime aynı anda birden fazla uygulama kurulumunu gerçekleştirmiş oldum. Makinelere tek tek bağlanmadım, paketleri tek tek kurmayı denemedim ve zaman kaybı yaşamadım.
Tüm makineleri kapatmak için bir .sh dosyası
#!/bin/bash
# Ansible inventory dosyasını belirt
INVENTORY_FILE="hosts"
# Tüm makineleri anında kapat
ansible all -i "$INVENTORY_FILE" -a "/sbin/shutdown now" --become
Tüm makinelerde bir klasör oluşturmak için: create_folder.sh
#!/bin/bash
# Ansible inventory dosyası
INVENTORY_FILE="hosts"
# Uzak makinelerde klasör oluştur
ansible all -i "$INVENTORY_FILE" -m file -a "path=/tmp/yeni_klasor state=directory mode=0755"
chmod +x create_folder.sh
Bir istisna, tüm hostlara değil, özel bir gruba işlem yapmak için ek bir parametre kullanılır:
ansible-playbook -i hosts package_install.yml --limit web
Command modülü ile uptime bilgisini öğrenme:
ansible all -i hosts -m command -a "uptime"
Copy komutu ile dosyaları hostlara kopyalamak:
ansible all -i hosts -m copy -a "src=dosya.txt dest=/tmp/dosya.txt"
Şimdi ise bir playbook ile hem paket kurulumu hem de bir dosya oluşturarak içerisine veri yazmayı deneyelim:
- name: Paket kur ve dosya kopyala
hosts: all
become: yes
tasks:
- name: htop paketini kur
apt:
name: htop
state: present
- name: Bilgi dosyasını kopyala
copy:
content: "Bu dosya Ansible tarafından oluşturulmuştur\n"
dest: /tmp/ansible_bilgi.txt
owner: ubuntu
group: ubuntu
mode: '0644'
Sırada bir servis kurmak ve o servisin çalışıp çalışmadığını check etmek var:
apache_setup.yml dosyasını oluşturuyorum ve içeriğini aşağıdaki gibi yapıyorum:
- name: Apache kurulumu ve servisi yönetimi
hosts: all
become: yes
tasks:
- name: Apache2 paketini kur
apt:
name: apache2
state: present
update_cache: yes
- name: Apache servisini başlat
service:
name: apache2
state: started
enabled: yes
Bu servisi sadece web hostlarıma kurmak istedim, o yüzden bu şekilde bir komut koşuyorum:
ansible-playbook -i hosts apache_setup.yml --limit web
Ve servislerin durumunu check etmek istiyorum:
When kullanarak bir yml dosyasının içerisine koşul ekleyebiliriz. Ancak bunu zaten --limit komutu ile de yapabilyoruz:
- name: Koşullu görev örneği
hosts: all
become: yes
tasks:
- name: Sadece worker1'de bu dosyayı oluştur
copy:
content: "Bu dosya sadece worker1 içindir\n"
dest: /tmp/worker1_ozel.txt
when: inventory_hostname == "worker1"
Gruplamayı yml dosyasının içerisinde de yapabiriz, böylelikle when koşulu veya --limit kullanmadan birden fazla görevi aslında yml dosyasında tek tek host gruplarına atamak mümkün:
Yeni bir yml dosyası oluşturdum: group_specific_tasks.yml
Bu yml dosyası sadece web ve db makinelerime işlem yapacak ve bu işlem örnekteki gibi bir file oluşturma işlemi olacağı gibi, app kurulumu, güncellemesi vs. gibi herhangi bir işlem olabilir:
- name: Web grubuna özel görev
hosts: web
become: yes
tasks:
- name: Web makinesine özel bilgi dosyası
copy:
content: "Bu worker bir WEB sunucusudur.\n"
dest: /tmp/web_bilgi.txt
- name: DB grubuna özel görev
hosts: db
become: yes
tasks:
- name: DB makinesine özel bilgi dosyası
copy:
content: "Bu worker bir VERİTABANI sunucusudur.\n"
dest: /tmp/db_bilgi.txt
Ansible Roles Yapısının Kullanımı
Ansible'da roles, yapılandırmaları görev, değişken, şablon, handler gibi mantıksal klasörlere ayırır.
Gerçek projelerde playbook'lar roles kullanılarak kurulur.
Örneğin webserver için bir role oluşturmak istiyorum, bu durumda aşağıdaki komutu çalıştırıyorum:
ansible-galaxy init roles/webserver
Ansible bu role için kendi özel yapısını oluşturur:
Tasks/main.yml içerisine aşağıdaki konfiği girdim:
- name: Apache kur
apt:
name: apache2
state: present
update_cache: yes
- name: Apache2 servis başlasın ve aktif kalsın
service:
name: apache2
state: started
enabled: yes
- name: Özel hoşgeldiniz sayfası
copy:
content: "Merhaba Hakan! Apache başarıyla çalışıyor.\n"
dest: /var/www/html/index.html
owner: root
group: root
mode: '0644'
Projeyi çalıştırabilmek için ana dizinimde (benim için ansible lab çalışmalarını yaptığım ve diğer hosts dosyamın bulunduğu yer) site.yml isimli bir dosya oluşturuyorum ve aşağıdaki gibi konfig giriyorum:
- name: Web makinelerine apache kur, servisi başlat, aktif kalsın ve özel hoşgeldin sayfası oluştur.
hosts: web
become: yes
roles:
- webserver
Böylelikle site.yml dosyasını playbook ile koştuğumda webserver rolünde daha önce tanımladığım tüm işlemler gerçekleştiriliyor. Daha işlevsel bir yapıya kavuşmuş oluyorum. Her şey tek bir yml dosyasında olmaktansa görev ve sorumluluklara göre yani rollere göre yml dosyalarını aslında ayırmış oluyorum.
ansible-playbook -i hosts site.yml
sudo systemctl status apache2
sudo systemctl restart apache2
sudo ufw allow 80
sudo ufw allow 443
sudo ufw reload
sudo ufw status
Ve ardından kendi ana bilgisayarımın tarayıcısını kullanarak http://192.168.1.110:80 bağlantısına gitmeyi çalıştığımda worker1 isimli makinemde çalışan apache2 üzerindeki sayfaya ulaşabildim. Ansible ile gönderilen ve sayfa girişine eklenen yazı da karşıma çıkmış oldu. Böylece çalışmayı başarıyla tamamladım.
Handlers Kullanımına Örnek
Bu deneme için init komutunu tekrar koştum ve ikinci bir dizin oluşmasını sağladım, ikinci bir role gibi. ansible-galaxy init roles/webroles2-handlers ve ilgili rolü koşmak için yeni bir yml dosyası oluşturarak ilerledim.
Handlers, bir görev değişiklik algılandığında tetiklenen özel görevlerdir. Genellikle servisleri yeniden başlatmak, yeniden yüklemek gibi işlemler için kullanılır. Bizde Apache web sayfamızın içeriğinde bir değişiklik algılandığında örnek olması için bir tetikleyici kurgulayacağız ve sistem bu değişikliği algılayarak otomatik olarak apache servisini restart edecek. Bu sadece basit bir örnek, ihtiyaca göre buradaki handlers yeteneklerinden farklı şekillerde yararlanılabilir.
roles/webroles2-handlers/tasks/main.yml içerisine bir ekleme yapıyorum, daha önce eklediğimiz görevlere ek olarak:
---
- name: Apache web sunucusunun kurulu olduğundan emin olun
ansible.builtin.apt:
name: apache2
state: present
update_cache: yes
become: yes
notify: restart_apache_service
- name: Ana sayfa içeriğini değiştirin
ansible.builtin.copy:
content: "<html><body><h1>Ansible Handler Pratiği Başarılı!</h1></body></html>"
dest: /var/www/html/index.html
become: yes
notify: restart_apache_service
Şimdi ise Handler dosyasını oluşturarak içerisine tetikleyicimizi ekliyoruz:
vi roles/webroles2-handlers/handlers/main.yml
---
- name: restart_apache_service
ansible.builtin.service:
name: apache2
state: restarted
become: yes
Şimdi ise Playbook'u oluşturalım: vi 11-handlers-web-webroles.yml
---
- name: Web server rolünü çalıştırma
hosts: web
roles:
- webroles2-handlers
Şimdi ise tetikleyiciyi test edebiliriz:
ansible-playbook -i hosts 11-handlers-web-webroles.yml
Bu çıktı bize şunu söylüyor: Ansible, web sayfasının içeriğinin değiştiğini algıladı. Bu değişiklik nedeniyle, playbook'taki diğer görevler tamamlandıktan sonra, tanımladığınız restart_apache_service handler'ını çalıştırdı. Handler başarılı bir şekilde çalışarak Apache'yi yeniden başlattı ve playbook'unuzu hatasız bir şekilde tamamladı.
Jinja2 Şablon Kullanımına Örnek
Öncelikle yeni bir role oluşturuyorum, bu 12. yml file'ım olmuş olacak.
#ansible-galaxy init info_creator
/roles/info_creator/templates/ dizini altında bilgi.txt.j2 isimli bir dosya oluşturdum ve içeriğini aşağıdaki gibi güncelledim:
Burada toplanan verilere aynı zamanda Ansible Facts ismi verilir.
Bu sunucuya ait bilgiler:
Hostname:
{{ ansible_hostname }}
IP Adresi: {{ ansible_host }}
İşletim Sistemi: {{ ansible_distribution }} {{ ansible_distribution_version }}
Tarih: {{ ansible_date_time.iso8601 }}
/tasks/main.yml içerisine de ilgili ana görevimi ekliyorum:
---
- name: Dinamik bilgi dosyasını oluşturun
ansible.builtin.template:
src: bilgi.txt.j2
dest: /home/ubuntu/bilgi.txt
owner: ubuntu
group: ubuntu
mode: '0644'
become: yes
ve artık playbook'u oluşturup koşabilirim:
#vi 12-create_info_jinja2_file.yml
ve içerisine:
---
- name: Dinamik bilgi dosyasını oluşturma
hosts: web
roles:
- info_creator
Artık playbook'u koştuktan sonra ilgili makinenin /home/ubuntu/ dizininde yeralan bilgi.txt dosyasını kontrol edebilir ve dinamik bir şekilde bu belgenin güncellendiğini görebilirim:
Jinja2 şablonları, statik dosyaları olduğu gibi kopyalamak yerine, dinamik olarak oluşturmanızı sağlar. Bu şablonlar, her sunucuya özel bilgileri (IP adresi, hostname, port gibi) kullanarak yapılandırma dosyalarını otomatik olarak doldurabilir. Örneğin, bir web sunucusu için Apache sanal host yapılandırma dosyası oluştururken ServerName ve DocumentRoot gibi değerleri sunucunun hostname'ine göre dinamik olarak ayarlayabilirsiniz. Bu sayede, farklı sunucular için ayrı ayrı dosyalar oluşturmak yerine tek bir şablonu kullanabilir ve kod tekrarını önleyebilirsiniz. Aynı zamanda veritabanı yapılandırma dosyalarında bellek ayarları gibi değerleri, sunucunun özelliklerine göre belirlemek için de Jinja2 şablonlarından yararlanabilirsiniz.
Diyelimki zabbix server'ınız var ve zabbix agentları onlarca makineye kurdunuz ve konfigüre ettiniz. Çeşitli nedenlerle zabbix server IP'ni değişti. Gidip tek tek makinelerinizdeki zabbix conf dosyasını düzenlemenize gerek yok, bunu bir yml file ile ansible kullanarak kolaylıkla halledebilirsiniz.
Bir başka örnek, makinelerinize cronjob ekleyebilirsiniz. Hatta düzenli cronjoblarınız varsa, envanterinize yeni eklenen bir makine olduğunda crontab'ına ilgili jobların eklenmesini de otomatikleştirebilirsiniz. Cronjob yml dosyanızı bir scriptin içerisine yazarsınız ve ilgili scripti de ansible kurulu makinenizin crontab'ine istediğiniz zaman aralığına göre eklerseniz. Bundan böylelikle sadece envanter dosyanızı yani hosts file'ı güncellemeniz yeterli olacaktır. Crontab otomatik zamanı geldiğinde eklenecek.
Veya farklı bir örnek, NTP sunucusu kurmak istediniz. Bunu elbette Crony ile yapabilirsiniz. Hem kurulumarı hem de ilgili konfigürasyonu ansible ile koşmanız mümkün. Birkaç dakikada tüm makinelerinizin baktığı NTP sunucusunu güncellenir. Ansible bu ve benzeri birden fazla esneklik ve kolaylık sağlıyor. Zaman zaman bazı örnekler paylaşmaya devam edeceğim, şimdilik bu yazıyı burada sonlandırıyorum.