etcd Kümesini Ansible ile Ubuntu 18.04 Üzerinde Kurma ve Güvenliğini Sağlama
Giriş
Dağıtık sistemlerde yapılandırma yönetimi ve servis keşfi, sistemlerin kararlılığı ve ölçeklenebilirliği için kritik öneme sahiptir. etcd, bu ihtiyaçları karşılamak üzere tasarlanmış, dağıtık ve güvenilir bir anahtar-değer deposudur. Kubernetes gibi popüler konteyner orkestrasyon platformlarının temelini oluşturan etcd, küme durumunu, yapılandırma verilerini ve meta verileri tutarlı bir şekilde depolamak için kullanılır.
Bu rehberde, etcd kümesini Ubuntu 18.04 işletim sistemi üzerinde Ansible otomasyon aracı kullanarak nasıl kuracağımızı ve güvenliğini sağlayacağımızı adım adım ele alacağız. Ansible, altyapı kod (Infrastructure as Code) prensiplerini benimseyerek tekrarlanabilir, tutarlı ve hatasız dağıtımlar yapmamızı sağlar. Güvenlik tarafında ise, etcd kümesinin hem istemci-sunucu hem de düğüm-düğüm iletişimi için TLS (Transport Layer Security) şifrelemesi ve kimlik doğrulaması kullanmasını sağlayacağız.
Ön Gereksinimler ve Hazırlık
etcd kümesi kurmaya başlamadan önce bazı ön gereksinimleri ve hazırlıkları tamamlamamız gerekiyor. Bu rehber için en az 3 adet Ubuntu 18.04 sunucuya ihtiyacımız olacak. Her sunucunun kendi IP adresine ve birbiriyle SSH erişimine sahip olması gerekmektedir.
Sunucu Hazırlığı
- Sunucular Arasında SSH Erişimi: Ansible kontrol makinesinden tüm etcd düğümlerine parola istemeden SSH erişimi kurulmalıdır. Bu genellikle SSH anahtarları kullanılarak yapılır.
- Sudo Yetkileri: etcd düğümlerinde Ansible’ın komutları çalıştırabilmesi için sudo yetkilerine sahip bir kullanıcı olmalıdır.
- Hostname ve
/etc/hostsYapılandırması: Her etcd düğümünün benzersiz bir hostname’i olmalı ve tüm düğümlerin birbirlerinin IP adreslerini ve hostname’lerini/etc/hostsdosyalarında (veya DNS’te) tanımlaması önerilir. Bu, kümenin kararlı çalışması için önemlidir.# etcd-node1 için sudo hostnamectl set-hostname etcd-node1 sudo nano /etc/hostsAşağıdakileri ekleyin (IP adreslerinizi güncelleyin)
192.168.1.101 etcd-node1 192.168.1.102 etcd-node2 192.168.1.103 etcd-node3 - Güvenlik Duvarı (UFW) Yapılandırması: etcd’nin çalışması için gerekli portları açmamız gerekmektedir.
2379/tcp: İstemci-sunucu iletişimi için.2380/tcp: Düğümler arası (peer-to-peer) iletişim için.22/tcp: SSH erişimi için.
sudo ufw allow 22/tcp sudo ufw allow 2379/tcp sudo ufw allow 2380/tcp sudo ufw enable
Ansible Kontrol Makinesi Hazırlığı
Ansible kontrol makinenize Ansible’ı kurmanız gerekmektedir:
sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
TLS Sertifikalarının Oluşturulması
etcd kümesinin güvenliğini sağlamak için TLS sertifikalarına ihtiyacımız var. Her etcd düğümü için bir sunucu sertifikası, istemcilerin etcd’ye bağlanması için bir istemci sertifikası ve hepsini imzalamak için bir Sertifika Yetkilisi (CA) sertifikası oluşturmalıyız. Bu adımı manuel olarak veya cfssl gibi araçlarla yapabilirsiniz. Aşağıda gerekli sertifika türleri ve kullanımları özetlenmiştir:
- CA Sertifikası (ca.pem, ca-key.pem): Tüm diğer sertifikaları imzalamak için kullanılır.
- Sunucu Sertifikaları (server.pem, server-key.pem): Her etcd düğümünün istemci ve diğer düğümlerle güvenli iletişim kurması için. Bu sertifikalar
CN(Common Name) olarak düğümün hostname’ini veSAN(Subject Alternative Name) olarak düğümün IP adresini ve hostname’ini içermelidir. - İstemci Sertifikası (client.pem, client-key.pem):
etcdctlgibi araçların veya diğer servislerin (örn. Kubernetes API sunucusu) etcd kümesine güvenli bir şekilde bağlanması için.
Oluşturduğunuz tüm sertifika dosyalarını (ca.pem, server.pem, server-key.pem, client.pem, client-key.pem) Ansible kontrol makinenizde, etcd rolünün files dizini altında (örneğin, roles/etcd/files/ssl/) saklayın. Bu dosyaları her düğüme kopyalayacağız.
Ansible Proje Yapısı Oluşturma
Ansible projemiz için aşağıdaki gibi bir dizin yapısı oluşturalım:
etcd-ansible/
├── inventory/
│ └── hosts.ini
├── group_vars/
│ └── all.yml
├── playbook.yml
└── roles/
└── etcd/
├── tasks/
│ └── main.yml
├── templates/
│ └── etcd.service.j2
└── files/
└── ssl/
├── ca.pem
├── server.pem
├── server-key.pem
├── client.pem
└── client-key.pem
inventory/hosts.ini
etcd düğümlerimizi tanımlayalım. ansible_host kullanarak her düğümün IP adresini belirtin.
[etcd_nodes]
etcd-node1 ansible_host=192.168.1.101
etcd-node2 ansible_host=192.168.1.102
etcd-node3 ansible_host=192.168.1.103
[all:vars]
ansible_user=your_ssh_user # SSH bağlantısı için kullanıcı adınız
ansible_become=yes # Sudo kullanmak için
group_vars/all.yml
Tüm etcd düğümleri için geçerli olacak değişkenleri tanımlayalım.
---
etcd_version: 3.4.13 # Kullanmak istediğiniz etcd sürümü
etcd_data_dir: /var/lib/etcd
etcd_config_dir: /etc/etcd
etcd_ssl_dir: "{{ etcd_config_dir }}/ssl"
etcd_peer_port: 2380
etcd_client_port: 2379
etcd_initial_cluster_token: etcd-cluster-token-01 # Küme başlatma için benzersiz bir token
Sertifika yolları
etcd_ca_file: "{{ etcd_ssl_dir }}/ca.pem"
etcd_server_cert_file: "{{ etcd_ssl_dir }}/server.pem"
etcd_server_key_file: "{{ etcd_ssl_dir }}/server-key.pem"
etcd_client_cert_file: "{{ etcd_ssl_dir }}/client.pem"
etcd_client_key_file: "{{ etcd_ssl_dir }}/client-key.pem"
playbook.yml
Ana oynatma kitabımız, etcd rolünü çağırır.
---
- name: etcd Kümesini Kurma ve Yapılandırma
hosts: etcd_nodes
roles:
- etcd
Ansible Rolü: etcd Kurulumu ve Yapılandırması
roles/etcd/tasks/main.yml
Bu dosya, etcd kurulumu, yapılandırması ve TLS sertifikalarının dağıtımını gerçekleştiren adımları içerir.
---
- name: Sistem paketlerini güncelle
apt:
update_cache: yes
upgrade: dist
become: yes
- name: Gerekli paketleri yükle
apt:
name:
- curl
- wget
- systemd
state: present
become: yes
- name: etcd kullanıcı ve grubunu oluştur
user:
name: etcd
group: etcd
system: yes
shell: /sbin/nologin
create_home: no
become: yes
- name: etcd veri ve yapılandırma dizinlerini oluştur
file:
path: "{{ item }}"
state: directory
owner: etcd
group: etcd
mode: '0700'
loop:
- "{{ etcd_data_dir }}"
- "{{ etcd_config_dir }}"
- "{{ etcd_ssl_dir }}"
become: yes
- name: etcd ikili dosyalarını indir ve çıkar
unarchive:
src: "https://github.com/etcd-io/etcd/releases/download/v{{ etcd_version }}/etcd-v{{ etcd_version }}-linux-amd64.tar.gz"
dest: /tmp
remote_src: yes
become: yes
- name: etcd ikili dosyalarını /usr/local/bin'e taşı
copy:
src: "/tmp/etcd-v{{ etcd_version }}-linux-amd64/{{ item }}"
dest: "/usr/local/bin/{{ item }}"
owner: root
group: root
mode: '0755'
remote_src: yes
loop:
- etcd
- etcdctl
become: yes
- name: Sertifika dosyalarını etcd düğümlerine kopyala
copy:
src: "ssl/{{ item }}"
dest: "{{ etcd_ssl_dir }}/{{ item }}"
owner: etcd
group: etcd
mode: '0400' # Özel anahtarlar için daha kısıtlı izinler
loop:
- ca.pem
- server.pem
- server-key.pem
- client.pem
- client-key.pem
become: yes
- name: systemd servis dosyasını şablondan oluştur
template:
src: etcd.service.j2
dest: /etc/systemd/system/etcd.service
owner: root
group: root
mode: '0644'
become: yes
notify:
- systemd daemon-reload
- etcd servisini yeniden başlat
- name: etcd servisini başlat ve etkinleştir
systemd:
name: etcd
state: started
enabled: yes
become: yes
- name: etcd kümesinin sağlıklı olmasını bekle
wait_for:
port: "{{ etcd_client_port }}"
host: "{{ ansible_host }}"
state: started
delay: 5
timeout: 60
delegate_to: localhost
when: inventory_hostname == 'etcd-node1' # Sadece bir düğümden kontrol edilebilir
roles/etcd/templates/etcd.service.j2
etcd için systemd servis dosyasını bu şablonu kullanarak oluşturacağız. ETCD_INITIAL_CLUSTER değişkeni, Ansible’ın Jinja2 yetenekleri kullanılarak dinamik olarak oluşturulacaktır.
[Unit]
Description=etcd - Highly-available key value store
Documentation=https://etcd.io
After=network.target
[Service]
User=etcd
Type=notify
Restart=always
RestartSec=5s
LimitNOFILE=40000
Environment="ETCD_DATA_DIR={{ etcd_data_dir }}"
Environment="ETCD_WAL_DIR={{ etcd_data_dir }}/wal"
Environment="ETCD_NAME={{ inventory_hostname }}"
Environment="ETCD_LISTEN_PEER_URLS=https://{{ ansible_host }}:{{ etcd_peer_port }}"
Environment="ETCD_LISTEN_CLIENT_URLS=https://{{ ansible_host }}:{{ etcd_client_port }},http://127.0.0.1:2379" # İstemci için HTTPS ve localhost HTTP
Environment="ETCD_ADVERTISE_CLIENT_URLS=https://{{ ansible_host }}:{{ etcd_client_port }}"
Environment="ETCD_INITIAL_ADVERTISE_PEER_URLS=https://{{ ansible_host }}:{{ etcd_peer_port }}"
Environment="ETCD_INITIAL_CLUSTER_TOKEN={{ etcd_initial_cluster_token }}"
Environment="ETCD_INITIAL_CLUSTER_STATE=new"
Peer TLS Yapılandırması
Environment="ETCD_PEER_CLIENT_CERT_AUTH=true"
Environment="ETCD_PEER_TRUSTED_CA_FILE={{ etcd_ca_file }}"
Environment="ETCD_PEER_CERT_FILE={{ etcd_server_cert_file }}"
Environment="ETCD_PEER_KEY_FILE={{ etcd_server_key_file }}"
Client TLS Yapılandırması
Environment="ETCD_CLIENT_CERT_AUTH=true"
Environment="ETCD_TRUSTED_CA_FILE={{ etcd_ca_file }}"
Environment="ETCD_CERT_FILE={{ etcd_server_cert_file }}"
Environment="ETCD_KEY_FILE={{ etcd_server_key_file }}"
Dinamik olarak initial cluster string oluşturma
{%- set initial_cluster_members = [] -%}
{%- for host in groups['etcd_nodes'] -%}
{%- set _ = initial_cluster_members.append(host + '=https://' + hostvars[host]['ansible_host'] + ':' + etcd_peer_port | string) -%}
{%- endfor -%}
Environment="ETCD_INITIAL_CLUSTER={{ initial_cluster_members | join(',') }}"
ExecStart=/usr/local/bin/etcd
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
[Install]
WantedBy=multi-user.target
Önemli Not: ETCD_LISTEN_CLIENT_URLS içinde http://127.0.0.1:2379 ekledik. Bu, özellikle Kubernetes gibi iç servislerin etcd’ye bağlanırken ek yapılandırma gerektirmeden localhost üzerinden HTTP ile bağlanabilmesi için yaygın bir pratiktir. Eğer tam güvenlik istiyorsanız bu satırı kaldırabilirsiniz, ancak o zaman tüm istemcilerin TLS ile bağlanması gerekecektir.
roles/etcd/handlers/main.yml
Servis değişiklikleri için handler tanımlayalım.
---
- name: systemd daemon-reload
systemd:
daemon_reload: yes
become: yes
- name: etcd servisini yeniden başlat
systemd:
name: etcd
state: restarted
become: yes
Ansible Playbook’u Çalıştırma
Tüm dosyaları oluşturduktan sonra, Ansible kontrol makinenizden aşağıdaki komutu çalıştırarak etcd kümesini dağıtabilirsiniz:
ansible-playbook -i inventory/hosts.ini playbook.yml
Ansible, her bir etcd düğümüne bağlanacak, etcd ikili dosyalarını indirecek, sertifikaları kopyalayacak, systemd servis dosyasını yapılandıracak ve etcd servisini başlatacaktır.
Küme Doğrulama ve Güvenliği Test Etme
Kurulum tamamlandıktan sonra, etcd kümesinin sağlıklı bir şekilde çalıştığını ve TLS’nin doğru yapılandırıldığını doğrulamamız gerekir.
etcdctl ile Küme Sağlığını Kontrol Etme
etcdctl aracını kullanarak küme üyelerini ve sağlık durumunu kontrol edebiliriz. TLS etkin olduğu için sertifika yollarını belirtmemiz gerekmektedir:
# etcdctl'i bir etcd düğümünde veya client sertifikalarına sahip bir makinede çalıştırın
etcdctl'in kurulu olduğundan emin olun (Ansible rolü kurar)
export ETCDCTL_API=3
export ETCDCTL_CACERT={{ etcd_ssl_dir }}/ca.pem
export ETCDCTL_CERT={{ etcd_ssl_dir }}/client.pem
export ETCDCTL_KEY={{ etcd_ssl_dir }}/client-key.pem
Küme üyelerini listele
etcdctl member list --endpoints=https://192.168.1.101:2379,https://192.168.1.102:2379,https://192.168.1.103:2379
Küme sağlık durumunu kontrol et
etcdctl endpoint health --endpoints=https://192.168.1.101:2379,https://192.168.1.102:2379,https://192.168.1.103:2379
Beklenen çıktı, tüm üyelerin durumunu, isLeader=true olan bir lideri ve tüm uç noktaların healthy olduğunu göstermelidir.
Veri Yazma ve Okuma Testi
Kümenin veri depolama yeteneğini test edelim:
# Bir anahtar-değer çifti yaz
etcdctl put mykey "Hello etcd cluster!"
Değeri oku
etcdctl get mykey
Bu komutlar başarılı olursa, etcd kümeniz doğru bir şekilde çalışıyor demektir.
Sonuç ve Sıkça Sorulan Sorular (SSS)
Bu rehberde, etcd kümesini Ansible kullanarak Ubuntu 18.04 üzerinde nasıl kuracağımızı ve TLS ile güvenliğini nasıl sağlayacağımızı öğrendik. Ansible’ın otomasyon yetenekleri sayesinde, tekrarlanabilir ve tutarlı bir dağıtım süreci elde ettik. TLS sertifikaları kullanarak hem istemci-sunucu hem de düğüm-düğüm iletişimini şifreledik ve kimlik doğrulamasını sağladık, böylece hassas yapılandırma verilerinizin güvenliğini artırdık.
Sıkça Sorulan Sorular (SSS)
- S: etcd kümesi neden başlamıyor veya küme üyesi olarak görünmüyor?
C: En yaygın nedenler şunlardır:
- Güvenlik Duvarı: 2379 ve 2380 portlarının tüm etcd düğümleri arasında açık olduğundan emin olun.
- Sertifika Sorunları: Sertifikaların doğru oluşturulduğundan, doğru yollara kopyalandığından ve izinlerinin (özellikle anahtar dosyalarının) kısıtlı olduğundan emin olun. etcd günlüklerini kontrol edin (
journalctl -u etcd). - Hostname/IP Eşleşmesi: Sertifikalardaki CN/SAN değerlerinin düğümün hostname ve IP adresleriyle eşleştiğinden emin olun.
/etc/hostsdosyasının doğru yapılandırıldığını kontrol edin. ETCD_INITIAL_CLUSTERYanlış Yapılandırılması: Bu değişkenin tüm küme üyelerini doğru IP adresleri ve portlarla listelediğinden emin olun.
- S:
etcdctlkomutu “connection refused” hatası veriyor, ne yapmalıyım?C: Bu genellikle iki nedenden kaynaklanır:
- etcd servisi çalışmıyor veya doğru portu dinlemiyor. (
systemctl status etcdile kontrol edin). - Güvenlik duvarı (
ufw)etcdctl‘in bağlanmaya çalıştığı portu (varsayılan 2379) engelliyor. - TLS yapılandırması yanlış.
ETCDCTL_CACERT,ETCDCTL_CERT,ETCDCTL_KEYortam değişkenlerinin veya--cacert,--cert,--keyargümanlarının doğru ayarlandığından emin olun.
- etcd servisi çalışmıyor veya doğru portu dinlemiyor. (
- S: Yeni bir etcd düğümünü mevcut bir kümeye nasıl eklerim?
C: Yeni bir düğüm eklemek, mevcut bir kümede
etcdctl member addkomutuyla yapılır, ardından yeni düğümünETCD_INITIAL_CLUSTER_STATEdeğeriexistingolarak ayarlanır. Bu rehberde sadece ilk kurulum ele alındı ancak bu, etcd’nin operasyonel karmaşıklıklarından biridir ve ayrı bir Ansible rolü veya playbook gerektirebilir. - S: Ubuntu 18.04 yerine başka bir sürüm kullanabilir miyim?
C: Evet, Ansible rolü büyük ölçüde dağıtım bağımsızdır. Ancak
aptmodülü yerineyumveyadnfgibi uygun paket yöneticilerini kullanmak ve systemd yollarının doğru olduğundan emin olmak için küçük değişiklikler yapmanız gerekebilir. etcd ikili dosyaları Linux dağıtımları arasında genellikle uyumludur.