Както видяхме в първата част на този блог, силно последователен клъстер от база данни като Galera не работи добре с инструменти за оркестриране на контейнери като Kubernetes или Swarm. Показахме ви как да разположите Galera и да конфигурирате управлението на процесите за Docker, така че да запазите пълен контрол върху поведението. Тази публикация в блога е продължение на това, ние ще разгледаме работата и поддръжката на клъстера.
За да обобщим някои от основните точки от част 1 на този блог, ние разположихме клъстер Galera с три възли, с ProxySQL и Keepalived на три различни хоста на Docker, където всички екземпляри на MariaDB работят като Docker контейнери. Следната диаграма илюстрира окончателното внедряване:
Изящно изключване
За да извършите грациозно изключване на MySQL, най-добрият начин е да изпратите SIGTERM (сигнал 15) към контейнера:
$ docker kill -s 15 {db_container_name}
Ако искате да изключите клъстера, повторете горната команда на всички контейнери на база данни, един възел в даден момент. Горното е подобно на извършването на "systemctl stop mysql" в услугата systemd за MariaDB. Използването на команда „docker stop“ е доста рисковано за услугата на базата данни, тъй като изчаква 10 секунди изчакване и Docker ще принуди SIGKILL, ако тази продължителност е надвишена (освен ако не използвате правилно --timeout стойност).
Последният възел, който се изключва грациозно, ще има seqno не е равно на -1 и safe_to_bootstrap флагът е зададен на 1 в /{datadir volume}/grastate.dat на хоста на Docker, например на хост2:
$ cat /containers/mariadb2/datadir/grastate.dat
# GALERA saved state
version: 2.1
uuid: e70b7437-645f-11e8-9f44-5b204e58220b
seqno: 7099
safe_to_bootstrap: 1
Откриване на най-напредналия възел
Ако клъстерът не се изключи грациозно или възелът, който се опитвате да стартирате, не е последният възел, напуснал клъстера, вероятно няма да можете да стартирате един от възлите Galera и може да срещнете следната грешка :
2016-11-07 01:49:19 5572 [ERROR] WSREP: It may not be safe to bootstrap the cluster from this node.
It was not the last one to leave the cluster and may not contain all the updates.
To force cluster bootstrap with this node, edit the grastate.dat file manually and set safe_to_bootstrap to 1 .
Galera почита възела, който има safe_to_bootstrap флаг, зададен на 1 като първи референтен възел. Това е най-сигурният начин да избегнете загуба на данни и да гарантирате, че правилният възел винаги се зарежда.
Ако получите грешката, първо трябва да открием най-напредналия възел, преди да вземем възела като първи, който ще бъде стартиран. Създайте преходен контейнер (с --rm флаг), го съпоставете със същата директория с данни и конфигурационна директория на действителния контейнер на базата данни с два командни флага на MySQL, --wsrep_recover и --wsrep_cluster_address . Например, ако искаме да знаем последното записано число на mariadb1, трябва да изпълним:
$ docker run --rm --name mariadb-recover \
--env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
--volume /containers/mariadb1/datadir:/var/lib/mysql \
--volume /containers/mariadb1/conf.d:/etc/mysql/conf.d \
mariadb:10.2.15 \
--wsrep_recover \
--wsrep_cluster_address=gcomm://
2018-06-12 4:46:35 139993094592384 [Note] mysqld (mysqld 10.2.15-MariaDB-10.2.15+maria~jessie) starting as process 1 ...
2018-06-12 4:46:35 139993094592384 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
...
2018-06-12 4:46:35 139993094592384 [Note] Plugin 'FEEDBACK' is disabled.
2018-06-12 4:46:35 139993094592384 [Note] Server socket created on IP: '::'.
2018-06-12 4:46:35 139993094592384 [Note] WSREP: Recovered position: e70b7437-645f-11e8-9f44-5b204e58220b:7099
Последният ред е това, което търсим. MariaDB отпечатва UUID на клъстера и поредния номер на последната извършена транзакция. Възелът, който съдържа най-голямо число, се счита за най-напреднал възел. Тъй като посочихме --rm , контейнерът ще бъде премахнат автоматично, след като излезе. Повторете горната стъпка на всеки хост на Docker, като замените --volume път до съответните обеми контейнери на базата данни.
След като сравните стойността, отчетена от всички контейнери на базата данни и решите кой контейнер е най-актуалният възел, променете safe_to_bootstrap флаг до 1 в /{datadir volume}/grastate.dat ръчно. Да приемем, че всички възли отчитат един и същ точен последователен номер, можем просто да изберем mariadb3 за стартиране, като променим safe_to_bootstrap стойност до 1:
$ vim /containers/mariadb3/datadir/grasate.dat
...
safe_to_bootstrap: 1
Запазете файла и започнете да зареждате клъстера от този възел, както е описано в следващата глава.
Зареждане на клъстера
Зареждането на клъстера е подобно на първата команда за изпълнение на докер, която използвахме при стартиране на клъстера за първи път. Ако mariadb1 е избраният възел за стартиране, можем просто да стартираме отново създадения контейнер за стартиране:
$ docker start mariadb0 # on host1
В противен случай, ако контейнерът за стартиране не съществува на избрания възел, да речем на host2, изпълнете командата bootstrap container и картографирайте съществуващите томове на mariadb2. Използваме mariadb0 като име на контейнера на host2, за да посочим, че е контейнер за стартиране:
$ docker run -d \
--name mariadb0 \
--hostname mariadb0.weave.local \
--net weave \
--publish "3306" \
--publish "4444" \
--publish "4567" \
--publish "4568" \
$(weave dns-args) \
--env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
--volume /containers/mariadb2/datadir:/var/lib/mysql \
--volume /containers/mariadb2/conf.d:/etc/mysql/mariadb.conf.d \
mariadb:10.2.15 \
--wsrep_cluster_address=gcomm:// \
--wsrep_sst_auth="root:PM7%[email protected]^1" \
--wsrep_node_address=mariadb0.weave.local
Може да забележите, че тази команда е малко по-къса в сравнение с предишната команда за стартиране, описана в това ръководство. Тъй като вече имаме потребителя на proxysql, създаден в първата ни команда за стартиране, можем да пропуснем тези две променливи на средата:
- --env MYSQL_USER=proxysql
- --env MYSQL_PASSWORD=proxysqlpassword
След това стартирайте останалите контейнери MariaDB, премахнете контейнера за стартиране и стартирайте съществуващия контейнер MariaDB на стартиращия хост. По принцип редът на командите би бил:
$ docker start mariadb1 # on host1
$ docker start mariadb3 # on host3
$ docker stop mariadb0 # on host2
$ docker start mariadb2 # on host2
В този момент клъстерът се стартира и работи с пълен капацитет.
Контрол на ресурсите
Паметта е много важен ресурс в MySQL. Тук се съхраняват буферите и кешовете и е от решаващо значение за MySQL да намали въздействието от твърде честото удряне на диска. От друга страна, размяната е лоша за производителността на MySQL. По подразбиране няма да има ограничения на ресурсите за работещите контейнери. Контейнерите използват толкова от даден ресурс, колкото ядрото на хоста позволява. Друго важно нещо е ограничението на файловия дескриптор. Можете да увеличите ограничението на дескриптора на отворен файл или "nofile" до нещо по-високо, за да се погрижите за броя на файловете, които MySQL сървърът може да отвори едновременно. Задаването на висока стойност няма да навреди.
За да ограничите разпределението на паметта и да увеличите лимита на файловия дескриптор към нашия контейнер на база данни, трябва да добавите --memory , --memory-swap и --ulimit параметри в командата "docker run":
$ docker kill -s 15 mariadb1
$ docker rm -f mariadb1
$ docker run -d \
--name mariadb1 \
--hostname mariadb1.weave.local \
--net weave \
--publish "3306:3306" \
--publish "4444" \
--publish "4567" \
--publish "4568" \
$(weave dns-args) \
--memory 16g \
--memory-swap 16g \
--ulimit nofile:16000:16000 \
--env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
--volume /containers/mariadb1/datadir:/var/lib/mysql \
--volume /containers/mariadb1/conf.d:/etc/mysql/mariadb.conf.d \
mariadb:10.2.15 \
--wsrep_cluster_address=gcomm://mariadb0.weave.local,mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local \
--wsrep_sst_auth="root:PM7%[email protected]^1" \
--wsrep_node_address=mariadb1.weave.local
Обърнете внимание, че ако --memory-swap е зададена на същата стойност като --memory , и --памет е зададен на положително цяло число, контейнерът няма да има достъп до суап. Ако --memory-swap не е зададено, размяната на контейнери по подразбиране ще бъде --memory умножете по 2. Ако --памет и --memory-swap са зададени на една и съща стойност, това ще попречи на контейнерите да използват каквато и да е размяна. Това е така, защото --memory-swap е количеството комбинирана памет и суап, които могат да се използват, докато --памет е само количеството физическа памет, което може да се използва.
Някои от ресурсите на контейнера, като памет и процесор, могат да се контролират динамично чрез командата "docker update", както е показано в следващия пример за надграждане на паметта на контейнер mariadb1 до 32G в движение:
$ docker update \
--memory 32g \
--memory-swap 32g \
mariadb1
Не забравяйте да настроите my.cnf съответно, за да отговарят на новите спецификации. Управлението на конфигурацията е обяснено в следващия раздел.
Управление на конфигурацията
Повечето от конфигурационните параметри на MySQL/MariaDB могат да бъдат променени по време на изпълнение, което означава, че не е необходимо да рестартирате, за да приложите промените. Вижте страницата с документация на MariaDB за подробности. Параметърът, посочен с "Динамичен:Да", означава, че променливата се зарежда веднага след промяна, без да е необходимо да рестартирате MariaDB сървъра. В противен случай задайте параметрите в персонализирания конфигурационен файл в хоста на Docker. Например на mariadb3 направете промените в следния файл:
$ vim /containers/mariadb3/conf.d/my.cnf
След това рестартирайте контейнера на базата данни, за да приложите промяната:
$ docker restart mariadb3
Уверете се, че контейнерът стартира процеса, като погледнете регистрационните файлове на docker. Извършвайте тази операция на един възел в даден момент, ако искате да направите промени в целия клъстер.
Резервно копие
Правенето на логическо архивиране е доста лесно, защото изображението на MariaDB също идва с двоичен файл mysqldump. Просто използвате командата "docker exec", за да стартирате mysqldump и да изпратите изхода във файл, свързан с пътя на хоста. Следната команда изпълнява архивиране на mysqldump на mariadb2 и го записва в /backups/mariadb2 вътре в host2:
$ docker exec -it mariadb2 mysqldump -uroot -p --single-transaction > /backups/mariadb2/dump.sql
Двоично архивиране като Percona Xtrabackup или MariaDB Backup изисква процесът за директен достъп до директорията с данни на MariaDB. Трябва или да инсталирате този инструмент в контейнера, или през хоста на машината, или да използвате специално изображение за тази цел, като изображение "perconalab/percona-xtrabackup", за да създадете архива и да го съхраните в /tmp/backup на хоста на Docker:
$ docker run --rm -it \
-v /containers/mariadb2/datadir:/var/lib/mysql \
-v /tmp/backup:/xtrabackup_backupfiles \
perconalab/percona-xtrabackup \
--backup --host=mariadb2 --user=root --password=mypassword
Можете също да спрете контейнера с innodb_fast_shutdown задайте на 0 и копирайте обема на datadir на друго място във физическия хост:
$ docker exec -it mariadb2 mysql -uroot -p -e 'SET GLOBAL innodb_fast_shutdown = 0'
$ docker kill -s 15 mariadb2
$ cp -Rf /containers/mariadb2/datadir /backups/mariadb2/datadir_copied
$ docker start mariadb2
Възстановяване
Възстановяването е доста лесно за mysqldump. Можете просто да пренасочите stdin към контейнера от физическия хост:
$ docker exec -it mariadb2 mysql -uroot -p < /backups/mariadb2/dump.sql
Можете също да използвате стандартния команден ред на mysql клиент отдалечено с правилно име на хост и стойност на порт, вместо да използвате тази команда "docker exec":
$ mysql -uroot -p -h127.0.0.1 -P3306 < /backups/mariadb2/dump.sql
За Percona Xtrabackup и MariaDB Backup трябва да подготвим архива предварително. Това ще превърти архива напред до момента, когато архивирането е завършено. Да кажем, че нашите Xtrabackup файлове се намират под /tmp/backup на хоста на Docker, за да го подготвите, просто:
$ docker run --rm -it \
-v mysql-datadir:/var/lib/mysql \
-v /tmp/backup:/xtrabackup_backupfiles \
perconalab/percona-xtrabackup \
--prepare --target-dir /xtrabackup_backupfiles
Подготвеното резервно копие под /tmp/backup на хоста на Docker след това може да се използва като MariaDB datadir за нов контейнер или клъстер. Да кажем, че просто искаме да проверим възстановяването на самостоятелен контейнер MariaDB, ще стартираме:
$ docker run -d \
--name mariadb-restored \
--env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
-v /tmp/backup:/var/lib/mysql \
mariadb:10.2.15
Ако сте извършили архивиране, като използвате подхода за спиране и копиране, можете просто да дублирате datadir и да използвате дублираната директория като обемни карти на MariaDB datadir за изпълнение на друг контейнер. Да кажем, че архивът е копиран под /backups/mariadb2/datadir_copied, можем да стартираме нов контейнер, като изпълним:
$ mkdir -p /containers/mariadb-restored/datadir
$ cp -Rf /backups/mariadb2/datadir_copied /containers/mariadb-restored/datadir
$ docker run -d \
--name mariadb-restored \
--env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
-v /containers/mariadb-restored/datadir:/var/lib/mysql \
mariadb:10.2.15
MYSQL_ROOT_PASSWORD трябва да съвпада с действителната root парола за това конкретно архивиране.
Неколкократни MySQL на Docker:Как да контейнеризирате вашата база данни Открийте всичко, което трябва да разберете, когато обмисляте да стартирате услуга MySQL върху виртуализацията на Docker контейнер. Изтеглете Бялата книгаНадстройка на версията на базата данни
Има два типа надстройка – надстройка на място или логическа надстройка.
Надстройката на място включва изключване на сървъра на MariaDB, замяна на старите двоични файлове с новите двоични файлове и след това стартиране на сървъра в старата директория с данни. След като започнете, трябва да стартирате mysql_upgrade скрипт за проверка и надграждане на всички системни таблици, както и за проверка на потребителските таблици.
Логическата надстройка включва експортиране на SQL от текущата версия с помощта на логическа помощна програма за архивиране, като например mysqldump, стартиране на новия контейнер с двоични файлове на надстроената версия и след това прилагане на SQL към новата версия на MySQL/MariaDB. Той е подобен на подхода за архивиране и възстановяване, описан в предишния раздел.
Въпреки това е добър подход винаги да архивирате вашата база данни, преди да извършите разрушителни операции. Следните стъпки са необходими при надграждане от текущото изображение, MariaDB 10.1.33 до друга основна версия, MariaDB 10.2.15 на mariadb3 се намира на host3:
-
Архивирайте базата данни. Няма значение физическо или логическо архивиране, но последното с mysqldump се препоръчва.
-
Изтеглете най-новото изображение, до което бихме искали да надстроим:
$ docker pull mariadb:10.2.15
-
Задайте innodb_fast_shutdown на 0 за нашия контейнер с база данни:
$ docker exec -it mariadb3 mysql -uroot -p -e 'SET GLOBAL innodb_fast_shutdown = 0'
-
Изящно изключване на контейнера на базата данни:
$ docker kill --signal=TERM mariadb3
-
Създайте нов контейнер с новото изображение за нашия контейнер с база данни. Запазете останалите параметри непокътнати, с изключение на използването на новото име на контейнера (в противен случай би било в конфликт):
$ docker run -d \ --name mariadb3-new \ --hostname mariadb3.weave.local \ --net weave \ --publish "3306:3306" \ --publish "4444" \ --publish "4567" \ --publish "4568" \ $(weave dns-args) \ --env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \ --volume /containers/mariadb3/datadir:/var/lib/mysql \ --volume /containers/mariadb3/conf.d:/etc/mysql/mariadb.conf.d \ mariadb:10.2.15 \ --wsrep_cluster_address=gcomm://mariadb0.weave.local,mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local \ --wsrep_sst_auth="root:PM7%[email protected]^1" \ --wsrep_node_address=mariadb3.weave.local
-
Изпълнете скрипт mysql_upgrade:
$ docker exec -it mariadb3-new mysql_upgrade -uroot -p
-
Ако не са възникнали грешки, премахнете стария контейнер, mariadb3 (новият е mariadb3-new):
$ docker rm -f mariadb3
-
В противен случай, ако процесът на надстройка се провали между тях, можем да се върнем към предишния контейнер:
$ docker stop mariadb3-new $ docker start mariadb3
Надстройката на основната версия може да се извърши подобно на надстройката на второстепенната версия, с изключение на това, че трябва да имате предвид, че MySQL/MariaDB поддържа само основно надграждане от предишната версия. Ако използвате MariaDB 10.0 и искате да надстроите до 10.2, първо трябва да надстроите до MariaDB 10.1, последвано от друга стъпка за надстройка до MariaDB 10.2.
Обърнете внимание на промените в конфигурацията, които се въвеждат и оттеглят между основните версии.
Отказ при отказ
В Galera всички възли са господари и изпълняват една и съща роля. С ProxySQL на снимката, връзките, които преминават през този шлюз, ще бъдат прекъснати автоматично, стига да има основен компонент, работещ за Galera Cluster (тоест повечето възли са изправени). Приложението няма да забележи никаква разлика, ако един възел на базата данни изпадне, защото ProxySQL просто ще пренасочи връзките към другите налични възли.
Ако приложението се свърже директно с MariaDB, заобикаляйки ProxySQL, преминаването на отказ трябва да се извърши от страната на приложението, като се посочи следващия наличен възел, при условие че възелът на базата данни отговаря на следните условия:
- Състояние wsrep_local_state_comment е Synced (Състоянието „Desynced/Donor“ също е възможно, само ако wsrep_sst_method е xtrabackup, xtrabackup-v2 или mariabackup).
- Състояние wsrep_cluster_status е Основно.
В Galera наличен възел не означава, че е здрав, докато не се потвърди горното състояние.
Намаляване
За да се мащабира, можем да създадем нов контейнер в същата мрежа и да използваме същия персонализиран конфигурационен файл за съществуващия контейнер на този конкретен хост. Например, да кажем, че искаме да добавим четвъртия контейнер MariaDB на host3, можем да използваме същия конфигурационен файл, монтиран за mariadb3, както е илюстрирано на следната диаграма:
Изпълнете следната команда на хост3, за да намалите мащаба:
$ docker run -d \
--name mariadb4 \
--hostname mariadb4.weave.local \
--net weave \
--publish "3306:3307" \
--publish "4444" \
--publish "4567" \
--publish "4568" \
$(weave dns-args) \
--env MYSQL_ROOT_PASSWORD="PM7%[email protected]^1" \
--volume /containers/mariadb4/datadir:/var/lib/mysql \
--volume /containers/mariadb3/conf.d:/etc/mysql/mariadb.conf.d \
mariadb:10.2.15 \
--wsrep_cluster_address=gcomm://mariadb1.weave.local,mariadb2.weave.local,mariadb3.weave.local,mariadb4.weave.local \
--wsrep_sst_auth="root:PM7%[email protected]^1" \
--wsrep_node_address=mariadb4.weave.local
След като контейнерът бъде създаден, той ще се присъедини към клъстера и ще извърши SST. Може да се осъществи достъп до порт 3307 външно или извън мрежата на Weave, или порт 3306 в хоста или в мрежата на Weave. Вече не е необходимо да включвате mariadb0.weave.local в адреса на клъстера. След като клъстерът се мащабира, трябва да добавим новия контейнер MariaDB в комплекта за балансиране на натоварването на ProxySQL чрез администраторска конзола:
$ docker exec -it proxysql1 mysql -uadmin -padmin -P6032
mysql> INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (10,'mariadb4.weave.local',3306);
mysql> INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (20,'mariadb4.weave.local',3306);
mysql> LOAD MYSQL SERVERS TO RUNTIME;
mysql> SAVE MYSQL SERVERS TO DISK;
Повторете горните команди на втория екземпляр на ProxySQL.
И накрая за последната стъпка, (можете да пропуснете тази част, ако вече сте изпълнили оператора "SAVE .. TO DISK" в ProxySQL), добавете следния ред в proxysql.cnf, за да го направите постоянен при рестартиране на контейнера на host1 и host2:
$ vim /containers/proxysql1/proxysql.cnf # host1
$ vim /containers/proxysql2/proxysql.cnf # host2
И добавете свързани с mariadb4 редове под mysql_server директива:
mysql_servers =
(
{ address="mariadb1.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="mariadb2.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="mariadb3.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="mariadb4.weave.local" , port=3306 , hostgroup=10, max_connections=100 },
{ address="mariadb1.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
{ address="mariadb2.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
{ address="mariadb3.weave.local" , port=3306 , hostgroup=20, max_connections=100 },
{ address="mariadb4.weave.local" , port=3306 , hostgroup=20, max_connections=100 }
)
Запазете файла и ще бъдем добре при следващото рестартиране на контейнера.
Намаляване
За да намалите мащаба, просто затворете контейнера грациозно. Най-добрата команда би била:
$ docker kill -s 15 mariadb4
$ docker rm -f mariadb4
Не забравяйте, че ако възелът на базата данни напусне клъстера неудобно, това не е част от намаляването и ще повлияе на изчисляването на кворума.
За да премахнете контейнера от ProxySQL, изпълнете следните команди и на двата ProxySQL контейнера. Например на proxysql1:
$ docker exec -it proxysql1 mysql -uadmin -padmin -P6032
mysql> DELETE FROM mysql_servers WHERE hostname="mariadb4.weave.local";
mysql> LOAD MYSQL SERVERS TO RUNTIME;
mysql> SAVE MYSQL SERVERS TO DISK;
След това можете да премахнете съответния запис в proxysql.cnf или просто да го оставите така. Така или иначе ще бъде разпознат като ОФЛАЙН от гледна точка на ProxySQL.
Резюме
С Docker нещата стават малко по-различни от конвенционалния начин за работа с MySQL или MariaDB сървъри. Обработването на услуги с поддържане на състоянието като Galera Cluster не е толкова лесно, колкото приложенията без състояние и изисква правилно тестване и планиране.
В следващия ни блог по тази тема ще оценим плюсовете и минусите на стартирането на Galera Cluster на Docker без инструменти за оркестрация.