Ansible ile Uzak Bilgisayarlara Docker ve Docker Compose Nasıl Yüklerim?

Önce “Ansible nedir?” sorusuna kısa bir cevapla başlamakta fayda var sanıyorum:

Ansible, ön tanımlı makinelere uzaktan yazılım yükleme, konfigürasyon düzenleme ve tanımlama ve altyapı hazırlama gibi operasyonları otomatize eden bir DevOps aracı olarak tanımlanabilir.

Terraform, Chef ve Puppet gibi yetkin ürünlerle beraber sahada boy gösteren Ansible, 2015 yılının sonundan beri RedHat çatısı altında varlığını sürdürüyor. Kendisini ön plana çıkartan en önemli özelliklerini şöyle özetlemek yanlış olmayacaktır diye düşünüyorum:

  • Agent’a gerek duymaksızın çalışması, istemci makinelere ek yük getirmediği için önemli artılarından bir tanesi. SSH ve WinRM üzerinden komutların iletilmesi sağlanıyor.
  • Yaml formatlı konfigürasyon dosyası (Ansible literatüründe playbook olarak adlandırılır) okunması ve geliştirilmesi kolay bir altyapı hazırlığı sunuyor.
  • Task bazlı sıralı bir şekilde çalışması, her task’ın çıktısını kullanıcı dostu bir şekilde göstermesi ve task’ların sonuçlarına göre akışın düzenlenebilmesi; kısaca bir workflow mantığı üzerine kurgulanmış bir ürün olması ürüne adaptasyonu oldukça kısaltıyor.

İnternette arattığınızda çıkan şu görsel aslında Ansible’ın mimarisini en net şekilde özetler nitelikte;

Kaynak: https://sysadmincasts.com/episodes/43-19-minutes-with-ansible-part-1-4

Girizgahı burada keserek, asıl konumuza dönelim istiyorum. Şu başlığın konusu olan kuruluma.

Docker ve Docker Compose Kurulumu

Yazının bundan sonrasında bir management node’a sahip olduğunuzu ve bu node’da Ansible’ın kurulu olduğunu varsayıyorum.

Örneği hazırlarken lokal makinemde 4 adet sanal makine oluşturdum — VirtualBox ile — . Bu makinelerin IP’leri ve görevleri şu şekilde;

  • MANAGEMENT NODE-> 192.168.56.4
  • CLIENT01 -> 192.168.56.5
  • CLIENT02 -> 192.168.56.6
  • CLIENT03 -> 192.168.56.7

Amacım da istemci makinelere ilgili kurulumları gerçekleştirmek. Bu işlemi gerçekleştirmek için nano /etc/ansible/hosts komutu ile envanterlerin tanımlanacağı konfigürasyon dosyasını açıyorum ve aşağıdaki satırları dosyanın en sonuna ekliyorum.

client01 ansible_host=192.168.56.5
client02 ansible_host=192.168.56.6
client03 ansible_host=192.168.56.7
[swarm_all]
client01
client02
client03
Örneğe devam etmeden önce belirtmekte fayda var; envantere tanımlı istemci makinelerinin ~/.ssh/authorized_keys dosyasında yönetici makinenin ~/.ssh/id_rsa.pub dosyasından kopyalanan ssh-key’i tanımlı olmalıdır. Bu sayede herhangi bir agent’a ihtiyaç duymadan, uzaktan komut çalıştırma mümkün olmakta.

Makinelere ulaşıp ulaşamadığımızı kontrol edelim. Bunun için ansible -m ping swarm_all komutu yeterli olacaktır. Eğer makinelerden aşağıdaki cevabı alıyorsak yola devam edebiliriz:

client01 | SUCCESS => {
"changed": false,
"ping": "pong"
}
client02 | SUCCESS => {
"changed": false,
"ping": "pong"
}
client03 | SUCCESS => {
"changed": false,
"ping": "pong"
}

Sıra geldi işin en keyifli noktasına. Yukarıda bahsettiğimiz workflow’u tanımlayacağımız ve .yml uzantılı playbook dosyasını oluşturalım:

Yukarıda tanımlı dosyayı yönetici makinede herhangi bir yere, istediğimiz bir isimle — ben docker-and-docker-compose.yml olarak adlandırdım — kaydedelim ve aşağıdaki komutu çalıştıralım:

ansible-playbook docker-and-docker-compose.yml

Komutu çalıştırdıktan sonra aşağıdakine benzer, task’ların durumlarını gösteren ekran çıktılarını göreceğiz;

TASK [Add Docker's official GPG key] *******************************************
ok: [client01]
ok: [client02]
ok: [client03]

Playbook dosyasını okumaya çalıştığınızda, akış tasarlamanın oldukça kolay olduğunu anlamanız çok zaman almayacak ancak bazı önemli noktaları not düşmekte fayda görüyorum.

Ansible Playbook

Kritik alanlardan biri root seviyedeki hosts alanı. Bu alana girilen ifade, hosts dosyasına tanımladığımız gruba işaret ediyor. all ifadesi kullanılarak, envanterdeki tüm makinelerde akışın çalışması sağlanabilir.

Referans olarak aşağıdaki workflow adımını — task — alalım;

- name: Add Docker's apt repository
apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_lsb.codename }} stable"
state: present
  • name: Task’lara dair yapacağınız açıklamaları bu alanda konumlandırabilirsiniz. Bu alana yazdığınız metin, ekrana basılan çıktıda da görünecektir.
  • apt_repository: Ansible içerisinde öntanımlı onlarca task bulunuyor. Paket yüklemesi, shell çalıştırma, servis tanımlama gibi komutları soyutlayan nesnelere task deniyor. Bu örnekte paket yöneticisine yeni bir paket kaynağı tanımlaması yapılıyor. {{ ansible_lsb.codename }} ifadesinde süslü parantezler içerisindeki ifade playbook variable olarak literatürde geçiyor. Örnek özelindeki ifade ile de, Linux dağıtımını almaya çalışıyoruz. Değişkenden; Ubuntu 16.04.4 ise “xenial”, Ubuntu 14.04.5 ise “trusty” gibi değerler dönecek ve metin içerisine yerleştirilecek. Kullanabileceğiniz bazı değişkenlere bu adresten ulaşabilirsiniz.
  • state: Yüklenecek paketin durumunun belirtildiği alan. Varsayılan olarak present değeri seçili. latest, build-dep gibi alternatifler de seçilebilir.

Her bir öntanımlı task’ın kendine has özellikleri — property — bulunmakta. https://docs.ansible.com/ansible/latest/modules/ adresinden bu listenin tamamına ulaşabilir ve örnekler yardımıyla kendi playbook’unuzu oluşturabilirsiniz.

Küçük Bir Bonus

Bunun bir arayüzü yok mudur? sorusu kafanızı kurcalıyorsa ücretsiz olarak dağıtılan AWX ve lisanslı Ansible Tower ürünleri ihtiyacınızı maksimum seviyede giderecektir. Ancak bu tür ürünleri öğrenmenin — hatta üründen keyif almanın — en güzel yolunun CLI kullanımından ve konfigürasyon dosyalarının elle tanımlanmasından geçtiğine inananlardanım.