Cấu hình systemd-journal-remote trên Fedora Server: Gom log tập trung qua HTTPS mTLS

Fedora tutorial - IT technology blog
Fedora tutorial - IT technology blog

2 giờ sáng và cú sốc server bốc hơi không dấu vết

Đúng 2h15 sáng, còi PagerDuty hú inh ỏi đánh thức cả nhà. Node worker gánh 80 job Celery ngầm trên cụm production bỗng dưng offline. Ping không phản hồi. SSH báo connection timed out. Mình vội mở web console của Hetzner bấm hard reset. Máy boot lại sau 40 giây, nhưng nguyên nhân sập thì biến mất không một dấu vết.

Mình dùng Fedora trên máy dev 2 năm nay vì ghiền kernel mới và dnf ổn định. Do đó, khi dựng 4 node worker mới, mình chọn luôn Fedora Server 40. Ai ngờ, vừa gõ journalctl -b -1 kiểm tra thì terminal trống trơn. Server dính Kernel Panic, Btrfs filesystem bị unmount ép buộc. Buffer log trong RAM chưa kịp flush xuống ổ NVMe thì nguồn đã ngắt. Mất log giữa đêm thực sự là ác mộng của dân on-call.

Vì sao chỉ lưu log cục bộ lại tiềm ẩn hiểm họa?

Mặc định trên Fedora, systemd-journald gom sạch log từ kernel, systemd service đến container Podman. Cơ chế ghi nhị phân này siêu nhanh và lọc log rất tiện. Tuy nhiên, việc giữ log ở ổ cứng cục bộ để lộ 3 điểm yếu chết người:

  • Bay màu dữ liệu khi kernel panic: Server mất điện hoặc crash cứng, log đọng ở RAM buffer chưa kịp ghi ra /var/log/journal/ coi như mất trắng.
  • Bị xóa dấu vết khi root bị hack: Hacker chui được vào máy sẽ purge sạch file journal đầu tiên để che giấu hành vi.
  • Cực hình khi quản lý từ 3 node trở lên: Mỗi lần debug lại phải mở 4 tab SSH gõ journalctl -u app.service. Làm vậy vừa chậm vừa dễ sót sự kiện tương quan giữa các node.

So sánh các giải pháp gom log phổ biến

Đứng trước bài toán này, anh em sysadmin thường có ba lựa chọn:

1. Cụm ELK (Elasticsearch, Logstash, Kibana) hoặc Graylog

Đây là giải pháp chuẩn chỉnh cho enterprise. Đổi lại, nó ngốn tài nguyên kinh khủng: riêng JVM đã nuốt 4-8GB RAM. Với cụm từ 3 đến 8 node nhỏ (VPS 2GB-4GB RAM), chạy ELK chẳng khác nào lấy dao mổ trâu đi giết gà.

2. Chuyển sang rsyslog truyền thống

Rsyslog ăn cực ít RAM (chưa tới 30MB) và quen thuộc. Khổ nỗi log đẩy đi dạng plain-text mặc định nên rất mất an toàn nếu không bọc stunnel. Tệ hơn, nó ép log có cấu trúc về chuỗi văn bản thô. Bạn sẽ mất sạch các trường metadata đắt giá như _SYSTEMD_UNIT, _PID, hay _COMM.

3. Dùng systemd-journal-remote và systemd-journal-upload qua HTTPS

Đây chính là vũ khí tích hợp sẵn trong systemd. Tiến trình chỉ tốn khoảng 15-25MB RAM trên mỗi host. Nó bảo lưu 100% metadata nhị phân và mã hóa hai chiều (mTLS) bằng chứng chỉ x509. Log đẩy real-time từng mili-giây. Dù worker có sập nguồn, dòng log trước đó 0.5 giây đã an tọa bên log server.

Triển khai systemd-journal-remote trên Fedora Server qua HTTPS

Mô hình lab mẫu gồm 2 máy:

  • Log Server (Fedora Server 40): Cổng HTTPS 19532, IP 192.168.10.50.
  • Client Node (Fedora Server 40): Đẩy log liên tục, IP 192.168.10.51.

Bước 1: Cài package mở rộng

Chạy lệnh này trên cả Log Server lẫn Client Node:

sudo dnf install -y systemd-journal-remote openssl

Bước 2: Tạo chứng chỉ số (mTLS) cho HTTPS

Để ngăn chặn máy lạ giả mạo đẩy rác vào log server, ta tạo chứng chỉ x509 xác thực 2 chiều (mTLS). Thực hiện ngay trên Log Server:

# Tạo thư mục lưu cert và khóa bảo mật
sudo mkdir -p /etc/ssl/journal-remote
cd /etc/ssl/journal-remote

# 1. Tạo Root CA nội bộ (hạn 10 năm)
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
  -keyout ca.key -out ca.pem -subj "/CN=Journal-Internal-CA"

