Ansible Notlarım
- Ansible Notlarım
- Docker İçinde Ansible Çalıştıralım
- ansible.cfg Dosyası
- Envanter Dosyası
- -y/ --toml Anahtarıyla Doğrulama
- INI Biçimli Bilgisayar & Grupları İçeren Dosya Oluşturmak
- Grup Tanımı ve Özel Anahtarlar (ungrouped, all)
- Veri Tiplerini type_debug İle Görüntülemek
- ansible_facts
- Metin İşlevleri
- split
- find İşlevi
- ŞARTLI İFADELER
- when İle Şartlı İfade Oluşturmak
- DÖNGÜLER
- with_items
- with_list
- with_lines
- with_nested
- loop
- MODÜLLER
- Hedef Makinelere PING Atmak İçin ping Modülünü Kullanalım
- command, raw, shell Modülleri
- file Modülüyle Dosya İşlemleri
- copy Modülüyle Dosya Oluşturmak
- linefile ile Metin Dosyalarındaki Satırları Yönetin
- line Modülü
- Grup ve Kullanıcı Eklemek/Silmek *
- debug Modülü
- playbook.yaml
- --check
- --tags
- dict2items
- items2dict
Dağıtım ağı kurduğumuza göre dağıtımın yapılacağı hedef makinelerin listesini, bu makinelerin ait olabileceği grupları ve bu grupların da alt gruplarını tanımlayabilmeliyiz. Dağıtım yapılacak hedefimiz belirli bir makine olabileceği gibi makinelerden oluşan grup ya da gruplar olabilir.
Statik ve dinamik olarak envanter oluşturabiliyoruz. Statik envanterleri tutacağımız dosyalar (ki bilgisayarları, gruplarını içerir) çoğunlukla ini veya yaml biçiminde kullanılsa da farklı dosya biçimlerinde oluşturulabilir.
Docker İçinde Ansible Çalıştıralım
# https://4sysops.com/archives/how-to-deploy-ansible-inside-a-docker-container/
# docker build -t ansible:latest .
# docker run -it ansibleFROM ubuntu:18.04ENV DEBIAN_FRONTEND=noninteractiveRUN apt-get update && \
apt-get install -y gcc python-dev libkrb5-dev && \
apt-get install python3-pip -y && \
pip3 install --upgrade pip && \
pip3 install --upgrade virtualenv && \
pip3 install pywinrm[kerberos] && \
apt install krb5-user -y && \
pip3 install pywinrm && \
pip3 install ansible
Şimdi ansible --version
ile yüklü sürümünü öğrenelim:
docker run -it ansible --version
ansible.cfg Dosyası
Aşağıdaki durumlara göre ansible.cfg
dosyamızın yeri belirlenir:
ANSIBLE_CONFIG
Ortam değişkeni tanımlı ve içindeki dosya adresi,ansible
Komutlarını çalıştırdığımız dizinin içinde./ansible.cfg
dosyası,ansible
Komutlarını çalıştırdığımız kullanıcının ev dizininde~/.ansible.cfg
dosyasyı yoksa~/ansible.cfg
(noktasız) dosyası,- hiç olmadı
/etc/ansible/ansible.cfg
dosyası
SSH Bağlantılarının ayarlarını [defaults]
içinde yapabiliyorken, yetkilerle ilgili ayarları [privilege_escalation]
bölümünde tanımlıyor.
[defaults]
#remote_user=root
#remote_port=22
#ask_pass=False
remote_user
Eğer belirtilmezse ansible içinde kullanılan kullanıcı olacaktır ve uzak bilgisayara bu kullanıcıyla bağlanılacaktır.
remote_port
SSH yapmak için kullanılan port numarasıdır ve değiştirilmezse 22 kalacaktır.
ask_pass
Varsayılan olarak bağlantıda kullanıcı şifresi sorulmaz çünkü SSH anahtarıyla kullanıcı doğrulaması yapmak ister. Ancak SSH bağlantısında kullanıcının şifresinin girilmesi beklenirse bu değerin True
olarak ayarlanması gerekecektir.
[privilege_escalation]
bölümünde bağlanırken kullandığımız kullanıcı yerine komutları çalıştırırken hangi kullanıcı olmak istediğimizi belirtiriz. Örneğin bağlantıda cem
adında super user
yetkisinde bir kullanıcı ile bağlantı izni verildi. Ama bir paket kurulumunu super user
yetkisiyle yapmamız gerekeceği için ya sudo
ile ya da su
ile paket kurulumunu başlatabiliriz. Yani cem
kullanıcısından süper kullanıcı olan başka bir kullanıcıya dönüşmemiz gerekecektir.
- Yetki yükseltmeye ihtiyacımız yoksa
become
değeriFalse
kalacaktır. - Yükselteceğimiz kullanıcı varsayılan
root
kullanıcısıdır ancak çoğu sistemroot
kullanıcısınıdisable
eder ve yeni bir kullanıcı tanımlayarak onun üstünden devam eder.become_user
işte bu yeni kullanıcı adı olmalı. become_method
olaraksudo
kullanıldığı gibisu
da kullanılabilir.- Yetki yükseltmede şifre sorulmasını istiyorsak
become_ask_pass
açık olmalı
Envanter Dosyası
Ref: *
Envanter bilgilerini tutan dosyayı -i
anahtarı ve dosya yoluyla verebiliriz. Envanter dosyasında tanımlı makinelerin hepsinde değil bir grup veya host üstünde çalışması için ilgili hedefin adını yazarız.
Bir örnekde command
modülünü kullanarak olsun:
Dosya yolunu vermediğimi vakit varsayılan konum, /etc/ansible/hosts adlı bir dosyadır. -i <dosya_yolu>
seçeneğini kullanarak komut satırında farklı bir envanter dosyası belirtebilirsiniz.
Ayrıca, birden çok envanter dosyası kullanabilir ve/veya Dinamik envanterle dinamik veya bulut kaynaklarından veya farklı biçimlerden (YAML, ini vb.) envanter çekebilirsiniz.
2.4 sürümünde tanıtılan Ansible, bunu esnek ve özelleştirilebilir hale getirmek için Envanter Eklentilerine sahiptir.
Ansible’ın konfigürasyon dosyasını ansible --version
verir:
Envanterimiz Ansible’ın konfigürasyon dosyası tarafından denetlenir. Hangi konfigürasyon dosyasının kullanımda olduğunu öğrenmek için Ansible’ın sürümünde kullandığımız komut ile ansible --version
konfigürasyon dosyasının yerini öğrenebiliriz.
Eğer çıktımızda config file
anahtarının değerindeki dosyamızın içeriğine gidersek `[defaults]` bölümü içinde `inventory` anahtarı varsa, değer kısmındaki dosya, statik olarak envanterimizin tutulduğu dosya yolu olacaktır:
[defaults]
inventory = /envanterimizin/sabit/dosya/yolu
Eğer config file
adında anahtarımıza değer atanmamışsa yani None
ise envanter dosyamızı /etc/ansible/hosts
dizininden kullanılacaktır.
Bizim konteyner içinde ne etc/ansible
dizini var, ne de ansible --version
içinde config file
ile ansible.cfg
dosyasının yeri belirtiliyor. Bu yüzden bu adreste anlatıldığı gibi bu github içeriğini yapıştırmak için önce /etc/ansible
dizini oluşturup içine bu içeriği yapıştıracağız ve artık konfigürasyon doyamız karşımızda:
Bu ayar dosyamızda envanter dosyamızın satırını yorum olmaktan çıkarıp, hedef adreste bir hosts
dosyasını oluşturalım (farklı adreste olur tabi):
Şimdilik bilgisayar adlarını tutacağımız /etc/ansible/hosts
dosyamızın doğruluğunu anlamak için ansible-inventory
komutunu kullanacağız. Denemelerimde hata aldığım, ‘yok bu farklı olmalı’ dediğim durumlar oldu ve nihayetinde (sonunda) aşağıdaki gibi geçerli (valid) bir çıktı elde ettim:
Biraz daha karmaşıklaştıralım:
- G_NRF’in sadece G_STO altında göründüğüne dikkat!
- Satır 20 ve 21'de 11.12.13.31 adresi tanımlı ancak G_NRF grubunda sadece bir kez görüntülüyor.
-y/--toml Anahtarıyla Doğrulama
Varsayılan olarak JSON biçiminde çıktı verirken, TOML formatı için --toml ve YAML formatı için -y anahtarını kullanırız:
TOML Formatı için python’un kütüphanesine gereksinim duyacaksınız:
INI Biçimli Bilgisayar & Grupları İçeren Dosya Oluşturmak
Doğrudan sunucu isim veya IP bilgileriyle bir dosyayı envanter dosyası olarak verebiliriz.
INI Biçimli:
mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
YAML Biçimli:
Her bilgisayar her zaman en az 2 gruba ait olacaktır (tümü ve gruplandırılmamış veya tümü ve başka bir grup).İki varsayılan grup vardır:
1. tümü (all)
2. gruplanmamış (ungrouped).all grubu, her ana bilgisayarı içerir.
ungrouped ise hepsinden grubu olmayan bilgisayarları içerir.
all & ungrouped bilinçli tanımlanmasa bile örtük olarak (implicit) tanımlı olacaklardır.all:
hosts:
192.168.12.50:
test_sunucu.alanadi.com:
children:
web_sunucular_grubu:
hosts:
sunucuAdi.alanAdi.com:
192.168.16.54:
dbservers:
hosts:
one.example.com:
testServers:
hosts:
# Bir bilgisayar farklı gruplar altında da tanımlanabilir
192.168.16.54:# host'a özel değişken tanımlayıp playbook içinde kullanabiliriz
two.example.com:
http_port_degisken: 80
hosta_ozgu_baska_degisken: 808
# bağlantı bilgileri de değişken olarak host içinde tanımlanabilir
ansible_connection: ssh
ansible_user: myuser localhost_takma_adi_bu_olsun:
ansible_connection: local
ansible_port: 5555
ansible_host: 127.0.0.1
Grup Tanımı ve Özel Anahtarlar (ungrouped, all)
Grup adlarında bölü karakterini kullanamazsınız. Ancak alt çizgiyi grup adlarında kullanabilirsiniz. Bilgisayar isimleriyle grup adı tanımlamayın!
- Gruplandırmadığınız sunucuları
ungrouped
anahtarıyla - Gruplandırsanız bile tüm sunucuları
all
anahtarıyla
işleme tabi tutabilirsiniz.
Veri Tiplerini type_debug İle Görüntülemek
Metin İşlevleri
split
- name: split ile bosluklardan bol
debug:
msg: "{{ metin.split() }}"- name: split ile \n karakterinden bol
debug:
msg: "{{ metin.split('\n') }}"- name: split ile \t karakterinden bol
debug:
msg: "{{ metin.split('\t') }}"
Çıktılar:
find İşlevi
---
- name: Metin islemleri
hosts:
- 1.1.1.4
become: true
vars:
metin: "bu \n bir '\n' metin olsun\ndegil \t mi?"
tasks:
# find İşlevi
- name: find ile icinde ara ve bul
debug:
msg: "{{ metin.find('bu') }}"
tags:
- find- name: find ile icinde ara ama bulama
debug:
msg: "{{ metin.find('şu') }}"
tags:
- find
Metin tipi değerin find
ile içinde ararken
DÖNGÜLER
Arama eklentileri (lookup plugins), Jinja2 şablonlama dilinin Ansible’a özgü bir uzantısıdır.
- Dış kaynaklardan (dosyalar, veritabanları, anahtar/değer depoları, API’ler ve diğer hizmetler) verilere erişmek için arama eklentilerini kullanabilirsiniz.
- Tüm şablonlar gibi, aramalar da Ansible kontrol makinesinde yürütülür ve değerlendirilir.
- Ansible, bir arama eklentisi tarafından döndürülen verileri standart şablonlama sistemiyle kullanılabilir hale getirir.
- Dış kaynaklardan gelen bilgilerle değişkenleri veya şablonları yüklemek için arama eklentilerini kullanabilirsiniz.
with_items
Bu arama, kendisine verilen öğelerin bir listesini döndürür, eğer üst düzey öğelerden herhangi biri de bir listeyse, onu düzleştirir, ancak tekrarlamaz.
with_list
Bu, içeriğin herhangi bir şekilde dönüştürülmesini istemiyorsanız, with_list döngüsü olarak kullanılmak üzere çoğunlukla bir noop’tur. flatten Süzgecinin kullanılması gibi çalışacaktır. Sadece birinci seviyede düzleştirme yapılır yani içi içe birden fazla dizi olursa [3,4,[2,1]]
için tek dizi yapar [3,4,2,1]
ancak daha fazla dizi iç içe olsa dahi [3,4,[2,[1,1]]]
sadece birinci seviyede düzleştirir: [3,4,2,[1,1]]
with_lines
Komuttan dönen stdout satırları list olarak verilir
with_nested
Giriş listelerinin öğelerini ayrıştıran listelerden oluşan bir liste
- name: Çarpraz olacak şekilde dizi döner
debug: var=item
with_nested:
- [ 'SARI', 'SIYAH' ]
- [ 'kirmizi', 'mavi', 'beyaz' ]
tags:
- with
- with_nested
loop
MODÜLLER
Hedef Makinelere PING Atmak İçin ping Modülünü Kullanalım
Tüm makineleri en kolayından ayaktalar mı diye ping modülüyle kontrol edebiliriz.
# ansible all -m ping
Eğer Ansible sunucumuzda openssh-client yoksa aşağıdaki hata mesajını alırız:
# ansible all -m ping
[WARNING]: Skipping unexpected key (g) in group (all), only "vars", "children" and "hosts" are
valid
1.1.1.2 | FAILED! => {
"msg": "Unable to execute ssh command line on a controller due to: [Errno 2] No such file or directory: b'ssh': b'ssh'"
}
Çözüm için ssh yapabilmemiz, bunun içinde ssh istemci uygulamasını kurmamız gerekir:
$ apt install -y openssh-client
Şimdi tekrar içinde sadece 1 sunucu olan listemize ping atalım:
Aldığımız hata:
1.1.1.3 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: root@1.1.1.3: Permission denied (publickey,password).",
"unreachable": true
}
Hatayı biraz daha ayrıntılı görmek için -vvv
argümanı kullanalım:
Hatamız 3 kere denenip aynı şekilde sonlanan:
<1.1.1.3> ESTABLISH SSH CONNECTION FOR USER: root
<1.1.1.3> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="root"' -o ConnectTimeout=10 -o ControlPath=/root/.ansible/cp/908e805cd5 1.1.1.3 '/bin/sh -c '"'"'echo ~root && sleep 0'"'"''
<1.1.1.3> (255, b'', b'root@1.1.1.3: Permission denied (publickey,password).\r\n')
Ansible SSH yaparken şifreyi giremediği için bu hatayı alıyor. Oysa elle denediğimizde şifre ekranı geliyor ve doğru giriş yaptığımızda ta taam:
O halde ping komutumuzun peşine her SSH bağlantısı kuracağı makine şifre sorsun diye --ask-pass
argümanı ekleyelim komuta:
Bu kez SSH bağlantılarında şifre girmemizi sağlayan sshpass
uygulamasının yokluğundan dert yanacak:
Kuralım ve tekrar deneyelim, sorunca şifreyi de girelim:
O halde sürekli --ask-pass
anahtarını girmemek için ansible.cfg
dosyamızda ask_pass
anahtarını True
değerine getirelim:
Sürekli şifre sormasını beklemek de otomasyon mantığına ters olduğuna göre farklı bir yöntem bulmalıyız..!
command İle AdHoc Komutlar Çalıştıralım
ping
Modülü ile bilgisayarlara ulaştık.
command, raw, shell Modülleri
Şimdi
command
ansible all -k -m command -a ‘cat /etc/passwd’raw
shell
modülleriyle komutlar çalıştıralım. shell
ve command
modüllerin çalışabilmesi için Ansible makinesinde Python kurulu olmalı, ancak raw
modülü için Python şartı olmadığı gibi doğrudan uzak makinede shell üstünde çalıştırır.
command
Modülü kabuk içinde çalışacak bir komutu çalıştırmayacaktır. export
ve set
komutları kabuğun ortam değişkenlerini ayarladığımız komutlar olup çalıştırabilmek için yukarıdaki örnekte olduğu gibi shell
modülünü kullanmamız gerekir.
Uzak makinede hata aldığımızda aşağıdaki gibi rc
değeri 0'dan farklı bir değer taşır. ls hede
diye bir dosya olmadığı için hata vererek çıkacaktır.
file Modülüyle Dosya İşlemleri
- Dosyaların, sembolik bağlantıların veya dizinlerin özniteliklerini ayarlayın.
- Alternatif olarak, dosyaları, sembolik bağlantıları veya dizinleri kaldırın.
- Diğer birçok modül, dosya modülüyle aynı seçenekleri destekler —
copy
,template
veassemble
dahil. - Windows hedefleri için bunun yerine ansible.windows.win_file modülünü kullanın.
- name: Aynı dosyaya dokunun, ancak bazı izinleri ekleyin/kaldırın
file:
path: /etc/foo.conf
state: touch
mode: u+rw,g-wx,o-rwx- name: Aynı dosyaya tekrar dokunun, ancak süreleri değiştirmeyin, bu, görevi önemsiz kılar
file:
path: /etc/foo.conf
state: touch
mode: u+rw,g-wx,o-rwx
modification_time: preserve
access_time: preserve- name: Mevcut değilse bir dizin oluşturun
file:
path: /etc/some_directory
state: directory
mode: '0755'- name: Dosyanın değişim ve erişim zamanını güncelleyin
file:
path: /etc/some_file
state: file
modification_time: now
access_time: now- name: Erişim süresini, epoch değerinden saniyeye göre ayarlayın
file:
path: /etc/another_file
state: file
access_time: '{{ "%Y%m%d%H%M.%S" | strftime(stat_var.stat.atime) }}'- name: Bir dizinin sahipliğini yinelemeli (recursive) değiştirme
file:
path: /etc/foo
state: directory
recurse: yes
owner: foo
group: foo- name: Dosyayı kaldır (dosya siler)
file:
path: /etc/foo.txt
state: absent
copy Modülüyle Dosya Oluşturmak
Nasıl kullanıldığına dair belegeleri görebilmek için:
# ansible-doc copy
Dosyayı kendi bilgisayarımızdan uzak sunucuya aktarmak istiyorsak:
- name: Copy file with owner and permissions
copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
owner: foo
group: foo
mode: '0644'
Kodumuz sadece metin içeriğiyle bir dosya oluşturmak ise aşağıdaki gibi:
linefile ile Metin Dosyalarındaki Satırları Yönetin
- Bu modül, belirli bir satırın bir dosyada olmasını sağlar veya geriye dönük bir normal ifade kullanarak mevcut bir satırı değiştirir.
- Bu, öncelikle yalnızca bir dosyadaki tek bir satırı değiştirmek istediğinizde kullanışlıdır.
- Birden çok benzer satırı değiştirmek istiyorsanız
replace
modülüne bakın veya bir dosyaya satır bloğu eklemek/güncellemek/kaldırmak istiyorsanızblockinfile
dosyasını kontrol edin. - Diğer durumlar için
copy
veyatemplate
modüllerine bakın.
line Modülü
Bir veya daha fazla komut çalıştırın ve çıktıyı satırlara bölün ve bunları bir liste olarak döndürün.
lookup
Modülü, dosya içeriğini Ansible denetleyicisinin dosya sistemindeki bir dosyadan döndürür.Metin türünde dosya içeriği döner:
debug: msg="{{ lookup('file', ‘/etc/resolv.conf') }}"
Tüm lookup
komutları gibi, bu da Ansible denetleyicisinde çalışır ve become
gibi diğer anahtar kelimelerden etkilenmez. Farklı izinler kullanmanız gerekiyorsa, komutu değiştirmeniz veya Ansible’ı başka bir kullanıcı olarak çalıştırmanız gerekir.
- name: Dosyadan oku, satır satır yazdır
debug:
msg: "`cat ...` ciktisindan satir: {{ item }}"
with_lines: cat /etc/resolv.conf
- name: Bir komut sonucu üzerinde döngü oluşturmaya ilişkin daha kullanışlı bir örnek
shell: "/usr/bin/frobnicate {{ item }}"
with_lines:
- "/usr/bin/frobnications_per_host --param {{ inventory_hostname }}"
Grup ve Kullanıcı Eklemek/Silmek *
ansible -i ./envanter.yaml takma_ad -m shell -a 'cat /etc/passwd'
ansible -i ./envanter.yaml takma_ad -m shell -a 'cat /etc/group'ansible -i ./envanter.yaml takma_ad -m group -a 'name=yeni_grup_adi'ansible -i ./envanter.yaml takma_ad -m user -a 'name=yeni_kullanici_adi group=yeni_grup_adi'ansible -i ./envanter.yaml takma_ad -m shell -a 'cat /etc/passwd'
ansible -i ./envanter.yaml takma_ad -m shell -a 'cat /etc/group'
Paket işlemleri kullanılacak modüller package
, yum
, apt
, bower
ve diğerleri kurmak için state=present
kaldırmak için state=absent
argümanları kullanılacak.
Yüklü olduğu için tekrar yüklemek istediğimizde bir şeyin değişmediği mesajını alacağız:
playbook.yaml
--check
argümanıyla YAML dosyasının doğrulamasını yaparız
$ ansible-playbook kullanici_ve_grup_yarat.yml --check
--tags
İle görevleri etiketleyip çalıştırırken süzebiliriz:
ansible-playbook playbook.yml --tags "cat,cikti,debug"
{{ degisken | dict2items }}
ile degiskenin ozellik ve değerlerini key-value ikilisi halinde sözlük tipine çevirir:
tasks:
- name: Debug ve dict2items ile degiskeni liste halinde yazdir
debug:
msg: "{{ item.key }} <-> {{ item.value }}"
loop: "{{ degisken | dict2items }}"
vars:
degisken:
anahtar1: deger1
anahtar2: deger2
anahtarNesne:
degerNesne:
anahtar: deger
key: value
tags:
- debug
- dict2items
{{ degisken | items2dict }}
ile anahtar değer ikililerini sözlük tipine çevirir:
debug Modülü
akak
- name: Debug ve dict2items ile degiskeni liste halinde yazdir
ansible.builtin.debug:
msg: "{{ item.key }} <-> {{ item.value }}"
loop: "{{ degisken | dict2items }}"
vars:
degisken:
anahtar1: deger1
anahtar2: deger2
anahtarNesne:
degerNesne:
anahtar: deger
key: value
tags:
- debug
- dict2items
cat ile dosya içeriğini bir değişkene atayıp debug ile görüntülemek:
- name: resolv.conf içeriğini görüntüle
command: cat resolv.conf chdir=/etc
register: komut_ciktisi
tags:
- cat- debug: msg="{{ komut_ciktisi.stdout }}"
tags:
- cat
lookup ile dosya içeriğini okumak:
- debug: msg="{{lookup('file', '/etc/passwd') }}"
var İle
- name: display multiple file contents
debug: var=item
with_file:
- "/etc/resolv.conf"
- "/etc/passwd"
debug şu şekilde de yazılabilir:
- debug:
var: item
with_file:
- "/etc/resolv.conf"
- "/etc/passwd"
ansible.cfg dosyamız hangi verileri eziyor görelim: