Percona multi-master mysql cluster kurulumu

Bu yazıda çoklu-master yapıdaki Percona cluster'ın kurulumunu anlatmaya çalışacağım. Kaynağım şurası, farklı-özel bir yapılandırma yapmayacağız üzerine.   Split-brain durumu için en az 3 box kurulum tavsiye ediliyor. Bu olay önemli, çünkü olası bir sorunda iki box da kendini master zannedebilir ve veri çakışması yaşayabilirsiniz. Bu yüzden STONITH özellikli bir HA çözümü incelemenizi tavsiye ederim. Bu yazıdaki amaç mükemmel cluster'ı oluşturmak değil, ayağa kaldırıp çalışır hale getirmek.   Aşağıdaki özelliklere sahip iki (veya daha fazla) ubuntu server gerekli:

  • Üzerinde mysql veya mariadb gibi bir servis bulunmayan/çalışmayan
  • IP dizilimleri şöyle (örnek): birinci sunucu - 11.11.11.11 (hostname box1) ve ikinci sunucu - 22.22.22.22 (hostname box2)

  Aksi belirtilmedikçe verilen komutlar replike olacak tüm sunucular içindir.   Saat yapılandırması Tüm sunucuların saatlerinin aynı olduğuna emin olun:

    ntpdate ntp.ubuntu.com

  hosts dosyası yapılandırması Sunucular birbirini çözümleyebilmeli, bu yüzden:

    echo -e "11.11.11.11 box1\n22.22.22.22 box2" >> /etc/hosts

  Sunucular arası izinler Sunucularda (yoksa) ssh key üretelim:

    ssh-keygen -t rsa

