Tôi Đã Giảm Một Nửa Thời Gian Boot Linux Server Bằng systemd-analyze Như Thế Nào

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

Cái Boot Không Chịu Kết Thúc

Sáu tháng trước, tôi có một vấn đề mà cứ mãi phớt lờ. Server Ubuntu 22.04 production của tôi — 4GB RAM, chạy vài Docker container và một Nginx reverse proxy — mất hơn 40 giây để boot. Với các maintenance window có kế hoạch trước thì chỉ khó chịu thôi. Nhưng với những lần reboot bất ngờ sau kernel update, nó bắt đầu cảm giác thực sự rủi ro.

Tôi cứ nghĩ đó là “chuyện bình thường của Linux” trên phần cứng cũ. Rồi một đồng nghiệp hỏi tôi đã bao giờ thực sự nhìn vào xem cái gì đang mất nhiều thời gian chưa. Tôi chưa bao giờ. Chính câu hỏi đó đã thay đổi cách tôi nghĩ về việc bảo trì server.

Đây là những gì tôi tìm thấy, nguyên nhân gây ra nó, và các bước cụ thể tôi dùng để đưa thời gian boot từ 40 giây xuống còn 18 giây — mà không vô hiệu hóa bất cứ thứ gì quan trọng.

Đọc Timeline Boot

Bắt đầu với systemd-analyze. Nó đi kèm sẵn với systemd nên không cần cài thêm gì. Chạy lệnh tóm tắt trước:

systemd-analyze

Trên server của tôi, lệnh này trả về:

Startup finished in 3.102s (kernel) + 37.841s (userspace) = 40.943s
multi-user.target reached after 37.729s in userspace

Phần kernel hầu như luôn dưới 5 giây. Mọi thứ thú vị đều xảy ra ở userspace — chuỗi các systemd unit khởi động sau khi kernel bàn giao. Con số 37 giây đó cho tôi biết có gì đó đang rất sai.

Xem thời gian chi tiết theo từng service với:

systemd-analyze blame

Lệnh này liệt kê mọi service được sắp xếp theo thời gian khởi động. Kết quả đầu bảng của tôi:

34.201s apt-daily-upgrade.service
 8.320s snapd.service
 4.118s NetworkManager-wait-online.service
 2.903s mysql.service
 1.440s cloud-init.service
 0.891s docker.service
 0.703s ssh.service

Một dòng nói lên tất cả: apt-daily-upgrade.service đang ngốn 34 giây một mình.

Trực Quan Hóa Chuỗi Dependency

Con số thuần túy không thể hiện được bức tranh dependency — một service có thể trông chậm trong khi thực ra nó đang bị chặn chờ thứ khác hoàn toàn. Biểu đồ SVG lấp đầy khoảng trống đó:

systemd-analyze plot > boot-analysis.svg

Mở file trong bất kỳ trình duyệt nào. Bạn sẽ thấy một biểu đồ dạng Gantt của mọi unit — thời điểm bắt đầu, thời lượng, và unit đó đang chờ gì. Trên server của tôi, tôi có thể thấy rằng NetworkManager-wait-online.service thực ra không chậm. Nó đang ngồi chờ, đợi apt-daily-upgrade.service giải phóng lock.

Để trace dependency theo dạng text nhanh hơn cho một unit cụ thể:

systemd-analyze critical-chain multi-user.target

Lệnh này tìm chuỗi dependency dài nhất dẫn đến target mặc định của bạn. Của tôi hiển thị:

multi-user.target @37.729s
└─apt-daily-upgrade.service @3.528s +34.201s
  └─apt-daily.service @3.411s +0.089s
    └─network-online.target @3.380s +0.031s

Chuỗi đã rõ ràng. Sửa apt-daily-upgrade.service, và mọi thứ phía sau sẽ nhanh lên.

Nguyên Nhân Gốc Rễ: Ba Nhóm Unit Chậm

Sau khi kiểm tra hàng chục server trong sáu tháng qua, thủ phạm luôn nằm trong ba nhóm:

1. Các Service Không Nên Chạy Lúc Boot

Tự động nâng cấp package (apt-daily-upgrade.service), làm mới snap (snapd.service), và cloud-init trên server bare-metal đều thuộc nhóm này. Chúng phục vụ mục đích thực sự — chỉ là không phải lúc boot trong khi server đang cố gắng đi vào hoạt động.

2. Các Service Chờ Mạng

NetworkManager-wait-online.service là cái bẫy điển hình. Nó chặn toàn bộ quá trình boot cho đến khi mạng kết nối hoàn toàn, nhưng hầu hết các service chỉ cần network stack lên — không nhất thiết phải routing được ra internet. Trên server của tôi, điều này đang thêm 4 giây không cần thiết.

3. Các Service Cấu Hình Sai Hoặc Bị Bỏ Lại

Một developer trước đó đã cài một monitoring agent, rồi gỡ nó ra — nhưng để lại file systemd unit. Mỗi lần boot, nó cố khởi động, thất bại, thử lại, và cuối cùng timeout. Âm thầm ngốn 6 giây, mỗi lần.

Sửa Từng Nhóm

Trì Hoãn Cập Nhật Tự Động

Cách sửa đúng cho apt-daily-upgrade.service là trì hoãn nó, không phải tắt hẳn. Cập nhật bảo mật vẫn quan trọng — bạn chỉ không muốn chúng chạy trong khi người dùng đang chờ server trở lại.

sudo systemctl edit apt-daily-upgrade.service

Thêm override này để đẩy nó ra 10 phút sau khi boot:

[Unit]
After=multi-user.target

[Service]
ExecStartPre=/bin/sleep 600

Hoặc dùng timer để lên lịch chạy vào một giờ cố định:

sudo systemctl edit apt-daily-upgrade.timer
[Timer]
OnBootSec=15min
OnCalendar=
OnCalendar=03:00

Trên server của tôi, việc trì hoãn timer đến 3 giờ sáng đã lấy lại 32 giây thời gian boot chỉ bằng một thay đổi. Cập nhật vẫn chạy — chỉ là khi không ai để ý.

Sửa NetworkManager-wait-online

Kiểm tra xem có thứ gì thực sự quan trọng phụ thuộc vào mạng hoàn toàn online lúc boot không:

systemd-analyze dot --require | grep network-online

Nếu không có gì trong kết quả trông có vẻ thiết yếu, thì tắt việc chờ đợi này là an toàn:

sudo systemctl disable NetworkManager-wait-online.service

Nếu một service thực sự cần kết nối internet lúc khởi động — chẳng hạn pull cấu hình từ Consul hoặc remote secrets store — thì giữ lại. Nhưng trước tiên hãy hỏi xem dependency đó có thực sự cần thiết không, hay chỉ là mặc định chưa được xem xét lại.

Xóa Các Unit Bị Bỏ Lại

Tìm những thứ đang âm thầm thất bại:

systemctl list-units --state=failed

Với mỗi unit thất bại gắn với phần mềm bạn không còn dùng:

sudo systemctl disable --now old-monitoring-agent.service
sudo rm /etc/systemd/system/old-monitoring-agent.service
sudo systemctl daemon-reload

Xử Lý snapd

Không dùng snap package? Gỡ snapd hẳn còn gọn hơn là disable nó:

# Trước tiên, liệt kê các snap đã cài
snap list

# Gỡ từng snap không cần dùng
sudo snap remove --purge snap-store
sudo snap remove --purge core20

# Sau đó gỡ bản thân snapd
sudo apt remove --purge snapd
sudo apt-mark hold snapd

Lệnh apt-mark hold ngăn snapd lén cài lại khi nâng cấp các package khác. Trên các server không dùng snap, thao tác này một mình đã lấy lại 6–10 giây.

Mask vs Disable vs Delay

Ba tùy chọn này thường xuyên bị lẫn lộn, và chọn sai gây ra vấn đề thực sự:

  • Disable — xóa service khỏi danh sách tự động khởi động, nhưng vẫn có thể khởi động thủ công hoặc được kéo vào như một dependency của unit khác.
  • Mask — chặn hoàn toàn unit, kể cả khi service khác cố kéo nó vào. Chỉ dùng khi bạn chắc chắn unit này không bao giờ nên chạy trên máy này.
  • Delay (override) — giữ service vẫn chạy nhưng dời thời điểm chạy. Lựa chọn tốt nhất cho các tác vụ bảo trì có giá trị thực sự nhưng thời điểm không phù hợp.
# Kiểm tra xem có gì bị ảnh hưởng nếu disable một unit
systemctl list-dependencies --reverse apt-daily-upgrade.service

# Mask một unit bạn không bao giờ muốn chạy
sudo systemctl mask iscsid.service

# Hủy mask
sudo systemctl unmask iscsid.service

Luôn chạy kiểm tra reverse dependency trước khi disable bất cứ thứ gì. Tôi đã một lần bỏ qua bước này, disable một service mà ba service khác phụ thuộc vào, rồi mất một tiếng debug Docker networking bị hỏng trong lần boot tiếp theo.

Kiểm Tra Lại Sau Khi Thay Đổi

Sau mỗi thay đổi, reboot và đo lại:

systemd-analyze
systemd-analyze blame | head -20

So sánh với baseline ban đầu. Vòng lặp đo-thay đổi-đo lại này chính xác là cách tôi đi từ 40 giây xuống 18 — ba vòng sửa có mục tiêu, không phải một lần quét lớn.

Con số cuối cùng sau tất cả các thay đổi:

Startup finished in 3.091s (kernel) + 14.802s (userspace) = 17.893s
multi-user.target reached after 14.690s in userspace

Các mục đầu bảng trong systemd-analyze blame bây giờ đều hợp lý — mysql, docker, nginx. Những thứ thực sự cần thời gian để khởi tạo. Không có gì lãng phí nữa.

Điều Thực Sự Quan Trọng

Thời gian boot chỉ là con số đo lường. Điều bạn thực sự làm với systemd-analyze là làm hiện rõ thứ mà hầu hết sysadmin chưa bao giờ nhìn vào: chính xác server của bạn đang làm gì trong 40 giây đầu tiên đó, và tại sao.

Boot chậm hầu như luôn là hệ quả của sự tích lũy — các service được cài rồi bị quên, các mặc định chưa bao giờ được xem xét lại, các dependency hướng desktop đang chạy trên server headless. Kiểm tra boot 30 phút mỗi vài tháng một lần mang lại lợi ích đáng kể: phục hồi nhanh hơn sau sự cố, ít lỗi khởi động bí ẩn hơn, và bức tranh rõ ràng về những gì thực sự đang chạy trên máy của bạn.

Bốn lệnh cần thuộc lòng:

  • systemd-analyze — tổng thời gian
  • systemd-analyze blame — phân tích chi tiết theo từng unit
  • systemd-analyze critical-chain — đường dependency dài nhất
  • systemd-analyze plot — timeline trực quan

Bắt đầu với blame. Tìm thủ phạm đứng đầu. Hiểu xem nó chậm tự thân hay đang chờ thứ khác. Rồi chọn: delay, disable, hay mask. Lặp lại cho đến khi con số trông hợp lý. Không phức tạp — chỉ cần thực sự ngồi nhìn vào mà thôi.

Share: