Puppet to narzędzie do zarządzania systemami typu open source służące do centralizacji i automatyzacji zarządzania konfiguracją. Narzędzia do automatyzacji pomagają zminimalizować ręczne i powtarzalne zadania oraz mogą zaoszczędzić dużo czasu.
Puppet domyślnie działa w modelu serwer/agent. Agenci pobierają swój „katalog” (ostateczny pożądany stan) z mastera i stosują go lokalnie. Następnie zgłaszają się z powrotem do serwera. Katalog jest obliczany w zależności od „faktów”, które maszyna wysyła do serwera, danych wejściowych użytkownika (parametry) i modułów (kod źródłowy).
W tym blogu pokażemy, jak wdrażać i zarządzać instancjami MySQL/MariaDB za pośrednictwem Puppet. Istnieje wiele technologii związanych z MySQL/MariaDB, takich jak replikacja (master-slave, Galera lub replikacja grupowa dla MySQL), systemy równoważenia obciążenia uwzględniające SQL, takie jak ProxySQL i MariaDB MaxScale, narzędzia do tworzenia kopii zapasowych i odzyskiwania i wiele innych, które omówimy w tym artykule seria blogów. Istnieje również wiele modułów dostępnych w Kuźni Lalek zbudowanych i utrzymywanych przez społeczność, które mogą pomóc nam uprościć kod i uniknąć ponownego wymyślania koła. W tym blogu skupimy się na replikacji MySQL.
puppetlabs/mysql
Jest to obecnie najpopularniejszy moduł Puppet dla MySQL i MariaDB (i prawdopodobnie najlepszy na rynku). Ten moduł zarządza zarówno instalacją, jak i konfiguracją MySQL, a także rozszerza Puppet, aby umożliwić zarządzanie zasobami MySQL, takimi jak bazy danych, użytkownicy i granty.
Moduł jest oficjalnie obsługiwany przez zespół Puppet (za pośrednictwem repozytorium puppetlabs Github) i obsługuje wszystkie główne wersje Puppet Enterprise 2019.1.x, 2019.0.x, 2018.1.x, Puppet>=5.5.10 <7.0.0 na RedHat, Ubuntu, Platformy Debian, SLES, Scientific, CentOS, OracleLinux. Użytkownik ma możliwość zainstalowania MySQL, MariaDB i Percona Server, dostosowując repozytorium pakietów
Poniższy przykład pokazuje, jak wdrożyć serwer MySQL. Na mistrzu marionetek zainstaluj moduł MySQL i utwórz plik manifestu:
(puppet-master)$ puppet module install puppetlabs/mysql
(puppet-master)$ vim /etc/puppetlabs/code/environments/production/manifests/mysql.pp
Dodaj następujące wiersze:
node "db1.local" {
class { '::mysql::server':
root_password => 't5[sb^D[+rt8bBYu',
remove_default_accounts => true,
override_options => {
'mysqld' => {
'log_error' => '/var/log/mysql.log',
'innodb_buffer_pool_size' => '512M'
}
'mysqld_safe' => {
'log_error' => '/var/log/mysql.log'
}
}
}
}
Następnie w węźle agenta marionetkowego uruchom następujące polecenie, aby zastosować katalog konfiguracji:
(db1.local)$ puppet agent -t
Przy pierwszym uruchomieniu może pojawić się następujący błąd:
Info: Certificate for db1.local has not been signed yet
Aby podpisać certyfikat, uruchom następujące polecenie na urządzeniu głównym Puppet:
(puppet-master)$ puppetserver ca sign --certname=db1.local
Successfully signed certificate request for db1.local
Spróbuj ponownie, używając polecenia „puppet agent -t”, aby ponownie zainicjować połączenie z podpisanym certyfikatem.
Powyższa definicja zainstaluje standardowe pakiety związane z MySQL dostępne w repozytorium dystrybucji systemu operacyjnego. Na przykład na Ubuntu 18.04 (Bionic) zainstalowano pakiety MySQL 5.7.26:
(db1.local) $ dpkg --list | grep -i mysql
ii mysql-client-5.7 5.7.26-0ubuntu0.18.04.1 amd64 MySQL database client binaries
ii mysql-client-core-5.7 5.7.26-0ubuntu0.18.04.1 amd64 MySQL database core client binaries
ii mysql-common 5.8+1.0.4 all MySQL database common files, e.g. /etc/mysql/my.cnf
ii mysql-server 5.7.26-0ubuntu0.18.04.1 all MySQL database server (metapackage depending on the latest version)
ii mysql-server-5.7 5.7.26-0ubuntu0.18.04.1 amd64 MySQL database server binaries and system database setup
ii mysql-server-core-5.7 5.7.26-0ubuntu0.18.04.1 amd64 MySQL database server binaries
Możesz wybrać innych dostawców, takich jak Oracle, Percona lub MariaDB z dodatkową konfiguracją w repozytorium (szczegóły w sekcji README). Poniższa definicja zainstaluje pakiety MariaDB z repozytorium MariaDB apt (wymaga modułu apt Puppet):
$ puppet module install puppetlabs/apt
$ vim /etc/puppetlabs/code/environments/production/manifests/mariadb.pp
# include puppetlabs/apt module
include apt
# apt definition for MariaDB 10.3
apt::source { 'mariadb':
location => 'http://sgp1.mirrors.digitalocean.com/mariadb/repo/10.3/ubuntu/',
release => $::lsbdistcodename,
repos => 'main',
key => {
id => 'A6E773A1812E4B8FD94024AAC0F47944DE8F6914',
server => 'hkp://keyserver.ubuntu.com:80',
},
include => {
src => false,
deb => true,
},
}
# MariaDB configuration
class {'::mysql::server':
package_name => 'mariadb-server',
service_name => 'mysql',
root_password => 't5[sb^D[+rt8bBYu',
override_options => {
mysqld => {
'log-error' => '/var/log/mysql/mariadb.log',
'pid-file' => '/var/run/mysqld/mysqld.pid',
},
mysqld_safe => {
'log-error' => '/var/log/mysql/mariadb.log',
},
}
}
# Deploy on db2.local
node "db2.local" {
Apt::Source['mariadb'] ->
Class['apt::update'] ->
Class['::mysql::server']
}
Zwróć uwagę na wartość key->id, gdzie istnieje specjalny sposób pobrania 40-znakowego identyfikatora, jak pokazano w tym artykule:
$ sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
$ apt-key adv --list-public-keys --with-fingerprint --with-colons
uid:-::::1459359915::6DC53DD92B7A8C298D5E54F950371E2B8950D2F2::MariaDB Signing Key <[email protected]>::::::::::0:
sub:-:4096:1:C0F47944DE8F6914:1459359915::::::e::::::23:
fpr:::::::::A6E773A1812E4B8FD94024AAC0F47944DE8F6914:
Gdzie wartość identyfikatora znajduje się w wierszu zaczynającym się od „fpr”, czyli „A6E773A1812E4B8FD94024AAC0F47944DE8F6914”.
Po zastosowaniu katalogu Puppet, możesz bezpośrednio uzyskać dostęp do konsoli MySQL jako root bez jawnego hasła, ponieważ moduł automatycznie konfiguruje ~/.my.cnf i zarządza nim. Jeśli chcielibyśmy zresetować hasło roota na coś innego, po prostu zmień wartość root_password w definicji Puppet i zastosuj katalog w węźle agenta.
Wdrażanie replikacji MySQL
Aby wdrożyć konfigurację MySQL Replication, należy utworzyć co najmniej dwa typy konfiguracji, aby oddzielić konfigurację master i slave. Master będzie miał wyłączoną opcję tylko do odczytu, aby umożliwić odczyt/zapis, podczas gdy urządzenia podrzędne będą skonfigurowane z włączoną opcją tylko do odczytu. W tym przykładzie użyjemy replikacji opartej na GTID, aby uprościć konfigurację (ponieważ konfiguracja wszystkich węzłów byłaby bardzo podobna). Będziemy chcieli zainicjować łącze replikacji do urządzenia głównego zaraz po uruchomieniu urządzenia podrzędnego.
Załóżmy, że mamy 3 węzły replikacji MySQL typu master-slave:
- db1.local — główny
- db2.local — urządzenie podrzędne nr 1
- db3.local — urządzenie podrzędne nr 2
Aby spełnić powyższe wymagania, możemy zapisać nasz manifest w następujący sposób:
# Puppet manifest for MySQL GTID-based replication MySQL 5.7 on Ubuntu 18.04 (Puppet v6.4.2)
# /etc/puppetlabs/code/environments/production/manifests/replication.pp
# node's configuration
class mysql {
class {'::mysql::server':
root_password => '[email protected]#',
create_root_my_cnf => true,
remove_default_accounts => true,
manage_config_file => true,
override_options => {
'mysqld' => {
'datadir' => '/var/lib/mysql',
'bind_address' => '0.0.0.0',
'server-id' => $mysql_server_id,
'read_only' => $mysql_read_only,
'gtid-mode' => 'ON',
'enforce_gtid_consistency'=> 'ON',
'log-slave-updates' => 'ON',
'sync_binlog' => 1,
'log-bin' => '/var/log/mysql-bin',
'read_only' => 'OFF',
'binlog-format' => 'ROW',
'log-error' => '/var/log/mysql/error.log',
'report_host' => ${fqdn},
'innodb_buffer_pool_size' => '512M'
},
'mysqld_safe' => {
'log-error' => '/var/log/mysql/error.log'
}
}
}
# create slave user
mysql_user { "${slave_user}@192.168.0.%":
ensure => 'present',
password_hash => mysql_password("${slave_password}")
}
# grant privileges for slave user
mysql_grant { "${slave_user}@192.168.0.%/*.*":
ensure => 'present',
privileges => ['REPLICATION SLAVE'],
table => '*.*',
user => "${slave_user}@192.168.0.%"
}
# /etc/hosts definition
host {
'db1.local': ip => '192.168.0.161';
'db2.local': ip => '192.169.0.162';
'db3.local': ip => '192.168.0.163';
}
# executes change master only if $master_host is defined
if $master_host {
exec { 'change master':
path => '/usr/bin:/usr/sbin:/bin',
command => "mysql --defaults-extra-file=/root/.my.cnf -e \"CHANGE MASTER TO MASTER_HOST = '$master_host', MASTER_USER = '$slave_user', MASTER_PASSWORD = '$slave_password', MASTER_AUTO_POSITION = 1; START SLAVE;\"",
unless => "mysql --defaults-extra-file=/root/.my.cnf -e 'SHOW SLAVE STATUS\G' | grep 'Slave_SQL_Running: Yes'"
}
}
}
## node assignment
# global vars
$master_host = undef
$slave_user = 'slave'
$slave_password = 'Replicas123'
# master
node "db1.local" {
$mysql_server_id = '1'
$mysql_read_only = 'OFF'
include mysql
}
# slave1
node "db2.local" {
$mysql_server_id = '2'
$mysql_read_only = 'ON'
$master_host = 'db1.local'
include mysql
}
# slave2
node "db3.local" {
$mysql_server_id = '3'
$mysql_read_only = 'ON'
$master_host = 'db1.local'
include mysql
}
Zmuś agenta do zastosowania katalogu:
(all-mysql-nodes)$ puppet agent -t
Na urządzeniu głównym (db1.local) możemy zweryfikować wszystkie podłączone urządzenia podrzędne:
mysql> SHOW SLAVE HOSTS;
+-----------+-----------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+-----------+------+-----------+--------------------------------------+
| 3 | db3.local | 3306 | 1 | 2d0b14b6-8174-11e9-8bac-0273c38be33b |
| 2 | db2.local | 3306 | 1 | a9dfa4c7-8172-11e9-8000-0273c38be33b |
+-----------+-----------+------+-----------+--------------------------------------+
Zwróć szczególną uwagę na sekcję "exec { 'change master' :", gdzie oznacza to, że polecenie MySQL zostanie wykonane w celu zainicjowania łącza replikacji, jeśli warunek zostanie spełniony. Wszystkie zasoby "exec" wykonywane przez Puppet muszą być idempotentne, co oznacza operację, która będzie miała ten sam efekt, niezależnie od tego, czy uruchomisz ją raz, czy 10001 razy. Istnieje wiele atrybutów warunku, których możesz użyć, takich jak „unless”, „onlyif” i „create”, aby zabezpieczyć poprawny stan i zapobiec zepsuciu konfiguracji przez Puppet. Możesz usunąć/skomentować tę sekcję, jeśli chcesz ręcznie zainicjować łącze replikacji.
Zarządzanie MySQL
Ten moduł może być używany do wykonywania wielu zadań związanych z zarządzaniem MySQL:
- opcje konfiguracji (modyfikacja, zastosowanie, konfiguracja niestandardowa)
- zasoby bazy danych (baza danych, użytkownik, dotacje)
- kopia zapasowa (tworzenie, planowanie, użytkownik kopii zapasowej, pamięć)
- proste przywracanie (tylko mysqldump)
- instalacja/aktywacja wtyczek
Zasób bazy danych
Jak widać w powyższym przykładzie manifestu, zdefiniowaliśmy dwa zasoby MySQL - mysql_user i mysql_grant - aby odpowiednio utworzyć użytkownika i nadać mu uprawnienia. Możemy również użyć klasy mysql::db, aby zapewnić obecność bazy danych z powiązanym użytkownikiem i uprawnieniami, na przykład:
# make sure the database and user exist with proper grant
mysql::db { 'mynewdb':
user => 'mynewuser',
password => 'passw0rd',
host => '192.168.0.%',
grant => ['SELECT', 'UPDATE']
}
Zwróć uwagę, że w replikacji MySQL wszystkie zapisy muszą być wykonywane tylko na masterze. Upewnij się więc, że powyższy zasób jest przypisany do mastera. W przeciwnym razie może dojść do błędnych transakcji.
Kopia zapasowa i przywracanie
Zwykle dla całego klastra wymagany jest tylko jeden host kopii zapasowej (chyba że replikujesz podzbiór danych). Do przygotowania zasobów kopii zapasowej możemy użyć klasy mysql::server::backup. Załóżmy, że w naszym manifeście mamy następującą deklarację:
# Prepare the backup script, /usr/local/sbin/mysqlbackup.sh
class { 'mysql::server::backup':
backupuser => 'backup',
backuppassword => 'passw0rd',
backupdir => '/home/backup',
backupdirowner => 'mysql',
backupdirgroup => 'mysql',
backupdirmode => '755',
backuprotate => 15,
time => ['23','30'], #backup starts at 11:30PM everyday
include_routines => true,
include_triggers => true,
ignore_events => false,
maxallowedpacket => '64M',
optional_args => ['--set-gtid-purged=OFF'] #extra argument if GTID is enabled
}
Puppet skonfiguruje wszystkie wymagania wstępne przed uruchomieniem kopii zapasowej - utworzenie użytkownika kopii zapasowej, przygotowanie ścieżki docelowej, przypisanie własności i uprawnień, ustawienie zadania cron i ustawienie opcji poleceń kopii zapasowej do użycia w dostarczonym skrypcie kopii zapasowej znajdującym się w /usr/local /sbin/mysqlbackup.sh. Następnie do użytkownika należy uruchomienie lub zaplanowanie skryptu. Aby wykonać natychmiastową kopię zapasową, po prostu wywołaj:
$ mysqlbackup.sh
Jeśli wyodrębnimy rzeczywiste polecenie mysqldump na podstawie powyższego, wygląda to tak:
$ mysqldump --defaults-extra-file=/tmp/backup.NYg0TR --opt --flush-logs --single-transaction --events --set-gtid-purged=OFF --all-databases
Dla tych, którzy chcą korzystać z innych narzędzi do tworzenia kopii zapasowych, takich jak Percona Xtrabackup, MariaDB Backup (tylko MariaDB) lub MySQL Enterprise Backup, moduł zapewnia następujące prywatne klasy:
- mysql::backup::xtrabackup (Percona Xtrabackup i MariaDB Backup)
- mysql::backup::mysqlbackup (Kopia zapasowa MySQL Enterprise)
Przykładowa deklaracja z Percona Xtrabackup:
class { 'mysql::backup::xtrabackup':
xtrabackup_package_name => 'percona-xtrabackup',
backupuser => 'xtrabackup',
backuppassword => 'passw0rd',
backupdir => '/home/xtrabackup',
backupdirowner => 'mysql',
backupdirgroup => 'mysql',
backupdirmode => '755',
backupcompress => true,
backuprotate => 15,
include_routines => true,
time => ['23','30'], #backup starts at 11:30PM
include_triggers => true,
maxallowedpacket => '64M',
incremental_backups => true
}
Powyższe zaplanuje dwie kopie zapasowe, jedną pełną kopię zapasową w każdą niedzielę o 23:30 i jedną przyrostową kopię zapasową codziennie z wyjątkiem niedzieli w tym samym czasie, jak pokazano w danych wyjściowych zadania cron po zastosowaniu powyższego manifestu:
(db1.local)$ crontab -l
# Puppet Name: xtrabackup-weekly
30 23 * * 0 /usr/local/sbin/xtrabackup.sh --target-dir=/home/backup/mysql/xtrabackup --backup
# Puppet Name: xtrabackup-daily
30 23 * * 1-6 /usr/local/sbin/xtrabackup.sh --incremental-basedir=/home/backup/mysql/xtrabackup --target-dir=/home/backup/mysql/xtrabackup/`date +%F_%H-%M-%S` --backup
Aby uzyskać więcej informacji i opcji dostępnych dla tej klasy (i innych klas), zapoznaj się z opisem opcji tutaj.
W aspekcie przywracania moduł obsługuje tylko przywracanie metodą kopii zapasowej mysqldump, importując plik SQL bezpośrednio do bazy danych za pomocą klasy mysql::db, na przykład:
mysql::db { 'mydb':
user => 'myuser',
password => 'mypass',
host => 'localhost',
grant => ['ALL PRIVILEGES'],
sql => '/home/backup/mysql/mydb/backup.gz',
import_cat_cmd => 'zcat',
import_timeout => 900
}
Plik SQL będzie ładowany tylko raz, a nie przy każdym uruchomieniu, chyba że zostanie użyte polecenie force_sql => true.
Opcje konfiguracji
W tym przykładzie użyliśmy manage_config_file => true z override_options do ustrukturyzowania naszych linii konfiguracyjnych, które później zostaną wypchnięte przez Puppet. Wszelkie modyfikacje pliku manifestu będą odzwierciedlać tylko zawartość docelowego pliku konfiguracyjnego MySQL. Ten moduł nie załaduje konfiguracji do środowiska wykonawczego ani nie zrestartuje usługi MySQL po wepchnięciu zmian do pliku konfiguracyjnego. Obowiązkiem administratora jest ponowne uruchomienie usługi w celu aktywowania zmian.
Aby dodać niestandardową konfigurację MySQL, możemy umieścić dodatkowe pliki w "includedir", domyślnie w /etc/mysql/conf.d. Pozwala nam to nadpisać ustawienia lub dodać dodatkowe, co jest pomocne, jeśli nie używasz override_options w klasie mysql::server. Zdecydowanie zaleca się skorzystanie z szablonu Puppet. Umieść niestandardowy plik konfiguracyjny w katalogu szablonów modułu (domyślnie , /etc/puppetlabs/code/environments/production/modules/mysql/templates), a następnie dodaj następujące wiersze w manifeście:
# Loads /etc/puppetlabs/code/environments/production/modules/mysql/templates/my-custom-config.cnf.erb into /etc/mysql/conf.d/my-custom-config.cnf
file { '/etc/mysql/conf.d/my-custom-config.cnf':
ensure => file,
content => template('mysql/my-custom-config.cnf.erb')
}
Aby zaimplementować parametry specyficzne dla wersji, użyj dyrektywy version, na przykład [mysqld-5.5]. Pozwala to na jedną konfigurację dla różnych wersji MySQL.
Puppet a ClusterControl
Czy wiesz, że możesz również zautomatyzować wdrażanie replikacji MySQL lub MariaDB za pomocą ClusterControl? Możesz użyć modułu ClusterControl Puppet, aby go zainstalować lub po prostu pobierając go z naszej strony internetowej.
W porównaniu z ClusterControl można spodziewać się następujących różnic:
- Trochę nauki, aby zrozumieć składnię Puppet, formatowanie, struktury, zanim będziesz mógł pisać manifesty.
- Manifest musi być regularnie testowany. Bardzo często pojawia się błąd kompilacji kodu, zwłaszcza jeśli katalog jest stosowany po raz pierwszy.
- Puppet zakłada, że kody są idempotentne. Warunek testu/sprawdzenia/weryfikacji leży w gestii autora, aby uniknąć zepsucia się z uruchomionym systemem.
- Puppet wymaga agenta w zarządzanym węźle.
- Niezgodność wsteczna. Niektóre stare moduły nie działały poprawnie w nowej wersji.
- Monitorowanie bazy danych/hosta należy skonfigurować osobno.
Kreator wdrażania ClusterControl prowadzi proces wdrażania:
Alternatywnie możesz użyć interfejsu wiersza poleceń ClusterControl o nazwie „s9s”, aby osiągnąć podobne wyniki. Następujące polecenie tworzy trzywęzłowy klaster replikacji MySQL (pod warunkiem, że wszystkie węzły są bez hasła, które zostało wcześniej skonfigurowane):
$ s9s cluster --create \
--cluster-type=mysqlreplication \
--nodes=192.168.0.41?master;192.168.0.42?slave;192.168.0.43?slave;192.168.0.44?master; \
--vendor=oracle \
--cluster-name='MySQL Replication 8.0' \
--provider-version=8.0 \
--db-admin='root' \
--db-admin-passwd='$ecR3t^word' \
--log
Powiązane zasoby Moduł Puppet for ClusterControl — dodawanie zarządzania i monitorowania do istniejących klastrów baz danych Jak zautomatyzować wdrażanie klastra MySQL Galera przy użyciu interfejsu wiersza polecenia s9s i szefa kuchni Przewodnik DevOps dotyczący automatyzacji infrastruktury baz danych dla handlu elektronicznego — powtórka i slajdy Obsługiwane są następujące konfiguracje replikacji MySQL/MariaDB:
- Replikacja master-slave (oparta na plikach/pozycji)
- Replikacja master-slave z GTID (MySQL/Percona)
- Replikacja master-slave z identyfikatorem MariaDB GTID
- Replikacja master-master (semi-sync/async)
- Replikacja łańcucha master-slave (semi-sync/async)
Po wdrożeniu, węzły/klastry mogą być monitorowane i w pełni zarządzane przez ClusterControl, w tym automatyczne wykrywanie awarii, przełączanie awaryjne urządzenia głównego, promowanie urządzeń podrzędnych, automatyczne odzyskiwanie, zarządzanie kopiami zapasowymi, zarządzanie konfiguracją i tak dalej. Wszystkie te elementy są połączone w jeden produkt. Edycja społecznościowa (bezpłatna na zawsze!) oferuje wdrażanie i monitorowanie. Średnio klaster bazy danych będzie gotowy do działania w ciągu 30 minut. Potrzebuje tylko bezhasłowego SSH do węzłów docelowych.
W następnej części przeprowadzimy Cię przez wdrożenie klastra Galera przy użyciu tego samego modułu Puppet. Bądź na bieżąco!