Đang tải bài học…
Nội dung sẽ hiển thị khi tải xong.
Nội dung sẽ hiển thị khi tải xong.
Tạo sự cố trong phạm vi lab của bài, thu bằng chứng, sửa rồi kiểm tra.
Đội frontend báo: gọi http://127.0.0.1:8081/ trên server thì nhận Connection refused. Người deploy khẳng định đã cấu hình port 8081 trong unit file và systemctl status kdc-api vẫn báo active (running).
Nhiệm vụ: khôi phục để kdc-api phục vụ trên port 8081, vẫn chạy dưới systemd, và viết RCA ngắn.
"Dịch vụ đang chạy" và "dịch vụ đang phục vụ đúng chỗ" là hai việc khác nhau. Bài này luyện thói quen tin vào evidence của hệ thống đang chạy (ss, journalctl, systemctl show) thay vì tin vào file cấu hình mà bạn nghĩ đang có hiệu lực.
ss -ltnp và log bằng journalctl.Environment= và EnvironmentFile= trong systemd.Đọc kỹ script trước khi chạy. Script từ chối chạy nếu không thấy marker /etc/kdc-lab. Lưu nội dung vào ~/break-wrong-port.sh trên VM rồi chạy sudo bash ~/break-wrong-port.sh.
#!/usr/bin/env bash
# KDC Break/Fix: wrong port. Chỉ chạy trên VM lab có /etc/kdc-lab.
set -euo pipefail
[[ $EUID -eq 0 ]] || { echo "Chạy bằng sudo." >&2; exit 1; }
grep -qs '^KDC-LAB' /etc/kdc-lab || { echo "Không thấy marker /etc/kdc-lab; script chỉ chạy trên máy lab." >&2; exit 1; }
read -r -p "Script sẽ tạo và cố ý cấu hình sai dịch vụ kdc-api. Tiếp tục? [y/N] " answer
[[ $answer == y ]] || exit 1
id -u kdc-api &>/dev/null || useradd --system --no-create-home --shell /usr/sbin/nologin kdc-api
install -d -m 755 /opt/kdc-api /etc/kdc
cat > /opt/kdc-api/app.py <<'PY'
import os
from http.server import BaseHTTPRequestHandler, HTTPServer
class Health(BaseHTTPRequestHandler):
def do_GET(self):
body = b"kdc-api ok\n"
self.send_response(200)
self.send_header("Content-Type", "text/plain")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
bind, port = os.environ["BIND"], int(os.environ["PORT"])
print(f"kdc-api listening on {bind}:{port}", flush=True)
HTTPServer((bind, port), Health).serve_forever()
PY
cat > /etc/kdc/api.env <<'ENV'
# Runtime settings for kdc-api
BIND=127.0.0.1
PORT=8018
ENV
chmod 640 /etc/kdc/api.env
cat > /etc/systemd/system/kdc-api.service <<'UNIT'
[Unit]
Description=KDC demo API
After=network.target
[Service]
User=kdc-api
Environment=BIND=127.0.0.1 PORT=8081
EnvironmentFile=/etc/kdc/api.env
ExecStart=/usr/bin/python3 /opt/kdc-api/app.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload
systemctl enable --now kdc-api.service
echo "Đã tạo sự cố. Bắt đầu từ: curl http://127.0.0.1:8081/"
sudo bash ~/break-wrong-port.sh chạy file script đã lưu bằng Bash với quyền quản trị. read -r -p "..." answer đọc xác nhận: -r giữ dấu backslash nguyên văn, -p in câu hỏi, answer là tên biến nhận câu trả lời. Chỉ nhập đúng y mới qua điều kiện [[ $answer == y ]]; Enter mặc định dừng.
id -u kdc-api chỉ in UID của user; &>/dev/null bỏ cả stdout/stderr, || useradd ... chỉ tạo user nếu chưa tìm thấy. Các khối <<'PY', <<'ENV', <<'UNIT' ghi file Python, cấu hình và unit; nội dung bên trong không phải lệnh terminal để chạy từng dòng. Các cấu trúc Bash này được giới thiệu ở bài tiến trình.
Ngay sau khi tạo sự cố, bấm Kiểm tra kết quả một lần: các tiêu chí phải chưa đạt. Đó là trạng thái xuất phát.
Không sửa gì trước khi có evidence. Ghi lại lệnh và kết quả quan trọng vào RCA khi đi.
ss -ltnp chọn socket đang nghe (-l), TCP (-t), IP/port số (-n), tiến trình (-p). Bộ lọc 'sport = :8081' giới hạn cổng local 8081, không sửa socket. journalctl -u <unit> -n 20 --no-pager đọc log gần nhất. systemctl show ... -p Environment -p EnvironmentFiles chọn hai thuộc tính để đối chiếu các nguồn cấu hình; việc đọc thuộc tính chưa thay đổi dịch vụ.
sudo ss -ltnp | grep python, journalctl -u kdc-api --no-pager -n 20, systemctl show kdc-api -p Environment -p EnvironmentFiles.EnvironmentFile= trong systemd.exec(5): biến đọc từ file ghi đè biến khai báo bằng Environment=. So sánh hai nguồn cấu hình.Tạo ~/kdc-labs/rca/wrong-port.md (lab root của agent):
# RCA: kdc-api không phục vụ trên port 8081
## Triệu chứng
## Evidence
## Nguyên nhân gốc
## Cách sửa
## Phòng tránh
Phần Phòng tránh nên trả lời: làm sao để lần sau chỉ có một nguồn cấu hình port, và kiểm tra nào sau deploy sẽ phát hiện lỗi này ngay?
sudo ss -ltnp 'sport = :8081'
curl -s http://127.0.0.1:8081/
systemctl is-enabled kdc-api
ss -ltnp gộp socket đang lắng nghe (-l), TCP (-t), địa chỉ/cổng dạng số (-n) và tiến trình (-p). Mẫu sport = :8081 lọc cổng nguồn 8081; dấu nháy giữ nguyên mẫu. curl -s ẩn thanh tiến độ; systemctl is-enabled xem service có tự chạy khi boot.
Chọn server và bấm Kiểm tra kết quả.
systemctl is-active.sudo systemctl disable --now kdc-api.service
sudo rm -f /etc/systemd/system/kdc-api.service /etc/kdc/api.env
sudo rm -rf /opt/kdc-api
sudo systemctl daemon-reload
sudo userdel kdc-api
systemctl disable --now bỏ cấu hình tự chạy khi boot và dừng service ngay. daemon-reload yêu cầu systemd đọc lại unit file sau khi sửa/xóa. rm -f xóa file và không hỏi xác nhận; -r thêm xóa đệ quy thư mục cùng nội dung, nên -rf gộp hai tùy chọn này. userdel xóa tài khoản lab; không có -r nên không xóa thêm home.