Tùy chỉnh kernel parameters với sysctl trên Linux: Tối ưu hiệu suất và bảo mật server

Linux tutorial - IT technology blog
Linux tutorial - IT technology blog

Đêm hôm đó, khoảng 2 giờ sáng, chuông báo động trên PagerDuty của mình reo inh ỏi, khiến mình bật dậy. Lần này không phải là lỗi triển khai (deploy) hay dịch vụ bị sập hoàn toàn, mà là hiệu suất của một microservice quan trọng đột nhiên giảm thê thảm.

Biểu đồ giám sát (Monitoring) nhảy múa loạn xạ, các yêu cầu gửi đến API cứ timeout liên tục, trong khi tải CPU và RAM trên server thì vẫn bình thường. Khách hàng bắt đầu than phiền, và mình toát mồ hôi hột, tự hỏi chuyện gì đang xảy ra với con server Ubuntu 22.04 4GB RAM mà mình đang quản lý.

Vấn đề thực tế: Hiệu suất server giảm không rõ nguyên nhân

Tình trạng này kéo dài, khiến trải nghiệm người dùng bị ảnh hưởng nghiêm trọng. Mọi dấu hiệu đều cho thấy ứng dụng vẫn đang chạy, nhưng dường như có một nút thắt cổ chai nào đó ở tầng hệ điều hành đang bóp nghẹt khả năng xử lý của nó. Các công cụ giám sát như htop, top đều cho kết quả bình thường về tài nguyên CPU, RAM, nhưng các chỉ số về network lại có vấn đề. Đặc biệt, mình nhận thấy số lượng kết nối thất bại và độ trễ tăng vọt, điều này thật sự đáng báo động.

Phân tích nguyên nhân: Kernel Parameters chưa được tối ưu

Sau vài phút vật lộn với log và các lệnh như netstat, mình phát hiện ra một lượng lớn kết nối ở trạng thái TIME_WAITCLOSE_WAIT đang chất đống. Điều này cho thấy nhân Linux (kernel) đang gặp khó khăn trong việc quản lý vòng đời các kết nối mạng, đặc biệt là khi server phải xử lý liên tục nhiều yêu cầu kết nối và ngắt kết nối trong thời gian ngắn. Có thể số lượng kết nối đã vượt giới hạn mặc định, hoặc cách kernel xử lý bộ nhớ cho socket chưa hiệu quả.

Vấn đề không nằm ở code ứng dụng, mà ở tầng hệ điều hành, cụ thể là các thông số kernel Linux (kernel parameters). Mặc định, các bản phân phối Linux như Ubuntu được cấu hình để hoạt động ổn định trên nhiều loại phần cứng và mục đích sử dụng, từ desktop cá nhân đến các server nhỏ.

Tuy nhiên, chúng không được tối ưu hóa cho một trường hợp cụ thể nào. Đặc biệt, với các server tải cao, nơi mỗi mili giây đều quý giá và khả năng xử lý hàng ngàn kết nối cùng lúc là cực kỳ quan trọng, cấu hình mặc định có thể trở thành nút thắt cổ chai.

Kernel parameters là các giá trị cấu hình được lưu trữ trong không gian bộ nhớ của kernel, có thể được thay đổi khi hệ thống đang chạy. Chúng kiểm soát mọi thứ từ cách nhân quản lý bộ nhớ ảo (virtual memory), xử lý network stack, cho đến các hành vi của hệ thống file. Các thông số này được truy cập thông qua hệ thống file ảo /proc/sys/. Chẳng hạn, khi bạn muốn xem giá trị của net.ipv4.tcp_tw_reuse, thực chất bạn đang đọc file /proc/sys/net/ipv4/tcp_tw_reuse.

Các cách giải quyết

1. Thay đổi tạm thời với lệnh sysctl -w

Trước mắt, mình cần một giải pháp nhanh chóng để hệ thống hoạt động trở lại và giảm tải cho PagerDuty. Công cụ sysctl chính là cứu cánh. Mình quyết định thử điều chỉnh một vài thông số liên quan đến network để xem có cải thiện không. Để kiểm tra giá trị hiện tại của một kernel parameter, mình dùng lệnh:

sysctl net.ipv4.tcp_tw_reuse

Để thay đổi tạm thời một thông số, mình dùng cờ -w:

sudo sysctl -w net.ipv4.tcp_tw_reuse=1

Mình thử tăng net.core.somaxconn (số lượng yêu cầu kết nối chờ tối đa) và cho phép tái sử dụng các socket ở trạng thái TIME_WAIT bằng cách bật net.ipv4.tcp_tw_reuse. Ngay lập tức, mình thấy các kết nối bắt đầu được giải phóng nhanh hơn, lỗi timeout giảm dần và server bắt đầu thở phào nhẹ nhõm. Tải giảm, khách hàng cũng dần yên tâm. Giải pháp này giúp mình vượt qua khoảnh khắc căng thẳng lúc 2 giờ sáng đó.

2. Thay đổi vĩnh viễn qua file cấu hình

Tuy nhiên, các thay đổi bằng sysctl -w chỉ có tác dụng cho đến khi server khởi động lại. Một khi server reboot, mọi thứ sẽ trở về mặc định. Để các thiết lập này có hiệu lực vĩnh viễn và không phải làm lại mỗi khi server khởi động, mình cần chỉnh sửa file cấu hình /etc/sysctl.conf hoặc thêm các file cấu hình riêng vào thư mục /etc/sysctl.d/.

Cách tốt nhất: Quản lý cấu hình sysctl bằng /etc/sysctl.d/

Mình thường thích tạo một file riêng trong thư mục /etc/sysctl.d/. Cách này giúp mình dễ dàng quản lý, kiểm soát từng nhóm thông số và rollback khi cần, mà không làm ảnh hưởng đến file sysctl.conf gốc của hệ thống. Tên file nên bắt đầu bằng hai chữ số để quy định thứ tự load (ví dụ: 99-custom-performance.conf), với số càng cao thì mức độ ưu tiên càng lớn.

Ví dụ, mình tạo file /etc/sysctl.d/99-custom-performance.conf:

sudo nano /etc/sysctl.d/99-custom-performance.conf

Và thêm vào đó các dòng sau:

# Cho phép tái sử dụng các socket TIME_WAIT một cách nhanh chóng.
# Giúp hệ thống nhanh chóng giải phóng các port bị kẹt ở trạng thái TIME_WAIT,
# tránh tình trạng hết port khi có nhiều kết nối mới.
net.ipv4.tcp_tw_reuse = 1

# Tăng hàng đợi kết nối tối đa (mặc định thường là 128).
# Rất quan trọng với các server cần chấp nhận nhiều kết nối mới nhanh chóng.
# Nếu giá trị quá thấp, các kết nối mới có thể bị từ chối.
net.core.somaxconn = 65535

# Tăng số lượng file descriptor tối đa mà hệ thống có thể mở.
# Mỗi socket là một file descriptor, tăng giới hạn này giúp tránh lỗi "Too many open files".
fs.file-max = 1000000

# Tăng bộ đệm nhận/gửi mặc định và tối đa cho socket TCP.
# Giúp cải thiện hiệu suất truyền dữ liệu trên network, đặc biệt với kết nối tốc độ cao.
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_max = 4194304

# Khoảng port mà các kết nối outbound có thể sử dụng.
# Mở rộng khoảng port để server có nhiều port khả dụng hơn cho các kết nối đi,
# tránh tranh chấp port trong các ứng dụng có nhiều outbound connection.
net.ipv4.ip_local_port_range = 1024 65535

# Điều chỉnh vm.swappiness để ưu tiên cache RAM thay vì swap.
# Giá trị thấp hơn giảm việc hệ thống ghi dữ liệu lên ổ đĩa (swap), từ đó cải thiện hiệu suất.
# Giá trị 0 khiến kernel tránh swap hoàn toàn (trừ khi hết RAM vật lý). Với server có đủ RAM, giá trị 10 là lựa chọn tốt.
vm.swappiness = 10

# Kích hoạt SYN cookies để bảo vệ chống lại tấn công SYN Flood.
# Khi hệ thống bị tấn công, SYN cookies giúp vẫn tiếp tục xử lý kết nối mà không sử dụng quá nhiều tài nguyên.
net.ipv4.tcp_syncookies = 1

# Giảm thời gian chờ cho các socket FIN-WAIT-2.
# Giúp giải phóng nhanh các tài nguyên network sau khi kết nối kết thúc.
net.ipv4.tcp_fin_timeout = 30

# Thời gian (giây) không hoạt động trước khi gửi gói tin keepalive.
# Giúp phát hiện và đóng các kết nối bị chết sớm hơn.
net.ipv4.tcp_keepalive_time = 600

# Buộc hệ thống panic khi có lỗi kernel (oops), hữu ích cho việc chẩn đoán sớm các vấn đề kernel.
# Quan trọng trong môi trường production để nhanh chóng nhận diện và sửa lỗi kernel.
kernel.panic_on_oops = 1

# Tắt IPv6 nếu không sử dụng.
# Giúp đơn giản hóa network stack và giảm thiểu rủi ro bảo mật không cần thiết.
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

Sau khi lưu file, để áp dụng các thay đổi mà không cần khởi động lại server, mình dùng lệnh:

sudo sysctl --system

Lệnh này sẽ đọc tất cả các file cấu hình trong thư mục /etc/sysctl.d/ và file /etc/sysctl.conf (nếu có), sau đó áp dụng các thông số mới vào kernel đang chạy. Bạn có thể kiểm tra lại các giá trị đã được áp dụng bằng lệnh sysctl -a | grep <parameter>.

Kinh nghiệm cá nhân và lợi ích

Sau nhiều lần thử nghiệm và điều chỉnh trên các môi trường khác nhau, mình nhận ra việc tạo các file cấu hình riêng biệt trong /etc/sysctl.d/ là cách quản lý hiệu quả nhất. Nó không chỉ giúp mình dễ dàng kiểm soát từng nhóm thông số mà còn cho phép rollback nhanh chóng nếu có vấn đề phát sinh.

Trên server production Ubuntu 22.04 với 4GB RAM mình đang quản lý, việc này giúp giảm đáng kể thời gian xử lý request, từ vài trăm mili giây xuống còn vài chục mili giây trong giờ cao điểm. Các sự cố timeout gần như không còn xảy ra, hệ thống hoạt động mượt mà hơn hẳn, giúp mình có những giấc ngủ ngon hơn, không còn phải lo lắng về những cú điện thoại lúc nửa đêm nữa.

Việc tối ưu kernel parameters không chỉ dừng lại ở hiệu suất mạng. Nó còn ảnh hưởng đến cách hệ thống quản lý bộ nhớ, I/O, và thậm chí cả bảo mật. Hiểu và điều chỉnh các thông số này là một phần quan trọng của việc quản trị hệ thống Linux chuyên nghiệp.

Kiểm tra và theo dõi hiệu suất sau khi thay đổi

Sau khi áp dụng bất kỳ thay đổi nào, mình luôn dùng các công cụ như netstat, ss, sar, iostat để theo dõi hiệu suất hệ thống. Việc này giúp mình xác định xem các thay đổi có mang lại hiệu quả mong muốn hay không và có gây ra tác dụng phụ nào không. Quan trọng là phải có dữ liệu để đánh giá khách quan.

# Xem tất cả các thông số sysctl hiện tại
sysctl -a

# Lọc các thông số liên quan đến TCP/IP
sysctl -a | grep "net.ipv4.tcp"

# Đếm số lượng kết nối ở trạng thái TIME_WAIT
sudo netstat -an | grep -i "time_wait" | wc -l

# Xem thông tin tóm tắt về các socket
sudo ss -s

# Xem thông tin về CPU, I/O, Network (lấy mẫu 5 lần, mỗi lần cách nhau 1 giây)
sar -u 1 5  # CPU utilization
sar -n DEV 1 5 # Network interface statistics
iostat -xz 1 5 # CPU and disk I/O statistics

Lưu ý quan trọng trước khi tối ưu

  • Sao lưu cấu hình: Trước khi thực hiện bất kỳ thay đổi lớn nào, hãy luôn sao lưu file /etc/sysctl.conf và các file trong /etc/sysctl.d/. Một bản sao lưu tốt sẽ giúp bạn dễ dàng phục hồi lại trạng thái trước đó nếu có vấn đề.
  • Kiểm tra trên môi trường Staging: Mỗi thay đổi kernel parameter đều có thể ảnh hưởng sâu rộng đến hệ thống. Mình khuyên bạn nên thử nghiệm kỹ lưỡng trên môi trường staging hoặc môi trường phát triển (development) có cấu hình tương tự production. Điều này giúp tránh rủi ro không đáng có khi áp dụng trực tiếp lên hệ thống chính.
  • Thay đổi từ từ: Đừng bao giờ thay đổi quá nhiều thông số cùng lúc mà không hiểu rõ tác dụng của chúng. Hãy thay đổi từng chút một, theo dõi sát sao hiệu suất hệ thống và đánh giá tác động của từng thay đổi.
  • Đọc tài liệu: Luôn tham khảo tài liệu chính thức của Linux kernel hoặc các nguồn uy tín để hiểu rõ hơn về từng thông số bạn muốn điều chỉnh. Kiến thức sâu về chúng sẽ giúp bạn đưa ra các quyết định tối ưu hơn.

Việc điều chỉnh kernel parameters bằng sysctl là một kỹ thuật mạnh mẽ giúp tối ưu hóa hiệu suất và tăng cường bảo mật cho server Linux.

Từ kinh nghiệm xử lý sự cố lúc nửa đêm, mình nhận ra rằng hiểu rõ cách kernel hoạt động và biết cách tinh chỉnh nó có thể cứu nguy cho hệ thống trong những tình huống cấp bách nhất. Đây là một kỹ năng không thể thiếu cho bất kỳ kỹ sư IT nào quản lý hệ thống Linux production, giúp bạn không chỉ giải quyết vấn đề mà còn xây dựng một hệ thống mạnh mẽ, ổn định, và mang lại giá trị cao hơn cho doanh nghiệp.

Share: