Ansible ve Terraform İle ELK Stack Kurulumu
Terraform
Ansible ve Terraform İle ELK Stack Kurulumu
Terraform
main.tf
1. Terraform Sağlayıcı ve Provider Tanımı
terraform {
required_providers {
hcloud = {
source = "hetznercloud/hcloud"
version = "~> 1.45"
}
}
}
Bu blok, Hetzner Cloud için gerekli Terraform sağlayıcısını (hcloud) tanımlar. Versiyon sabitlemesi ile hem kararlılık hem de ileri uyumsuzlukların önüne geçilmiş olur.
provider "hcloud" {
token = var.hcloud_token
}
Hetzner API’sine erişim sağlayan hcloud provider’ı burada tanımlanıyor. Token dışarıdan değişken olarak alınıyor ve hassas bilgilerin versiyon kontrolüne girmemesi sağlanıyor.
2. Özel Ağ (Private Network) Oluşturulması
resource "hcloud_network" "private_net" {
name = "elastic-network"
ip_range = "192.168.122.0/24"
}
Bu kaynak, sunucuların bağlanacağı özel bir ağ tanımlar. Bu ağ sadece Hetzner içi özel IP trafiği için kullanılacak, böylece güvenli ve izole bir iletişim kanalı sağlanmış olur.
resource "hcloud_network_subnet" "subnet" {
network_id = hcloud_network.private_net.id
type = "server"
network_zone = "eu-central"
ip_range = "192.168.122.0/24"
}
hcloud_network_subnet ile ağın aktif olarak kullanılabilmesi için bir subnet tanımlanır. Hetzner Cloud’da özel ağlar bu şekilde subnet üzerinden sunuculara atanır.
3. Sunucu Bilgilerinin Tanımlanması (Local Variables)
locals {
servers = [
{ name = "es-node-1", ip = "192.168.122.10" },
{ name = "es-node-2", ip = "192.168.122.11" },
{ name = "es-node-3", ip = "192.168.122.12" },
{ name = "kibana", ip = "192.168.122.13" },
]
}
Bu blok, sunucuların isim ve özel IP adreslerini içeren bir liste tanımlar. Bu yapı sayesinde dinamik sunucu oluşturma mümkün olur. Sabit IP ataması, Ansible ile yapılacak yapılandırmaların deterministik olması açısından önemlidir.
4. Dinamik Sunucu Oluşturma
resource "hcloud_server" "nodes" {
for_each = { for s in local.servers : s.name => s }
name = each.value.name
image = "ubuntu-24.04"
server_type = "cpx11"
ssh_keys = [var.ssh_key]
for_eachkullanılarak listedeki her sunucu ayrı bir kaynak gibi yönetilir.- Ubuntu 24.04 imajı, uzun vadeli destek (LTS) ve en son güncellemeler için tercih edilir.
cpx11tipi Hetzner’de küçük ve uygun fiyatlı bir sunucu türüdür, test ve küçük üretim ortamları için yeterlidir.
public_net {
ipv6_enabled = false
ipv4_enabled = true
}
IPv6 devre dışı bırakılmış; IPv4 ile dış erişim sağlanıyor. Bu ayar, güvenlik duvarı ve ağ yapılandırmasını sadeleştirir.
network {
network_id = hcloud_network.private_net.id
ip = each.value.ip
}
}
Her sunucu, daha önce tanımlanan elastic-network isimli özel ağa atanıyor. IP adresi statik verildiği için Ansible yapılandırmaları ya da güvenlik kuralları doğrudan bu adreslere göre ayarlanabilir.
Genel Değerlendirme
Bu main.tf dosyası ile:
- Bir özel ağ ve subnet oluşturuluyor
- Dört adet sunucu (3 Elasticsearch, 1 Kibana) bu özel ağa atanmış şekilde kuruluyor
- Statik özel IP adresleri, konfigürasyon ve servis içi iletişimde kararlılığı garantiliyor
- Tüm sunucular Hetzner Cloud üzerinde otomatik olarak provision ediliyor
variables.tf
1. hcloud_token
variable "hcloud_token" {
type = string
default = "API-KEY"
}
- Hetzner Cloud API erişimi için gerekli olan güvenlik anahtarıdır.
defaultolarak örnek bir API anahtarı ("API-KEY") verilmiş olsa da, bu gerçek ortamlarda genellikle.tfvarsdosyasıyla ya da ortam değişkeni (environment variable) ile geçilmelidir.- Hassas bilgi olduğu için
sensitive = trueparametresi eklenerek Terraform çıktılarında gizlenmesi önerilir (örnek geliştirmelerde bu eksik).
Güvenlik Tavsiyesi:
variable "hcloud_token" {
type = string
sensitive = true
}
2. ssh_key
variable "ssh_key" {
type = string
default = "faruk"
}
- Hetzner Cloud sunucularına erişim için önceden Hetzner hesabına yüklenmiş olan SSH anahtarının adı burada tanımlanır.
- Bu ad,
hcloud_serverkaynaklarındassh_keys = [var.ssh_key]şeklinde kullanılarak sunuculara otomatik olarak yetkilendirilmiş SSH erişimi sağlar.
Not:
Bu anahtarın Hetzner Cloud kontrol panelinde SSH Keys bölümünde mevcut olması gerekir. Aksi takdirde Terraform hata verir.
3. server_type
variable "server_type" {
type = string
default = "cpx11"
}
- Hetzner Cloud’da kullanılacak sunucu tipi belirlenir.
cpx11, düşük kaynaklı ama fiyat-performans açısından uygun bir sunucu tipidir (2 vCPU, 2 GB RAM).- Bu değişkenin tanımlanması, sunucu kaynak tipini merkezî şekilde yönetmeyi sağlar. Gerektiğinde daha yüksek kapasiteli örneklerle değiştirmek çok kolaylaşır (örneğin
cx21ya dacpx31)
Ansible
inventory.ini
Genel Yapı
[elasticsearch_master]
[elasticsearch_master]
x.x.x.x node_name=es-node-1
- Bu grup, Elasticsearch cluster’ında ilk başlatılacak ve diğer node’ların bağlanacağı ana (master) düğümü tanımlar.
node_name=es-node-1değişkeni,elasticsearch.ymlyapılandırmasındanode.nameolarak kullanılır.
Ayrıca:
- Token üretimi (
elasticsearch-create-enrollment-token) - Sertifika üretimi
- Servis token oluşturma gibi işlemler de bu host üzerinden yapılır.
[elasticsearch_nodes]
[elasticsearch_nodes]
x.x.x.x node_name=es-node-2
x.x.x.x node_name=es-node-3
- Bu grup, veri taşıyan (data node) Elasticsearch düğümleridir.
- Master tarafından oluşturulan cluster’a
enrollment tokenile bağlanırlar. node_nameher biri için farklı olarak atanmalı veelasticsearch.ymliçinde kullanılır.
🎯 Bu ayrım, cluster mimarisinde yönetim ve veri taşıma işlevlerini birbirinden ayırmak için önemlidir.
[kibana]
[kibana]
x.x.x.x node_name=kibana
- Web tabanlı arayüz sunucusudur.
- Elasticsearch ile bağlantısını service account token üzerinden sağlar.
- Aynı zamanda kendi TLS sertifikası ile kullanıcıya HTTPS arayüz sunar.
kibana.ymlvekibana-keystorekonfigürasyonları burada çalıştırılır.
[loadbalancer]
[loadbalancer]
x.x.x.x
- Elasticsearch için gelen istekleri TLS destekli olarak yönlendiren ters proxy (Nginx) sunucusudur.
- Jinja2 ile oluşturulan
nginx.confiçindekiupstreambloğu bu grubun IP’lerine göre otomatik yazılır.
Teknik Detay ve Uyum Notları
inventory_hostnameAnsible'da her zaman host'un tanımlı IP'sidir →hostvars[host]['inventory_hostname']gibi kullanımlarla dinamik şablonlar oluşturulmuştur.node_namedeğişkeni özellikleelasticsearch-configure.ymlgibi playbook’lardalineinfilemodülü ile kullanılmaktadır.groups['kibana'][0],groups['elasticsearch_nodes']gibi ifadeler ile diğer node’laradelegate_tovehostvarsüzerinden erişim sağlanmıştır.- IP adresleri
x.x.x.xolarak örnek bırakılmış ama gerçek ortamda her sunucuya ait özel veya genel IP adresi ile doldurulmalıdır.
elasticsearch-installation.yml
✅ Genel Amaç
Elasticsearch sunucularını Hetzner Cloud üzerinde dağıttıktan sonra, bu playbook ile hem elasticsearch_master hem de elasticsearch_nodes host gruplarında:
- Gerekli bağımlılıkların kurulması
- Elasticsearch paketinin indirilmesi
- Paketin kurulumu
adımları gerçekleştirilir.
📍 Hedef Hostlar
hosts: elasticsearch_master:elasticsearch_nodes
:operatörü Ansible’da union (birleşim) anlamına gelir.- Bu sayede hem master hem de data node’lar aynı kurulumdan geçer.
- Elasticsearch kurulumu tüm düğümlerde benzer olduğu için doğru bir stratejidir.
⚙️ Vars Tanımları
vars:
elasticsearch_deb_url: "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-9.0.3-amd64.deb"
elasticsearch_deb_file: "/tmp/elasticsearch.deb"
- Versiyon sabitlenmiş şekilde Elastic’in resmi deposundan
.debdosyası indiriliyor. varsbloğu ile parametrik yapı kurulmuş; bu dosya başka versiyonlara uyarlanabilir hale getirilmiş.- İyi bir pratik olarak bu değişkenler ayrı bir
group_vars/elasticsearch_nodes.ymldosyasına alınabilir.
🔧 Tasks Analizi
1. Ensure dependencies are installed
- name: Ensure dependencies are installed
apt:
name: wget
state: present
update_cache: true
wgetElasticsearch paketini indirmek için gereklidir.update_cache: trueile APT cache’i taze tutulur, bu da hata riskini azaltır.
2. Download Elasticsearch .deb package
- name: Download Elasticsearch .deb package
get_url:
url: "{{ elasticsearch_deb_url }}"
dest: "{{ elasticsearch_deb_file }}"
mode: '0644'
get_urlmodülü, uzak URL’den paket indirir.- Dosya
/tmpklasörüne kaydedilir. mode: '0644'ile erişim izinleri sistem gerekliliklerine uygun hale getirilmiş.
3. Install Elasticsearch .deb package
- name: Install Elasticsearch .deb package
apt:
deb: "{{ elasticsearch_deb_file }}"
state: present
.debdosyasını sistemde kurmak içinaptmodülünündeb:parametresi kullanılmış.- Bu yöntem, doğrudan
dpkg -iyerine daha güvenlidir çünkü bağımlılık yönetimi APT tarafından yapılır.
elasticsearch-configure.yml
Genel Amaç
Bu playbook, tüm Elasticsearch düğümlerinde aşağıdaki yapılandırmaları gerçekleştirir:
- Cluster adı
- Node adı
- Dinleme IP’si (
network.host) - HTTP portu (
http.port)
Bu yapılandırma, Elasticsearch node’larının birbirleriyle haberleşmesini ve dışarıdan erişilebilir olmasını sağlar.
Hedef Hostlar
hosts: elasticsearch_master:elasticsearch_nodes
- Tüm Elasticsearch node’larını hedefler.
node_namedeğişkeninin dinamik olarak farklı olması gerektiği varsayılıyor (örneğininventory.iniiçinde her hosta özel olarak tanımlanmış).
Vars Tanımları
vars:
network_host: "0.0.0.0"
http_port: "9200"
cluster_name: "es-cluster"
network_host: 0.0.0.0: Tüm arayüzlerden erişim sağlar. Dış erişim gerektiren durumlarda bu ayar zorunludur. Güvenlik duvarı veya Nginx ile sınırlanmalıdır.http_port: Varsayılan Elasticsearch HTTP portudur. İstenirse değiştirilebilir.cluster_name: Elasticsearch node'larının aynı cluster’a ait olduğunu belirtir.
⚠️
node_namedeğişkeni vars olarak burada tanımlanmamış. Bunun Ansibleinventory.inidosyasında host bazında tanımlı olması beklenir:
[elasticsearch_nodes]
es-node-1 node_name=es-node-1
es-node-2 node_name=es-node-2
Görev: Konfigürasyon Satırlarını Ayarlama
- name: Set multiple config lines
ansible.builtin.lineinfile:
path: /etc/elasticsearch/elasticsearch.yml
regexp: "^#?{{ item.key }}:"
line: "{{ item.key }}: {{ item.value }}"
backrefs: true
loop:
- { key: 'cluster.name', value: '{{ cluster_name }}' }
- { key: 'node.name', value: '{{ node_name }}' }
- { key: 'network.host', value: '{{ network_host }}' }
- { key: 'http.port', value: '{{ http_port }}' }
lineinfilemodülü ileelasticsearch.ymldosyası satır satır düzenleniyor.regexp: İlgili ayar satırı varsa onu bulur.^#?{{ item.key }}:ifadesi hem aktif hem de yorum satırı olan ayarları hedef alır.line: Ayarın yeni değeri yazılır.backrefs: true:regexp'in eşleşmesini güncelleme işlemiyle bağlar.
elasticsearch-create-master.yml
Genel Amaç
- Elasticsearch master node’un servisini başlatmak
elasticsistem kullanıcısının şifresini sıfırlamak (non-interaktif)- Servisin başarılı bir şekilde HTTPS üzerinden ayakta olduğunu doğrulamak
hedef Host
hosts: elasticsearch_master
- Sadece
masternode üzerinde çalışır. - Elasticsearch’te kullanıcı kimlik doğrulaması ve güvenlik ayarları yalnızca master üzerinden başlatılır, bu da doğru bir tercihtir.
Vars Tanımları
vars:
elastic_password: "elastic"
elastic_port: "9200"
elastic_host: "localhost"
elastic_password:elasticsistem kullanıcısı için atanacak şifre (geliştirme ortamında sabitlenmiş, üretim ortamında vars dosyasına veya vault’a alınmalı).elastic_hostveelastic_port: Sağlık kontrolü içinurimodülünde kullanılıyor.
Görevler
1. Elasticsearch Servisini Başlatma
- name: Start elasticsearch
ansible.builtin.systemd:
name: elasticsearch
state: started
enabled: true
- Servis başlatılır ve sistem yeniden başlatıldığında otomatik açılması sağlanır.
2. Elastic Kullanıcısının Parolasını Sıfırlama
- name: Reset elastic user password non-interactively
become: true
ansible.builtin.shell: |
printf "{{ elastic_password }}\n{{ elastic_password }}\n" | /usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic -s -b -i
args:
executable: /bin/bash
- Elasticsearch 8.x/9.x ile birlikte gelen
elasticsearch-reset-passwordaracı, parola sıfırlamada kullanılır.
Bu komut:
-s: sistem kullanıcı parolasını sıfırlamak için-b: batch mode (non-interaktif)-i: kullanıcıdan tekrar onay istemesi içinprintfkomutu ile parolanın iki kez girilmesi simüle edilir.
3. Servisin Durumunu Tekrar Doğrulama
- name: Ensure Elasticsearch is running
systemd:
name: elasticsearch
state: started
enabled: true
- Önceki task’e ek olarak servis kontrolü bir daha yapılıyor.
- Gereksiz tekrar gibi görünebilir, ama parola sıfırlama sonrası servisin çökme ihtimali varsa bu adım güvenliği artırır.
4. Elasticsearch Sağlık Kontrolü (HTTPS ile)
- name: Wait for Elasticsearch to start with HTTPS (skip SSL verification)
uri:
url: "https://{{ elastic_host }}:{{ elastic_port }}"
method: GET
status_code: 200
validate_certs: false
url_username: elastic
url_password: "{{ elastic_password }}"
urimodülü ile Elasticsearch arayüzüne HTTPS üzerinden bağlanılır.validate_certs: false: SSL henüz yapılandırılmadıysa geçici olarak devre dışı bırakılır.- Kullanıcı adı ve parola ile temel doğrulama (basic auth) yapılır.
status_code: 200ile servis sağlığı kontrol edilir.
elasticsearch-join-each-node.yml
Genel Amaç
- Worker node’ları, master node’un oluşturduğu cluster’a token üzerinden otomatik olarak bağlamak
- Süreç içinde Elasticsearch servisini geçici olarak durdurup yeniden başlatmak
- Yapının kurulum aşamasında deterministik bir şekilde işlemesini sağlamak
Hedef Hostlar
hosts: elasticsearch_nodes
- Sadece veri taşıyacak olan worker node’lara uygulanır.
- Master node dışındaki tüm Elasticsearch sunucularını kapsar.
Vars Tanımı
vars:
es_bin_dir: "/usr/share/elasticsearch/bin"
- Elasticsearch CLI araçlarının bulunduğu dizin.
- Hem master’da token üretmek, hem node üzerinde
reconfigureişlemi yapmak için bu klasör kullanılır.
Görevler
1. Token Üretimi (Master Node Üzerinden)
- name: Generate token from master for this node
args:
chdir: "{{ es_bin_dir }}"
delegate_to: "{{ groups['elasticsearch_master'][0] }}"
command: ./elasticsearch-create-enrollment-token -s node
register: enrollment_token
delegate_to: Bu komut hedef worker node’da değil, master node’da çalıştırılır.elasticsearch-create-enrollment-token -s nodekomutu, bir worker node’un cluster’a katılması için geçici, güvenli bir token üretir.registerile token çıktısı alınır ve ileride kullanılmak üzere saklanır.
Her node için ayrı token üretildiği varsayılıyor. Tek token’la birden fazla node join edilemiyorsa bu yaklaşım doğru. Ancak tek token birden fazla node’a izin veriyorsa, token önceden generate edilip
group_varsile dağıtılabilir.
2. Token Debug
- name: Show token (debug)
debug:
var: enrollment_token.stdout
- Token çıktısının kontrol amacıyla gösterilmesini sağlar.
- Geliştirme ortamlarında faydalı; üretim ortamlarında
no_log: trueile gizlenmelidir.
3. Elasticsearch Servisini Durdurma
- name: Stop Elasticsearch
systemd:
name: elasticsearch
state: stopped
elasticsearch-reconfigure-nodekomutu servis kapalıyken çalışmalıdır.- Bu nedenle worker node üzerindeki servis geçici olarak durdurulur.
4. Cluster’a Katılım (Node Reconfigure)
- name: Join this node to cluster with token
args:
chdir: "{{ es_bin_dir }}"
command: printf "y\n" | ./elasticsearch-reconfigure-node --enrollment-token {{ enrollment_token.stdout }}
elasticsearch-reconfigure-nodekomutu, token ile node’u mevcut cluster’a bağlar.- Komut interaktif olarak “emin misin?” sorusu sorar.
printf "y\n"ile bu soru cevaplanarak otomasyon tamamlanır.
5. Elasticsearch Servisini Başlatma
- name: Start Elasticsearch
systemd:
name: elasticsearch
state: started
enabled: true
- Cluster’a katıldıktan sonra servis yeniden başlatılır ve sistem açılışında çalışacak şekilde etkinleştirilir.
6. Bekleme Süresi
- name: Pause for a sec
ansible.builtin.pause:
minutes: 1
- Elasticsearch yeniden başlarken zaman alabilir.
- Burada sabit bir
pauseyerinewait_formodülü ile port kontrolü yapmak daha sağlam bir yaklaşımdır.
- name: Wait until Elasticsearch is available
wait_for:
port: 9200
delay: 10
timeout: 120
kibana-installation.yml
Genel Amaç
Kibana’nın:
- Gerekli bağımlılıklar yüklenerek
- Elastic’in resmi deposundan
.debpaketi indirilerek - Paket kurulumu tamamlanarak
sunucuya eksiksiz bir şekilde yüklenmesini sağlamaktır.
Hedef Host
hosts: kibana
- Sadece
kibanagrubundaki sunucular hedeflenir. - Bu grubun
inventory.iniiçerisindenode_name=kibanagibi tanımlanmış olması beklenir.
Vars Tanımları
vars:
kibana_deb_url: "https://artifacts.elastic.co/downloads/kibana/kibana-9.0.3-amd64.deb"
kibana_deb_file: "/tmp/kibana.deb"
- Elastic’in resmi sitesinden indirilecek
.debdosyasının URL’si ve hedef dizini tanımlanır. - Versiyon kontrolü burada sabit; farklı versiyonlar için playbook yeniden kullanılabilir olacak şekilde parametrik yapılmış.
Gelişmiş yapılandırmalarda bu değişkenlerin
group_vars/kibana.ymliçine alınması önerilir.
Tasks Analizi
1. wget Bağımlılığının Kurulması
- name: Ensure dependencies are installed
apt:
name: wget
state: present
update_cache: true
wgetkomutu bazı sistemlerde yüklü gelmez,.debdosyasını indirmeden önce sistemin hazırlandığı bir adımdır.update_cache: trueile APT önbelleği güncellenerek olası paket çözümleme hataları engellenir.
Alternatif olarak
curlkullanılabilir, ancakget_urlmodülü Ansible’ın kendi iç yapısıyla daha uyumludur.
2. Kibana Paketinin İndirilmesi
- name: Download Kibana .deb package
get_url:
url: "{{ kibana_deb_url }}"
dest: "{{ kibana_deb_file }}"
mode: '0644'
get_urlmodülü ile doğrudan Elastic’in CDN’inden.debpaketi indirilir.mode: '0644'ile dosyanın erişim izinleri uygun şekilde ayarlanır.- Böylece
apttarafından okunabilir olur.
3. Paket Kurulumu
- name: Install Kibana .deb package
apt:
deb: "{{ kibana_deb_file }}"
state: present
.debpaketi sistem üzerinde kurulurken,aptmodülünündeb:parametresi ile çalışması tercih edilmiş.- Bu yöntem:
dpkg -igibi komutlara göre bağımlılıkları daha iyi çözer- Sistemdeki
aptekosistemiyle uyumlu çalışır
kibana-configuration.yml
Genel Amaç
Bu playbook ile Kibana:
- HTTPS üzerinden çalışacak şekilde yapılandırılır
- Elasticsearch ile bağlantısı güvenli hale getirilir
- Service account token kullanarak kimlik doğrulaması yapılır
kibana.ymlkonfigürasyonu otomatikleştirilir
Hedef Host
hosts: kibana
- Sadece
kibanagrubuna ait node hedeflenir. - Elasticsearch cluster’a bağlanmak için gerekli yapılandırmalar tek sunucuya uygulanır.
Vars Tanımları
vars:
elastic_ip: "https://{{ hostvars[groups['loadbalancer'][0]]['inventory_hostname'] }}:9200"
token_api_endpoint: "_security/service/elastic/kibana/credential/token/kibana_token"
elastic_password: "elastic"
elastic_ip: Kibana'nın Elasticsearch ile konuşacağı adres (bir load balancer varsayılmış).token_api_endpoint: Elasticsearch REST API üzerinden servis account token oluşturma uç noktası.elastic_password: İlk kurulum sonrasıelastickullanıcısı ile erişim sağlanır.
Gelişmiş senaryolarda bu şifre Vault ile şifrelenmeli ya da
no_log: trueile maskelenmelidir.
Görevler
1. kibana.yml İçin Temel Ayarları Yapılandırma
- name: Set multiple config lines
lineinfile:
path: /etc/kibana/kibana.yml
...
loop: [...]
Bu görev Kibana’nın çekirdek ayarlarını yapılandırır:
server.host,server.port: Kibana'nın hangi arayüzden yayın yapacağı belirlenir.server.publicBaseUrl: Genelde ters proxy kullanıldığında dışarıya ilan edilen URL’dir.server.ssl.*: Kibana ile kullanıcı arayüzü arasında HTTPS kullanımı sağlanır.elasticsearch.ssl.*: Kibana’nın Elasticsearch’e bağlanırken güvenli TLS doğrulaması yapmasını sağlar.
🎯 Bu yapılandırma sayesinde hem dış kullanıcı arayüzü, hem backend güvenliği sağlanmış olur.
2. elasticsearch.hosts Bloğunu Tanımlama
- name: Elasticsearch host listesini ayarla
blockinfile:
path: /etc/kibana/kibana.yml
marker: "# {mark} ANSIBLE MANAGED BLOCK elasticsearch.hosts"
block: |
elasticsearch.hosts:
{% for host in groups['loadbalancer'] %}
- https://{{ host }}:9200
{% endfor %}
blockinfileileelasticsearch.hostsparametresi toplu halde yazılır.- Burada Jinja2 döngüsü kullanılarak birden fazla load balancer veya ES endpoint’ine bağlanma imkanı sağlanmış.
markeretiketi ile Ansible’ın bu bloğu tekrar çalıştırdığında nereden başlayıp nerede bitireceği bellidir.
3. jq Paketini Yükleme
- name: Install jq
apt:
name: jq
...
jq, JSON çıktılarından sadecetoken.valuegibi alanları almak için kullanılır.- Bu komut olmadan
curlçıktısı işlenemez, dolayısıyla bir ön koşul olarak yüklenmiştir.
4. Elasticsearch Üzerinden Service Token Alma
- name: Get Kibana service account token
shell: >
curl -XPOST -k -u elastic:"{{ elastic_password }}" "{{ elastic_ip }}/{{ token_api_endpoint }}" | jq .token.value -r
register: kibana_token
- Elasticsearch REST API ile
elastickullanıcısı aracılığıyla yeni birkibana_tokenoluşturulur. jq .token.value -r: sadece token değerini döndürür (çıktıyı sadeleştirir).-k: SSL sertifikası henüz tam doğrulanmadığı için geçici olarak devre dışı bırakılmıştır.
Bu token, Kibana’nın Elasticsearch’e güvenli bir şekilde bağlanmasını sağlayan kimlik bilgisidir
5. Token’ı Kibana Keystore’a Eklemek
- name: Add token to kibana keystore
shell: >
echo "{{ kibana_token.stdout }}" | ./kibana-keystore add elasticsearch.serviceAccountToken -x
args:
chdir: /usr/share/kibana/bin
kibana-keystore, Kibana’da gizli bilgileri şifreli olarak saklayan bir sistemdir.- Bu token oraya
elasticsearch.serviceAccountTokenanahtarıyla yazılır. -x: stdin üzerinden gelen veriyi okur (non-interaktif kullanım için gereklidir).
kibana-generate-ssl-certificates.yml
Genel Amaç
- Elasticsearch master node üzerinde, Kibana için SSL sertifikası üretmek
- Üretilen sertifika dosyalarını Kibana sunucusuna kopyalamak
/etc/kibana/certs/dizinine sertifikaları yerleştirip yetkilendirmek
Play 1: Elasticsearch Master Üzerinde Sertifika Oluşturulması
- name: SSL certificate preparation and distribution for Kibana
hosts: elasticsearch_master
1. Keystore’dan Şifre Çekme
- name: Show secure password from keystore
command: "{{ es_bin_path }}/elasticsearch-keystore show xpack.security.http.ssl.keystore.secure_password"
register: keystore_password
- Mevcut
http.p12sertifika paketini açabilmek için keystore’daki SSL şifresi alınır. stdoutdeğeriopensslkomutunda kullanılmak üzere saklanır.
Gelişmiş kullanımda
no_log: trueile şifre çıktısı gizlenmelidir.
2. CA Private Key Çıkarılması
- name: Extract CA private key from p12
command: "openssl pkcs12 -in {{ certs_path }}/http.p12 -nocerts -nodes -out {{ certs_path }}/http_ca.key -passin pass:{{ keystore_password.stdout }}"
.p12paketi içerisindeki CA private key çıkarılır vehttp_ca.keyolarak kaydedilir.- Bu key, Kibana için yeni bir sertifika üretiminde kullanılacaktır.
3. Kibana Sertifikasının Üretilmesi
- name: Generate PEM certificate for Kibana using its IP
command: >
{{ es_bin_path }}/elasticsearch-certutil cert --pem
--ca-cert {{ certs_path }}/http_ca.crt
--ca-key {{ certs_path }}/http_ca.key
--ip {{ hostvars[groups['kibana'][0]]['inventory_hostname'] }}
--out {{ output_path }}/kibana.zip -s
elasticsearch-certutilile.crtve.keydosyalarını içeren PEM formatında bir sertifika paketi (kibana.zip) oluşturulur.--ip: Kibana’nın özel IP’si kullanılarak IP bazlı sertifika oluşturulur.-s: interaktif sorular devre dışı bırakılır.
Play 2: Kibana Üzerinde Sertifikaların Kurulması
- name: Configure Kibana with certificates
hosts: kibana
1. Sertifika Paketini Kopyalama (kibana.zip)
- name: Copy kibana.zip to host
synchronize:
src: "{{ output_path }}/kibana.zip"
dest: "{{ output_path }}/kibana.zip"
delegate_to: "{{ groups['elasticsearch_master'][0] }}"
synchronizemodülü, rsync benzeri bir şekilde Elasticsearch master’dan Kibana sunucusunakibana.zippaketini taşır.delegate_to: işlem aslında Kibana üzerinde çalışırken, dosya master’dan alınır.
2. CA Sertifikasının Kopyalanması (http_ca.crt)
- name: Copy http_ca.crt to host
copy:
src: "{{ certs_path }}/http_ca.crt"
dest: "{{ output_path }}/http_ca.crt"
delegate_to: "{{ groups['elasticsearch_master'][0] }}"
- Elasticsearch’in kök sertifikası Kibana’ya manuel olarak taşınır.
- Bu sertifika sayesinde Kibana, Elasticsearch’in HTTPS bağlantısını doğrulayabilir.
3. Kibana Sertifika Dizininin Oluşturulması
- name: Ensure /etc/kibana/certs directory exists
file:
path: /etc/kibana/certs
state: directory
...
- Sertifikaların kalıcı olarak tutulacağı dizin yaratılır.
- Gerekli sahiplik (
kibana:kibana) ve izinler (0755) atanır.
4. kibana.zip Arşivinin Açılması
- name: Unzip kibana.zip to /etc/kibana/certs
unarchive:
src: /tmp/kibana.zip
dest: /etc/kibana/certs
remote_src: true
...
kibana.zipiçeriği/etc/kibana/certs/dizinine açılır.- İçerisinde
instance.crtveinstance.keydosyaları yer alır.
5–6. CA Sertifikasının Taşınması ve Yetkilendirilmesi
- name: Move http_ca.crt to /etc/kibana/certs
command: mv /tmp/http_ca.crt /etc/kibana/certs/http_ca.crt
- name: Set ownership and permissions on http_ca.crt
file:
path: /etc/kibana/certs/http_ca.crt
owner: kibana
group: kibana
mode: '0774'
http_ca.crtdizine taşınır ve doğru kullanıcı/izin ayarları yapılır.- Bu dosya
kibana.yml'deelasticsearch.ssl.certificateAuthoritiesparametresine karşılık gelir.
kibana-sync-ssl-certificates.yml
Genel Amaç
- Master node’dan sertifikaları kontrol makinesine çekmek
- Kontrol makinesinden Kibana sunucusuna yüklemek
- Kibana üzerinde
/etc/kibana/certsdizininde bu dosyaları hazır hale getirmek
Teknik Analiz
1. kibana.zip Dosyasını Kontrol Makinesine Alma
- name: Fetch kibana.zip to control machine
fetch:
src: "{{ output_path }}/kibana.zip"
dest: "/tmp/kibana.zip"
flat: true
delegate_to: "{{ groups['elasticsearch_master'][0] }}"
fetch: Uzak host’tan dosyayı kontrol makinesine indirir.delegate_to: Elasticsearch master node üzerinde çalışır.flat: true: Dosya hedef dizine alt klasör yaratmadan direkt olarak/tmp'ye kopyalanır.
2. kibana.zip Dosyasını Kibana Sunucusuna Kopyalama
- name: Copy kibana.zip to Kibana host
copy:
src: "/tmp/kibana.zip"
dest: "{{ output_path }}/kibana.zip"
- Bu adımda kontrol makinesindeki
kibana.zip, Kibana sunucusuna kopyalanır. - Burada
fetch → copymodeli izlenmiştir (push–pull ayrımı).
3. http_ca.crt Sertifikasını Fetch Etme
- name: Fetch http_ca.crt to control machine
fetch:
src: "{{ certs_path }}/http_ca.crt"
dest: "/tmp/http_ca.crt"
flat: true
delegate_to: "{{ groups['elasticsearch_master'][0] }}"
- CA sertifikası da aynı yöntemle Elasticsearch master’dan alınır.
4. CA Sertifikasını Kibana Sunucusuna Kopyalama
- name: Copy http_ca.crt to Kibana host
copy:
src: "{{ output_path }}/http_ca.crt"
dest: "/etc/kibana/certs/http_ca.crt"
- Bu dosya, Kibana’nın Elasticsearch’e bağlanırken SSL doğrulaması yapmasını sağlar.
5. unzip Paketini Yükleme
- name: Install unzip
apt:
name: unzip
state: present
kibana.zipdosyasını açmak için gerekli bağımlılık kurulmuş.- Bazı dağıtımlarda ön yüklü gelmeyebilir, bu nedenle iyi bir güvenlik önlemidir.
6. kibana.zip Arşivini Açma
- name: Extract kibana.zip
unarchive:
src: /tmp/kibana.zip
dest: /etc/kibana/certs
remote_src: true
kibana.zipiçindeinstance.crtveinstance.keydosyaları yer alır.remote_src: true→ ZIP dosyasının zaten uzak sistemde bulunduğunu belirtir./etc/kibana/certsdizinine çıkarılır.
⚠️ Sertifikaların izin ve sahiplikleri burada eksik kalmış.
filemodülüyleowner: kibana,mode: '0640'gibi ayarlar yapılmalıdır.
Yöntemsel Karşılaştırma
Yöntem Açıklama delegate_to + synchronize Daha hızlıdır, doğrudan node’dan node’a aktarım yapılır (rsync) fetch + copy Daha kontrollüdür, kontrol makinesinde log tutma ve dışa aktarma mümkündür. Bazı güvenlik senaryolarında tek opsiyondur
Her iki yöntem de doğru kullanım senaryosuna göre geçerlidir.
kibana-start-service.yml
Genel Amaç
- Kibana servisini başlatmak (
started) - Her sistem boot’unda servisin otomatik çalışmasını sağlamak (
enabled)
Hedef Host
hosts: kibana
- Kibana rolüne sahip node’ları hedefler.
- Bu playbook, genellikle konfigürasyon ve sertifika işlemlerinden sonra çalıştırılır.
Görev Analizi
- name: Start Kibana Service
systemd:
name: kibana
state: started
enabled: true
systemdmodülü kullanılarak Kibana servisi yönetilir.state: started: Servis anlık olarak başlatılır.enabled: true: Sistem yeniden başlasa bile servis otomatik olarak başlatılır.
Eğer servis çalışmazsa, bu noktada muhtemel hata logları
/var/log/kibana/altında incelenmelidir.
Loadbalancer
es-loadbalancer.yml – Ansible Playbook Analizi
Amaç
- Nginx’in yüklenmesi
- Jinja2 şablon dosyasının
/etc/nginx/conf.d/altına yerleştirilmesi - Nginx’in yapılandırmayı uygulayacak şekilde yeniden yüklenmesi
Görevler
- Nginx Kurulumu
- name: Ensure Nginx is installed
apt:
name: nginx
state: present
update_cache: true
- Yük dengeleyici servisi olan Nginx kuruluyor.
update_cache: trueile APT önbelleği güncellenerek en güncel paketlerin kullanılması sağlanıyor.
- Nginx Yapılandırmasının Dağıtılması
- name: Deploy Nginx load balancer configuration
template:
src: nginx-loadbalancer.conf.j2
dest: "{{ nginx_conf_path }}"
owner: root
group: root
mode: '0644'
templatemodülü ile dinamik bir Jinja2 şablonu hedef sisteme işlenerek yazılıyor.- Bu sayede Elasticsearch node’larının IP adresleri envantere göre otomatik olarak yerleştirilebiliyor.
- Nginx Servisinin Yeniden Yüklenmesi
- name: Reload Nginx to apply new configuration
systemd:
name: nginx
state: reloaded
enabled: true
- Nginx servis dosyası reload ediliyor.
enabled: trueile sistem yeniden başladığında aktif kalması sağlanıyor.
nginx-loadbalancer.conf.j2 – Jinja2 Tabanlı Nginx Şablon Analizi
Yapı
server {
listen 9200 ssl;
server_name _;
ssl_certificate /etc/kibana/certs/instance/instance.crt;
ssl_certificate_key /etc/kibana/certs/instance/instance.key;
- Nginx burada
9200portunu dinliyor (Elasticsearch’in default portu). - TLS ile güvenli bağlantı kuruluyor.
- Sertifikalar Kibana’nın
/etc/kibana/certs/dizininden kullanılıyor. (Bunlar genellikleinstance.crt/.keyolarak sertifika üretim aşamasında elde edilir.) - Bu yaklaşımda TLS termination Load Balancer’da gerçekleşiyor.
Proxy Ayarları
location / {
proxy_pass https://es_backends;
proxy_ssl_verify off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
proxy_pass: Gelen istekleres_backendsupstream bloğuna yönlendirilir.proxy_ssl_verify off: Elasticsearch backend'lerinin sertifikası doğrulanmaz (geliştirme ortamları için makul ama üretim için önerilmez).- Header bilgileri preserve edilir.
Upstream Tanımı (Dinamik Olarak Inventory’den)
upstream es_backends {
{% for host in groups['elasticsearch_master'] + groups['elasticsearch_nodes'] %}
server {{ hostvars[host]['inventory_hostname'] }}:9200;
{% endfor %}
}
- Elasticsearch master ve node’lar birlikte load balancer arkasına ekleniyor.
- IP’ler
inventory_hostnameile çekiliyor. - Bu yapı sayesinde Ansible inventory dosyasını güncellemek, Nginx backend listesini otomatik olarak güncellemek anlamına gelir.
Kibana Reverse Proxy
kibana-reverse-proxy.yml – Ansible Playbook Analizi
Amaç
- Nginx yüklenir
/etc/nginx/conf.d/kibana.confdosyası deploy edilir- Servis yeniden yüklenerek aktif hale getirilir
Görevler
- Nginx’in Kurulumu
- name: Ensure Nginx is installed
apt:
name: nginx
state: present
update_cache: true
- Nginx henüz kurulu değilse yüklenir
- Reverse proxy altyapısının temelini oluşturur
- Şablon Dosyasının Dağıtılması
- name: Deploy Nginx Reverse-Proxy
template:
src: kibana.conf.j2
dest: "{{ nginx_conf_path }}"
kibana.conf.j2şablonu/etc/nginx/conf.d/kibana.confolarak yerleştirilir.- Tüm değişiklikler Ansible üzerinden merkezi olarak yönetilir.
- Nginx Servisinin Yeniden Yüklenmesi
- name: Reload Nginx to apply new configuration
systemd:
name: nginx
state: reloaded
enabled: true
- Nginx yapılandırmasını yeniden yükler.
- Sistem başlatıldığında Nginx’in otomatik olarak başlatılmasını sağlar.
kibana.conf.j2 – Nginx Reverse Proxy Şablon Dosyası Analizi
HTTP’den HTTPS’ye Yönlendirme
server {
listen 80;
server_name _;
return 301 https://$host$request_uri;
}
- 80 portuna gelen HTTP istekleri, 443 portuna yönlendirilir
301 Moved Permanentlyile kalıcı HTTPS yönlendirmesi yapılır- SEO ve kullanıcı deneyimi açısından önemlidir
HTTPS Reverse Proxy (TLS)
server {
listen 443 ssl;
server_name _;
ssl_certificate /etc/kibana/certs/instance/instance.crt;
ssl_certificate_key /etc/kibana/certs/instance/instance.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
- Kibana arayüzü artık TLS (HTTPS) üzerinden sunulur
- Sertifikalar daha önce oluşturulup
/etc/kibana/certs/dizinine yerleştirilmişti - TLS 1.2 ve 1.3 protokolleri destekleniyor (güncel güvenlik standardı)
- Güvenli şifreleme algoritmaları belirlenmiş
Proxy Ayarları
location / {
proxy_pass https://localhost:5601;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
proxy_pass: Kibana servisine (localhost:5601) trafik yönlendirilirUpgradeveConnectionbaşlıkları, WebSocket bağlantılarını desteklemek için gereklidir (Kibana buna ihtiyaç duyar)proxy_cache_bypass: Cache sistemlerininUpgradebaşlığına göre baypas edilmesini sağlar
Proje Github repositorysine adresten ulaşabilirsiniz https://github.com/farukerdem34/es-ansible/
메타데이터
- post_id
- 724c14e8af86
- slug
- ansible-ve-terraform-i̇le-elk-stack-kurulumu-724c14e8af86
- url
- https://medium.com/@faruk3rdem/ansible-ve-terraform-i%CC%87le-elk-stack-kurulumu-724c14e8af86
- canonical_url
- https://medium.com/@faruk3rdem/ansible-ve-terraform-i%CC%87le-elk-stack-kurulumu-724c14e8af86
- author_url
- https://medium.com/@faruk3rdem
- status
- ok
- fetched_at
- 2026-07-18 17:48:23