Xây dựng Loadbalancer cho các server MySQL với HAproxy trên Ubuntu

Mô hình :

1 - Load Balancer
Hostname: haproxy 
OS: Ubuntu server 16.04
Private IP: 172.17.3.102

2 - Node 1
Hostname: mysql-1 
OS: Ubuntu server 16.04 
Private IP: 172.17.3.103

3 - Node 2 
Hostname: mysql-2 
OS: Ubuntu server 16.04 
Private IP: 172.17.3.104

Cấu hình :

Chuẩn bị các node database server :

Tiến hành cài đặt MySQL lần lượt trên các node :

[email protected]:~$ sudo apt-get install mysql

Sau khi cài đặt, tiến hành chỉnh sửa file mysql.cnf trong đường dẫn /etc/mysql/mysql.conf.d/ (Lưu ý là các OS khác như CenOS thì đường dẫn có thể khác nhé !) Dùng bất kỳ trình editor nào trên linux mà bạn thích để thao tác, ở đây mình dùng nano. Sau khi mở file lên, tiến hành edit 2 dòng như sau :

  • Comment hoặc xóa dòng blind-address = 127.0.0.1, commend bằng cách thêm dấu # vào phía trước . - Thực hiện tương tự trên cả 2 máy MySQL server nhé. Mục đích của việc này là để cho user login local được . Chuẩn bị cho việc test thôi, nếu ai không bị ảnh hưởng thì bỏ qua nhé.
  • Bỏ Comment dòng server-id = 1 và lần lượt cho cái giá trị ID mà mình mong muốn trên mỗi server MySQL. Ở đây mình cho ID lần lượt là 1 và 2 tương ứng với 2 máy mysql-1mysql-2 . Mục đích của bước này chỉ dùng để test. Ai có cách test khác thì cứ sử dụng nhé, ko nhất thiết phải làm theo mình đâu ^^.

Sau khi edit thì restart MySQL nhé : sudo service mysql restart

Tiếp theo là tiến hành tạo User để connect với HAproxy. Trên mỗi node database cần tạo 2 user. 1 dùng cho HAproxy check status và 1 dùng connect sử dụng. Username và password nên tạo như nhau ở cả 2 server vì trên thực tế sử dụng thì 2 node database này sẽ đồng bộ với nhau.

User thứ nhất

mysql > Inser into mysql.user (Host,User,ssl_cipher,x509_issuer,x509_subject) values ('IP_HAproxy','USER','abc','abc','abc');

Lưu ý : trường Host thì các bạn điền IP của HAproxy vào nhé,còn user thì thích điền gì thì điền. Ví dụ : mysql > Inser into mysql.user (Host,User,ssl_cipher,x509_issuer,x509_subject) values ('172.17.3.102','haproxy_checkstatus','abc','abc','abc');

Vì lý do chả hiểu sao mình tạo user với 2 trường (Host,User) thì nó lại trả về kết quả kêu 3 thằngssl_cipher,x509_issuer,x509_subject kia không được null. Thế là mình gán luôn giá trị cho 3 thằng đó. Cao nhân nào biết chỗ này tại sao thì comment hướng dẫn mình với nghen 😦.

User thứ hai Tạo và gắn full quyền luôn.

mysql > GRANT ALL PRIVILEGES ON *.* TO 'USER'@'IP_HAproxy' IDENTIFIED BY 'PASSWORD' WITH GRANT OPTION; 

Lưu ý Các trường USER ,IP_HAproxyPASSWORD các bạn tự điền nhé. Ví dụ: mysql > GRANT ALL PRIVILEGES ON *.* TO 'super'@'172.17.3.102' IDENTIFIED BY '12345' WITH GRANT OPTION; Sau khi tạo xong thì chạy mysql > FLUSH PRIVILEGES; cho Mysql cập nhật nhé.

Lần lượt làm tương tự trên cả 2 máy MySQL nhé. Sau khi chuẩn bị xong, các bạn có thể check kết quả các bước trên như sau :

Xem các user đã tạo :

mysql> select user from mysql.user;
+------------------+
| user             |
+------------------+
| super     |
| haproxy_checkstatus|
| debian-sys-maint |
| mysql.sys        |
| root             |
+------------------+

Xem server_ID đã gán

mysql> show variables like 'server_id';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 1     |
+---------------+-------+

Config HAproxy :

Install HAproxy : sudo apt-get install haproxy Khởi động HAproxy : sudo service haproxy star Config : sudo nano /etc/haproxy/haproxy.cfg Nội dung file config như sau :

global
        log 127.0.0.1 local0 notice
        user haproxy
        group haproxy
        maxconn 256
        daemon
    defaults
        log global
        retries 2
        timeout connect 5000ms
        timeout client  50000ms
        timeout server  50000ms

    listen mysql-cluster
        bind 172.17.3.102:3306
        mode tcp
        option mysql-check user haproxy_checkstatus

        balance roundrobin
            server mysql-1 172.17.3.103:3306 check
            server mysql-2 172.17.3.104:3306 check


Các cần lưu ý phần khai báo này nhé :

listen mysql-cluster
        bind 172.17.3.102:3306
        mode tcp
        option mysql-check user haproxy_checkstatus

Khai báo cho HAproxy listen mysql-cluster ( cụm database server) trên ip 172.17.3.102:3306 của HAproxy port mặc định của MySQL là 3306 - Khai báo này giúp cho chúng ta có thể truy cập đến các server MySQL thông qua HAproxy Tùy chọn option hỗ trợ chúng ta theo dõi tình trạng của các node tham gia vào cùng một Loadbalancing của HAproxy . Với MySQL, HAproxy có hỗ trợ tùy chọn mysql-check với khai báo user tương ứng đã tạo ở trên. Các bạn có thể tham khảo thêm các option của HAproxy tại haproxy.org

Tiếp theo là khai báo cân bằng tải cho các server MySQL.


        balance roundrobin
            server sql1 172.17.3.103:3306 check
            server sql2 172.17.3.104:3306 check

Test :

Sau khi đã hoàn thành các bước trên. Các bạn tiến hành test như sau : dùng một máy khác cài đặt mysql-client và connect vào cụm database thông qua HAproxy.

[email protected]hungdhm-Inspiron:~$ mysql -h 172.17.3.102 -u super -p

Connect thành công, tiến hành kiểm tra xem đang connect vào Node data nào nhé :

mysql> show variables like 'server_id';
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    3348
Current database: *** NONE ***

+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 1     |
+---------------+-------+
1 row in set (0.01 sec)


Đang connect vào Node mysql-1 với ID khi nãy gán là 1. Giờ thoát ra và connect lại và kiểm tra để thấy sự khác biệt .

mysql> show variables like 'server_id';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 2     |
+---------------+-------+
1 row in set (0.01 sec)


Sau khi thoát ra và connect lại thì chúng ta đã connect được vào Node mysql-2 với ID là 2.

Kết luận:

Trong phần này chúng ta đã xây dựng được một loadbalancer có nhiệm vụ cân bằng tải cho các Node database. Ở phần tiếp theo của bài viết, mình sẽ tiếp tục thực hiện việc đồng bộ các node data với nhau và tích hợp luôn cả Keepalived để tăng tính chịu lỗi cho cả mô hình 😃