Ardından birbirlerine tanıtalım: (box1'de)

    ssh-copy-id root@box2

(box2'de)

    ssh-copy-id root@box1

  Depo ekleme ve kurulum

    echo "deb http://repo.percona.com/apt precise main" > /etc/apt/sources.list.d/Percona.list 
    
    gpg --keyserver hkp://keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A && gpg -a --export CD2EFD2A | apt-key add -

Biraz da pinning gerekli:

    echo -e "Package: *\nPin: origin percona.com\nPin-Priority: 1000\n\nPackage: *\nPin: origin repo.percona.comg\nPin-Priority: 1000\n\nPackage: libmysqlclient18\nPin: origin repo.percona.com\nPin-Priority: 1000" > /etc/apt/preferences.d/00XtraDB.pref

Ardından kuralım:

    apt-get update && apt-get install -y percona-xtradb-cluster-client-5.5 percona-xtradb-cluster-server-5.5 percona-xtradb-cluster-common-5.5 percona-xtradb-cluster-galera-2.x percona-xtrabackup libmysqlclient18 rsync netcat-openbsd tinyca

Kurulum sırasında Mysql root parolası sorulacak, tüm sunucularda aynı parolayı girip devam ediyoruz. Bu yazıda örnek olarak "patates" kullanacağız. Kurulumda uyarı olarak bazı ek fonksiyonların tanımlatılabileceği söyleniyor, mysql konsolunda tanımlatıyalım:

    service mysql restart
    mysql -uroot -p
    
    
    mysql> CREATE FUNCTION fnv1a_64 RETURNS INTEGER SONAME 'libfnv1a_udf.so';
    
    mysql> CREATE FUNCTION fnv_64 RETURNS INTEGER SONAME 'libfnv_udf.so';
    
    mysql> CREATE FUNCTION murmur_hash RETURNS INTEGER SONAME 'libmurmur_udf.so';

  Yapılandırma Ram miktarına göre örnek config dosyaları /usr/share/mysql/ altında. Bunlardan ihtiyacımıza göre olanı kopyalıyoruz ve replika yapılandırmasıyla birleştiriyoruz. Örn:

    cp -f /usr/share/mysql/my-large.cnf /etc/mysql/my.cnf 
    cat /usr/share/mysql/wsrep.cnf >> /etc/mysql/my.cnf

Mysql sunucuyu durdurup, bazı parametreler ekliyoruz:

    pkill -f mysql 
    rm -f /var/lock/subsys/mysql
    service mysql stop
    echo -e " \n# DATA STORAGE #\ndatadir = /var/lib/mysql\npid-file = /var/run/mysqld/mysqld.pid\n# MyISAM #\nkey-buffer-size = 32M\nmyisam-recover = FORCE,BACKUP\n\n# SAFETY #\nmax-allowed-packet = 16M\nmax-connect-errors = 1000000\ninnodb = FORCE\n\n# CACHES AND LIMITS #\ntmp-table-size = 32M\nmax-heap-table-size = 32M\nmax-connections = 500\nthread-cache-size = 50\nopen-files-limit = 65535\ntable-definition-cache = 1024\ntable-open-cache = 2048\n\n# LOGGING #\nlog-error = /var/log/mysql/error.log\nlog-queries-not-using-indexes = 0\nslow-query-log = 0\nslow-query-log-file = /var/log/mysql/slow.log\n" >> /etc//mysql/my.cnf

Log ve PID dizinlerini oluşturalım, izinlerini verelim:

    mkdir -p /var/log/mysqld
    mkdir -p /var/run/mysqld
    chown -R mysql:mysql /var/log/mysqld
    chown -R mysql:mysql /var/run/mysqld

InnoDB tablo optimizasyonunu açalım ve logları 64 MB'a getirelim:

    sed -i "s|#innodb_|innodb_|g" /etc/mysql/my.cnf
    sed -i "s|innodb_log_file_size|innodb_log_file_size = 64M\n##|g" /etc/mysql/my.cnf

Önceki InnoDB kalıntılarını silelim:

    rm -f /var/lib/mysql/ib_logfile*

Cluster Yapılandırması (wsrep_cluster_name bölümünde istediğimiz bir cluster ismi girelim, tüm sunucularda aynı olacak)

    sed -i 's|wsrep_provider=none|wsrep_provider=/usr/lib/libgalera_smm.so|g' /etc/mysql/my.cnf    
    sed -i -e 's|\[mysqld\]|\[mysqld\]\n# * Cluster icin GEREKLI ayarlar#\n# * DOKUNMAYIN\n|' /etc/mysql/my.cnf
    sed -i 's|#wsrep_provider_options=|wsrep_provider_options="pc.ignore_sb = yes; gcache.size=2G; gcache.page_size=1G"|g' /etc/mysql/my.cnf
    sed -i 's|wsrep_cluster_name="my_wsrep_cluster"|wsrep_cluster_name="Deneme_Cluster"|g' /etc/mysql/my.cnf
    sed -i 's|wsrep_sst_method=rsync|wsrep_sst_method=xtrabackup|g' /etc/mysql/my.cnf
    sed -i 's|wsrep_slave_threads=1|wsrep_slave_threads=16|g' /etc/mysql/my.cnf

wsrep_sst_auth bölümünde parolamızı tanımlayalım:

    sed -i 's|wsrep_sst_auth=root:|wsrep_sst_auth="root:patates"|g' /etc/mysql/my.cnf

SST xbstream aktifleştiriyoruz:

    echo -e "\n[sst]\nstreamfmt=xbstream" >> /etc/mysql/my.cnf

Birinci sunucuda

    sed -i 's|#wsrep_node_name=|wsrep_node_name="box1"|' /etc/mysql/my.cnf
    sed -i 's|#wsrep_node_address=|wsrep_node_address="box1"|' /etc/mysql/my.cnf
    sed -i 's|#wsrep_node_incoming_address=|wsrep_node_incoming_address=11.11.11.11|' /etc/mysql/my.cnf
    sed -i 's|#wsrep_sst_receive_address=|wsrep_sst_receive_address=11.11.11.11|' /etc/mysql/my.cnf

İkinci sunucuda

    sed -i 's|#wsrep_node_name=|wsrep_node_name="box2"|' /etc/mysql/my.cnf
    sed -i 's|#wsrep_node_address=|wsrep_node_address="box2"|' /etc/mysql/my.cnf
    sed -i 's|#wsrep_node_incoming_address=|wsrep_node_incoming_address=22.22.22.22|' /etc/mysql/my.cnf
    sed -i 's|#wsrep_sst_receive_address=|wsrep_sst_receive_address=22.22.22.22|' /etc/mysql/my.cnf

Bkz. aşağıdaki satırı tüm sunuculara tanımladık. RAM yapılandırması ile beraber split-brain durumunda servisin her sunucuda devam edebilmesini sağlıyor. Bu istemediğiniz sonuçlara yol açabilir.

    wsrep_provider_options="pc.ignore_sb = yes; gcache.size=2G; gcache.page_size=1G"

  **İlk çalıştırma **Tüm sunuculardaki tüm mysql servislerini durduruyoruz, aşırıya kaçıp gebertelim ne var ne yok:

    service mysql stop 
    pkill -9 -f maria
    pkill -9 -f percona
    pkill -9 -f mysql
    pkill -9 -f rsync
    pkill -9 -f innobackupex

  İkinci/diğer sunucularda Hangi sunuculara/sunucuya bağlanacaksa hostname'lerini veriyoruz, birden fazla ise arasına virgül atıp listeliyoruz box1,box3,box4 gibi):

    sed -i 's|#wsrep_cluster_address="dummy://"|wsrep_cluster_address="gcomm://box1"|' /etc/mysql/my.cnf

Birinci sunucuda benzer düzenlemeyi yapıyoruz:

    sed -i 's|#wsrep_cluster_address="dummy://"|wsrep_cluster_address="gcomm://box2"|' /etc/mysql/my.cnf

Ardından diğer sunucular çalışmadığı için, cluster'ı ayağa kaldırmak için bootstrap işlemi yapıyoruz.

    /etc/init.d/mysql bootstrap-pxc

Sonra yine birincide, mysql_secure_installation çalıştırıp test kullanıcısını vs siliyoruz, parolayı değiştirmemeye dikkat edin:

    mysql_secure_installation

Diğer sunucuları çalıştırırken, birinci üzerinde cluster durumunu görüntülemek istersek:

    watch -d -n1 -x mysql -B --password=patates -e "SHOW STATUS WHERE variable_name ='wsrep_local_state_comment' OR variable_name ='wsrep_cluster_size' OR variable_name ='wsrep_incoming_addresses' OR variable_name ='wsrep_cluster_status' OR variable_name ='wsrep_connected' OR variable_name ='wsrep_ready' OR variable_name ='wsrep_local_state_uuid' OR variable_name ='wsrep_cluster_state_uuid';"

İkinci ve diğer sunucularda data dizinini silerek, çalıştırıyoruz:

    rm -frv /var/lib/mysql/*
    service mysql start