Ansible Playbook'larla Elastik Yığını Otomatik Olarak Güncelleyin
Yayınlanan: 2022-03-11Binlerce cihazdan oluşan bir ağ için günlük analizi, Elastik Yığını merkezi günlük kaydı çözümü olarak kullanmaya karar vermeden önce karmaşık, zaman alıcı ve sıkıcı bir görevdi. Çok akıllıca bir karar olduğunu kanıtladı. Yalnızca tüm günlüklerimi aramak için tek bir yere sahip olmakla kalmıyor, aynı zamanda aramalarımda neredeyse anında sonuçlar, analiz ve sorun giderme için inanılmaz derecede yardımcı olan güçlü görselleştirmeler ve bana ağa yararlı bir genel bakış sağlayan güzel panolar alıyorum.
Elastik Yığın sürekli olarak yeni ve şaşırtıcı özellikler yayınlar, çok aktif bir geliştirme hızı sağlar ve genellikle her ay iki yeni sürüm sunar. Yeni özelliklerden ve iyileştirmelerden yararlanabileceğimden emin olmak için ortamımı her zaman güncel tutmayı seviyorum. Ayrıca hatalardan ve güvenlik sorunlarından uzak tutmak için. Ancak bu, ortamı sürekli güncellememi gerektiriyor.
Elastic web sitesi, ürünlerinin yükseltme süreci de dahil olmak üzere açık ve ayrıntılı belgelere sahip olsa da, özellikle Elasticsearch kümesi olmak üzere manuel olarak yükseltme yapmak karmaşık bir iştir. İlgili birçok adım var ve çok özel bir sıranın izlenmesi gerekiyor. Bu nedenle, uzun zaman önce Ansible Playbook'ları kullanarak tüm süreci otomatikleştirmeye karar verdim.
Bu Ansible eğitiminde, Elastic Stack kurulumumu otomatik olarak yükseltmek için geliştirilmiş bir dizi Ansible Playbook'ta bize yol göstereceğim.
Elastik Yığın Nedir?
Eskiden ELK yığını olarak bilinen Elastic Stack, açık kaynak şirketi Elastic'ten Elasticsearch, Logstash ve Kibana'dan oluşur ve bunlar birlikte verilerinizi indekslemek, aramak ve analiz etmek için güçlü bir platform sağlar. Geniş bir uygulama yelpazesi için kullanılabilir. Günlüğe kaydetme ve güvenlik analizinden uygulama performans yönetimine ve site aramasına kadar.
Elasticsearch , yığının çekirdeğidir. Çok büyük miktarda depolanmış veriye karşı bile neredeyse gerçek zamanlı arama sonuçları sunabilen dağıtılmış bir arama ve analiz motorudur.
Logstash , birçok farklı kaynaktan (yazdığım kadarıyla 50 resmi giriş eklentisi) veri alan veya alan, ayrıştıran, filtreleyen ve dönüştüren ve bir veya daha fazla olası çıktıya gönderen bir işlem hattıdır. Bizim durumumuzda Elasticsearch çıktı eklentisiyle ilgileniyoruz.
Kibana , kullanıcı ve operasyon ön yüzünüzdür. Verilerinizi görselleştirmenize, aramanıza, gezinmenize ve bu konuda size harika bilgiler veren panolar oluşturmanıza olanak tanır.
Ansible nedir
Ansible, sistemleri yapılandırmak, yazılımları dağıtmak veya yükseltmek ve karmaşık BT görevlerini düzenlemek için kullanılabilen bir BT otomasyon platformudur. Ana hedefleri basitlik ve kullanım kolaylığıdır. Ansible'ın en sevdiğim özelliği aracısız olmasıdır, yani yönetmek istediğim ana bilgisayarlara ve cihazlara herhangi bir ekstra yazılım yüklemem ve yönetmem gerekmiyor. Elastik Yığınımızı otomatik olarak yükseltmek için Ansible otomasyonunun gücünü kullanacağız.
Sorumluluk Reddi ve Dikkatli Bir Söz
Burada paylaşacağım oyun kitapları, resmi ürünün belgelerinde açıklanan adımlara dayanmaktadır. Yalnızca aynı ana sürümün yükseltmeleri için kullanılması amaçlanmıştır. Örneğin: 5.x
→ 5.y
veya 6.x
→ 6.y
burada x
> y
. Ana sürümler arasındaki yükseltmeler genellikle ek adımlar gerektirir ve bu senaryolar bu durumlarda çalışmaz.
Ne olursa olsun, yükseltme için çalışma kitaplarını kullanmadan önce her zaman sürüm notlarını, özellikle de son değişiklikler bölümünü okuyun. Başucu kitaplarında yürütülen görevleri anladığınızdan emin olun ve önemli hiçbir şeyin değişmediğinden emin olmak için her zaman yükseltme talimatlarını kontrol edin.
Bunu söyledikten sonra, Elasticsearch'ün 2.2 sürümünden beri bu oyun kitaplarını (veya önceki sürümleri) sorunsuz bir şekilde kullanıyorum. O zamanlar, bildikleriyle aynı sürüm numarasını paylaşmadıkları için her ürün için tamamen ayrı oyun kitaplarım vardı.
Bunu söyledikten sonra, bu makalede yer alan bilgileri kullanmanızdan hiçbir şekilde sorumlu değilim.
Hayali Ortamımız
Başucu kitaplarımızın çalışacağı ortam, 6 CentOS 7 sunucusundan oluşacaktır:
- 1 x Logstash Sunucusu
- 1 x Kibana Sunucusu
- 4 x Elasticsearch düğümü
Ortamınızın farklı sayıda sunucuya sahip olması önemli değildir. Envanter dosyasına uygun şekilde yansıtabilirsiniz ve oyun kitapları sorunsuz çalışmalıdır. Bununla birlikte, RHEL tabanlı bir dağıtım kullanmıyorsanız, dağıtıma özgü birkaç görevi (esas olarak paket yöneticisi öğeleri) değiştirmeniz için bir alıştırma olarak bırakacağım.
Envanter
Ansible, playbook'ları hangi ana bilgisayarlara karşı çalıştırması gerektiğini bilmek için bir envantere ihtiyaç duyar. Dört hayali senaryomuz için aşağıdaki envanter dosyasını kullanacağız:
[logstash] server01 ansible_host=10.0.0.1 [kibana] server02 ansible_host=10.0.0.2 [elasticsearch] server03 ansible_host=10.0.0.3 server04 ansible_host=10.0.0.4 server05 ansible_host=10.0.0.5 server06 ansible_host=10.0.0.6
Bir Ansible envanter dosyasında, herhangi bir [section]
bir ana bilgisayar grubunu temsil eder. Envanterimizde 3 grup ana bilgisayar vardır: logstash
, kibana
ve elasticsearch
. Playbook'larda sadece grup isimlerini kullandığımı fark edeceksiniz. Bu, envanterdeki ana bilgisayar sayısının önemli olmadığı, gruplar doğru olduğu sürece oyun kitabının çalışacağı anlamına gelir.
Yükseltme Süreci
Yükseltme işlemi aşağıdaki adımlardan oluşacaktır:
1) Paketleri önceden indirin
2) Logstash Yükseltmesi
3) Elasticsearch kümesinin Sürekli Yükseltilmesi
4) Kibana Yükseltmesi
Ana amaç, arıza süresini en aza indirmektir. Çoğu zaman kullanıcı farkına bile varmaz. Bazen Kibana birkaç saniyeliğine kullanılamayabilir. Bu benim için kabul edilebilir.
Ana Ansible Playbook
Yükseltme işlemi, bir dizi farklı çalışma kitabından oluşur. Ansible'ın import_playbook özelliğini, tüm süreçle ilgilenmek üzere çağrılabilecek tek bir ana oyun kitabı dosyasında tüm oyun kitaplarını düzenlemek için kullanacağım.
- name: pre-download import_playbook: pre-download.yml - name: logstash-upgrade import_playbook: logstash-upgrade.yml - name: elasticsearch-rolling-upgrade import_playbook: elasticsearch-rolling-upgrade.yml - name: kibana-upgrade import_playbook: kibana-upgrade.yml
Oldukça basit. Bu, oyun kitaplarının yürütülmesini belirli bir sırayla düzenlemenin bir yoludur.
Şimdi yukarıdaki Ansible playbook örneğini nasıl kullanacağımızı düşünelim. Bunu nasıl uyguladığımızı daha sonra açıklayacağım, ancak 6.5.4 sürümüne yükseltmek için uygulayacağım komut bu:
$ ansible-playbook -i inventory -e elk_version=6.5.4 main.yml
Paketleri önceden indirin
Bu ilk adım aslında isteğe bağlıdır. Bunu kullanmamın nedeni, çalışan bir hizmeti yükseltmeden önce durdurmanın genel olarak iyi bir uygulama olduğunu düşünmemdir. Şimdi, hızlı bir İnternet bağlantınız varsa, paket yöneticinizin paketi indirme süresi önemsiz olabilir. Ancak durum her zaman böyle değildir ve herhangi bir hizmetin kapalı olduğu süreyi en aza indirmek istiyorum. Bu, ilk oyun kitabımın tüm paketleri önceden indirmek için yum kullanacağı yoldur. Böylece yükseltme zamanı geldiğinde indirme adımı çoktan halledilmiş olur.
- hosts: logstash gather_facts: no tasks: - name: Validate logstash Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+") - name: Get logstash current version command: rpm -q logstash --qf %{VERSION} args: warn: no changed_when: False register: version_found - name: Pre-download logstash install package yum: name: logstash-{{ elk_version }} download_only: yes when: version_found.stdout is version_compare(elk_version, '<')
İlk satır, bu oynatmanın yalnızca logstash
grubuna uygulanacağını belirtir. İkinci satır, Ansible'a ana bilgisayarlar hakkında gerçekleri toplama zahmetine girmemesini söyler. Bu, oyunu hızlandıracaktır, ancak oyundaki görevlerin hiçbirinin ev sahibi hakkında herhangi bir bilgiye ihtiyaç duymadığından emin olun.
Oyundaki ilk görev, elk_version
değişkenini doğrulayacaktır. Bu değişken, yükseltmekte olduğumuz Elastik Yığın sürümünü temsil eder. Ansible-playbook komutunu çağırdığınızda bu iletilir. Değişken geçilmezse veya geçerli bir format değilse, oyun derhal kurtarılacaktır. Bu görev aslında tüm oyunlardaki ilk görev olacak. Bunun nedeni, oyunların istendiği veya gerekli olduğu takdirde izole olarak yürütülmesine izin vermektir.
İkinci görev, Logstash'in mevcut sürümünü almak ve version_found
değişkenine kaydolmak için rpm
komutunu kullanacak. Bu bilgi bir sonraki görevde kullanılacaktır. args:
, warn: no
ve changed_when: False
satırları ansible-lint'i mutlu etmek için vardır, ancak kesinlikle gerekli değildir.
Son görev, paketi gerçekten önceden indiren komutu yürütecektir. Ancak yalnızca yüklü Logstash sürümü hedef sürümden daha eskiyse. Kullanılmayacaksa indirmeyi ve daha eski veya aynı sürümü işaret etmeyin.
Diğer iki oyun temelde aynıdır, ancak Logstash yerine Elasticsearch ve Kibana'yı önceden indireceklerdir:
- hosts: elasticsearch gather_facts: no tasks: - name: Validate elasticsearch Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+") - name: Get elasticsearch current version command: rpm -q elasticsearch --qf %{VERSION} args: warn: no changed_when: False register: version_found - name: Pre-download elasticsearch install package yum: name: elasticsearch-{{ elk_version }} download_only: yes when: version_found.stdout is version_compare(elk_version, '<') - hosts: kibana gather_facts: no tasks: - name: Validate kibana Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+") - name: Get kibana current version command: rpm -q kibana --qf %{VERSION} args: warn: no changed_when: False register: version_found - name: Pre-download kibana install package yum: name: kibana-{{ elk_version }} download_only: yes when: version_found.stdout is version_compare(elk_version, '<')
Logstash Yükseltmesi
Logstash, yükseltilecek ilk bileşen olmalıdır. Bunun nedeni, Logstash'in Elasticsearch'ün daha eski bir sürümüyle çalışmasının garanti edilmesidir.
Oyunun ilk görevleri, indirme öncesi karşılığı ile aynıdır:
- name: Upgrade logstash hosts: logstash gather_facts: no tasks: - name: Validate ELK Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+") - name: Get logstash current version command: rpm -q logstash --qf %{VERSION} changed_when: False register: version_found
Son iki görev bir blokta bulunur:
- block: - name: Update logstash yum: name: logstash-{{ elk_version }} state: present - name: Restart logstash systemd: name: logstash state: restarted enabled: yes daemon_reload: yes when: version_found.stdout is version_compare(elk_version, '<')
Ne when
koşullu, bloktaki görevlerin yalnızca hedef sürüm mevcut sürümden daha yeniyse yürütüleceğini garanti eder. Blok içindeki ilk görev, Logstash yükseltmesini gerçekleştirir ve ikinci görev, hizmeti yeniden başlatır.

