Tối ưu hóa thời gian boot Linux với systemd-analyze: Phân tích và tăng tốc khởi động máy chủ

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

Bối cảnh & Lý do

Khi một cloud instance bất ngờ khởi động lại hoặc khi bạn cần cập nhật kernel đồng loạt trên 50 node, việc phải chờ đợi kết nối SSH gây tốn kém chi phí thực sự. Mỗi giây downtime trôi qua đều đáng giá. Trong các autoscaling group và cụm failover cluster, quá trình khởi tạo máy chủ chậm chạp sẽ làm trễ các bước health check và khiến lưu lượng truy cập bị gián đoạn.

Hầu hết các bản phân phối Linux hiện đại đều sử dụng systemd ngầm bên dưới. Mặc dù systemd khởi chạy các service song song—một bước tiến vượt bậc so với SysVinit trước đây—nhưng các cấu hình mặc định lại tích tụ nhiều thứ cồng kềnh theo thời gian. Các network target ảo, tình trạng timeout bộ nhớ lưu trữ và các daemon chạy nền không cần thiết có thể dễ dàng biến một lần reboot gọn gàng chỉ 8 giây thành một quá trình rùa bò kéo dài tới 90 giây.

Hãy ngừng đoán xem service nào đang làm chậm quá trình boot. Thay vào đó, hãy dựa vào những con số cụ thể. Công cụ tích hợp sẵn systemd-analyze sẽ lập hồ sơ phân tích các phụ thuộc của unit, chỉ rõ chuỗi điểm nghẽn và vạch ra chính xác những tiến trình ngốn tài nguyên đến từng mili-giây.

Cài đặt

Tin vui là: systemd-analyze đã được tích hợp sẵn trong gói systemd cơ bản trên hầu hết các bản phân phối phổ biến, bao gồm Ubuntu, Debian, AlmaLinux, Rocky Linux và Fedora. Bạn hiếm khi cần phải cài đặt thêm phần mềm nào khác.

Kiểm tra xem công cụ này đã có sẵn trên máy của bạn hay chưa:

systemd-analyze --version

Nếu bạn đang chạy một container tối giản hoặc một cloud image rút gọn đã bị lược bỏ các tiện ích phụ trợ, hãy cài đặt gói cốt lõi thông qua trình quản lý gói của hệ thống.

Trên Debian và Ubuntu:

sudo apt update
sudo apt install -y systemd

Trên RHEL, AlmaLinux và Rocky Linux:

sudo dnf install -y systemd

Cấu hình & Phân tích hiệu năng

Việc tinh chỉnh thời gian boot được thực hiện theo quy trình 4 bước: đo lường hiệu năng ban đầu, xác định chính xác các điểm nghẽn, vô hiệu hóa những gì không cần thiết và kiểm tra lại kết quả.

1. Kiểm tra tổng thời gian boot

Bắt đầu bằng việc thu thập chỉ số baseline từ lần khởi động gần nhất:

systemd-analyze time

Bạn sẽ thấy kết quả đầu ra được chia thành 3 giai đoạn rõ rệt:

Startup finished in 5.120s (kernel) + 2.840s (initrd) + 21.430s (userspace) = 29.390s
graphical.target reached after 21.390s in userspace

Chỉ số userspace phản ánh toàn bộ các service, daemon và script được tải sau khi kernel bàn giao quyền điều khiển. Trong ví dụ này, userspace chiếm 21,4 giây trên tổng số 29,4 giây boot. Đây chính là phần bạn có toàn quyền kiểm soát trực tiếp và là nơi dễ dàng mang lại hiệu quả tối ưu nhất.

2. Xác định các unit chạy chậm với Blame

Tiếp theo, hãy liệt kê các unit đang hoạt động được xếp hạng theo thời gian khởi tạo:

systemd-analyze blame | head -n 15

Kết quả điển hình trên máy chủ thường làm lộ diện những “thủ phạm” quen thuộc:

12.421s NetworkManager-wait-online.service
 8.114s cloud-init.service
 3.650s snapd.service
 2.102s apt-daily.service
 1.218s polkit.service

Đừng vội hoang mang. Một service mất 12 giây để khởi động không nhất thiết sẽ làm chậm toàn bộ quá trình boot của bạn đúng 12 giây.

3. Truy vết Critical Chain

Vì systemd khởi động các service song song, nên các tác vụ nền độc lập vẫn chạy song hành mà không làm gián đoạn việc đăng nhập của người dùng. Để tìm chuỗi tuần tự thực sự cản trở máy chủ đạt tới multi-user.target, hãy truy vết đường dẫn tới hạn (critical path):

systemd-analyze critical-chain multi-user.target

Cây phân cấp thu được sẽ cho thấy thời điểm mỗi unit phụ thuộc bắt đầu chạy và thời gian nó làm chậm trễ target:

multi-user.target @21.390s
└─nginx.service @20.120s +1.250s
  └─network-online.target @20.100s
    └─NetworkManager-wait-online.service @7.680s +12.420s
      └─NetworkManager.service @6.100s +1.580s

Hãy chú ý đến mục +12.420s của NetworkManager-wait-online.service. Riêng unit này đã chặn network-online.target, làm trì hoãn Nginx và kéo dài thời gian khởi động thêm hơn 12 giây.

4. Tạo biểu đồ Boot trực quan dạng tương tác

Bạn thích xem dưới dạng hình ảnh trực quan hơn? Hãy xuất toàn bộ chuỗi khởi động thành một file đồ họa vector:

systemd-analyze plot > /tmp/boot_analysis.svg

Mở file SVG này trong bất kỳ trình duyệt nào. Nó sẽ hiển thị một timeline dạng thác nước (waterfall) trực quan, chi tiết từng đợt tăng đột biến CPU, hoạt động I/O đĩa và các thanh thời gian chạy chính xác từ đầu đến cuối của từng service.

5. Loại bỏ và Mask các Service không cần thiết

Sau khi đã xác định được các tác nhân gây nghẽn tiềm ẩn, hãy loại bỏ chúng một cách có hệ thống.

Vô hiệu hóa NetworkManager-wait-online:
Nhiều server production thường bị nghẽn ở NetworkManager-wait-online.service. Theo mặc định, nó sẽ chặn tiến trình cho đến khi tất cả các giao diện mạng đạt trạng thái sẵn sàng (carrier state). Nếu server của bạn sử dụng IP tĩnh hoặc DHCP cloud tiêu chuẩn trên eth0, hãy mask unit này để cắt giảm ngay lập tức 10 đến 15 giây thời gian boot:

sudo systemctl disable NetworkManager-wait-online.service
sudo systemctl mask NetworkManager-wait-online.service

Đóng băng Cloud-Init trên các Instance đã cấu hình xong:
Cloud-init rất cần thiết trong lần khởi động đầu tiên để thêm SSH key và phân vùng ổ đĩa. Tuy nhiên, ở các lần reboot tiếp theo, việc truy vấn các endpoint metadata của cloud qua HTTP lại làm phát sinh thêm 6 đến 10 giây chờ đợi lãng phí. Khi việc khởi tạo cấu hình đã hoàn tất, hãy tắt các lượt kiểm tra thừa thãi này:

# Bỏ qua cloud-init trong những lần khởi động tiếp theo
sudo touch /etc/cloud/cloud-init.disabled

Trên một cloud node chạy Ubuntu 22.04 (2 vCPU, 4GB RAM), việc mask các bước chờ mạng không cần thiết và tắt cloud-init đã giúp giảm tổng thời gian khởi động userspace từ 21,4 giây xuống chỉ còn 4,8 giây.

Mask các Service ngoại vi và Desktop:
Các cloud instance dạng headless và máy chủ gắn rack không bao giờ cần đến Bluetooth, smart card hay modem di động. Hãy mask chúng hoàn toàn để systemd từ chối kích hoạt kể cả khi chúng được gọi như một phụ thuộc gián tiếp:

sudo systemctl mask ModemManager.service
sudo systemctl mask bluetooth.service
sudo systemctl mask cups.service

6. Rút ngắn thời gian chờ Timeout của Service bị treo

Theo mặc định, systemd dành thời gian ân hạn 90 giây cho các service không phản hồi khi khởi động hoặc tắt máy. Nếu một tiến trình chạy nền bị treo, toàn bộ quá trình reboot của bạn sẽ bị khựng lại một phút rưỡi. Hãy áp đặt giới hạn 15 giây trong /etc/systemd/system.conf:

sudo sed -i 's/#DefaultTimeoutStartSec=90s/DefaultTimeoutStartSec=15s/' /etc/systemd/system.conf
sudo sed -i 's/#DefaultTimeoutStopSec=90s/DefaultTimeoutStopSec=15s/' /etc/systemd/system.conf
sudo systemctl daemon-reload

Kiểm tra & Giám sát

Khởi động lại máy chủ để đánh giá hiệu quả cải thiện trong điều kiện thực tế:

sudo reboot

Khi máy chủ kết nối lại thành công, hãy chạy lại systemd-analyze để so sánh với các số liệu ban đầu:

systemd-analyze time

Kiểm tra các tác động ngoài ý muốn. Đảm bảo rằng không có service phụ thuộc nào bị lỗi do một dependency đã bị mask:

systemctl --failed

Kiểm tra system journal để tìm các cảnh báo hoặc chu kỳ phụ thuộc phát sinh trong quá trình dọn dẹp:

journalctl -b -p warning..err

Hãy lưu lại một bản sao biểu đồ boot mới trước khi thực hiện các đợt nâng cấp kernel hoặc hệ điều hành lớn. Việc so sánh đối chiếu các biểu đồ SVG theo thời gian sẽ giúp bạn phát hiện sớm các daemon bất thường trước khi tình trạng boot chậm ảnh hưởng đến môi trường production.

Share: