Архив метки: Software

Mysql. Установка и добавление данных/Настройка Master-Master репликации/Настройка Master-Slave репликации/Администрирование percona mysql

Решил написать несколько статей о установке, настройке и роботе с mysql базой данных. В качестве mysql-сервера будем использовать Percona Server 5.6 под управлением операционной системой Ubuntu 12.04. Данная серия статей будет полезной для людей, которые впервые сталкиваются с базами данных(БД) mysql, и хотят немного изучить установку, базовые команды(запросы), научиться делать backup и restore данных, настройку и тестирование репликации БД percona mysql.
В этой части пойдет речь о базовой установке и добавлении тестовой БД, репликация которой будет настроена далее.

Поскольку статьи будут взаимосвязаны, наведем схему репликации (рис. 1) и базовую конфигурацию серверов.




Роль хостаИмя хоста (hostname)IP хоста
Master server 1m-serv1192.168.1.201
Master server 2m-serv2192.168.1.202
Slave server 1m-slave1192.168.1.203
Slave server 2m-slave2192.168.1.204




Рисунок 1 — Схема репликации







1 Установка




Для начала нам нужно установить Percona Server 5.6.
Mysql нужно установить на всех серверах, в нашем случаи на 4-х (2 мастера, 2 слейва). Начинаем установку.




root@m-serv1:~# apt-key adv --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A
Executing: gpg --ignore-time-conflict --no-options --no-default-keyring --secret-keyring /tmp/tmp.igWqa1jBp0 --trustdb-name /etc/apt/trustdb.gpg --keyring /etc/apt/trusted.gpg --primary-keyring /etc/apt/trusted.gpg --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A
gpg: requesting key CD2EFD2A from hkp server keys.gnupg.net
gpg: key CD2EFD2A: public key "Percona MySQL Development Team <mysql-dev@percona.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1
 
root@m-serv1:~# cat >> /etc/apt/sources.list.d/percona-mysql.list
deb http://repo.percona.com/apt precise main
deb-src http://repo.percona.com/apt precise main
root@m-serv1:~# apt-get update
root@m-serv1:~# apt-get install percona-server-server




При установке, у Вас спросят пароль root-a, который будет использоваться для подключения к mysql серверу – не забудьте его. Далее можно запустить mysql_secure_installation для обновления пароля, удаления ненужных БД и пользователей.




root@m-serv1:~# mysql_secure_installation
Enter current password for root (enter for none):
OK, successfully used password, moving on...
 
You already have a root password set, so you can safely answer 'n'.
Change the root password? [Y/n] Y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!
 
Remove anonymous users? [Y/n] Y
 ... Success!
 
Disallow root login remotely? [Y/n] Y
 ... Success!
 
Remove test database and access to it? [Y/n] Y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!
 
Reload privilege tables now? [Y/n] Y
 ... Success!




Все эти действия нужно проделать на m-serv2m-slave1 и m-slave2. Теперь можно создать тестовую БД.




2 Добавление данных




2.1 Создание тестовой БД




Можно создать БД (testdb) на одном сервере, сделать ее дамп и развернуть на всех остальных. Что мы и сделаем.
Подключаемся на m-serv1 к mysql консоли и создаем тестовую БД.




root@m-serv1:~# mysql -u root -p
mysql> CREATE DATABASE testdb;




Далее добавим таблицу в новую БД.




mysql> CREATE TABLE IF NOT EXISTS testdb.users (id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20));




Теперь добавим одну строку в таблицу users.




mysql> INSERT INTO users(name) VALUES ("Alex");




Далее проверим что у нас получилось.




mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| testdb             |
+--------------------+
5 rows in set (0.02 sec)
 
mysql> use testdb; show tables;
Database changed
+------------------+
| Tables_in_testdb |
+------------------+
| users            |
+------------------+
1 row in set (0.00 sec)
 
mysql> use testdb; select * from users;
Database changed
+----+------+
| id | name |
+----+------+
|  1 | Alex |
+----+------+
1 row in set (0.00 sec)
 
mysql> use testdb; describe users;
Database changed
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(20)      | YES  |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.03 sec)




Как видим, мы успешно создали БД testdb и в ней создали таблицу users, в которую добавили новую запись.




2.2 Дамп и деплой БД на всех серверах




Снимаем дамп нашей новой БД и копируем его на второй мастер m-serv2.




root@m-serv1:~# mysqldump -u root -p testdb  > testdb.sql
root@m-serv1:~# rsync testdb.sql alex@m-serv2:/home/alex/




Теперь логинимся на второй сервер и разворачиваем дамп.




root@m-serv2:~# mysql -u root -p -e 'create database testdb;'
root@m-serv2:~# mysql -uroot -p testdb < testdb.sql
root@m-serv2:~# mysql -u root -p -e 'use testdb; select * from users;'
+----+------+
| id | name |
+----+------+
|  1 | Alex |
+----+------+




Те же действия нужно проделать со слейвами(m-slave1 и m-slave2), т.е. синкануть БД на оба слейва и развернуть таким же макаром.




2.3 Создание юзера для репликации




Теперь нужно создать юзера, который будет заниматься репликацией. Для этого переходим в mysql консоль и создаем юзера replica с правами “replication slave”.




mysql> CREATE USER 'replica'@'%' IDENTIFIED BY '%repl2015';
Query OK, 0 rows affected (0.22 sec)
 
mysql> GRANT replication slave ON *.* TO 'replica'@'%';
Query OK, 0 rows affected (0.10 sec)




Как вы поняли, эти действия нужно проделать на всех 4-х серверах.




3 Настройка репликации




В mysql существует два типа репликации данных:




  • Master-Slave
  • Master-Master




Master-Slave репликация. На Master сервере данные добавляются, удаляются и изменяются. Slave сервер стягивает эти обновления себе и постепенно выполняет все полученные запросы. Если на Slave сервере будет добавлена новая таблица или БД, то данные не попадут на Master.
При Master-Master репликации данные попавшие на оба сервера будут среплицированы между собой.




3.1 Master-Master репликация




Сначала настроим Мастер-Мастер репликацию (рис. 2).




Рисунок 2 — Схема Master-Master репликации




Теперь переходим к настройке репликации.
Для этого нам нужно добавить конфигурационный файл /etc/mysql/my.cnf для каждого mysql-сервера, который входит в репликацию. Здесь нужно прописать уникальный идентификатор сервера и БД, которые нужно и не нужно реплицировать. Также здесь прописывается множество дополнительных настроек mysql сервера, о которых можно узнать на официальном сайте. Я же наведу самую нужную малость.




3.1.1 Настройка m-serv1 мастера




Сначала настроим первый мастер-сервер.




root@m-serv1:~# cat /etc/mysql/my.cnf
[mysqld]
#Уникальный идентификатор сервера
server-id = 1
 
#Логи ошибок
log_error = /var/log/mysql/mysql.err
 
#Путь к bin-логам сервера(бинлог, который ведет мастер)
log-bin = /var/lib/mysql/server-mysql-bin
log-bin-index = /var/lib/mysql/server-mysql-bin.index
 
#Путь к relay-логам слейва (бинлог, скачанный с мастера)
relay-log = /var/lib/mysql/slave-mysql-relay-bin
relay-log-index = /var/lib/mysql/slave-mysql-relay-bin.index
 
#БД, которые нужно/не нужно реплицировать
replicate-do-db = testdb
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
replicate-ignore-db=performance_schema
 
#Не вести журнал бин-лога для БД
binlog-ignore-db = information_schema
binlog-ignore-db = mysql
binlog-ignore-db = performance_schema
 
#Чтобы не было конфликтов автоинкремента, говорим серверу,
#чтобы id генерировались начиная с 3-го прибавляя по 10,
# например 13, 23, 33, 43...
auto_increment_increment = 10
auto_increment_offset = 3
 
#Сохранять логи с мастера в своий бин-лог, чтобы передать слейву
log-slave-updates




Как видим, здесь мы добавили для репликации только testdb БД. Теперь рестартуем mysql.




root@m-serv1:~# /etc/init.d/mysql restart
 * Stopping MySQL (Percona Server) mysqld                                                                                                                       [ OK ]
 * Starting MySQL (Percona Server) database server mysqld                                                                                                       [ OK ]
 * Checking for corrupt, not cleanly closed and upgrade needing tables.




3.1.2 Настройка m-serv2 мастера




Настройка второго мастера аналогична первому, только меняется id и offset




root@m-serv2:~# cat /etc/mysql/my.cnf
[mysqld]
#Уникальный идентификатор сервера
server-id = 2
 
#Логи ошибок
log_error = /var/log/mysql/mysql.err
 
#Путь к bin-логам сервера(бинлог, который ведет мастер)
log-bin = /var/lib/mysql/server-mysql-bin
log-bin-index = /var/lib/mysql/server-mysql-bin.index
 
#Путь к relay-логам слейва (бинлог, скачанный с мастера)
relay-log = /var/lib/mysql/slave-mysql-relay-bin
relay-log-index = /var/lib/mysql/slave-mysql-relay-bin.index
 
#БД, которые нужно/не нужно реплицировать
replicate-do-db = testdb
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
replicate-ignore-db=performance_schema
 
#Не вести журнал бин-лога для БД
binlog-ignore-db = information_schema
binlog-ignore-db = mysql
binlog-ignore-db = performance_schema
 
#Чтобы не было конфликтов автоинкремента, говорим серверу,
#чтобы id генерировались начиная с 4-го прибавляя по 10,
# например 14, 24, 34, 44...
auto_increment_increment = 10
auto_increment_offset = 4
 
#Сохранять логи с мастера в своий бин-лог, чтобы передать слейву
log-slave-updates




Рестартуем mysql.




root@m-serv2:~# /etc/init.d/mysql restart
 * Stopping MySQL (Percona Server) mysqld                                                                                                                       [ OK ]
 * Starting MySQL (Percona Server) database server mysqld                                                                                                       [ OK ]
 * Checking for corrupt, not cleanly closed and upgrade needing tables.




3.1.3 Запуск репликации




Сначала запустим репликацию на первом мастере m-serv1. Для этого нам нужно знать MASTER_LOG_FILE и MASTER_LOG_POS m-serv2 сервера, т.е. нашего второго мастера. Логинимся на m-serv2 и смотрим master status.




root@m-serv2:~# mysql -u root -p -e 'show master status;'
+-------------------------+----------+--------------+------------------------------------------+-------------------+
| File                    | Position | Binlog_Do_DB | Binlog_Ignore_DB                                 | Executed_Gtid_Set |
+-------------------------+----------+--------------+------------------------------------------+-------------------+
| server-mysql-bin.000001 |      120 |              | information_schema,mysql,performance_schema      |                   |
+-------------------------+----------+--------------+------------------------------------------+-------------------+




Следовательно MASTER_LOG_FILE = server-mysql-bin.000001, а MASTER_LOG_POS = 120. Теперь переходим на m-serv1 и настраиваем репликацию.




root@m-serv1:~# mysql -u root -p -e "CHANGE MASTER TO MASTER_HOST = '192.168.1.202', MASTER_USER = 'replica', MASTER_PASSWORD = '%repl2015', MASTER_LOG_FILE = 'server-mysql-bin.000001', MASTER_LOG_POS = 120;"




Все интуитивно понятно. Теперь стартуем слейв и смотрим статус.




root@m-serv1:~# mysql -u root -p -e 'start slave;'
root@m-serv1:~# mysql -u root -p -e 'show slave status G;'
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.202
                  Master_User: replica
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: server-mysql-bin.000001
          Read_Master_Log_Pos: 120
               Relay_Log_File: slave-mysql-relay-bin.000002
                Relay_Log_Pos: 290
        Relay_Master_Log_File: server-mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: testdb
          Replicate_Ignore_DB: information_schema,mysql,performance_schema
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 120
              Relay_Log_Space: 469
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 2
                  Master_UUID: 25f9f3ac-fd3b-11e4-bb77-080027ead940
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0




Со всего этого вывода нас интересуют Seconds_Behind_Master (время отставания реплики от мастера), Slave_IO_State (должно писать, что ждет новостей от мастера), Slave_IO_Running (Yes) и Slave_SQL_Running (Yes). Если репликация идет нормально, реплика будет следовать за мастером (номер лога в Master_Log_File и позиция Exec_Master_Log_Pos будут расти). Отставания реплики от мастера (Seconds_Behind_Master), должно быть нулевым, но может расти. Если же значение Slave_IO_State пусто, а Seconds_Behind_Master равно NULL, репликация не началась.
У нас все гуд. Поэтому узнаем master статус на m-serv1 и беремся за m-serv2.




root@m-serv1:~# mysql -u root -p -e 'show master status;'
+-------------------------+----------+--------------+------------------------------------------+-------------------+
| File                    | Position | Binlog_Do_DB | Binlog_Ignore_DB                                 | Executed_Gtid_Set |
+-------------------------+----------+--------------+------------------------------------------+-------------------+
| server-mysql-bin.000005 |      120 |              | information_schema,mysql,performance_schema      |                   |
+-------------------------+----------+--------------+------------------------------------------+-------------------+




Логинимся на m-serv2 и стартуем репликация.




root@m-serv2:~# mysql -u root -p -e "CHANGE MASTER TO MASTER_HOST = '192.168.1.201', MASTER_USER = 'replica', MASTER_PASSWORD = '%repl2015', MASTER_LOG_FILE = 'server-mysql-bin.000005', MASTER_LOG_POS = 120;"
root@m-serv2:~# mysql -u root -p -e 'start slave;'
root@m-serv2:~# mysql -u root -p -e 'show slave status G;'
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.201
                  Master_User: replica
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: server-mysql-bin.000005
          Read_Master_Log_Pos: 120
               Relay_Log_File: slave-mysql-relay-bin.000002
                Relay_Log_Pos: 290
        Relay_Master_Log_File: server-mysql-bin.000005
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: testdb
          Replicate_Ignore_DB: information_schema,mysql,performance_schema
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 120
              Relay_Log_Space: 469
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: f208be92-fa66-11e4-a905-08002742f2f0
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0




Все прошло успешно. О парочке возможных ошибок и их исправлении будет написано в следующей статье.




3.1.4 Тестируем репликацию




Теперь можно немножко и протестировать. Перейдем на m-serv1 и добавим в testdb.users новую строку.




