Published on

Cấu hình remote database cho WordOps / EasyEngine

Authors

Hiện tại có một dịch vụ khác mang tên TiDB còn miễn phí "hơn", giúp bạn có thể tối ưu được tài nguyên của server mà cũng giảm luôn thời gian và công sức quản lý server database: Sử dụng MySQL server miễn phí với TiDB Cloud

Trong thời gian sử dụng gói AWS Free Tier, mình hay băn khoăn nếu chúng ta có thể tận dụng càng nhiều càng tốt những dịch vụ miễn phí đi kèm thay vì chỉ sử dụng EC2 hay không. AWS có hàng tá các dịch vụ mà chúng ta hay bỏ qua nhưng cực kì hữu dụng, trong đó có RDS hay ElasticCache.

Tại sao nên sử dụng remote database

Kiến trúc một (hay nhiều) website sử dụng 2 máy chủ: một máy chủ để chạy webserver như Apache, Nginx và một máy chủ còn lại sử dụng làm database server chạy MySQL, MariaDB đã trở nên rất phổ biến và là một kiến trúc cơ bản các bạn cần xem qua nếu muốn có một ứng dụng hiệu suất cao. Việc phân tách thành hai server khác nhau giúp chúng ta đạt được hai yếu tố quan trọng, đó là bảo mậttốc độ.

true

Ảnh DigitalOcean.com

Vì không còn MySQL server nặng nề chạy cùng nữa nên web server có nhiều tài nguyên để tận dụng hơn, nhất là bộ nhớ RAM. Đây cũng là một cách thông minh để giảm chi phí hàng tháng mà vẫn nhận được cấu hình tương đương, thậm chí hơn.

Việc tách riêng giữa app và database server sau này giúp ta dễ dàng hơn trong việc mở rộng theo chiều ngang nơi mà chúng ta sẽ thêm server, VPS vào một pool ảo thay vì nâng cấp cấu hình của server hiện tại (mở rộng theo chiều dọc). Sau này nếu có điều kiện hơn, chúng ta còn có thể triển khai mô hình 3-tier vào. Tuy nhiên đó là một chủ đề khác dành cho một bài viết khác, mời anh em tiếp tục chủ đề hôm nay.

Ví dụ ở Vultr, 5$/tháng bạn sẽ có 1 CPU core và 1GB RAM, tuy nhiên, 10$/tháng bạn vẫn chỉ có 1 CPU core và 2GB RAM. Vì vậy việc chạy 2 máy chủ 5$ sẽ nhận được mức cấu hình tổng cộng 2 CPU core, 2GB RAM, tốt hơn việc bỏ ra 10$/tháng.

Ngoài ra, chúng ta có thể tăng cường thêm một chút bảo mật bằng việc giới hạn chỉ có web server mới được kết nối vào database server. Điều này một phần nào đó giúp database server nằm ngoài những con mắt tò mò của hacker.


Kết nối hai server cùng VPC với AWS

Thật ra với AWS mọi chuyện rất đơn giản, bạn chỉ việc tạo các instance cùng một VPC (và nên cùng một subnet) là đã có một mạng ảo sẵn rồi. Tương tự như vậy, khi tạo RDS instance, bạn cũng cho instance này cùng một VPC là được, sau đó kết nối từ EC2 bằng hostname được cung cấp.


Kết nối hai server cùng Private network với Vultr

Để kết nối hai máy chủ ở Vultr với nhau, chúng ta sẽ sử dụng tính năng Private network có chức năng tạo một mạng LAN ảo giữa các server với nhau. Việc này giúp tốc độ kết nối giữa các máy chủ luôn được cao nhất, latency thấp nhất và không phải expose (phơi bày) các kết nối giữa các server ra mạng public bên ngoài để đảm bảo bảo mật.

https://www.youtube.com/watch?v=5CJ_NkczfEg 🔗

Lưu ý: Tính năng Private network yêu cầu tất cả các server muốn join network phải đặt ở cùng location để đảm bảo tốc độ tốt nhất.

Hiện tại tính năng Private network của Vultr đang miễn phí hoàn toàn và tính năng này cũng có trên rất nhiều nhà cung cấp khác như Digital Ocean, Linode,...

Tạo Private network trên Vultr

Bạn hãy truy cập vào trang quản trị Vultr và bấm vào tab Network, bấm vào nút Add network để thêm network mới. Vultr hiện tại đang miễn phí việc tạo và sử dụng Private network, tuy nhiên đang giới hạn 5 network ở mỗi location.

true

  • Location: bạn hãy chọn location mà dự định sẽ tạo server.
  • Description: điền gì cũng được, để bạn dễ phân biệt giữa các Private network khác nhau. Mình thì hay dùng tên dự án + VPC (Virtual Private Cloud).
  • Network: nếu bạn không rành về mạng, bạn nên thay đổi thành 10.99.0.0/20 để giống với tài liệu chính thức 🔗 của Vultr hoặc 10.0.0.0/24 để giống video mình hướng dẫn, hoặc cứ để nguyên, cũng không có khó khăn gì ở phần sau đâu.

Sau đó nhấn Add network là bạn đã tạo thành công một Private network cho bạn rồi.

Kết nối Private network vào server của bạn

Hãy lần lượt nhấn vào từng server để tiếp tục kết nối vào Private network. Ở đây mình tạo sẵn 2 server là appserverdbserver ứng với từng chức năng của nó.

true

Chuyển sang tab Settings, trong danh sách Private network sẽ hiện ra network mà mình vừa tạo khi nãy, chọn vào và nhấn Attach network. Bạn phải làm bước này (attach) với tất cả server mà bạn dự định cho vào cùng Private network. Lưu ý khi nhấn Attach network thì server của bạn cũng sẽ tự động restart để nhận mạng mới.

true

Cấu hình Private network cho Ubuntu 18.x trở lên

Vì Ubuntu 18.x trở lên đã chuyển sang sử dụng netplan nên việc cấu hình có đôi chút yêu cầu hơn so với các phiên bản khác. Hãy kết nối vào cả hai server và thực hiện lần lượt trên từng server gõ lệnh sau:

vi /etc/netplan/10-ens7.yaml

Và chèn vào nội dung như bên dưới:

network:
   version: 2
   renderer: networkd
   ethernets:
     ens7:
       match:
         macaddress: **01:23:45:67:89:ab**
       mtu: 1450
       dhcp4: no
       addresses: \[**10.0.0.200**/24\]

Lưu ý nhớ đổi 10.99.0 thành 10.0.0 như trong video mình gửi nhé. Số 200 sau cùng là địa chỉ LAN IP của từng server của bạn. Ví dụ mình đặt cho database server là 10.0.0.200/24 và app server là 10.0.0.100/24 để dễ phân biệt.

Đối với Ubuntu 18.xx trở lên, bạn còn phải cung cấp địa chỉ MAC, có thể tìm thấy trong Server > Settings > Private network.

Sau khi đã thay đổi xong, bạn có thể nhập câu lệnh netplan apply để xác nhận cấu hình, vậy là xong.

Cấu hình Private network cho Ubuntu 16.xx

Với Ubuntu 16.xx, hãy gõ lệnh bên dưới và chèn vào nội dung tương ứng.

vi /etc/network/interfaces
auto ens7
 iface ens7 inet static
     address **10.0.0**.200
     netmask 255.255.0.0
     mtu 1450

Chỉnh sửa địa chỉ IP tĩnh theo ý bạn muốn, sau đó lưu lại và nhấn ifup ens7 để xác nhận cấu hình mạng.

Cấu hình Private network cho CentOS 6/7

Hãy gõ lệnh bên dưới, chèn vào nội dung tương ứng và nhớ chỉnh sửa cho phù hợp.

vi /etc/sysconfig/network-scripts/ifcfg-eth1
 DEVICE=eth1
 ONBOOT=yes
 NM_CONTROLLED=no
 BOOTPROTO=static
 IPADDR=**10.0.0**.200
 NETMASK=255.255.0.0
 IPV6INIT=no
 MTU=1450

Chỉnh sửa địa chỉ IP tĩnh theo ý bạn muốn, sau đó lưu lại và nhấn ifup ens7 để xác nhận cấu hình mạng.

Kiểm tra thử kết nối giữa hai server

Sau khi đã kết nối 2 server với nhau, cách dễ nhất bạn có thể kiểm tra nó được kết nối chưa là ping địa chỉ IP của máy kia, vậy là xong. Mình cũng có thử dùng iperf để tính toán tốc độ truyền tải của 2 server nhau và cho kết quả khá ấn tượng trên Vultr. Đặc biệt là dung lượng truyền tải giữa Private network không bị tính vào tổng dung lượng tối đa trong tháng mà là unlimited nhé.

true

true


Cấu hình remote database với WordOps và EasyEngine

Hiện tại, để cấu hình WordOps có thể sử dụng remote database, chúng ta phải làm một số bước nhất định. Việc này tốt nhất nên được thực hiện ở server mới hoàn toàn và chưa cài đặt WordOps, như vậy sẽ tốt hơn. Nếu bạn đang có website đang chạy? Hãy backup và restore sau khi thực hiện xong bài viết này. Dưới đây là danh sách tóm tắt các bước mình sẽ hướng dẫn:

  1. Cài đặt WordOps.
  2. Cài đặt mysql-client và chuyển kết nối sang remote database.
  3. Chỉnh sửa mã nguồn WordOps (tùy chọn) và build lại WordOps.
  4. Xong.

Đầu tiên, hãy tiến hành cài đặt MySQL trên dbserver trước khi cài WordOps trên appserver bạn nhé.

Bước 1. Cấu hình dbserver

Bây giờ chúng ta bắt đầu bước cấu hình database server nha. Ở đây bạn có nhiều sự lựa chọn, sử dụng RDS của AWS, tự cài đặt MySQL trên server. Trên dbserver, bạn không cần cài đặt WordOps, chỉ cần cấu hình như một server database bình thường thôi.

AWS

Hãy chắc chắn rằng appserver của bạn có thể kết nối tới dbserver bằng cách gõ câu lệnh telnet trên appserver. Nếu không hãy kiểm tra lại security group của dbserver (RDS) và appserver (EC2) bạn vừa tạo. Lưu ý:

  • Nhớ thay dòng in đậm thành hostname/IP của dbserver của bạn.
  • Nên sử dụng private IP thay vì public IP.
  • Dùng web Port check 🔗 để chắc chắn rằng MySQL không mở public từ public IP.
root@appserver:~$ apt update && apt install telnet
root@appserver:~$ telnet **wordops-db.cgp414qdscum.ap-southeast-1.rds.amazonaws.com** 3306
N
5.7.28-log7,g d���2-/'F3P-\*)5mysql_native_password

Nếu trong phần kết quả trả về có phiên bản MySQL hoặc dòng chữ mysql_native_password có nghĩa là đã kết nối thành công rồi. Ngoài ra, bạn cũng có thể connect từ appserver với câu lệnh bên dưới, trong đó thay root bằng tài khoản admin của RDS và đoạn cuối cùng thành hostname server RDS của bạn.

root@appserver:~$ mysql -u **root** -p -h **wordops-db.cgp414qdscum.ap-southeast-1.rds.amazonaws.com**

MySQL / Server tự cài

Để cài đặt MySQL server cho máy chủ Ubuntu, bạn hãy gõ câu lệnh như bên dưới. Lưu ý WordOps chỉ hỗ trợ tới MySQL Server 5.7 thôi bạn nhé.

root@dbserver:~$ wo stack install --mysql

Sau đó chúng ta lấy mật khẩu của MySQL root ở đường dẫn /etc/mysql/conf.d/my.cnf để dùng cho bước tiếp theo ngay sau đây. Đối với MySQL (không phải AWS RDS), hãy thực hiện 2 câu lệnh bên dưới để cho phép tài khoản root có thể được kết nối từ bên ngoài dbserver bạn nhé. Nhớ thay đổi thông tin tương ứng:

  • 10.0.0.200 thành private IP của dbserver
  • 10.0.0.100 thành private IP của appserver
  • password thành mật khẩu root mà bạn đã cài đặt ở trên.
root@dbserver:~$ mysql -u root -p -e "grant all privileges on \*.\* to 'root'@'******%******' IDENTIFIED BY '**password**' with grant option;" 
root@dbserver:~$ mysql -u root -p -e "flush privileges;"

Tiếp tục mở tập tin /etc/mysql/my.cnf và chỉnh sửa dòng bind-address thành 0.0.0.0 và khởi động lại MySQL sau đó.

skip-name-resolve = 1
# Instead of skip-networking the default is now to listen only on localhost which is more compatible and is not less secure.
bind-address = **0.0.0.0**
max_connections = 100

Khởi động lại MySQL server bằng câu lệnh:

root@dbserver:~$ service mysql restart

Cuối cùng thử kết nối tới dbserver bằng cách gõ câu lệnh telnet trên appserver. Lưu ý:

  • Nhớ thay dòng in đậm thành hostname/IP của dbserver của bạn.
  • Nên sử dụng private IP thay vì public IP.
  • Dùng web Port check 🔗 để chắc chắn rằng MySQL không mở public từ public IP.
root@appserver:~$ apt update && apt install telnet
root@appserver:~$ telnet **10.0.0.10** 3306
N
5.7.28-log7,g d���2-/'F3P-\*)5mysql_native_password

Bước 2. Cài đặt WordOps

Bước này đơn giản và nhanh chóng, có lẽ đã thân thuộc với anh em rồi nên mình sẽ không nói nhiều. Hãy sử dụng câu lệnh bên dưới để cài đặt WordOps trên appserver trước bạn nhé:

wget -qO wo wops.cc && sudo bash wo

Trong quá trình cài đặt, script sẽ yêu cầu bạn nhập tên và địa chỉ email để dùng cho tài khoản admin mặc định sau này. Sau khi nhập xong hết thì script cũng tiến hành các bước còn lại tự động.

Bước 3. Cài đặt mysql-client

Tiếp theo, chúng ta tiến hành cài đặt mysql-client trên appserver để "mồi" một kết nối đến remote database đã cài đặt sẵn ở phần đầu. Nếu không làm bước này, WordOps sẽ tiến hành cài đặt MySQL server ở các bước sau gây ra lãng phí tài nguyên trên app server vì bạn không cần dùng tới nữa.

Hãy dùng câu lệnh bên dưới để cài đặt mysql-client trước trên appserver:

wo stack install --mysqlclient

Sau đó, hãy tạo một tập tin mới với đường dẫn /etc/mysql/conf.d/my.cnf chứa thông tin remote database có nội dung như sau:

[client]
host = 10.0.0.200
user = root
password = aSecurePassword

Hãy thay đổi host thành địa chỉ IP hoặc hostname của database server, userpassword thành thông tin tương ứng như đã cài đặt tại bước 1 và lưu lại.

Bước 4. Clone mã nguồn của WordOps và build lại

Nếu bạn không sử dụng AWS RDS mà cài đặt một MySQL server riêng, hãy bỏ qua bước này.

Có một số vấn đề về việc phân chia quyền master của RDS nên chúng ta phải chỉnh sửa mã nguồn của WordOps để script có thể tạo database, tạo user, phân quyền trên RDS,... Bước này cũng thực hiện trên appserver bạn nhé.

Đầu tiên hãy clone mã nguồn WordOps về bằng câu lệnh:

git clone https://github.com/WordOps/WordOps.git

Sau đó mở tập tin WordOps/wo/cli/plugins/site_functions.py tìm đến dòng 219 và chỉnh sửa như sau hoặc xem commit này 🔗 để dễ hình dung hơn.

"grant all privileges on \`{0}\`.\* to \`{1}\`@\`{2}\`"

và sửa thành:

"grant SELECT,CREATE,INSERT,UPDATE,DELETE,DROP on \`{0}\`.\* to \`{1}\`@\`{2}\`"

Sau đó tiến hành build lại WordOps bằng câu lệnh:

rm -rf /usr/local/lib/python3.6/dist-packages/wo-3\*
cd WordOps/
python3 setup.py install

Nếu không có thông báo lỗi gì có nghĩa là bạn đã chỉnh sửa thành công, có thể tiếp tục chuyển sang bước tiếp theo.

Bước 5. Cấu hình WordOps sử dụng % thay vì localhost

Hãy chỉnh sửa tập tin /etc/wo/wo.conf, tìm dòng grant-host và chỉnh từ localhost thành % là xong. Bạn Thái Bảo góp ý các bạn cũng có thể dùng câu lệnh dưới đây thay cho việc mở file thủ công để chỉnh sửa cho nhanh nhé.

sed -i 's/grant-host = localhost/grant-host = \\%/' /etc/wo/wo.conf

Bước 6. Tạo trang web đầu tiên

Sau khi thực hiện xong bước 4, bạn đã có thể tạo trang web đầu tiên và tiến hành kiểm tra các thông số của database server và web server như thế nào nhé. Lưu ý, khi cài đặt WordPress, thông số hostname của MySQL server sẽ là hostname của RDS hoặc private IP của database server, nếu không WordPress sẽ báo lỗi không tìm thấy MySQL server.

Kết luận

Vậy là xong, từ đây bạn đã có thể sử dụng một database server riêng nhưng vẫn không thay đổi gì chức năng của WordOps. Mọi thao tác thêm, sửa và xóa website trên WordOps vẫn hoạt động bình thường.

Theo mình đây là thay đổi khá đơn giản nhưng hiệu quả mang lại thì rất cao. Với một web server có cấu hình rất thấp (như t2.micro của AWS), việc tách ra và mang database server ra riêng giúp giảm CPU ultilization và giảm đáng kể lượng RAM sử dụng.

Ngoài ra, bài viết này cũng giúp bạn tận dụng gói AWS Free Tier để cho website một tốc độ nhanh nhất có thể chứ không chỉ gói gọn ở EC2.