Elasticsearch Cluster Rolling Upgrade
Elasticsearch kümesinde kesinti olmayacağından emin olmak için sürekli yükseltme yapmalıyız. Bu, her seferinde bir düğümü yükselteceğimiz, yalnızca kümenin yeşil durumda (tamamen sağlıklı) olduğundan emin olduktan sonra herhangi bir düğümün yükseltilmesine başlayacağımız anlamına gelir.
Oyunun başından itibaren farklı bir şey fark edeceksiniz:
- name: Elasticsearch rolling upgrade hosts: elasticsearch gather_facts: no serial: 1
Burada serial: 1
. Ansible'ın varsayılan davranışı, yapılandırmada tanımlanan eşzamanlı ana bilgisayar sayısı olan paralel olarak birden çok ana bilgisayara karşı oynatmayı yürütmektir. Bu satır, oyunun aynı anda yalnızca bir ev sahibine karşı yürütülmesini sağlar.
Ardından, oyun boyunca kullanılacak birkaç değişken tanımlıyoruz:
vars: es_disable_allocation: '{"transient":{"cluster.routing.allocation.enable":"none"}}' es_enable_allocation: '{"transient":{"cluster.routing.allocation.enable": "all","cluster.routing.allocation.node_concurrent_recoveries": 5,"indices.recovery.max_bytes_per_sec": "500mb"}}' es_http_port: 9200 es_transport_port: 9300
Oyunda göründükleri gibi her değişkenin anlamı açık olacaktır.
Her zaman olduğu gibi ilk görev, hedef sürümü doğrulamaktır:
tasks: - name: Validate ELK Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+")
Aşağıdaki görevlerin çoğu, Elasticsearch kümesine karşı REST çağrılarının yürütülmesinden oluşacaktır. Çağrı, herhangi bir düğüme karşı yürütülebilir. Bunu oyundaki mevcut ana bilgisayara karşı yürütebilirsiniz, ancak bazı komutlar, mevcut ana bilgisayar için Elasticsearch hizmeti kapalıyken yürütülür. Bu nedenle, sonraki görevlerde, REST çağrılarını çalıştırmak için farklı bir ana bilgisayar seçtiğinizden emin oluyoruz. Bunun için set_fact modülünü ve Ansible envanterindeki gruplar değişkenini kullanacağız.
- name: Set the es_host for the first host set_fact: es_host: "{{ groups.elasticsearch[1] }}" when: "inventory_hostname == groups.elasticsearch[0]" - name: Set the es_host for the remaining hosts set_fact: es_host: "{{ groups.elasticsearch[0] }}" when: "inventory_hostname != groups.elasticsearch[0]"
Ardından, devam etmeden önce hizmetin mevcut düğümde çalıştığından emin oluruz:
- name: Ensure elasticsearch service is running systemd: name: elasticsearch enabled: yes state: started register: response - name: Wait for elasticsearch node to come back up if it was stopped wait_for: port: "{{ es_transport_port }}" delay: 45 when: response.changed == true
Önceki oyunlarda olduğu gibi, mevcut sürümü kontrol edeceğiz. Bu süre dışında rpm çalıştırmak yerine Elasticsearch REST API kullanacağız. rpm komutunu da kullanabilirdik ama bu alternatifi göstermek istiyorum.
- name: Check current version uri: url: http://localhost:{{ es_http_port }} method: GET register: version_found retries: 10 delay: 10
Kalan görevler, yalnızca geçerli sürüm hedef sürümden daha eskiyse yürütülecek bir bloğun içindedir:
- block: - name: Enable shard allocation for the cluster uri: url: http://localhost:{{ es_http_port }}/_cluster/settings method: PUT body_format: json body: "{{ es_enable_allocation }}"
Şimdi, tavsiyeme uyup belgeleri okuduysanız, bu adımın tam tersi olması gerektiğini fark etmişsinizdir: parça tahsisini devre dışı bırakmak. Parçaların herhangi bir nedenle daha önce devre dışı bırakılması durumunda bu görevi ilk önce buraya koymak istiyorum. Bu önemlidir çünkü bir sonraki görev kümenin yeşile dönmesini bekleyecektir. Parça tahsisi devre dışı bırakılırsa, küme sarı kalır ve görevler zaman aşımına uğrayana kadar askıda kalır.
Bu nedenle, parça ayırmanın etkinleştirildiğinden emin olduktan sonra kümenin yeşil durumda olduğundan emin oluruz:
- name: Wait for cluster health to return to green uri: url: http://localhost:{{ es_http_port }}/_cluster/health method: GET register: response until: "response.json.status == 'green'" retries: 500 delay: 15
Düğüm hizmeti yeniden başlatıldıktan sonra kümenin yeşile dönmesi uzun zaman alabilir. Bu, satırların retries: 500
ve delay: 15
. Bu, kümenin yeşile dönmesi için 125 dakika (500 x 15 saniye) bekleyeceğimiz anlamına gelir. Düğümleriniz gerçekten çok büyük miktarda veri içeriyorsa, bunu ayarlamanız gerekebilir. Vakaların çoğu için, fazlasıyla yeterli.
Şimdi parça tahsisini devre dışı bırakabiliriz:
- name: Disable shard allocation for the cluster uri: url: http://localhost:{{ es_http_port }}/_cluster/settings method: PUT body_format: json body: {{ es_disable_allocation }}
Ve hizmeti kapatmadan önce, isteğe bağlı, ancak önerilen eşitleme temizlemesini uygularız. Senkronizasyon temizleme gerçekleştirdiğimizde bazı indeksler için 409 hatası almak nadir değildir. Bunu göz ardı etmek güvenli olduğundan, başarı durum kodları listesine 409'u ekledim.
- name: Perform a synced flush uri: url: http://localhost:{{ es_http_port }}/_flush/synced method: POST status_code: "200, 409"
Şimdi, bu düğüm yükseltilmeye hazır:
- name: Shutdown elasticsearch node systemd: name: elasticsearch state: stopped - name: Update elasticsearch yum: name: elasticsearch-{{ elk_version }} state: present
Hizmet durdurulduğunda, düğümü yeniden başlatmadan önce tüm parçaların tahsis edilmesini bekleriz:
- name: Wait for all shards to be reallocated uri: url=http://{{ es_host }}:{{ es_http_port }}/_cluster/health method=GET register: response until: "response.json.relocating_shards == 0" retries: 20 delay: 15
Parçalar yeniden tahsis edildikten sonra Elasticsearch hizmetini yeniden başlatır ve tamamen hazır olmasını bekleriz:
- name: Start elasticsearch systemd: name: elasticsearch state: restarted enabled: yes daemon_reload: yes - name: Wait for elasticsearch node to come back up wait_for: port: "{{ es_transport_port }}" delay: 35 - name: Wait for elasticsearch http to come back up wait_for: port: "{{ es_http_port }}" delay: 5
Şimdi, parça tahsisini yeniden etkinleştirmeden önce kümenin sarı veya yeşil olduğundan emin oluyoruz:
- name: Wait for cluster health to return to yellow or green uri: url: http://localhost:{{ es_http_port }}/_cluster/health method: GET register: response until: "response.json.status == 'yellow' or response.json.status == 'green'" retries: 500 delay: 15 - name: Enable shard allocation for the cluster uri: url: http://localhost:{{ es_http_port }}/_cluster/settings method: PUT body_format: json body: "{{ es_enable_allocation }}" register: response until: "response.json.acknowledged == true" retries: 10 delay: 15
Ve bir sonrakini işlemeden önce düğümün tamamen iyileşmesini bekleriz:
- name: Wait for the node to recover uri: url: http://localhost:{{ es_http_port }}/_cat/health method: GET return_content: yes register: response until: "'green' in response.content" retries: 500 delay: 15
Tabii ki, daha önce de söylediğim gibi, bu blok yalnızca gerçekten sürümü yükseltiyorsak yürütülmelidir:
when: version_found.json.version.number is version_compare(elk_version, '<')
Kibana Yükseltmesi
Yükseltilecek son bileşen Kibana'dır.
Tahmin edebileceğiniz gibi, ilk görevler Logstash yükseltmesinden veya indirme öncesi oyunlardan farklı değil. Bir değişkenin tanımı dışında:
- name: Upgrade kibana hosts: kibana gather_facts: no vars: set_default_index: '{"changes":{"defaultIndex":"syslog"}}' tasks: - name: Validate ELK Version fail: msg="Invalid ELK Version" when: elk_version is undefined or not elk_version is match("\d+\.\d+\.\d+") - name: Get kibana current version command: rpm -q kibana --qf %{VERSION} args: warn: no changed_when: False register: version_found
Onu kullanan göreve geldiğimizde set_default_index
değişkenini açıklayacağım.
Kalan görevler, yalnızca Kibana'nın kurulu sürümü hedef sürümden daha eskiyse yürütülecek bir bloğun içinde olacaktır. İlk iki görev Kibana'yı güncelleyecek ve yeniden başlatacak:
- name: Update kibana yum: name: kibana-{{ elk_version }} state: present - name: Restart kibana systemd: name: kibana state: restarted enabled: yes daemon_reload: yes
Kibana için bu yeterli olmalıydı. Ne yazık ki, bazı nedenlerden dolayı, yükseltmeden sonra Kibana, varsayılan dizin modeline olan referansını kaybeder. Bu, yükseltmeden sonra erişen ilk kullanıcının varsayılan dizin modelini tanımlamasını istemesine neden olur ve bu da karışıklığa neden olabilir. Bunu önlemek için, varsayılan dizin düzenini sıfırlama görevi eklediğinizden emin olun. Aşağıdaki örnekte, syslog
, ancak ne kullanıyorsanız onu değiştirmelisiniz. Yine de dizini ayarlamadan önce Kibana'nın hazır ve istekleri sunmaya hazır olduğundan emin olmalıyız:
- name: Wait for kibana to start listening wait_for: port: 5601 delay: 5 - name: Wait for kibana to be ready uri: url: http://localhost:5601/api/kibana/settings method: GET register: response until: "'kbn_name' in response and response.status == 200" retries: 30 delay: 5 - name: Set Default Index uri: url: http://localhost:5601/api/kibana/settings method: POST body_format: json body: "{{ set_default_index }}" headers: "kbn-version": "{{ elk_version }}"
Çözüm
Elastik Yığın değerli bir araçtır ve henüz kullanmadıysanız kesinlikle bir göz atmanızı tavsiye ederim. Olduğu gibi harika ve sürekli gelişiyor, o kadar ki sürekli yükseltmeye ayak uydurmak zor olabilir. Umarım bu Ansible Playbook'lar benim için olduğu kadar sizin için de faydalı olabilir.
Bunları GitHub'da https://github.com/orgito/elk-upgrade adresinde kullanıma sundum. Üretim dışı bir ortamda test etmenizi öneririm.
Elasticsearch'ü uygulamanıza dahil etmek isteyen bir Ruby on Rails geliştiricisiyseniz, Core Toptal Yazılım Mühendisi Arkadiy Zabazhanov'un yazdığı Ruby on Rails için Elasticsearch: Chewy Gem'e Yönelik Bir Eğitim'e göz atın.