# 2. Tạo Certificate cho Log Server
sudo openssl req -new -nodes -newkey rsa:2048 \
  -keyout server.key -out server.csr -subj "/CN=192.168.10.50"
sudo openssl x509 -req -days 1095 -in server.csr \
  -CA ca.pem -CAkey ca.key -CAcreateserial -out server.pem

# 3. Tạo Certificate cho Client Node
sudo openssl req -new -nodes -newkey rsa:2048 \
  -keyout client.key -out client.csr -subj "/CN=192.168.10.51"
sudo openssl x509 -req -days 1095 -in client.csr \
  -CA ca.pem -CAkey ca.key -CAcreateserial -out client.pem

# Set quyền an toàn: chỉ user service đọc được
sudo chown -R systemd-journal-remote:systemd-journal-remote /etc/ssl/journal-remote
sudo chmod 600 /etc/ssl/journal-remote/*.key

Đẩy 3 file ca.pem, client.pem, client.key sang Client Node qua scp:

scp ca.pem client.pem client.key [email protected]:/tmp/

# Trên Client Node:
sudo mkdir -p /etc/ssl/journal-remote
sudo mv /tmp/{ca.pem,client.pem,client.key} /etc/ssl/journal-remote/
sudo chown -R systemd-journal-upload:systemd-journal-upload /etc/ssl/journal-remote
sudo chmod 600 /etc/ssl/journal-remote/client.key

Bước 3: Cấu hình Log Server đón log

Chỉnh sửa file cấu hình nhận log trên Log Server:

sudo nano /etc/systemd/journal-remote.conf

Nội dung cấu hình chuẩn:

[Remote]
Seal=false
SplitMode=host
ServerKeyFile=/etc/ssl/journal-remote/server.key
ServerCertificateFile=/etc/ssl/journal-remote/server.pem
TrustedCertificateFile=/etc/ssl/journal-remote/ca.pem

Hai tham số cần nhớ:

  • SplitMode=host: Tự động gom log từng client vào file riêng theo hostname/IP tại /var/log/journal/remote/.
  • TrustedCertificateFile: Bật chế độ mTLS. Chỉ client mang cert được CA nội bộ ký mới được phép upload log.

Mở port trên firewalld và kích hoạt socket:

# Mở port 19532 TCP
sudo firewall-cmd --add-port=19532/tcp --permanent
sudo firewall-cmd --reload

# Bật socket (systemd sẽ tự spawn service khi có luồng log tới)
sudo systemctl enable --now systemd-journal-remote.socket

Bước 4: Cấu hình Client Node stream log

Trên máy Client Node, mở file /etc/systemd/journal-upload.conf:

sudo nano /etc/systemd/journal-upload.conf

Khai báo endpoint và cert client:

[Upload]
URL=https://192.168.10.50:19532
ServerKeyFile=/etc/ssl/journal-remote/client.key
ServerCertificateFile=/etc/ssl/journal-remote/client.pem
TrustedCertificateFile=/etc/ssl/journal-remote/ca.pem

Khởi chạy service đẩy log:

sudo systemctl enable --now systemd-journal-upload.service

Kiểm tra tình trạng kết nối:

sudo systemctl status systemd-journal-upload.service

Nếu terminal hiện Active: active (running) kèm dòng Uploaded ... bytes, luồng log đã thông suốt qua kênh HTTPS mã hóa.

Bước 5: Truy vấn log từ xa

Quay lại Log Server và kiểm tra thư mục nhận log:

ls -lh /var/log/journal/remote/

Bạn sẽ thấy file remote-192.168.10.51.journal. Dùng ngay cờ --file để lọc dữ liệu với đầy đủ tốc độ truy vấn nhị phân quen thuộc:

# Theo dõi log thời gian thực giống như đang tail -f
sudo journalctl --file=/var/log/journal/remote/remote-192.168.10.51.journal -f

# Lọc riêng các lỗi nghiêm trọng (từ Error tới Emergency)
sudo journalctl --file=/var/log/journal/remote/remote-192.168.10.51.journal -p err..emerg -n 50

Kinh nghiệm thực chiến khi vận hành production

Mô hình này nhẹ và bền, nhưng bạn cần để tâm hai việc:

1. Tránh tràn ổ cứng (Disk exhaustion): Các node đẩy log liên tục có thể làm đầy phân vùng /var sau vài tháng. Hãy tạo file /etc/tmpfiles.d/journal-remote.conf để systemd tự dọn dẹp log cũ hơn 30 ngày:

# Dọn dẹp log remote sau 30 ngày
d /var/log/journal/remote 0755 systemd-journal-remote systemd-journal-remote 30d

2. Xử lý khi rớt mạng tạm thời: systemd-journal-upload duy trì con trỏ trạng thái (cursor state). Khi mạng giữa hai node chập chờn, client sẽ tự buffer lại log cục bộ và đẩy bù ngay khi kết nối phục hồi mà không làm mất log.

Share: