Trong lộ trình chuyển dịch website từ Single-VPS sang cụm Multi-Server, bước đi giúp giải phóng hiệu năng rõ rệt nhất là tách hệ quản trị cơ sở dữ liệu (MySQL, MariaDB hoặc PostgreSQL) sang một máy chủ VPS chuyên dụng. Khi tách riêng, bạn có thể dành khoảng 75% đến 80% dung lượng RAM vật lý cho bộ đệm InnoDB Buffer Pool mà không lo bị các tiến trình web (PHP-FPM, Node.js) tranh chấp tài nguyên dẫn tới nguy cơ kích hoạt Linux OOM Killer. Đồng thời, toàn bộ năng lực đọc ghi ngẫu nhiên (IOPS) của ổ cứng NVMe sẽ được ưu tiên phục vụ các truy vấn dữ liệu.
Tuy nhiên, điểm mấu chốt khi đưa cơ sở dữ liệu sang máy chủ mới nằm ở tầng mạng. Nếu cấu hình sai card mạng hoặc để lưu lượng truy vấn đi qua Internet, độ trễ mạng sẽ tăng vọt từ mức 0.05ms (cục bộ) lên tới hàng chục mili-giây, kéo tụt tốc độ phản hồi của toàn bộ website. Ngoài ra, việc mở cổng cơ sở dữ liệu ra bên ngoài mà thiếu lớp kiểm soát truy cập sẽ mở rộng bề mặt dễ bị tấn công trước các đợt dò quét mật khẩu (brute-force) tự động.
Bài viết này hướng dẫn bạn quy trình thiết lập mạng riêng nội bộ (Private VPC), giới hạn cổng kết nối qua bind-address và tường lửa UFW, phân quyền truy cập theo địa chỉ IP nguồn, cùng các bước đo kiểm nhằm duy trì độ trễ giữa Web Server và Database Server dưới 0.8ms.
Yêu cầu hạ tầng trước khi cấu hình
Trước khi tiến hành cấu hình, bạn cần chuẩn bị hai máy chủ đáp ứng các tiêu chí sau:
- Cùng nhà cung cấp và trung tâm dữ liệu: Hai VPS cần được đặt trong cùng một trung tâm dữ liệu, lý tưởng nhất là chung một Availability Zone. Bạn nên tránh đặt Web Server và Database Server ở hai nhà cung cấp khác nhau, bởi việc kết nối qua Internet giữa hai bên sẽ khiến độ trễ tăng cao và thiếu ổn định.
- Kích hoạt mạng nội bộ: Hầu hết các nhà cung cấp hạ tầng điện toán đám mây hiện nay (như Vietnix, Bizfly Cloud, Hetzner Cloud, DigitalOcean, AWS) đều hỗ trợ tính năng mạng riêng nội bộ (Private VPC) miễn phí hoặc với chi phí thấp. Mỗi VPS khi kích hoạt sẽ có thêm một card mạng thứ hai (ví dụ
eth1hoặcens10). - Quy ước dải mạng nội bộ:
- Dải mạng con (Subnet):
10.0.0.0/24 - Máy chủ Web (Web-01):
10.0.0.10 - Máy chủ Database (DB-01):
10.0.0.20
Bước 1: Thiết lập card mạng nội bộ qua Netplan
Trên các bản phân phối Linux như Ubuntu 22.04 LTS hoặc 24.04 LTS, cấu hình mạng được quản lý tập trung thông qua Netplan.
Trước tiên, bạn đăng nhập SSH vào máy chủ Database (DB-01) và kiểm tra danh sách card mạng hiện có:
ip -br linkKết quả trả về thường hiển thị dạng:
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
eth0 UP 52:54:00:12:34:56 <BROADCAST,MULTICAST,UP,LOWER_UP>
eth1 DOWN 52:54:00:78:9a:bc <BROADCAST,MULTICAST> Trong đó, eth0 là card mạng kết nối Internet (IP public), còn eth1 là card mạng nội bộ đang ở trạng thái chưa kích hoạt (DOWN).
Mở tệp cấu hình Netplan trên DB-01:
sudo nano /etc/netplan/01-netcfg.yamlThiết lập địa chỉ IP tĩnh cho eth1 mà không khai báo gateway (nhằm tránh xung đột với cổng định tuyến mặc định ra Internet của eth0):
network:
version: 2
renderer: networkd
ethernets:
eth0:
dhcp4: true
eth1:
addresses:
- 10.0.0.20/24
mtu: 1500Lưu tệp và áp dụng cấu hình:
sudo netplan applyKiểm tra card mạng eth1 đã nhận IP thành công:
ip -4 addr show dev eth1Dòng thông tin inet 10.0.0.20/24 brd 10.0.0.255 scope global eth1 cho thấy card mạng đã hoạt động. Bạn thực hiện thao tác tương tự trên máy chủ Web-01 với địa chỉ IP tương ứng là 10.0.0.10/24.
Bước 2: Cấu hình MySQL lắng nghe trên card mạng nội bộ
Theo mặc định sau khi cài đặt, MySQL chỉ lắng nghe kết nối cục bộ trên địa chỉ loopback 127.0.0.1. Khi chuyển sang mô hình máy chủ độc lập, người quản trị đôi khi cấu hình bind-address = 0.0.0.0 để cho phép kết nối từ xa.
Thiết lập 0.0.0.0 sẽ mở cổng 3306 ra mọi giao diện mạng, bao gồm cả IP công cộng. Điều này làm tăng bề mặt dễ bị tấn công do các botnet trên Internet liên tục dò quét cổng và thử mật khẩu, gây lãng phí tài nguyên CPU của máy chủ.
Giải pháp an toàn là gắn dịch vụ MySQL vào đúng địa chỉ IP của card mạng nội bộ:
Mở tệp cấu hình MySQL trên DB-01:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnfTìm tham số bind-address và chuyển sang IP nội bộ của DB-01:
[mysqld]
# Chỉ chấp nhận kết nối trên card mạng nội bộ
bind-address = 10.0.0.20
# Tắt phân giải DNS ngược để tăng tốc bắt tay kết nối (TCP Handshake)
skip-name-resolveLưu tệp và khởi động lại dịch vụ MySQL:
sudo systemctl restart mysqlKiểm tra cổng lắng nghe bằng lệnh ss:
sudo ss -tulpn | grep 3306Kết quả hợp lệ hiển thị như sau:
tcp LISTEN 0 151 10.0.0.20:3306 0.0.0.0:* users:(("mysqld",pid=14205,fd=31))Khi cột Local Address hiển thị 10.0.0.20:3306 (thay vì 0.0.0.0:3306), dịch vụ MySQL đã được giới hạn an toàn trong phạm vi mạng nội bộ.
Bước 3: Cấu hình tường lửa UFW bảo vệ cổng cơ sở dữ liệu
Song song với bind-address, lớp bảo vệ tiếp theo theo nguyên tắc thiết lập tường lửa bảo vệ VPS là sử dụng UFW để kiểm soát lưu lượng ngay tại tầng nhân Linux.
Trên máy chủ DB-01, bạn thiết lập chính sách mặc định là chặn toàn bộ lưu lượng đến:
# Thiết lập chính sách mặc định
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Cho phép SSH nội bộ từ máy chủ Web (hoặc IP VPN quản trị)
sudo ufw allow in on eth1 from 10.0.0.10 to any port 22 proto tcp comment "Internal SSH from Web-01"
# Nếu bạn cần SSH khẩn cấp từ IP tĩnh văn phòng qua card eth0 (thay thế bằng IP thực tế của bạn)
# sudo ufw allow in on eth0 from 118.69.xxx.xxx to any port 22 proto tcp comment "Admin Office SSH"
# Chỉ cho phép duy nhất IP nội bộ của Web-01 kết nối vào cổng MySQL trên card eth1
sudo ufw allow in on eth1 from 10.0.0.10 to any port 3306 proto tcp comment "Allow MySQL from Web-01"
# Bật tường lửa
sudo ufw enableXác nhận lại trạng thái tường lửa:
sudo ufw status verboseKết quả kiểm tra:
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
22/tcp on eth1 ALLOW IN 10.0.0.10 # Internal SSH from Web-01
3306/tcp on eth1 ALLOW IN 10.0.0.10 # Allow MySQL from Web-01Với cấu hình này, các gói tin gửi tới cổng 3306 từ Internet (eth0) hoặc từ bất kỳ địa chỉ IP nào khác ngoài 10.0.0.10 sẽ bị tường lửa loại bỏ (DROP) ngay lập tức.
Bước 4: Phân quyền tài khoản MySQL theo IP nguồn
Trong cơ sở dữ liệu MySQL, quyền truy cập của người dùng luôn gắn liền với máy chủ nguồn (Host). Một sai lầm phổ biến trong thực tế là cấp quyền dạng 'username'@'%' (trong đó ký tự % đại diện cho mọi địa chỉ IP).
Để đảm bảo an toàn cho dữ liệu, bạn cần chỉ định chính xác địa chỉ IP nội bộ của Web Server (10.0.0.10):
Đăng nhập vào MySQL trên DB-01:
sudo mysql -u root -pThực thi câu lệnh tạo người dùng và gán quyền hạn tối thiểu cần thiết:
-- Tạo tài khoản ứng dụng chỉ cho phép kết nối từ 10.0.0.10
CREATE USER 'app_prod'@'10.0.0.10' IDENTIFIED BY 'MatKhauPhucTapItNhat32KyTuRanDom123!';
-- Cấp quyền vừa đủ trên cơ sở dữ liệu phục vụ website
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER, LOCK TABLES
ON production_db.* TO 'app_prod'@'10.0.0.10';
-- Nạp lại bảng phân quyền
FLUSH PRIVILEGES;
-- Kiểm tra lại danh sách người dùng
SELECT user, host FROM mysql.user WHERE user = 'app_prod';Kết quả trả về hiển thị rõ:
+----------+-----------+
| user | host |
+----------+-----------+
| app_prod | 10.0.0.10 |
+----------+-----------+Bước 5: Đo kiểm độ trễ và băng thông mạng nội bộ
Bước kiểm tra này giúp bạn xác định chất lượng đường truyền nội bộ trước khi đưa hệ thống vào phục vụ tải thực tế. Từ máy chủ Web-01, bạn thực hiện lần lượt 3 bước đo kiểm:
1. Đo độ trễ qua ICMP ping
Chạy 100 gói tin ping với tần suất nhanh để kiểm tra độ ổn định của switch mạng ảo:
ping -c 100 -i 0.2 10.0.0.20Quan sát kết quả ở dòng cuối cùng:
100 packets transmitted, 100 received, 0% packet loss, time 20184ms
rtt min/avg/max/mdev = 0.312/0.458/0.782/0.068 msTiêu chuẩn nghiệm thu tham chiếu:
- Độ trễ trung bình (
avg): Thông thường nên duy trì dưới 1.0ms (mức 0.3ms – 0.6ms là rất lý tưởng trong cùng một Datacenter). Nếu độ trễ thường xuyên vượt trên 1.5ms – 2.0ms, bạn nên kiểm tra lại tình trạng nghẽn trên hạ tầng ảo hóa. - Tỷ lệ rớt gói (
packet loss): Cần đạt 0.0% trong mạng nội bộ. - Độ lệch chuẩn (
mdev): Nên giữ dưới 0.1ms – 0.2ms để hạn chế hiện tượng giật (jitter).
2. Đo băng thông qua iperf3
Khi chạy sao lưu cơ sở dữ liệu (mysqldump) hoặc tải các bảng dữ liệu lớn, băng thông mạng nội bộ ảnh hưởng trực tiếp đến thời gian hoàn thành tác vụ.
Cài đặt công cụ trên cả hai máy chủ:
sudo apt install -y iperf3Trên máy chủ DB-01, khởi chạy iperf3 ở chế độ máy chủ lắng nghe trên IP nội bộ:
iperf3 -s -B 10.0.0.20(Lưu ý tạm thời mở cổng 5201 trên UFW của DB-01 cho 10.0.0.10 nếu cần đo kiểm: sudo ufw allow from 10.0.0.10 to any port 5201 proto tcp).
Trên máy chủ Web-01, chạy lệnh kiểm tra băng thông với 4 luồng song song:
iperf3 -c 10.0.0.20 -P 4Kết quả mong đợi:
[SUM] 0.00-10.00 sec 1.10 GBytes 944 Mbits/sec receiverBăng thông đo được xấp xỉ 940 Mbps cho thấy card mạng nội bộ đang hoạt động đúng với tốc độ thiết kế 1 Gbps.
3. Kiểm tra kết nối TCP và truy vấn SQL thực tế
Từ Web-01, kiểm tra khả năng bắt tay qua cổng TCP:
nc -zv 10.0.0.20 3306Kết quả hiển thị: Connection to 10.0.0.20 3306 port [tcp/mysql] succeeded!.
Tiếp tục thực hiện một truy vấn SQL thực tế từ dòng lệnh của Web-01:
mysql -h 10.0.0.20 -u app_prod -p'MatKhauPhucTapItNhat32KyTuRanDom123!' production_db -e "SELECT @@hostname AS db_host, NOW() AS server_time;"Khi câu lệnh trả về đúng tên máy chủ cơ sở dữ liệu và thời gian hiện tại, bạn có thể yên tâm rằng việc xác thực tài khoản và định tuyến mạng nội bộ đã sẵn sàng.
Bước 6: Tinh chỉnh tham số mạng Linux tránh treo kết nối
Khi Web Server và Database Server duy trì nhiều kết nối TCP đồng thời, thiết bị chuyển mạch ảo (vSwitch) của nhà cung cấp hạ tầng có thể tự động ngắt các kết nối rảnh rỗi (idle connection) mà không gửi cờ RST. Tình trạng này dễ khiến ứng dụng bị treo khi cố gắng tái sử dụng các kết nối đã đứt trong connection pool.
Để hạn chế rủi ro này, bạn nên cấu hình lại tham số TCP keepalive và bộ đệm mạng trên cả hai máy chủ:
Mở tệp cấu hình sysctl:
sudo nano /etc/sysctl.d/99-network-tuning.confThêm các tham số sau:
# Rút ngắn thời gian gửi gói tin TCP Keepalive thăm dò (mặc định 7200s là quá lâu)
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_keepalive_probes = 5
# Tăng hàng đợi kết nối mạng chờ xử lý
net.core.somaxconn = 4096
# Tăng kích thước bộ đệm nhận và gửi TCP cho mạng tốc độ cao
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216Áp dụng cấu hình ngay mà không cần khởi động lại máy chủ:
sudo sysctl --systemBảng kiểm tra nghiệm thu và phương án rollback
Trước khi chỉnh sửa tệp môi trường .env của ứng dụng chính thức, bạn nên soát lại toàn bộ tiêu chuẩn qua bảng kiểm tra dưới đây:
| Hạng mục kiểm tra | Lệnh xác minh | Kết quả đạt yêu cầu | Rủi ro nếu không đạt |
|---|---|---|---|
| Card mạng nội bộ | ip -br a show eth1 | Hiển thị đúng IP 10.0.0.20/24 | Mất liên lạc mạng nội bộ |
| MySQL Bind Address | ss -tulpn \| grep 3306 | Chỉ lắng nghe trên 10.0.0.20:3306 | Bị quét cổng từ ngoài Internet |
| Tường lửa UFW | ufw status | Chặn mặc định, chỉ mở 3306 cho 10.0.0.10 | Bị tấn công leo thang đặc quyền |
| Phân quyền người dùng | SELECT host FROM mysql.user | Chỉ gán duy nhất 10.0.0.10 | Lộ tài khoản nếu mật khẩu yếu |
| Độ trễ trung bình Ping | ping -c 50 10.0.0.20 | Độ trễ RTT ≤ 0.8ms | TTFB của website bị tăng cao |
| Bỏ qua DNS Lookup | Trong my.cnf | Đã bật skip-name-resolve | Kết nối bị nghẽn vài giây |
Chuyển đổi ứng dụng và phương án rollback
Sau khi các mục kiểm tra đều đạt yêu cầu, bạn tiến hành chuyển đổi tệp cấu hình trên Web Server:
# Tệp .env cũ
# DB_HOST=127.0.0.1
# Cấu hình mới trỏ sang VPS Database chuyên dụng
DB_CONNECTION=mysql
DB_HOST=10.0.0.20
DB_PORT=3306
DB_DATABASE=production_db
DB_USERNAME=app_prod
DB_PASSWORD=MatKhauPhucTapItNhat32KyTuRanDom123!Khởi động lại ứng dụng web (hoặc PHP-FPM / Docker) và theo dõi sát nhật ký lỗi error.log.
Phương án Rollback: Nếu trong vòng 15 phút đầu tiên sau khi chuyển đổi, bạn nhận thấy website phản hồi chậm bất thường hoặc phát sinh lỗi kết nối cơ sở dữ liệu chưa rõ nguyên nhân, hãy thực hiện rollback theo thứ tự sau:
- Mở tệp
.envtrên Web Server và đổi lạiDB_HOST=127.0.0.1. - Khởi động lại ứng dụng web.
- Khởi động lại dịch vụ MySQL cục bộ cũ trên Web Server.
Thao tác này đưa hệ thống quay lại trạng thái Single-VPS ban đầu một cách an toàn mà không làm gián đoạn dịch vụ của người dùng.
Lộ trình triển khai tiếp theo
Sau khi đã tách biệt cơ sở dữ liệu sang máy chủ riêng an toàn, bước tiếp theo trong lộ trình mở rộng quy mô là đưa máy chủ Web về mô hình phi trạng thái (stateless). Bạn có thể tham khảo bài viết so sánh giải pháp lưu trữ tệp tải lên giữa NFS, MinIO và S3 Object Storage để chuẩn bị phương án lưu trữ tập trung, trước khi đưa bộ cân bằng tải Nginx vào điều phối lưu lượng cho nhiều Web Server song song.