root@m-serv1:~# mysql -u root -p -e 'USE testdb; INSERT INTO users(name) VALUES ("Vova");'
root@m-serv1:~# mysql -u root -p -e 'USE testdb; SELECT * FROM users;'
+----+------+
| id | name |
+----+------+
|  1 | Alex |
|  3 | Vova |
+----+------+




Теперь проверим среплицировалась ли запись на второй сервер.




root@m-serv2:~# mysql -u root -p -e 'USE testdb;SELECT * FROM users;'
+----+------+
| id | name |
+----+------+
|  1 | Alex |
|  3 | Vova |
+----+------+




Все в порядке, запись попала на второй сервер. Теперь добавим запись на втором сервере и посмотрим попадет ли она на первый мастер.




root@m-serv2:~# mysql -u root -p -e 'USE testdb; INSERT INTO users(name) VALUES ("Pasha");'
root@m-serv2:~# mysql -u root -p -e 'USE testdb; SELECT * FROM users;'
+----+-------+
| id | name  |
+----+-------+
|  1 | Alex  |
|  3 | Vova  |
|  4 | Pasha |
+----+-------+




Смотрим на первом мастере.




root@m-serv1:~# mysql -u root -p -e 'USE testdb; SELECT * FROM users;'
+----+-------+
| id | name  |
+----+-------+
|  1 | Alex  |
|  3 | Vova  |
|  4 | Pasha |
+----+-------+




Как видим, все ок. Добавим еще по одной записи.




root@m-serv1:~# mysql -u root -p -e 'USE testdb;INSERT INTO users(name) VALUES ("Frodo");'
root@m-serv1:~# mysql -u root -p -e 'USE testdb; SELECT * FROM users;'
+----+-------+
| id | name  |
+----+-------+
|  1 | Alex  |
|  3 | Vova  |
|  4 | Pasha |
| 13 | Frodo |
+----+-------+
 
root@m-serv2:~# mysql -u root -p -e 'USE testdb; INSERT INTO users(name) VALUES ("Misha");'
root@m-serv2:~# mysql -u root -p -e 'USE testdb; SELECT * FROM users;'
+----+-------+
| id | name  |
+----+-------+
|  1 | Alex  |
|  3 | Vova  |
|  4 | Pasha |
| 13 | Frodo |
| 14 | Misha |
+----+-------+




Как видим, если запись добавлена с сервера m-serv1, то поле auto_increment(id) имеет значения 3, 13, а при добавлении записей с m-serv2, эти значения равны 4, 14. Это нужно чтобы избежать ошибок типа Duplicate entry.




Продолжим знакомство с Percona mysql репликацией и перейдем к настройке и тестированию Master-Slave репликации. Как и в предыдущих статьях, наведу рисунок нашей схемы репликации, которую мы затеяли (рис. 3).




Рисунок 3 — Схема Master-Slave репликации




3.2 Master-Slave репликация




Мастер-Мастер репликация была настроена, теперь можно добавлять слейвы (рис. 3). Для этого нам нужно добавить конфигурационный файл /etc/mysql/my.cnf для каждого mysql-слейва, который входит в репликацию.




3.2.1 Настройка m-slave1 слейва




Сначала настроим первый слейв-сервер.




root@m-slave1:~# cat /etc/mysql/my.cnf
[mysqld]
#Уникальный идентификатор сервера
server-id = 3
 
#Логи ошибок
log_error = /var/log/mysql/mysql.err
 
#Путь к relay-логам слейва (бинлог, скачанный с мастера)
relay-log = /var/lib/mysql/slave-mysql-relay-bin
relay-log-index = /var/lib/mysql/slave-mysql-relay-bin.index
 
#БД, которые нужно/не нужно реплицировать
replicate-do-db = testdb
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
replicate-ignore-db=performance_schema
 
#Чтобы не было конфликтов автоинкремента, говорим серверу,
#чтобы id генерировались начиная с 4-го прибавляя по 10,
# например 11, 21, 31, 41...
auto_increment_increment = 10
auto_increment_offset = 1




Теперь рестартуем mysql




root@m-slave1:~# /etc/init.d/mysql restart
 * Stopping MySQL (Percona Server) mysqld                                                                                                                       [ OK ]
 * Starting MySQL (Percona Server) database server mysqld                                                                                                       [ OK ]
 * Checking for corrupt, not cleanly closed and upgrade needing tables.




3.2.2 Настройка m-slave2 слейва




Переходим к настройке второго слейва.




root@m-slave2:~# cat /etc/mysql/my.cnf
[mysqld]
#Уникальный идентификатор сервера
server-id = 4
 
#Логи ошибок
log_error = /var/log/mysql/mysql.err
 
#Путь к relay-логам слейва (бинлог, скачанный с мастера)
relay-log = /var/lib/mysql/slave-mysql-relay-bin
relay-log-index = /var/lib/mysql/slave-mysql-relay-bin.index
 
#БД, которые нужно/не нужно реплицировать
replicate-do-db = testdb
replicate-ignore-db=information_schema
replicate-ignore-db=mysql
replicate-ignore-db=performance_schema
 
#Чтобы не было конфликтов автоинкремента, говорим серверу,
#чтобы id генерировались начиная с 4-го прибавляя по 10,
# например 12, 22, 32, 42...
auto_increment_increment = 10
auto_increment_offset = 2




Теперь рестартуем mysql




root@m-slave2:~# /etc/init.d/mysql restart
 * Stopping MySQL (Percona Server) mysqld                                                                                                                       [ OK ]
 * Starting MySQL (Percona Server) database server mysqld                                                                                                       [ OK ]
 * Checking for corrupt, not cleanly closed and upgrade needing tables.




3.2.3 Запуск репликации




Если вы следовали  пункту 3.1.4  (Тестирование мастер репликации) после настройки Мастер – Мастер репликации, то на обоих слейвах нужно разворачивать новый дамп testdb, так как в эту БД добавлялись данные. Т.е. для слейва m-slave1 нужно снять дамп с мастера m-serv1 и развернуть (описано в  пункте 2.2 Дамп и деплой), для m-slave2 дамп нужно снять с m-serv2 и развернуть. После того, как дамп будет развернут, у нас будут следующие данные в БД testdb.




root@m-slave1:~# mysql -u root -p -e 'use testdb;select * from users;'
Enter password:
+----+-------+
| id | name  |
+----+-------+
|  1 | Alex  |
|  3 | Vova  |
|  4 | Pasha |
| 13 | Frodo |
| 14 | Misha |
+----+-------+




Т.е. те же данные, что остались на мастер-серверах после тестирования Масте-Мастер репликации.
Теперь осталось запустить репилкацию. В случаи с m-slave1 мастер сервер должен быть m-serv1, поэтому переходим на первый мастер сервер и смотрим MASTER_LOG_FILE и MASTER_LOG_POS.




root@m-serv1:~# mysql -u root -p -e 'show master status;'
Enter password:
+-------------------------+----------+--------------+--------------------------------------------------+-------------------+
| File                    | Position | Binlog_Do_DB | Binlog_Ignore_DB                                 | Executed_Gtid_Set |
+-------------------------+----------+--------------+--------------------------------------------------+-------------------+
| server-mysql-bin.000006 |      120 |              | information_schema,mysql,performance_schema      |                   |
+-------------------------+----------+--------------+--------------------------------------------------+-------------------+




Следовательно MASTER_LOG_FILE = server-mysql-bin.000006, а MASTER_LOG_POS = 120. Теперь переходим обратно на m-slave1 и настраиваем репликацию.




root@m-slave1:~# mysql -u root -p -e "CHANGE MASTER TO MASTER_HOST = '192.168.1.201', MASTER_USER = 'replica', MASTER_PASSWORD = '%repl2015', MASTER_LOG_FILE = 'server-mysql-bin.000006', MASTER_LOG_POS = 120;"




Все интуитивно понятно. Теперь стартуем слейв и смотрим статус.




root@m-slave1:~# mysql -u root -p -e 'start slave;'
root@m-slave1:~# mysql -u root -p -e 'show slave status G;'
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.201
                  Master_User: replica
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: server-mysql-bin.000006
          Read_Master_Log_Pos: 120
               Relay_Log_File: slave-mysql-relay-bin.000002
                Relay_Log_Pos: 290
        Relay_Master_Log_File: server-mysql-bin.000006
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: testdb
          Replicate_Ignore_DB: information_schema,mysql,performance_schema
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 120
              Relay_Log_Space: 469
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 1
                  Master_UUID: f208be92-fa66-11e4-a905-08002742f2f0
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0




Все ок. Теперь делаем те же движения для m-slave2. Переходим на второй мастер сервер и смотрим MASTER_LOG_FILE и MASTER_LOG_POS.




root@m-serv2:~# mysql -u root -p -e 'show master status;'
Enter password:
+-------------------------+----------+--------------+--------------------------------------------------+-------------------+
| File                    | Position | Binlog_Do_DB | Binlog_Ignore_DB                                 | Executed_Gtid_Set |
+-------------------------+----------+--------------+--------------------------------------------------+-------------------+
| server-mysql-bin.000002 |      120 |              | information_schema,mysql,performance_schema      |                   |
+-------------------------+----------+--------------+--------------------------------------------------+-------------------+




Следовательно MASTER_LOG_FILE = server-mysql-bin.000002, а MASTER_LOG_POS = 120. Теперь переходим обратно на m-slave2 и настраиваем репликацию.




root@m-slave2:~# mysql -u root -p -e "CHANGE MASTER TO MASTER_HOST = '192.168.1.202', MASTER_USER = 'replica', MASTER_PASSWORD = '%repl2015', MASTER_LOG_FILE = 'server-mysql-bin.000002', MASTER_LOG_POS = 120;"




Все интуитивно понятно. Теперь стартуем слейв и смотрим статус.




root@m-slave2:~# mysql -u root -p -e 'start slave;'
root@m-slave2:~# mysql -u root -p -e 'show slave status G;'
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.1.202
                  Master_User: replica
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: server-mysql-bin.000002
          Read_Master_Log_Pos: 120
               Relay_Log_File: slave-mysql-relay-bin.000002
                Relay_Log_Pos: 290
        Relay_Master_Log_File: server-mysql-bin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: testdb
          Replicate_Ignore_DB: information_schema,mysql,performance_schema
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 120
              Relay_Log_Space: 469
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 2
                  Master_UUID: 25f9f3ac-fd3b-11e4-bb77-080027ead940
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0




3.2.4 Тестируем репликацию




Тестируем всю нашу цепочку репликации (рис. 1). Перейдем на первый мастер сервер и добавим новую запись в testdb.users.




root@m-serv1:~# mysql -u root -p -e 'USE testdb; INSERT INTO users(name) VALUES ("Server1 record");'
root@m-serv1:~# mysql -u root -p -e 'select * from testdb.users;'
+----+----------------+
| id | name           |
+----+----------------+
|  1 | Alex           |
|  3 | Vova           |
|  4 | Pasha          |
| 13 | Frodo          |
| 14 | Misha          |
| 23 | Server1 record |
+----+----------------+




Теперь проверяем добавилась ли запись на все слейвы и на второй мастер




root@m-slave1:~# mysql -u root -p -e 'use testdb;select * from users;'
+----+----------------+
| id | name           |
+----+----------------+
|  1 | Alex           |
|  3 | Vova           |
|  4 | Pasha          |
| 13 | Frodo          |
| 14 | Misha          |
| 23 | Server1 record |
+----+----------------+
 
root@m-slave2:~# mysql -u root -p -e 'use testdb;select * from users;'
+----+----------------+
| id | name           |
+----+----------------+
|  1 | Alex           |
|  3 | Vova           |
|  4 | Pasha          |
| 13 | Frodo          |
| 14 | Misha          |
| 23 | Server1 record |
+----+----------------+
 
root@m-serv2:~# mysql -u root -p -e 'use testdb;select * from users;'
+----+----------------+
| id | name           |
+----+----------------+
|  1 | Alex           |
|  3 | Vova           |
|  4 | Pasha          |
| 13 | Frodo          |
| 14 | Misha          |
| 23 | Server1 record |
+----+----------------+




Как видим, все в порядке. Теперь добавим запись на втором мастере.




root@m-serv2:~# mysql -u root -p -e 'USE testdb; INSERT INTO users(name) VALUES ("Server2 record");'
root@m-serv2:~# mysql -u root -p -e 'select * from testdb.users;'
+----+----------------+
| id | name           |
+----+----------------+
|  1 | Alex           |
|  3 | Vova           |
|  4 | Pasha          |
| 13 | Frodo          |
| 14 | Misha          |
| 23 | Server1 record |
| 24 | Server2 record |
+----+----------------+




Теперь проверяем добавилась ли запись на все слейвы и на первый мастер




root@m-slave1:~# mysql -u root -p -e 'use testdb;select * from users;'
+----+----------------+
| id | name           |
+----+----------------+
|  1 | Alex           |
|  3 | Vova           |
|  4 | Pasha          |
| 13 | Frodo          |
| 14 | Misha          |
| 23 | Server1 record |
| 24 | Server2 record |
+----+----------------+
 
root@m-slave2:~# mysql -u root -p -e 'use testdb;select * from users;'
+----+----------------+
| id | name           |
+----+----------------+
|  1 | Alex           |
|  3 | Vova           |
|  4 | Pasha          |
| 13 | Frodo          |
| 14 | Misha          |
| 23 | Server1 record |
| 24 | Server2 record |
+----+----------------+
 
root@m-serv1:~# mysql -u root -p -e 'use testdb;select * from users;'
+----+----------------+
| id | name           |
+----+----------------+
|  1 | Alex           |
|  3 | Vova           |
|  4 | Pasha          |
| 13 | Frodo          |
| 14 | Misha          |
| 23 | Server1 record |
| 24 | Server2 record |
+----+----------------+




Как видим, репликация работает как и предполагалось.




4. Распространенные ошибки




==========================================================================
Ошибка: ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
Решение:




mysql> reset slave;
Query OK, 0 rows affected (0.00 sec)
 
mysql> CHANGE MASTER TO MASTER_HOST='192.168.1.201', MASTER_USER='rep_user', MASTER_PASSWORD='rep_user', MASTER_PORT=3306, MASTER_LOG_FILE='mysql-bin.000005', MASTER_LOG_POS=120, MASTER_CONNECT_RETRY=10;
Query OK, 0 rows affected, 2 warnings (0.05 sec)
 
mysql> start slave;




==========================================================================
Ошибки:




  • Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND for deleting row
  • Can’t drop database ‘********’: database doesn’t exist’
  • Error ‘Duplicate entry’
  • Could not execute Write_rows event on table ***********: Duplicate entry ‘XXXXXXXX’ for key ‘ххххххх’, Error_code: 1062




Решение: Эти ошибки можно просто скипнуть, но посмотреть их причины сначала.




mysql -uroot -p -e 'STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE;'




==========================================================================
Ошибка: Relay log read failure (#1594): Could not parse relay log event entry.
Решение:




#Подключаемся к серверу, где возникла проблема и смотрим статус репликации
root@server:~# mysql -uroot -p -e 'show slave status G;' | grep -E 'Relay_Master_Log_File|Exec_Master_Log_Pos'
        Relay_Master_Log_File: mysql-bin.008189
      Exec_Master_Log_Pos: 71687831
 
# Останавливаем репликацию и обновляем бин-лог и позицию
#master_log_file = Relay_Master_Log_File = mysql-bin.008189
#master_log_pos = Exec_Master_Log_Pos = 71687831
root@server:~# mysql -uroot -p -e "STOP SLAVE;"
root@server:~# mysql -uroot -p -e "CHANGE MASTER TO master_log_file='mysql-bin.008189', master_log_pos=71687831;"
 
#Стартуем слейв
root@server:~# mysql -uroot -p218e5ccb4a834382%FBF87B604F1FE14B -e "START SLAVE;"




==========================================================================




5. Полезные команды




5.1 Резервное копирования и восстановление БД




Дамп одной базы данных.




mysqldump -u root -p companyDB  > company_DB.sql




Дамп нескольких баз данных.




mysqldump -u root -p --databases companyDB projectsDB  > company_and_projects_DBs.sql




Дамп всех баз данных.




mysqldump -u root -p --all-databases > all_DBs.sql




Дамп одной таблицы.




mysqldump -u root -p companyDB employeesTB > companyDB_employeesTB.sql




Дамп структуры базы данных.




mysqldump -u root -p --no-data companyDB > companyDB_structure.sql




Дамп только триггеров, процедур и событий с gzip-ом.




mysqldump --no-create-info --no-data --triggers --routines --events –u root -p companyDB| gzip > companyDB.sql.gz




Простой скрипт дампа для cron-a.




#!/bin/bash
# Список БД через пробел
dbs="cacti_db inventory_db monitor_db"
# Маленький лог файл для хранение информиции о старте бекапа
echo "`date +%Y-%m-%d` - Start sync backups" >> /tmp/backup.log
for databases in $dbs
do
        /usr/bin/mysqldump --max_allowed_packet=512M -uroot -p'your_pass_here' $databases | gzip > /tmp/`date +${databases}.sql.%Y-%m-%d.gz`
        if [ "$?" -eq 0 ]
        then
                /usr/bin/rsync --remove-source-files -a /tmp/`date +${databases}.sql.%Y-%m-%d.gz` mystorage.company.com:/backups/
        else
                echo "`date +%Y-%m-%d` - FAILED to sync $databases" >> /tmp/backup.log
        fi
done




Развернуть дамп существующей базы данных, способ 1.




mysql -u root -p companyDB < companyDB.sql




Развернуть дамп существующей базы данных, способ 2.




mysql> use companyDB;
mysql> source companyDB.sql




Развернуть дамп существующей базы данных из архива.




zcat companyDB.sql.gz | mysql -u root -p companyDB




Развернуть дамп несуществующий базы данных, способ 1.




mysql> create database companyDB;
mysql> use companyDB;
mysql> source companyDB.sql;




Развернуть дамп несуществующий базы данных, способ 2.




mysql -u root -p -e "create database companyDB;"
mysql -u root -p companyDB < companyDB.sql




5.2 Переменные, состояние и статус БД




Проверить состояние БД.




mysqladmin -u root -p ping




Узнать версию БД.




mysqladmin -u root -p version
или
mysql> select version();




Статус БД.




mysqladmin -u root -p status
или
mysql> status;




Здесь,




  • Uptime: сколько секунд работает mysql сервер.
  • Threads: суммарное количество подключений к mysql серверу.
  • Questions: суммарное количество выполненных запросов за время работы сервера.
  • Slow queries: суммарное число запросов, выполненных за время, которое превышает long_query_time.
  • Opens: суммарное количество открытых таблиц сервером.
  • Flush tables: сколько раз таблица была flushed.
  • Open tables: суммарное количество открытых таблиц в базе.




Список переменных статуса mysql.




mysqladmin -u root -p extended-status
или
mysql -u root -p -e 'show status;'




Список всех системных(глобальных) переменных сервера.




mysqladmin -u root -p variables
или
mysql> show variables;




Список процессов/запросов в mysql.




mysqladmin -u root -p processlist
или
mysql> show processlist;




Обновлять каждую секунду список процессов.




mysqladmin -u root -p -i 1 processlist




Список золочёных таблиц.




mysql -u root -p -e 'show open tables WHERE In_use > 0;'




Перезагрузка(запись изменений) привилегий.




mysqladmin -u root -p reload




Очистка (закроет все базы и переоткроет логи).




mysqladmin -u root -p refresh




Потушить сервер.




mysqladmin -u root -p shutdown




Stop/start репликации.




mysqladmin  -u root -p stop-slave
mysqladmin  -u root -p start-slave




5.3 Работа со базами данных и таблицами




Поменять пароль root-а.




mysqladmin -u root -p'old_pass' password 'new_pass'
или
mysql> use mysql;
mysql> update user set password=PASSWORD("newpass") where User='ENTER-USER-NAME-HERE';




Создать БД.




mysqladmin -u root -p create test1db
или
mysql> create database test1db;




Удалить БД.




mysqladmin -u root -p drop test1db
или
mysql> drop test1db;




Список flush-команд.




mysqladmin -u root -p flush-hosts
mysqladmin -u root -p flush-logs
mysqladmin -u root -p flush-privileges
mysqladmin -u root -p flush-status
mysqladmin -u root -p flush-tables
mysqladmin -u root -p flush-threads




Несколько команд в одной.




mysqladmin -u root -p processlist stat




Посмотреть существующие базы.




mysqlshow -u root -p




Посмотреть все таблицы конкретной БД.




mysqlshow -u root -p test1db




… с количеством полей




mysqlshow -v -u root -p test1db




… с количеством полей и строк




mysqlshow -v -v -u root -p test1db




… со структурой таблицы




mysqlshow -u root -p mysql servers




… со структурой таблицы по конкретному полю




mysqlshow -u root -p mysql servers server_name




5.4 Работа с пользователями




Создать нового юзера




mysql> create user 'user1'@'localhost' identified by 'user1pass';




Добавить все права на все базы и все таблицы.




#GRANT [тип прав] ON [название БД].[название таблицы] TO '[имя пользователя]'@'localhost';
mysql> grant ALL PRIVILEGES ON *.* to 'user1'@'localhost';
mysql> flush privileges;




Удаление прав для пользователя.




#REVOKE [тип прав] ON [название БД].[название таблицы] FROM '[имя пользователя]'@'localhost';
mysql> revoke ALL on *.* from 'user1'@'localhost';




Удалить пользователя.




mysql> drop user 'user1'@'localhost';




5.4.1 Сброс пароля root, если забыли.




1. Остановка сервера




# /etc/init.d/mysql stop




2. Запуск mysql со скипом привилегий




mysqld --skip-grant-tables --user=mysql &
или
mysqld_safe --skip-grant-tables &




3. Логинимся в БД без пароля. Пароль хэшируется с помощью функции PASSWORD(str). Это специальная функция, которая возвращает строку 16-byte и используется системой аутентификации исключительно mysql сервером. Поэтому, используйте MD5 или SHA1 для хранения паролей приложений, которые юзают mysql, но не PASSWORD.




mysql> use mysql;
mysql> select Host,User,Password  from user;
+-----------+------------------+-------------------------------------------+
| Host      | User             | Password                                  |
+-----------+------------------+-------------------------------------------+
| localhost | root             | *30657C01D8312B05274147BF51D53702F90CB68C |
| ubuntu    | root             | *30657C01D8312B05274147BF51D53702F90CB68C |
| 127.0.0.1 | root             | *30657C01D8312B05274147BF51D53702F90CB68C |
| ::1       | root             | *30657C01D8312B05274147BF51D53702F90CB68C |
| localhost |                  |                                           |
| ubuntu    |                  |                                           |
| localhost | debian-sys-maint | *90A841D52ED52171F0500125A2460FA4443BCF7F |
+-----------+------------------+-------------------------------------------+
7 rows in set (0.00 sec)




4. Теперь меняем пароль.




mysql> update user set Password=PASSWORD('alex1111') WHERE User='root';
Query OK, 4 rows affected (0.00 sec)
Rows matched: 4  Changed: 4  Warnings: 0




5. Так как данная информация храниться в mysql кэше — нужно его освободить, иначе пароль останется закешированным и дела не будет




mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)




6. Теперь останавливаем mysqld, который запускали вручную и запускаем init-скрипт.




kill `pgrep mysql`
/etc/init.d/mysql start
 * Starting MySQL (Percona Server) database server mysqld




Установка и настройка Percona XtraDB Cluster




Поднять mysql кластер можно в несколько раз быстрее используя такую вещь, как Percona XtraDB Cluster, о чем и пойдет речь в данной статье.

Создадим Percona XtraDB Cluster с трех серверов под управлением операционной системы Ubuntu 12.04.
Установка будет произведена из репозитория. Для начала, логинимся на первый сервер, добавляем ключик и репозитории.




root@pxc1:~#apt-key adv --keyserver keys.gnupg.net --recv-keys 1C4CBDCDCD2EFD2A
root@pxc1:~#vim /etc/apt/sources.list.d/pxe.list
…
deb http://repo.percona.com/apt precise main
deb-src http://repo.percona.com/apt precise main
...
root@pxc1:~#apt-get update




Теперь ставим непосредственно Percona XtraDB Cluster пакет.




root@pxc1:~#apt-get install percona-xtradb-cluster-56




Во время установки нужно будет ввести пароль для доступа к mysql БД.
Перед добавлением ноды в кластер, нужно стопнуть mysql.




root@pxc1:~#/etc/init.d/mysql stop




Добавляем главный конфигурационных файл для первого mysql PXC1 сервера.




root@pxc1:~#cat /etc/mysql/my.cnf
…
[mysqld]
 
# Логи
log_error = /var/log/mysql/mysql.err
# Директория с БД
datadir=/var/lib/mysql
# Пользователь
user=mysql
# Путь к Galera модуля
wsrep_provider=/usr/lib/libgalera_smm.so
# URL с IP адресами серверов, которые входят в кластер
wsrep_cluster_address=gcomm://192.168.1.150,192.168.1.151,192.168.1.152
# Формат бинлогов
binlog_format=ROW
# Дефолтный механизм хранения данных
default_storage_engine=InnoDB
# Режим лока при работе с автоинкремент значениями
innodb_autoinc_lock_mode=2
 
# Адрес первой ноды в кластере
wsrep_node_address=192.168.1.150
 
# Метод передачи снепшотов БД
wsrep_sst_method=xtrabackup-v2
 
# Имя кластера
wsrep_cluster_name=test_mysql_cluster
 
# Аутентификация для SST
wsrep_sst_auth="sstuser:DOGUQpj0Se8Q9oy7"
…




Теперь можно стартовать mysql сервер в режиме bootstrap.




root@pxc1:~#/etc/init.d/mysql bootstrap-pxc




После этого у нас добавиться первая нода в кластер. Для проверки, можно запустить команду.




root@pxc1:~# mysql -u root -p -e "show status like 'wsrep%';" | grep -E 'local_state|cluster|ready|connected'
 
wsrep_local_state_uuid  b2cf979d-54ca-11e5-9bb4-628c43a251a6
wsrep_local_state       4
wsrep_local_state_comment       Synced
wsrep_cluster_conf_id   1
wsrep_cluster_size      1
wsrep_cluster_state_uuid        b2cf979d-54ca-11e5-9bb4-628c43a251a6
wsrep_cluster_status    Primary
wsrep_connected ON
wsrep_ready     ON




Этот вывод означает, что все ок. Теперь нужно добавить юзера с привилегиями для SST операций, которого мы добавили в конце my.cnf файла.




root@pxc1:~# mysql -u root -p
 
mysql> CREATE USER 'sstuser'@'localhost' IDENTIFIED BY 'DOGUQpj0Se8Q9oy7';
Query OK, 0 rows affected (1.27 sec)
 
mysql> GRANT RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'sstuser'@'localhost';
Query OK, 0 rows affected (0.62 sec)
 
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.48 sec)




Далее переходим к настройке второго сервера. Устанавливаем mysql Percona XtraDB Cluster таким же образом и переходим к редактированию my.cnf файла.




root@pxc2:~#cat /etc/mysql/my.cnf
…
[mysqld]
 
# Логи
log_error = /var/log/mysql/mysql.err
# Директория с БД
datadir=/var/lib/mysql
# Пользователь
user=mysql
# Путь к Galera модуля
wsrep_provider=/usr/lib/libgalera_smm.so
# URL с IP адресами серверов, которые входят в кластер
wsrep_cluster_address=gcomm://192.168.1.150,192.168.1.151,192.168.1.152
# Формат бинлогов
binlog_format=ROW
# Дефолтный механизм хранения данных
default_storage_engine=InnoDB
# Режим лока при работе с автоинкремент значениями
innodb_autoinc_lock_mode=2
 
# Адрес первой ноды в кластере
wsrep_node_address=192.168.1.151
 
# Метод передачи снепшотов БД
wsrep_sst_method=xtrabackup-v2
 
# Имя кластера
wsrep_cluster_name=test_mysql_cluster
 
# Аутентификация для SST
wsrep_sst_auth="sstuser:DOGUQpj0Se8Q9oy7"
…




И стартуем mysql в нормально режиме.




root@pxc2:~#/etc/init.d/mysql start




После этого, второй сервер добавиться в кластер. Проверяем.




root@pxc2:~# mysql -u root -p -e "show status like 'wsrep%';" | grep -E 'local_state|cluster|ready|connected'
 
wsrep_local_state_uuid  b2cf979d-54ca-11e5-9bb4-628c43a251a6
wsrep_local_state       4
wsrep_local_state_comment       Synced
wsrep_cluster_conf_id   4
wsrep_cluster_size      2
wsrep_cluster_state_uuid        b2cf979d-54ca-11e5-9bb4-628c43a251a6
wsrep_cluster_status    Primary
wsrep_connected ON
wsrep_ready     ON




Ну и добавляем последнюю ноду. Устанавливаем Percona XtraDB Cluster и создаем my.cnf.




root@pxc3:~#cat /etc/mysql/my.cnf
…
[mysqld]
 
# Логи
log_error = /var/log/mysql/mysql.err
# Директория с БД
datadir=/var/lib/mysql
# Пользователь
user=mysql
# Путь к Galera модуля
wsrep_provider=/usr/lib/libgalera_smm.so
# URL с IP адресами серверов, которые входят в кластер
wsrep_cluster_address=gcomm://192.168.1.150,192.168.1.151,192.168.1.152
# Формат бинлогов
binlog_format=ROW
# Дефолтный механизм хранения данных
default_storage_engine=InnoDB
# Режим лока при работе с автоинкремент значениями
innodb_autoinc_lock_mode=2
 
# Адрес первой ноды в кластере
wsrep_node_address=192.168.1.152
 
# Метод передачи снепшотов БД
wsrep_sst_method=xtrabackup-v2
 
# Имя кластера
wsrep_cluster_name=test_mysql_cluster
 
# Аутентификация для SST
wsrep_sst_auth="sstuser:DOGUQpj0Se8Q9oy7"
…




И стартуем mysql.




root@pxc3:~#/etc/init.d/mysql start




Проверяем статус кластера.




root@pxc3:~# mysql -u root -p -e "show status like 'wsrep%';" | grep -E 'local_state|cluster|ready|connected'
 
wsrep_local_state_uuid  b2cf979d-54ca-11e5-9bb4-628c43a251a6
wsrep_local_state       4
wsrep_local_state_comment       Synced
wsrep_cluster_conf_id   7
wsrep_cluster_size      3
wsrep_cluster_state_uuid        b2cf979d-54ca-11e5-9bb4-628c43a251a6
wsrep_cluster_status    Primary
wsrep_connected ON
wsrep_ready     ON




Как видим, у нас все 3 ноды успешно добавлены в кластер. Теперь можно протестировать работу.
Переходим на первую ноду, создаем тестовую БД, таблицу и добавляем запись в неё.




root@pxc1:~# mysql -u root –p
 
mysql> CREATE DATABASE firstDB;
Query OK, 1 row affected (0.01 sec)
 
mysql> USE firstDB;
Database changed
 
mysql> CREATE TABLE records (rec VARCHAR(50));
Query OK, 0 rows affected (0.08 sec)
 
mysql> INSERT INTO records VALUE ("pxc1 record");
Query OK, 1 row affected (0.12 sec)
 
mysql> SELECT * FROM records;
+-------------+
| rec         |
+-------------+
| pxc1 record |
+-------------+
1 row in set (0.00 sec)




Теперь идем на второй сервер и проверяем работает ли репликация.




root@pxc2:~# mysql -uroot -p
 
mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| firstDB            |
| mysql              |
| performance_schema |
| test               |
+--------------------+




Как видим, БД среплицировалась. Теперь добавив еще одну запись в таблицу.




mysql> INSERT INTO records VALUE ("pxc2 record");
Query OK, 1 row affected (0.04 sec)
 
mysql> SELECT * FROM records;
+-------------+
| rec         |
+-------------+
| pxc1 record |
| pxc2 record |
+-------------+
2 rows in set (0.00 sec)




Первая запись среплицировалась и теперь у нас есть две записи. Проверяем последний сервер.




root@pxc3:~# mysql -u root -p
 
mysql> USE firstDB;
Database changed
 
mysql> SELECT * FROM records;
+-------------+
| rec         |
+-------------+
| pxc1 record |
| pxc2 record |
+-------------+
2 rows in set (0.00 sec)




Кластер работает как положено. Для тестов, еще можно выключить одну машину и через некоторое время включить обратно. В этом случаи в кластере будет только две машины, а после включения третей – все данные, которые были добавлены в период колапса будут среплицированы на поднявшуюся ноду.




Источник: http://sysadm.pp.ua/linux/mysql-install.html



2021-08-27T15:36:39
Software

Создание Jenkins backup/restore в Unix/Linux

Я рассказывал в своих заметках о установке, настройке, масштабировании и о джобах в Jenkins-е. В голову пришло еще то, что нужно еще и иметь бэкапы для того, чтобы можно было откатится назад. Я нагуглил пару решений. Но еще не решил какое лучше. По этому, расскажу о них.




Полезное чтиво:




Установка Jenkins в Unix/Linux




Работа с Jenkins-CLI в Unix/Linux




Установка Jenkins и Jenkins-slave в Unix/Linux




Настройка языка в Jenkins




Создание Jenkins backup/restore в Unix/Linux




И так, нам понадобится установить плагин(ы) (можно и один на выбор, я использовал несколько для сравнения):




  • Thin backup
  • Backup Plugin
  • Periodic Backup
  • SCM Sync configuration




Можно заюзать и другие решения:




  • Использовать Git и взять «$JENKINS_HOME» под него.
  • Написать BASH скрипт и создать джобу на ее выполнение.




Перейдем к решениям!




Использование Thin backup плагина для backup/restore Jenkins-а в Unix/Linux




Переходим «Manage Jenkins» -> «Manage Plugins» и устанавливаем «Thin backup». Я обычно всегда перезапускаю дженкинс для того, чтобы применились все настройки и все работало.




PS: Для перезагрузки дженкинс-сервера, я использую «Restart Safely» плагин.




Настройки бекапа, переходим в «Manage Jenkins» -> «ThinBackup»:




Плагин ThinBackup для Jenkins-а




В данном плагине имеются:




  • Backup Now — Кнопка чтобы сделать бекап сейчас.
  • Restore — Служит для рестора данных.
  • Settings — Настройка для бэкапа.




Начнем с настройки, нажимаем по нему:




Настройка thinBackup плагина для бэкапа дженкинса




Я отметил нужные мне поля и нажал на кнопку «Save». Т. е у меня будут выполнятся бэкапы по заданному расписанию и складыватся в «/backups» папку. Теперь можно запустить «Backup now» чтобы выполнился бэкап.




Вот и все. Можно юзать данный плагин для бэкаа и рестора.




Использование Backup Plugin плагина для backup/restore Jenkins-а в Unix/Linux




Переходим «Manage Jenkins» -> «Manage Plugins» и устанавливаем «Backup plugin». Я обычно всегда перезапускаю дженкинс для того, чтобы применились все настройки и все работало.




Настройки бекапа, переходим в «Manage Jenkins» -> «Backup manager»:







В данном плагине имеются:




  • Setup — Служит для настройки бэкапов.
  • Backup Hudson configuration — Чтобы создать бэкап.
  • Restore Hudson configuration — Для рестора бэкапа.




Я привел настройку к такому виду:







После настроек нажимаем на «Save». Нажимаем на «Backup Hudson configuration» для создания бэкапа.




Использование Periodic Backup плагина для backup/restore Jenkins-а в Unix/Linux




Переходим «Manage Jenkins» -> «Manage Plugins» и устанавливаем «Periodic Backup». Я обычно всегда перезапускаю дженкинс для того, чтобы применились все настройки и все работало.




Настройки бекапа, переходим в «Manage Jenkins» -> «Periodic Backup Manager»:




Меню Periodic Backup plugin




Плагин не сконфигурирован и его нужно отконфигурить. Что я и сделаю сейчас, нажимаем на «Configure»:




Настройка Periodic Backup plugin




Вот и все. Можно выполнить бэкап! Данный плагин понравился больше чем другие!




Использование SCM Sync configuration плагина для backup/restore Jenkins-а в Unix/Linux




Переходим «Manage Jenkins» -> «Manage Plugins» и устанавливаем «SCM Sync configuration». Я обычно всегда перезапускаю дженкинс для того, чтобы применились все настройки и все работало.




Создам проект в гитлабе, например «configurations/jenkins».В данной проекте я буду хранить все настройки.




Переходим в «Manage Jenkins» -> «Configure System» и находим поле «SCM» и заполняем поля. У меня не получилось подружится с этим плагином вообще. Снес его!




Использование bash-скрипта для backup/restore Jenkins-а в Unix/Linux




Можно написать скрипты на любой вкус, используя bash. Есть плагин для запуска скриптов через джобу. Сейчас поставим данный плагин.




Переходим «Manage Jenkins» -> «Manage Plugins» и устанавливаем «Exclusive Execution». Я обычно всегда перезапускаю дженкинс для того, чтобы применились все настройки и все работало. Создам структуру: Projects->Configurations. Т.е папка Projects в ней будут проекты, в данном случае «Configurations» — конфиги (Для создания папки, нажмите «New item» и выбирете «folder»).




Переходим в проект и нажимаем на «New item» и кликаем по «Freestyle project». Вводим имя для проекта, у меня — «jenkins-backup» и нажимаем на «OK»:




Freestyle project для Jenkins бекапа




Потом переходим в созданный проект и нажимаем на «Configure» и находим поле «Source Code Management» и прописываем УРЛ где будет лежать скрипт для бэкапа у меня это готовое решение какого-то чела, например:




настройка SCM




Идем дальше и переходим во «Build Triggers» вкладку и заполним:







Т.е заполним переодичность с которой будет запускаться скрипт.sh1 lines




H 3 * * *




После этого переходим во «Build» вкладку и затем, из списка выбираем «Execute shell». и прописываем параметры для запуска:




Настройка запуска скрипта с параметрами через Build-execute shell




Добавляем в поле следующий текст:sh1 lines




./jenkins-backup.sh $JENKINS_HOME /backups/backup_`date +"%Y_%m_%d_%H:%M:%S"`.tar.gz




И на этом все, нажимаем на «Save». После этого, будет выполнятся бекап по заданному времени. Если есть необходимость, то можно запустить джобу маннуалли (Нажав на «Build Now»).




PS: Можно сделать бэкап-ротейт чтобы все старые бэкапы удалялись автоматом, например, можно добавить еще один «Execute shell» команду:sh1 lines




find /backups/backup_* -mtime +7 -delete




Т.е бэкапы будут хранится 7 дней, остальные будут удалены.




Вот еще один пример скрипта, который можно использовать:sh42 lines




#!/bin/bash

# Setup
#
# - Create a new Jenkins Job
# - Mark "None" for Source Control Management
# - Select the "Build Periodically" build trigger
#   - configure to run as frequently as you like
# - Add a new "Execute Shell" build step
#   - Paste the contents of this file as the command
# - Save
#  
# NOTE: before this job will work, you'll need to manually navigate to the $JENKINS_HOME directory 
# and do the initial set up of the git repository.  
# Make sure the appropriate remote is added and the default remote/branch set up.
#  

# Jenkins Configuraitons Directory
cd $JENKINS_HOME

# Add general configurations, job configurations, and user content
git add -- *.xml jobs/*/*.xml userContent/*

# only add user configurations if they exist
if [ -d users ]; then
    user_configs=`ls users/*/config.xml`

    if [ -n "$user_configs" ]; then
        git add $user_configs
    fi
fi

# mark as deleted anything that's been, well, deleted
to_remove=`git status | grep "deleted" | awk '{print $3}'`

if [ -n "$to_remove" ]; then
    git rm --ignore-unmatch $to_remove
fi

git commit -m "Automated Jenkins commit"

git push -q -u origin master




Как по мне, все тут логично и понятно что он делаеет… Аналогичным способом можно сделать джобу и запускать переодически. Тем самым, все конфиг-файлы, будут попадать в гит.




Вывод: Я протестировал несколько плагинов и выбрал — использовать скрипты или Thin backup, Periodic Backup плагины. Но если есть другие решения, — пишите, дополню материал.




Я для клиента писал вот такой скрипт:sh38 lines




#!/usr/bin/env bash


# JENKINS_HOME
#  +- config.xml     (jenkins root configuration)
#  +- *.xml          (other site-wide configuration files)
#  +- userContent    (files in this directory will be served under your http://server/userContent/)
#  +- fingerprints   (stores fingerprint records)
#  +- nodes          (slave configurations)
#  +- plugins        (stores plugins)
#  +- secrets        (secretes needed when migrating credentials to other servers)
#  +- workspace (working directory for the version control system)
#      +- [JOBNAME] (sub directory for each job)
#  +- jobs
#      +- [JOBNAME]      (sub directory for each job)
#          +- config.xml     (job configuration file)
#          +- latest         (symbolic link to the last successful build)
#          +- builds
#              +- [BUILD_ID]     (for each build)
#                  +- build.xml      (build result summary)
#                  +- log            (log file)
#                  +- changelog.xml  (change log)

echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";
echo "==================== Jenkins backup ====================";
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~";

JENKINS_DIR="/mnt/data/jenkins"
JENKINS_BACKUP_DIR="/mnt/data/jenkins_backup"

cp -r ${JENKINS_DIR}/*.xml ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/userContent ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/fingerprints ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/nodes ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/plugins ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/secrets ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/workspace ${JENKINS_BACKUP_DIR}
cp -r ${JENKINS_DIR}/jobs ${JENKINS_BACKUP_DIR}




Проверялось, — работает!











Резервное копирование для Jenkins




Все, кто занимается задачами CI/CD, так или иначе знают про Jenkins, даже если им посчастливилось не иметь с ним дела.




Этот непотопляемый кадавр продолжает жить и процветать по следующим причинам:




  • гибкость настроек (от настраиваемых диалоговых окон до встроенного Groovy);
  • архитектура с поддержкой плагинов и обширный набор готовых плагинов на все случаи жизни;
  • и самое главное — большой накопленный объём пользовательских проектов, которые проще продолжать развивать и поддерживать в среде Дженкинса, чем пытаться мигрировать на более современные и приятные платформы.




Очевидно, что чем важнее данные внутри Дженкинса для тех, кто им пользуется, тем актуальнее для них резервное копирование этих данных.




Однако здесь возникают два небольших препятствия:




  • настройки, временные данные и файлы проектов смешаны внутри рабочего каталога в одну кучу;
  • штатного механизма не существует, вместо него есть энное число посторонних костылей, распространяемых в виде плагинов, описаний и копипаст.




Поэтому, взяв за основу один из таких костылей, мы написали свой собственный.




Список предварительных пожеланий к нему был примерно таким:




  • резервная копия должна иметь минимальный размер и максимальную скорость создания (например, дамп виртуальной машины или снимок ZFS с сотнями гигабайт проектов не годится);
  • после восстановления нам достаточно иметь полностью настроенный сервер без предыдущего состояния — который знает, как выполнять новые job’ы, но ничего не помнящий про старые;
  • поскольку настройки имеют текстовый вид, пусть они сохраняются в Git-репозиторий;
  • если Jenkins предназначен для автоматического выполнения заданий, пусть самостоятельно выполняет всю работу по своему обслуживанию.




Общая схема:




  • в $JENKINS_HOME создаётся Git-репозиторий;
  • на Git-сервере для него создаётся origin (далее приводятся настройки для Gitlab);
  • в Дженкинсе создаётся периодическое задание, которое сохраняет в Git ключевые файлы;
  • для уменьшения размера от плагинов сохраняются только манифесты, при восстановлении плагины скачиваются заново.




Сначала создайте пользователя и репозиторий в Gitlab’e:




  • пользователь = jenkins-backup-robot;
  • репозиторий = jenkins-configs;
  • URL репозитория скопируйте в буфер обмена;
  • откройте Repository => Settings => Members;
  • назначьте jenkins-backup-robot мантейнером (иначе Gitlab не даст сделать ему первый push в пустой репозиторий).




Теперь идите в командную строку сервера, на котором работает Jenkins:




  • нам требуется создать SSH-ключ и Git-репозиторий:




sudo -Hiu jenkins

cd ~

git init

git config --global user.name Jenkins

git config --global user.email "jenkins@$(hostname -f)"

git remote add origin ВСТАВЬТЕ_ЗДЕСЬ_URL_GIT_РЕПОЗИТОРИЯ

test -s ~/.ssh/id_rsa.pub || ssh-keygen

cat ~/.ssh/id_rsa.pub




Созданный SSH-ключ надо импортировать в Gitlab:




  • Это делается в разделе Admin => Users => jenkins-backup-robot => Impersonate => Personal Settings => SSH keys.




Создайте в Дженкинсе новое задание:




  • Name: Backup Jenkins configs to Git
  • Type: Free job
  • Label: master
  • SCM: None
  • Build: Build Periodically
  • Schedule: 20 04 * * *
  • Build step: Execute Shell
  • Command:




#!/bin/sh -e



cd "$JENKINS_HOME"



# Add general configurations, secrets, job configurations, nodes, user content, users and plugins info:

ls -1d *.xml secrets/ jobs/*/*.xml nodes/*/*.xml userContent/* users/*/config.xml 

    plugins/*/META-INF/MANIFEST.MF 2>/dev/null | grep -v '^queue.xml$' | xargs -r -d 'n' git add --



# Track deleted files:

LANG=C git status | awk '$1 == "deleted:" { print $2; }' | xargs -r git rm --ignore-unmatch



LANG=C git status | grep -q '^nothing to commit' || {

    git commit -m "Automated Jenkins commit at $(date '+%Y-%m-%d %H:%M')"

    git push -q -u origin master

}




  • SAVE




Пояснения:




  • Метка “master” нужна, если у Дженкинса есть slave-узлы. Если их нет, метку в задании можете не указывать. Если они есть, то в списке узлов отредактируйте свойства мастера и в поле “Labels” добавьте “master”. Если вы этого не сделаете, Дженкинс попытается выполнять задание через агентов на всех узлах, а это явно не то, что нам требуется.
  • Если для подключения к Git-серверу используется SSH, перед выполнением задания не забудьте подключиться к нему вручную, чтобы git push не завершался с ошибкой из-за StrictHostKeyChecking.




Заключительный шаг в Gitlab’e после успешного git push:




  • в свойствах репозитория откройте раздел Members и понизьте уровень доступа для Дженкинса с Maintainer до Developer;
  • в Settings => Repository => Protected branches поменяйте для ветки “master” разрешение “Allow to push” с Maintainers на Maintainers+Developers.




Восстановление плагинов:




  • Т.к. мы сохраняем только манифесты плагинов, после восстановления из резервной копии нам потребуется просканировать каталог с манифестами и составить список команд для загрузки дистрибутивов:




sudo -Hiu jenkins

cd ~/plugins/

gawk 'BEGIN     { RS = "rn" }

      BEGINFILE { n = v = "" }

      ENDFILE   { printf "curl -sS -L -O http://updates.jenkins-ci.org/download/plugins/%s/%s/%s.hpin", n, v, n }

      $1 == "Short-Name:"     { n = $2 }

      $1 == "Plugin-Version:" { v = $2 }

    ' ./*/META-INF/MANIFEST.MF > ./download_all_plugins.sh




  • Обратите внимание, что вместо awk используется gawk (GNU awk), т.к. классический awk не понимает BEGINFILE и ENDFILE. В некоторых дистрибутивах gawk устанавливается по умолчанию, в некоторых его потребуется установить вручную.
  • Если gawk отработает без ошибок, запустите сгенерированный им файл:




sudo -Hiu jenkins

cd ~/plugins/

gawk 'BEGIN     { RS = "rn" }

      BEGINFILE { n = v = "" }

      ENDFILE   { printf "curl -sS -L -O http://updates.jenkins-ci.org/download/plugins/%s/%s/%s.hpin", n, v, n }

      $1 == "Short-Name:"     { n = $2 }

      $1 == "Plugin-Version:" { v = $2 }

    ' ./*/META-INF/MANIFEST.MF > ./download_all_plugins.sh




  • Самостоятельно распаковывать и устанавливать скачанные hpi-файлы не требуется — перезапустите Дженкинс и он сделает это сам.




Источники: https://linux-notes.org/sozdanie-jenkins-backup-restore-v-unix-linux/ и https://cdnnow.ru/blog/jenkins-backup/



2021-08-19T10:17:29
Software

Многоступенчатая сборка Docker-образов / Multi-Stage Docker Builds




Это особенно актуально для приложений, разработка которых ведется на компилируемых языках программирования. Используя эту возможность, вы сможете существенно сокращать размер вашего итогового образа не, прибегая к хитрым трюкам, которые я описывал в статье «6 советов по уменьшению Docker образа» Суть подхода заключается в том, чтобы не заботиться о количестве получающихся слоев в процессе сборки вашего приложения и копировать результаты сборки из одного образа в другой. В этой статье я покажу, как это реализуется на практике. Выдумывать ничего не буду, а просто покажу вам это на уже готовых примерах из официальной документации.




Процесс до появления многоэтапных сборок




Одной из самых сложных задач по созданию Docker образов является уменьшение размера итогового образа, ведь каждая команда в Dockerfile добавляет отдельный слой к итоговому образу. Поэтому нам всегда нужно помнить, что необходимо очищать любые не нужные нам артефакты в текущем слое, прежде чем перейти к следующему. Чтобы написать действительно эффективный Dockerfile, нам традиционно необходимо было использовать кучу shell-трюков, чтобы с одной стороны сделать как можно меньше слоев, а с другой, чтобы оставить в каждом созданном слое минимальное количество артефактов.




Вообще говоря, это очень распространенная практика использовать несколько Dockerfile-ов в одном проекте: один для разработки (содержит все необходимое для создания вашего приложения), другой оптимизированный для создания итогового образа, который будет использоваться в продуктиве, в котором должно быть только ваше приложение и все то, что необходимо для его запуска. Эта практика в свое время получила название «шаблон строителя». Однако, поддержание в актуальном состоянии двух Dockerfile-ов не есть что-то удобное.




Вот пример двух Dockerfile-ов (Dockerfile.build и Dockerfile), речь о которых идет выше:




Dockerfile:





FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY app .
CMD ["./app"]




Dockerfile.build:





FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN go get -d -v golang.org/x/net/html 
  && CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .




И конечно же скрипт, автоматизирующий всю работу:




build.sh:





#!/bin/sh
echo Building alexellis2/href-counter:build

docker build --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy   
    -t alexellis2/href-counter:build . -f Dockerfile.build

docker create --name extract alexellis2/href-counter:build  
docker cp extract:/go/src/github.com/alexellis/href-counter/app ./app  
docker rm -f extract

echo Building alexellis2/href-counter:latest

docker build --no-cache -t alexellis2/href-counter:latest .
rm ./app




Когда вы запускаете build.sh скрипт, он создает первый образ, делает из него контейнер, чтобы скопировать артефакты, а затем создать второй образ. Оба образа занимают место на вашей системе, и еще какое-то место у вас занимают артефакты приложения на вашем локальном диске.




Многоэтапные сборки значительно упрощают эту ситуацию!




Использование многоэтапных (multi-stage) сборок




При многоэтапной сборке вы используете несколько операторов FROM в вашем Dockerfile. Каждая инструкция FROM использует произвольный базовый образ и начинает новый этап сборки. Вы можете выборочно копировать артефакты с одного этапа на другой, оставляя только то, что вам необходимо в конечном образе. Чтобы показать, как это работает, давайте адаптируем Dockerfile из предыдущего раздела для этого процесса.




Dockerfile:





FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]





Теперь вам нужен только один Dockerfile. Более того, вам больше не нужен и отдельный скрипт сборки. Просто запустите сборку образа привычной командой.




docker build -t avmaksimov/href-counter:latest .




Конечным результатом вашей является точно такой же крошечный продуктивный образ, однако сложность процесса значительно сократилась. Теперь вам не нужно создавать промежуточные образы, и вам больше не нужно извлекать промежуточные артефакты на вашу локальную систему.




Как это работает? Вторая команда FROM начинает новый этап сборки с базового образа alpine:latest. Инструкция COPY — from = 0 копирует артефакты с предыдущего этапа сборки на текущий этап, благодаря чему необходимые для сборки Go SDK и любые промежуточные артефакты не сохраняются в конечном образе.




Именование этапов сборки




По умолчанию этапы никак не называются, и вы ссылаетесь на них по их целочисленному номеру, начиная с 0 для первой инструкции FROM. Тем не менее, у вас есть возможность давать своим этапам понятные имена, добавив как в команду FROM. Этот пример улучшает предыдущий, используя имена для этапов. Это также означает, что даже если порядок инструкций в вашем Dockerfile со временем изменится, инструкции COPY не сломаются.




Dockerfile:





FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"] 




С появлением в Docker поддержки многоэтапных сборок управлять процессами самих сборок стало значительно проще. Надеюсь, вы это тоже оцените! Побольше вам автоматизации и поменьше ручных операций!










Многоступенчатая сборка Docker-образов




В прошлом я уже говорил о создании миниатюрных Docker-образов, но теперь, когда у Docker появилась многоступенчатая сборка, пришла пора вернуться к этому вопросу. Раньше нам приходилось создавать бинарный файл на одном шаге и собирать docker-образ на другом. Это было немного неудобно и требовало некоторых ухищрений. Давайте посмотрим, как многоступенчатые сборки улучшили ситуацию.




Замечание. Для этого нужен Docker 17.05 или более поздний.




Начнем с простой программы на Go:




package mainimport "fmt"func main() {
fmt.Println("Hello world!")
}




Соберем ее с помощью образа golang:alpine одноступенчатым способом (single-stage build). Вот Dockerfile:




FROM golang:alpine
WORKDIR /app
ADD . /app
RUN cd /app && go build -o goapp
ENTRYPOINT ./goapp




Теперь соберем образ и запустим контейнер:




docker build -t treeder/hello .
docker run --rm treeder/hello




Все работает, но давайте посмотрим на размер с помощью docker images | grep treeder/hello.







258 МБ — многовато для крошечного бинарного файла. Теперь давайте попробуем многоступенчатуюсборку (multi-stage build) с использованием нового Dockerfile:




# стадия сборки
FROM golang:alpine AS build-env
ADD . /src
RUN cd /src && go build -o goapp

# финальная стадия
FROM alpine
WORKDIR /app
COPY --from=build-env /src/goapp /app/
ENTRYPOINT ./goapp




Соберем и запустим снова:




docker build -t treeder/hello .
docker run --rm treeder/hello




Проверим размер:







6,35 МБ — намного лучше.




Что это означает? Что многоступенчатые сборки — отличная вещь. Ими стоит пользоваться практически в любом случае!







Источник: https://medium.com/southbridge/%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%B5%D0%BD%D1%87%D0%B0%D1%82%D0%B0%D1%8F-%D1%81%D0%B1%D0%BE%D1%80%D0%BA%D0%B0-docker-%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2-8b766785f75a



2021-08-18T19:41:17
Software

РУКОВОДСТВО ПО УСТАНОВКЕ JITSI MEET В LINUX

Jitsi Meet — это бесплатное программное обеспечение для видеоконференций с открытым исходным кодом на базе WebRTC, которое работает на Linux, macOS, Windows, iOS и Android. Если вы не доверяете Zoom, вы можете запустить собственную платформу для видеоконференций на собственном сервере. Преимущество Jitsi Meet заключается в том, что все ваши данные передаются только через ваш сервер, а шифрование TLS обеспечивает защиту от перехвата и прослушивания. Это руководство покажет вам, как установить Jitsi Meet на сервер Ubuntu 18.04 и 20.04, а также Debian 10.







ОСОБЕННОСТИ JITSI MEET




  • Совершенно бесплатно
  • Поделитесь экраном своего компьютера с другими (Screensharing)
  • Режим докладчика, который позволяет одновременно использовать экран и камеру
  • Вы можете поделиться системным звуком во время демонстрации экрана
  • Вы можете назначить авторизованных пользователей модераторами. Модератор может отключить звук у каждого участника одним щелчком мыши
  • Связь по сети зашифрована с использованием DTLS-SRTP
  • Сквозное шифрование
  • Вы можете установить пароль для своей конференции, чтобы предотвратить вход случайных незнакомцев
  • Запишите конференцию и сохраните ее в Dropbox
  • Транслируйте на YouTube Live и сохраняйте запись на YouTube
  • Приложения для Android и iOS
  • Текстовый чат
  • Вы можете поделиться текстовым документом
  • Телефонный доступ к конференции
  • Исходящий вызов телефонному абоненту
  • Вы можете встроить вызов Jits Meet на любую веб-страницу с помощью всего нескольких строк кода




СИСТЕМНЫЕ ТРЕБОВАНИЯ




Вам понадобится:




  • Linux сервер и non-root user с привилегиями sudo
  • Доменное имя, указывающее на ваш сервер




ШАГ 1. УСТАНОВИТЕ JITSI MEET ИЗ ОФИЦИАЛЬНОГО РЕПОЗИТОРИЯ ПАКЕТОВ




Jitsi Meet не включен в репозиторий Ubuntu по умолчанию. Мы можем установить его из официального репозитория пакетов Jitsi, который также содержит несколько других полезных программных пакетов. Войдите на свой сервер через SSH, затем выполните следующую команду, чтобы добавить официальный репозиторий Jitsi.




echo 'deb https://download.jitsi.org stable/' | sudo tee /etc/apt/sources.list.d/jitsi-stable.list




Импортируйте открытый ключ Jitsi, чтобы менеджер пакетов APT мог проверять целостность пакетов, загруженных из этого репозитория.




wget -qO -  https://download.jitsi.org/jitsi-key.gpg.key | sudo apt-key add -




Поскольку для репозитория Jitsi требуется HTTPS-соединение, нам нужно установить пакет apt-transport-https, чтобы APT установил HTTPS-соединение с репозиторием Jitsi.




sudo apt install apt-transport-https




Затем обновите локальный индекс пакета и установите Jitsi Meet в Ubuntu.




sudo apt update

sudo apt install jitsi-meet




Во время установки вам необходимо ввести имя хоста для вашего экземпляра Jitsi. Это имя хоста, которое будет отображаться в адресной строке веб-браузера, когда посетители присоединятся к вашей видеоконференции. Вы можете использовать описательное имя хоста, например meet.example.com.







На следующем экране вы можете выбрать создание нового самозаверяющего сертификата TLS (Generate a new self-signed certificate), чтобы позже вы могли получить и установить доверенный сертификат Let’s Encryption.







В процессе установки будут настроены некоторые параметры ядра Linux, которые сохраняются в файле /etc/sysctl.d/20-jvb-udp-buffers.conf. После завершения установки Jitsi Meet автоматически запустится. Вы можете проверить его статус с помощью:




systemctl status jitsi-videobridge2




Пример вывода:




? jitsi-videobridge2.service - Jitsi Videobridge

   Loaded: loaded (/lib/systemd/system/jitsi-videobridge2.service; enabled; vendor preset: enabled)

   Active: active (running) since Fri 2020-04-24 12:11:13 UTC; 3min 27s ago

 Main PID: 3665 (java)

    Tasks: 37 (limit: 65000)

   CGroup: /system.slice/jitsi-videobridge2.service

           L-3665 java -Xmx3072m -XX:+UseConcMarkSweepGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp Dnet.java.sip.communicator.SC_HOME_DIR_LOCATION=/etc/jitsi -Dnet.java.sip.communicator.SC_HO	




Пакет jitsi-meet также извлекал другие пакеты в качестве зависимостей, например




  • openjdk-8-jre-headless: среда выполнения Java. Это необходимо, потому что Jitsi Meet написан на языке Java.
  • jicofo: Jitsi Conference Focus (systemctl status jicofo)
  • prosody: Легкий сервер Jabber / XMPP (systemctl status prosody)
  • coturn: сервер TURN и STUN для VoIP (systemctl status coturn)




ШАГ 2. ОТКРОЙТЕ ПОРТЫ В БРАНДМАУЭРЕ




Jitsi Meet прослушивает несколько портов UDP, что можно увидеть с помощью следующей команды. (Если на вашем сервере Ubuntu нет команды netstat, вы можете запустить команду sudo apt install net-tools, чтобы установить ее.)




sudo netstat -lnptu | grep java







Чтобы участники могли присоединиться к видеоконференции из веб-браузера, вам необходимо открыть TCP-порт 80 и 443. А для передачи видео по сети откройте UDP-порт 10000 и 5000. Если вы используете брандмауэр UFW, запустите следующую команду, чтобы открыть эти порты.




sudo ufw allow 80,443/tcp

sudo ufw allow 10000,5000/udp




ШАГ 3. ПОЛУЧИТЕ ДОВЕРЕННЫЙ СЕРТИФИКАТ LET’S ENCRYPT TLS




Перейдите в службу хостинга DNS (обычно это ваш регистратор домена), чтобы создать запись DNS A для вашего имени хоста Jitsi (meet.example.com). Затем запустите следующий скрипт, чтобы получить доверенный сертификат Let’s Encrypt TLS:




sudo /usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh




Введите свой адрес электронной почты, чтобы получать важные уведомления об учетной записи. Затем он загрузит certbot и получит сертификат TLS.




This script will:

- Need a working DNS record pointing to this machine(for domain jitsi.example.com)

- Download certbot-auto from https://dl.eff.org to /usr/local/sbin

- Install additional dependencies in order to request Let’s Encrypt certificate

- If running with jetty serving web content, will stop Jitsi Videobridge

- Configure and reload nginx or apache2, whichever is used

- Configure the coturn server to use Let's Encrypt certificate and add required deploy hooks

- Add command in weekly cron job to renew certificates regularly



You need to agree to the ACME server's Subscriber Agreement (https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf)

by providing an email address for important account notifications

Enter your email and press [ENTER]:




Если все в порядке, вы увидите следующее сообщение, указывающее, что сертификаты TLS были успешно получены и установлены.







Обратите внимание, что этот сценарий использует запрос http-01, что означает, что ваш веб-сервер Apache или Nginx должен прослушивать порт 80 общедоступного IP-адреса. Если ваша серверная среда не поддерживает вызов http-01, вам не следует запускать приведенный выше сценарий. Вам нужно использовать другие типы задач. В этом случае используем вызов DNS.




sudo certbot --agree-tos -a dns-cloudflare -i nginx --redirect --hsts --staple-ocsp --email me@example.com -d meet.example.com




Где:




  • --agree-tos: примите условия использования.
  • -a dns-cloudflare: используем плагин DNS cloudflare для аутентификации, потому что используем службу Cloudflare DNS.
  • -i nginx: использовать плагин nginx для установки сертификата TLS. Если вы используете Apache, вам необходимо заменить nginx на apache.
  • --redirect: принудительно использовать HTTPS с помощью 301 редиректа.
  • --hsts: добавлять заголовок Strict-Transport-Security к каждому ответу HTTP. Заставить браузер всегда использовать TLS для домена. Защищает от удаления SSL/TLS.
  • --staple-ocsp: включает сшивание OCSP. Допустимый ответ OCSP прикреплен к сертификату, который сервер предлагает во время TLS.




ШАГ 4. ВКЛЮЧИТЕ HTTP2




HTTP2 может улучшить скорость загрузки веб-страницы. Чтобы включить HTTP2 в Nginx, отредактируйте файл конфигурации виртуального хоста.




sudo nano /etc/nginx/sites-enabled/meet.example.com.conf




Найдите следующие две строки.




listen 443 ssl;

listen [::]:443 ssl;




Добавьте http2 в конце каждой строки.




listen 443 ssl http2;

listen [::]:443 ssl http2;




Сохраните и закройте файл. Затем перезагрузите Nginx, чтобы изменения вступили в силу.




sudo systemctl reload nginx




ШАГ 5. НАЧНИТЕ НОВУЮ ОНЛАЙН-ВСТРЕЧУ




Теперь посетите https://meet.example.com, и вы сможете начать конференцию. Для передачи звука вам необходимо разрешить веб-браузеру использовать ваш микрофон. А для передачи видео вам необходимо разрешить веб-браузеру доступ к вашей камере.







Дайте вашей встрече название и нажмите кнопку Go. После начала собрания вы можете при желании установить пароль для собрания.







ШАГ 6. НАСТРОЙТЕ АУТЕНТИФИКАЦИЮ ПОЛЬЗОВАТЕЛЯ




По умолчанию любой может перейти к вашему серверу Jitsi Meet, создать комнату и начать собрание. Чтобы настроить аутентификацию пользователя, отредактируйте файл конфигурации Prosody.




sudo nano /etc/prosody/conf.d/meet.example.com.cfg.lua




Найдите следующую строку.




authentication = "anonymous"




Измените его на следующее, что потребует от пользователя ввода имени пользователя и пароля для начала конференции.




authentication = "internal_plain"




Однако мы не хотим, чтобы участники вводили имя пользователя и пароль при присоединении к конференции, поэтому нам нужно создать анонимный вход для гостей, добавив следующие строки в конец этого файла. Обратите внимание, что вам не нужно создавать запись A DNS для guest.meet.example.com.




VirtualHost "guest.meet.example.com"

    authentication = "anonymous"

    c2s_require_encryption = false




Сохраните и закройте файл. Затем отредактируйте файл конфигурации Jitsi Meet.




sudo nano /etc/jitsi/meet/meet.example.com-config.js




Найдите следующую строку:




// anonymousdomain: 'guest.example.com',




Удалите двойные косые черты и измените гостевой домен. Замените meet.example.com своим настоящим именем хоста Jitsi Meet.




anonymousdomain: 'guest.meet.example.com',




Сохраните и закройте файл. Затем отредактируйте файл конфигурации Jicofo.




sudo nano /etc/jitsi/jicofo/sip-communicator.properties




Добавьте следующую строку в конец этого файла.




org.jitsi.jicofo.auth.URL=XMPP:meet.example.com




Сохраните и закройте файл. Перезапустите службы systemd, чтобы изменения вступили в силу.




sudo systemctl restart jitsi-videobridge2 prosody jicofo




Чтобы создать учетные записи пользователей в Jisi Meet, выполните следующую команду. Вам будет предложено ввести пароль для нового пользователя.




sudo prosodyctl register username meet.example.com




Теперь, если вы создаете комнату в Jitsi Meet, вам нужно будет ввести имя пользователя и пароль.







СОВЕТЫ ПО УСТРАНЕНИЮ НЕПОЛАДОК




Если вы столкнулись с ошибками, вы можете проверить журнал ошибок Nginx (/var/log/nginx/error.log), чтобы узнать, что не так. Также проверьте журналы служб systemd.




sudo journalctl -eu jitsi-videobridge2

sudo journalctl -eu prosody

sudo journalctl -eu jicofo	




Если вы видите ошибку You have been disconnected (Вы были отключены) при запуске собрания в Jitsi, возможно, вы забыли изменить meet.example.com на свое настоящее имя хоста Jitsi Meet в файлах конфигурации.







ОПЦИОНАЛЬНО: НАСТРОИТЬ JIGASI ДЛЯ ТЕЛЕФОННОГО НАБОРА ИЛИ ИСХОДЯЩЕГО ВЫЗОВА




Jitsi предлагает телефонный интерфейс, который позволяет пользователям подключаться к конференции или делать звонки с напоминанием. Установите пакет jigasi (шлюз Jitsi для SIP).




sudo apt install jigasi




Во время установки вам нужно будет ввести свое имя пользователя и пароль SIP. Если у вас его нет, вы можете создать бесплатную учетную запись SIP на сайте OnSIP.com.







Если вы настроили аутентификацию пользователя на шаге 6, вам необходимо отредактировать файл конфигурации Jigasi.




sudo nano /etc/jitsi/jigasi/sip-communicator.properties




Найдите следующие строки.




# org.jitsi.jigasi.xmpp.acc.USER_ID=SOME_USER@SOME_DOMAIN

# org.jitsi.jigasi.xmpp.acc.PASS=SOME_PASS

# org.jitsi.jigasi.xmpp.acc.ANONYMOUS_AUTH=false




Раскомментируйте их и введите учетную запись и пароль, которые вы создали на шаге 6.




org.jitsi.jigasi.xmpp.acc.USER_ID=user1@meet.example.com

org.jitsi.jigasi.xmpp.acc.PASS=user1_password

org.jitsi.jigasi.xmpp.acc.ANONYMOUS_AUTH=false	




Сохраните и закройте файл. Перезапустите службу jigasi systemd.




sudo systemctl restart jigasi




ОПЦИОНАЛЬНО: НАСТРОИТЬ COTURN




Если во время установки Jitsi Meet вы видите следующее сообщение, вам необходимо настроить Coturn, чтобы он работал правильно.




Warning! Could not resolve your external ip address! Error:^

Your turn server will not work till you edit your /etc/turnserver.conf config file.

You need to set your external ip address in external-ip and restart coturn service.




Отредактируйте файл конфигурации Coturn.




sudo nano /etc/turnserver.conf




Найдите следующую строку.




external-ip=127.0.0.1




Замените 127.0.0.1 общедоступным IP-адресом вашего сервера. Сохраните и закройте файл. Затем перезапустите Coturn.




sudo systemctl restart coturn




ИТОГИ




Готово! Мы успешно установили Jitsi Meet на наш Linux сервер.







Источник: https://wiki.merionet.ru/servernye-resheniya/83/rukovodstvo-po-ustanovke-jitsi-meet-v-linux/



2021-08-17T10:26:44
Software

Установка Jitsi Meet в Ubuntu 18.04

Введение




Jitsi Meet — приложение с открытым исходным кодом на базе WebRTC, предназначенное для проведения видеоконференций. Сервер Jitsi Meet создает виртуальные залы для видеоконференций на несколько человек, для доступа к которым требуется только браузер и которые обеспечивают функции, аналогичные Zoom или Skype. Преимущество конференции Jitsi заключается в том, что все ваши данные передаются только через ваш сервер, а комплексное шифрование TLS обеспечивает защиту от перехвата и несанкционированного прослушивания. С Jitsi вы можете быть уверены, что ваша частная информация будет защищена.




В этом обучающем модуле мы установим и настроим сервер Jitsi Meet в Ubuntu 18.04. Конфигурация по умолчанию позволяет любому пользователю создавать новые конференции. Такая настройка не идеальна для общедоступного сервера в Интернете, поэтому мы также настроим Jitsi Meet так, чтобы новые конференции могли создавать только зарегистрированные пользователи. После создания конференции к ней могут присоединиться любые пользователи, если у них есть уникальная ссылка и пароль (если он установлен).




Предварительные требования




Для прохождения этого обучающего руководства вам потребуется следующее:




  • Один сервер Ubuntu 18.04, настроенный в соответствии с инструкциями по начальной настройке сервера с Ubuntu 18.04, а также non-root user с привилегиями sudo. Требуемый размер сервера в основном зависит от доступной пропускной способности и ожидаемого количества пользователей сервера. В следующей таблице примерно показано, что может потребоваться.
  • Доменное имя, настроенное так, чтобы указывать на ваш сервер. Вы можете узнать, как указывать домены на DigitalOcean Droplet, из руководства Настройка имени хоста с помощью DigitalOcean. В этом руководстве используется пример доменного имени jitsi.your-domain.




Если вы выберете сервер для запуска экземпляра Jitsi Meet, вам нужно будет рассмотреть системные ресурсы, требующиеся для хостинга конференций. Следующая информация о тесте собрана на основе одноядерной виртуальной машины с использованием настроек видео высокого качества:




ПроцессорПропускная способность сервера
Два участника3%30 Кбит/с восходящее, 100 Кбит/с нисходящее
Три участника15%7 Мбит/с восходящее, 6,5 Мбит/с нисходящее




Разница в использовании ресурсов между двумя и тремя участниками обусловлена тем, что Jitsi перенаправляет данные вызовов напрямую между клиентами, если их только двое. Если имеется более двух клиентов, данные вызова пересылаются через сервер Jitsi Meet.




Шаг 1 — Настройка имени хоста системы




На этом шаге мы изменим имя хоста системы для соответствия доменного имени, которое вы планируете использовать для своего экземпляра Jitsi Meet, и сопоставим это имя хоста с IP-адресом localhost, 127.0.0.1. Jitsi Meet использует обе эти настройки при установке и генерировании файлов конфигурации.




Вначале установите имя хоста системы на доменное имя, которое вы будете использовать для вашего экземпляра Jitsi. Следующая команда устанавливает имя текущего хоста и изменяет каталог /etc/hostname, где хранится имя хоста системы в промежутке между перезагрузками:




sudo hostnamectl set-hostname jitsi.your-domain




Запущенная команда разбивается на части следующим образом:




  • hostnamectl — это утилита из набора инструментов systemd, предназначенная для правления именем хоста системы.
  • set-hostname устанавливает имя хоста системы.




Для проверки успешного запуска запустите следующую команду:




hostname




Эта команда возвращает имя хоста, заданное командой hostnamectl:




Outputjitsi.your-domain




Далее мы установим локальное сопоставление имени хоста сервера с циклическим IP-адресом, 127.0.0.1. Для этого откройте файл /etc/hosts в текстовом редакторе:




sudo nano /etc/hosts




Затем добавьте следующую строку:/etc/hosts




127.0.0.1 jitsi.your-domain




Сопоставление доменного имени сервера Jitsi Meet с адресом 127.0.0.1 позволяет серверу Jitsi Meet использовать несколько сетевых процессов, устанавливающих локальные соединения друг с другом на IP-адресе 127.0.0.1. Для аутентификации и шифрования этих соединений используется сертификат TLS, зарегистрированный на ваше доменное имя. Локальное сопоставление доменного имени с адресом 127.0.0.1 позволяет использовать сертификат TLS для этих соединений локальной сети.




Сохраните и закройте файл.




Теперь ваш сервер имеет имя хоста, требуемое Jitsi для установки. На следующем шаге мы откроем порты брандмауэра, которые требуются Jitsi и установщику сертификата TLS.




Шаг 2 — Настройка брандмауэра




Выполняя указания руководства Начальная настройка сервера с Ubuntu 18.04, вы включили брандмауэр UFW и открыли порт SSH. Серверу Jitsi требуется открыть несколько портов, чтобы он мог взаимодействовать с вызывающими клиентами. Процессу установки TLS также требуется открыть порт, чтобы можно было провести аутентификацию запроса сертификата.




Открыты будут следующие порты:




  • 80/tcp используется для запроса сертификата TLS.
  • 443/tcp используется для создания веб-страницы конференции.
  • 4443/tcp,10000/udp используется для приема и передачи шифрованного трафика вызова.




Запустите следующие команды ufw, чтобы открыть эти порты:




sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 4443/tcp
sudo ufw allow 10000/udp




Проверьте их добавление с помощью команды ufw status:




sudo ufw status




Если эти порты открыты, вы увидите следующий вывод:




OutputStatus: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
4443/tcp                   ALLOW       Anywhere
10000/udp                  ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)
4443/tcp (v6)              ALLOW       Anywhere (v6)
10000/udp (v6)             ALLOW       Anywhere (v6)




Теперь сервер готов к установке Jitsi, которую мы выполним на следующем шаге.




Шаг 3 — Установка Jitsi Meet




На этом шаге мы добавим стабильный репозиторий Jitsi на ваш сервер, а затем установим пакет Jitsi Meet из этого репозитория. Так вы гарантируете, что всегда будете использовать последний стабильный пакет Jitsi Meet.




Вначале загрузите ключ Jitsi GPG с помощью утилиты загрузки wget:




wget https://download.jitsi.org/jitsi-key.gpg.key




Диспетчер пакетов apt будет использовать этот ключ GPG для проверки пакетов, которые вы будете загружать из репозитория Jitsi.




Затем добавьте загруженный ключ GPG в кольцо ключей apt, используя утилиту apt-key:




sudo apt-key add jitsi-key.gpg.key




Теперь вы можете удалить файл ключа GPG, потому что он больше не требуется:




rm jitsi-key.gpg.key




Теперь мы добавим репозиторий Jitsi на ваш сервер, создав новый файл источника, содержащий репозиторий Jitsi. Откройте и создайте новый файл с помощью редактора:




sudo nano /etc/apt/sources.list.d/jitsi-stable.list




Добавьте эту строку в файл для репозитория Jitsi:/etc/apt/sources.list.d/jitsi-stable.list




deb https://download.jitsi.org stable/




Сохраните файл и закройте редактор.




В заключение проведите обновление системы, чтобы получить список пакетов из репозитория Jitsi, а затем установите пакет jitsi-meet:




sudo apt update
sudo apt install jitsi-meet




Во время установки jitsi-meet вам будет предложено ввести желаемое доменное имя (например, jitsi.your-domain) для вашего экземпляра Jitsi Meet.







Примечание. Вы перемещаете курсор с поля hostname, чтобы выделить кнопку<OK>клавишей TAB. Нажмите ENTER, когда<OK>выделяется для отправки имени хоста.




Затем откроется новое диалоговое окно, где нужно указать, хотите ли вы, чтобы Jitsi создал и использовал самоподписанный сертификат TLS или использовал уже имеющийся сертификат:







Если у вас нет сертификата TLS для вашего домена Jitsi, выберите первую опцию,«Генерировать новый самоподписанный сертификат».




Теперь ваш экземпляр Jitsi Meet установлен с самоподписанным сертификатом TLS. При использовании такого сертификата в браузере будут выводиться предупреждения, поэтому на следующем шаге мы получим подписанный сертификат TLS.




Шаг 4 — Получение подписанного сертификата TLS




Jitsi Meet использует сертификаты TLS для шифрования трафика вызова, чтобы никто не мог прослушивать вызов через Интернет. Сертификаты TLS — это те же сертификаты, которые используются сайтами для активации URL с протоколом HTTPS.




Jitsi Meet предоставляет программу для автоматической загрузки сертификата TLS для вашего доменного имени. Эта программа использует утилиту Certbot. Вам нужно будет установить эту программу до того, как вы запустите скрипт установки сертификата.




Вначале добавьте в систему репозиторий Certbot, чтобы убедиться, что вы используете последнюю версию Certbot. Запустите следующую команду, чтобы добавить новый репозиторий и обновить систему:




sudo add-apt-repository ppa:certbot/certbot




Затем установите пакет certbot:




sudo apt install certbot




Теперь ваш сервер может спокойно запускать программу установки сертификата TLS, предоставленную Jitsi Meet:




sudo /usr/share/jitsi-meet/scripts/install-letsencrypt-cert.sh




При запуске скрипта откроется следующий диалог ввода адреса электронной почты:




Output-------------------------------------------------------------------------
This script will:
- Need a working DNS record pointing to this machine(for domain jitsi.example.com)
- Download certbot-auto from https://dl.eff.org to /usr/local/sbin
- Install additional dependencies in order to request Let’s Encrypt certificate
- If running with jetty serving web content, will stop Jitsi Videobridge
- Configure and reload nginx or apache2, whichever is used
- Configure the coturn server to use Let's Encrypt certificate and add required deploy hooks
- Add command in weekly cron job to renew certificates regularly

You need to agree to the ACME server's Subscriber Agreement (https://letsencrypt.org/documents/LE-SA-v1.1.1-August-1-2016.pdf)
by providing an email address for important account notifications
Enter your email and press [ENTER]:




Этот адрес электронной почты будет отправлен эмитенту сертификата https://letsencrypt.org и будет использоваться для уведомлений о безопасности и других вопросах, связанных с сертификатом TLS. Для продолжения установки необходимо ввести адрес электронной почты. После этого установка продолжится без дальнейших остановок.




После ее завершения ваш экземпляр Jitsi Meet будет настроен для использования подписанного сертификата TLS для вашего доменного имени. Обновление сертификатов также будет производиться автоматически, поскольку программа установки разместила по адресу /etc/cron.weekly/letsencrypt-renew скрипт обновления, который будет запускаться каждую неделю.




Программа установки TLS использовала порт 80 для проверки наличия у вас контроля вашего доменного имени. Теперь вы получили сертификат, и вашему серверу больше не нужно открывать порт 80, потому что порт 80 используется для обычного трафика HTTP без шифрования. Jitsi Meet обслуживает сайт только по протоколу HTTPS через порт 443.




Закройте этот порт в брандмауэре с помощью следующей команды ufw:




sudo ufw delete allow 80/tcp




Теперь ваш сервер Jitsi Meet запущен и готов к тестированию. Откройте браузер и введите свое доменное имя. Вы сможете создать новую конференцию и пригласить других пользователей.




Конфигурация Jitsi Meet по умолчанию разрешает всем посетителям главной страницы вашего сервера Jitsi Meet создавать новые конференции. Для проведения конференции будут использоваться ресурсы вашего сервера, поэтому нежелательно давать такую возможность сторонним пользователям. На следующем шаге мы настроим ваш экземпляр Jitsi Meet так, чтобы конференции могли создавать только зарегистрированные пользователи.




Шаг 5 — Блокировка создания конференций




На следующем шаге мы настроим ваш сервер Jitsi Meet так, чтобы конференции могли создавать только зарегистрированные пользователи. Мы отредактируем файлы, котоыре были сгенерированы программой установки и настроены с использованием вашего доменного имени.




В следующих примерах мы будем использовать переменную your_domain вместо доменного имени.




Откройте sudo nano /etc/prosody/conf.avail/your_domain.cfg.lua в текстовом редакторе:




sudo nano /etc/prosody/conf.avail/your_domain.cfg.lua




Отредактируйте эту строку:/etc/prosody/conf.avail/your_domain.cfg.lua




...
        authentication = "anonymous"
...




Следующим образом:/etc/prosody/conf.avail/your_domain.cfg.lua




...
        authentication = "internal_plain"
...




Эта конфигурация предписывает Jitsi Meet использовать аутентификацию с именем пользователя и паролем, прежде чем разрешить новому посетителю создавать конференции.




Затем добавьте в конец файла следующий раздел:/etc/prosody/conf.avail/your_domain.cfg.lua




...
VirtualHost "guest.your_domain"
    authentication = "anonymous"
    c2s_require_encryption = false




Эта конфигурация позволяет анонимным пользователям присоединяться к конференциям, созданным пользователем, прошедшим аутентификацию. Однако для входа у гостя должен иметься уникальный адрес и пароль конференции (если этот пароль задан).




Здесь вы добавили guest. перед доменным именем. Например, для jitsi.your-domain мы указываем put guest.jitsi.your-domain. Имя хоста guest.обычно используется Jitsi Meet для внутренних целей. Это имя не вводится в браузер, и не надо создавать для него запись DNS.




Откройте другой файл конфигурации по адресу /etc/jitsi/meet/your_domain-config.js в текстовом редакторе:




sudo nano /etc/jitsi/meet/your_domain-config.js




Отредактируйте эту строку:/etc/jitsi/meet/your_domain-config.js




...
        // anonymousdomain: 'guest.example.com',
...




Следующим образом:/etc/jitsi/meet/your_domain-config.js




...
        anonymousdomain: 'guest.your_domain',
...




Если вы используете имя хоста guest.your_domain, которое мы использовали ранее, эта конфигурация укажет Jitsi Meet, какое внутреннее имя хоста следует использовать для гостей, не прошедших аутентификацию.




Затем откройте /etc/jitsi/jicofo/sip-communicator.properties:




sudo nano /etc/jitsi/jicofo/sip-communicator.properties




Добавьте следующую строку для завершения изменений конфигурации:/etc/jitsi/jicofo/sip-communicator.properties




org.jitsi.jicofo.auth.URL=XMPP:your_domain




Эта конфигурация перенаправляет процессы Jitsi Meet на локальный сервер, который выполняет аутентификацию пользователя, которая теперь обязательна.




Ваш экземпляр Jitsi Meet теперь настроен, и конференции могут создавать только зарегистрированные пользователи. После создания конференции к ней может присоединиться кто угодно без регистрации. Для этого им потребуется уникальный адрес конференции и пароль, если он задан создателем конференции.




Мы настроили Jitsi Meet так, чтобы требовать аутентификацию пользователей при создании конференций, и теперь вам нужно зарегистрировать этих пользователей и их пароли. Для этого мы используем утилиту prosodyctl.




Запустите следующую команду, чтобы добавить на сервер пользователя:




sudo prosodyctl register user your_domain password




Добавляемый здесь пользователь не является системным пользователем. Этот пользователь сможет только создать конференцию, но не сможет войти на ваш сервер через SSH.




Перезапустите процессы Jitsi Meet для загрузки новой конфигурации:




sudo systemctl restart prosody.service
sudo systemctl restart jicofo.service
sudo systemctl restart jitsi-videobridge2.service




Теперь экземпляр Jitsi Meet будет требовать ввести имя пользователя и пароль в диалоге при создании конференции.







Теперь ваш сервер Jitsi Meet настроен и имеет защищенную конфигурацию.




Заключение




В этой статье мы рассказали о развертывании сервера Jitsi Meet, который вы можете использовать для хостинга защищенных частных видеоконференций. Теперь вы можете дополнить свой экземпляр Jitsi Meet инструкциями из Jitsi Meet Wiki.



2021-08-17T10:04:48
Software

Платформа для проведения видеоконференций BigBlueButton. Установка

У всех нас может возникнуть потребность в проведении видеоконференции. Цели могут быть разные: совещание, обучение, а быть может и просто чтобы поболтать с друзьями.




Инструментов для таких задач сейчас представлено немало, но в рамках этой статьи хотелось бы остановиться именно на BigBlueButton. Главная идея при разработке данной платформы — «Она должна быть проста в использовании как большая синяя кнопка».




В данной статье мы поговорим о том, как установить BigBlueButton, в конце лежит ссылочка на интерактив.




Кому интересен данный вопрос — добро пожаловать под кат.




▍ Системные требования




На момент написания данной статьи версия BigBlueButton 2.3 является самой свежей. Посмотрим минимальные системные требования для сервера в документации к BBB:







Если Вы устанавливаете BigBlueButton для локальной разработки на рабочей станции, Вы можете пренебречь некоторыми требованиями, поскольку к серверу будет подключаться лишь несколько клиентов. Ориентируясь на требования выше, Вы можете понизить их следующим образом:







Вне зависимости от конфигурации оборудования, на сервер нужно будет установить SSL-сертификат. Причина в следующем: чтобы пользователи могли делиться аудио- и видеопотоками со своих компьютеров, все браузеры требуют валидный SSL-сертификат, дабы дать доступ к веб-камере и микрофону пользователя через WebRTC. Если подключаться к BigBlueButton только по IP-адресу, то браузеры заблокируют клиенту BBB доступ к веб-камере и микрофону.




▍ Заказ сервера




Для начала нам нужен сервер для размещения на нём BigBlueButton. На случай если он уже имеется — пролистайте до следующего раздела.




Разберём заказ сервера на примере RUVDS.




Переходим на сайт RUVDS.
Нажимаем на «Выбрать VPS».







В разделе «Своя конфигурация» нажимаем на «Собрать».







В появившейся форме заполняем данные для входа в аккаунт RUVDS и нажимаем «Войти». Если же аккаунта нет, нажимаем «Регистрация». Мы предполагаем, что аккаунт уже есть.







Выбираем из списка нужный дата-центр.







Пролистываем чуть ниже и выбираем нужную конфигурацию сервера. Напомним, что если сервер нужен для проведения видеоконференций, то необходимо 8 ядер CPU и 16 ГБ RAM. Если же на нём предполагается разработка, то будет достаточно 4 ядер и 8 ГБ соответственно.
В случае, если предполагается запись видеоконференций, объём диска должен быть не менее 500 ГБ. Если же не предполагается, то достаточно 100 ГБ; будет с небольшим запасом.
В качестве шаблона сервера выбираем «Docker CE — Ubuntu 18.04».
Затем выбираем необходимый срок аренды сервера.







Пролистав ещё чуть ниже, соглашаемся с условием публичной оферты, предоставляем согласие на обработку персональных данных, а затем нажимаем кнопку «Оплатить».







Появится форма выбора метода оплаты. Выбираем наиболее удобный и проходим через процедуру платежа.







После успешной оплаты появится соответствующее сообщение.
Нажимаем на кнопку «Мои сервера»




Появится список, содержащий только что заказанный сервер. Все необходимые данные для подключения (IP-адрес, user, password) будут находиться в соответствующих полях.










▍ Привязка доменного имени к серверу




Для корректной работы и получения SSL-сертификата, к серверу должно быть привязано доменное имя. Если оно уже привязано — пролистайте до следующего раздела.




Инструкция по привязке доменного имени на примере регистратора reg.ru




Привязка доменного имени к серверу на примере бесплатного сервиса freenom.com




Заходим на сайт freenom.com, вводим желаемое доменное имя и нажимаем на кнопку «Проверить доступность».







Далее нажимаем «Оформить заказ».







Затем кликаем «Use DNS».







В появившихся полях выбираем срок предоставления доменного имени, IP-адрес сервера и нажимаем кнопку «Continue».







В появившейся форме вводим валидный адрес электронной почты и нажимаем «Verify My Email Address».







Проверяем входящую почту на предмет пришедшего письма от Freenom. В пришедшем письме переходим по ссылке валидации.







В открывшейся форме заполняем поля.







После заполнения формы ставим флажок, соглашаясь с условиями, и нажимаем на «Complete Order».







Появление сообщения о подтверждении заказа свидетельствует, что процедура прошла успешно.







Потребуется некоторое время, пока обновленная информация о доменных записях распространится между другими DNS-серверами. Это может занять до 24 часов.




▍ Подготовка и проверка перед установкой




Итак, у нас есть сервер с 64-битным Ubuntu версии 18.04, с привязанным доменным именем. Перед тем как приступать непосредственно к инсталляции, проведём несколько проверок, чтобы убедиться, что сервер соответствует минимальным требованиям.
Проведение этих проверок сильно уменьшает шансы столкнуться с проблемами в процессе установки.
Также, установим необходимые пакеты и обновим сервер.




Подключимся к серверу по SSH. Инструкцию для пользователей Windows можно найти здесь.




Также, если мы подключаемся под пользователем root, то префиксы команд sudo везде ниже не нужны.




В первую очередь обновим сервер:




sudo apt update
sudo apt dist-upgrade




Затем установим пакет gnupg:




sudo apt install gnupg




Убедимся, что локаль сервера — en_US.UTF-8:




$ cat /etc/default/locale
LANG="en_US.UTF-8"




Если локаль отличается от en_US.UTF-8, наберём несколько команд, чтобы это исправить:




$ sudo apt-get install -y language-pack-en
$ sudo update-locale LANG=en_US.UTF-8"




Затем нужно выйти из SSH-сессии и зайти снова, это перезагрузит настройки локали для сессии.
Наберём команду cat /etc/default/locale. Необходимо убедиться, что есть только одна строка LANG=«en_US.UTF-8».




Если Вы видите ещё одну строку LC_ALL=en_US.UTF-8, уберите её из /etc/default/locale, после чего завершите SSH-сессию и откройте её снова.




Далее, выполняем команду sudo systemctl show-environment и убеждаемся, что видим LANG=en_US.UTF-8:




$ sudo systemctl show-environment
LANG=en_US.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin




Если LANG=en_US.UTF-8 нет, то выполняем команду sudo systemctl set-environment LANG=en_US.UTF-8, а затем ещё раз выполняем sudo systemctl show-environment, чтобы убедиться, что в выводных данных LANG=en_US.UTF-8




Затем убедимся, что на сервере есть 16 ГБ оперативной памяти при помощи команды free -h. Выводные данные должны быть примерно такими:




$ free -h
              total        used        free      shared  buff/cache   available
Mem:            15G        3.1G        1.0G        305M         11G         12G
Swap:            0B          0B          0B




Если в строке Mem в столбце total менее 15G, то серверу недостаточно памяти для запуска BigBlueButton в боевом режиме, и необходимо увеличить количество памяти хотя бы до 16G. Впрочем, если Вы планируете использовать сервер для задач разработки, 8G будет достаточно.




Далее, убедимся, что на сервер установлена Ubuntu 18.04:




$  cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.5 LTS"




Удостоверимся, что запущена 64-разрядная версия Ubuntu:




$ uname -m
x86_64




Далее, проверим, что сервер поддерживает IPv6:




$ ip addr | grep inet6
inet6 ::1/128 scope host
...




Если нет строки inet6 ::1/128 scope host, то после установки BigBlueButton нужно будет внести изменения в настройки FreeSWITCH, чтобы отключить поддержку IPv6.




Следующим шагом убедимся, что сервер запущен на ядре Linux v.4.x:




$ uname -r
4.15.0-NNN-generic




Далее, проверим, что у сервера есть минимум 8 ядер. Напоминаем, что для задач разработки достаточно 4 ядра:




$ cat /proc/cpuinfo | awk '/^processor/{print $3}' | wc -l
8




Итак, мы закончили предустановочные проверки и настройки. Следующий шаг — непосредственно установка BigBlueButton.




▍ Установка BigBlueButton




Установка BigBlueButton производится скриптом bbb-install.sh. Данная ссылка содержит подробную информацию по использованию данного скрипта.




Как пример, команда ниже устанавливает BigBlueButton 2.3, используя имя хоста bbb-test.cf и адрес электронной почты (для Let’s Encrypt) notice@example.com. Она устанавливает (или обновляет, если команда перезапущена позже) последнюю версию BigBlueButton 2.3 при помощи опции -v bionic-230. Также, она устанавливает демо-API (-a) и сетевой экран (-w)




wget -qO- https://ubuntu.bigbluebutton.org/bbb-install.sh | bash -s -- -v bionic-230 -s bbb-test.cf -e notice@example.com  -a -w




Перед выполнением команды замените электронную почту notice@example.com на валидную.




После того как скрипт bbb-install.sh закончит свою работу, можно проверить состояние сервера командой bbb-conf —check.




Результат будет примерно таким:




$ sudo bbb-conf --check

BigBlueButton Server 2.3.10 (2419)

                    Kernel version: 4.15.0-153-generic

                      Distribution: Ubuntu 18.04.5 LTS (64-bit)

                            Memory: 16414 MB

                         CPU cores: 8



/etc/bigbluebutton/bbb-web.properties (override for bbb-web)

/usr/share/bbb-web/WEB-INF/classes/bigbluebutton.properties (bbb-web)

       bigbluebutton.web.serverURL: https://bbb-test.cf

                defaultGuestPolicy: ALWAYS_ACCEPT

                 svgImagesRequired: true



/etc/nginx/sites-available/bigbluebutton (nginx)

                       server_name: bbb-test.cf

                              port: 80, [::]:80

                              port: 443 ssl



/opt/freeswitch/etc/freeswitch/vars.xml (FreeSWITCH)

                       local_ip_v4: 193.108.114.47

                   external_rtp_ip: 193.108.114.47

                   external_sip_ip: 193.108.114.47



/opt/freeswitch/etc/freeswitch/sip_profiles/external.xml (FreeSWITCH)

                        ext-rtp-ip: $${local_ip_v4}

                        ext-sip-ip: $${local_ip_v4}

                        ws-binding: 193.108.114.47:5066

                       wss-binding: 193.108.114.47:7443



/usr/local/bigbluebutton/core/scripts/bigbluebutton.yml (record and playback)

                     playback_host: bbb-test.cf

                 playback_protocol: https

                            ffmpeg: 4.2.4-1ubuntu0.1bbb2~18.04



/etc/bigbluebutton/nginx/sip.nginx (sip.nginx)

                        proxy_pass: 193.108.114.47

                          protocol: http



/usr/local/bigbluebutton/bbb-webrtc-sfu/config/default.yml (Kurento SFU)

                        kurento.ip: 193.108.114.47

                       kurento.url: ws://127.0.0.1:8888/kurento

                    kurento.sip_ip: 193.108.114.47

                    localIpAddress: 193.108.114.47

               recordScreenSharing: true

                     recordWebcams: true

                  codec_video_main: VP8

               codec_video_content: VP8



/usr/share/meteor/bundle/programs/server/assets/app/config/settings.yml (HTML5 client)

                             build: 1829

                        kurentoUrl: wss://bbb-test.cf/bbb-webrtc-sfu

                  enableListenOnly: true

                    sipjsHackViaWs: true



/usr/share/bbb-web/WEB-INF/classes/spring/turn-stun-servers.xml (STUN Server)

                              stun: stun.l.google.com:19302





# Potential problems described below

..........................

# Warning: The API demos are installed and accessible from:

#

#    https://bbb-test.cf

#

# and

#

#    https://bbb-test.cf/demo/demo1.jsp

#

# These API demos allow anyone to access your server without authentication

# to create/manage meetings and recordings. They are for testing purposes only.

# If you are running a production system, remove them by running:

#

#    apt-get purge bbb-demo




Также, можно использовать команду sudo bbb-conf —status чтобы проверить все ли процессы BigBlueButton стартовали и работают.




Примерный результат:




nginx —————————————————► [ - active]

freeswitch ————————————► [ - active]

redis-server ——————————► [ - active]

bbb-apps-akka —————————► [ - active]

bbb-fsesl-akka ————————► [ - active]

tomcat8 ———————————————► [ - active]

mongod ————————————————► [ - active]

bbb-html5 —————————————► [ - active]

bbb-webrtc-sfu ————————► [ - active]

kurento-media-server ——► [ - active]

bbb-html5-backend@1 ———► [ - active]

bbb-html5-backend@2 ———► [ - active]

bbb-html5-frontend@1 ——► [ - active]

bbb-html5-frontend@2 ——► [ - active]

etherpad ——————————————► [ - active]

bbb-web ———————————————► [ - active]




▍ Итог




Итак, мы рассмотрели системные требования к BigBlueButton, выполнили предустановочные операции и провели установку продукта.
Перейдём по ссылке bbb-test.cf и посмотрим что мы получили в итоге.




Появится приветственное меню. Введём в поле ввода своё имя и нажмём «Join»:







Затем давайте попробуем включить микрофон в конференции:







Разрешаем доступ к микрофону:







Нажимаем на «Да», если наш голос слышен, или на «Нет» в противном случае:







Итак, открылась сама конференция:







В ней уже можно проводить собрания, несмотря на то, что это API — демонстрационное.
Если потребуется разработать что-либо на базе BigBlueButton, продукт обладает обширной документацией, что здорово поможет в деле.




Ну что же, пора и завершаться. Стабильной работы оборудования и приятных конференций!







Источник: https://habr.com/ru/company/ruvds/blog/570804/



2021-08-17T09:56:14
Software