0
0
Lập trình
Sơn Tùng Lê
Sơn Tùng Lê103931498422911686980

Tự động hóa DevOps với Python: Giám sát hệ thống thông minh

Đăng vào 7 tháng trước

• 9 phút đọc

Tự động hóa DevOps với Python: Giám sát hệ thống thông minh với khả năng tự phục hồi

Tự động hóa là nền tảng của văn hóa DevOps hiện đại. Dù có các công cụ mạnh mẽ như Kubernetes, Docker và các nền tảng CI/CD, thì các script vẫn giữ vai trò quan trọng trong việc quản lý hạ tầng hiệu quả.

Trong bài viết này, chúng ta sẽ xây dựng một script giám sát hệ thống bằng Python không chỉ theo dõi tài nguyên hệ thống mà còn thực hiện khôi phục tự động khi phát hiện sự cố.


Tại sao nên sử dụng script trong DevOps?

Script mang lại nhiều lợi ích chính cho quy trình DevOps:

  • Phản ứng nhanh – Một script có thể phát hiện và sửa chữa sự cố chỉ trong vài giây.
  • Độ nhất quán – Các tác vụ luôn được thực hiện theo cùng một cách, giảm thiểu lỗi do con người.
  • Khả năng mở rộng – Một script có thể quản lý hàng trăm máy chủ.
  • Tài liệu – Một script được viết tốt có thể phục vụ như tài liệu thực thi.

Script giám sát đầy đủ bằng Python

python Copy
#!/usr/bin/env python3
"""
Giám sát hệ thống thông minh và khôi phục tự động
Tác giả: Nhóm DevOps Bulgaria
Phiên bản: 2.0
"""

import psutil
import subprocess
import logging
import smtplib
import json
import time
from datetime import datetime
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from typing import Dict, List, Optional
import argparse
import sys
import os

class SystemMonitor:
    def __init__(self, config_file: str):
        self.load_config(config_file)
        self.setup_logging()
        self.cooldowns = {}

    def load_config(self, config_file: str):
        try:
            with open(config_file, "r") as f:
                self.config = json.load(f)
        except Exception as e:
            print(f"Lỗi khi tải cấu hình: {e}")
            sys.exit(1)

    def setup_logging(self):
        log_file = "/var/log/system_monitor.log"
        logging.basicConfig(
            filename=log_file,
            level=logging.INFO,
            format="%(asctime)s - %(levelname)s - %(message)s"
        )
        logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))

    def get_metrics(self) -> Dict[str, float]:
        return {
            "cpu_percent": psutil.cpu_percent(interval=1),
            "memory_percent": psutil.virtual_memory().percent,
            "disk_percent": psutil.disk_usage("/").percent,
            "load_average": psutil.getloadavg()[0]
        }

    def check_services(self) -> Dict[str, bool]:
        results = {}
        for service in self.config.get("services", []):
            try:
                result = subprocess.run(
                    ["systemctl", "is-active", "--quiet", service],
                    check=False
                )
                results[service] = (result.returncode == 0)
            except Exception:
                results[service] = False
        return results

    def attempt_recovery(self, service: str) -> bool:
        logging.warning(f"Đang cố gắng khởi động lại dịch vụ: {service}")
        try:
            subprocess.run(
                ["systemctl", "restart", service],
                check=True
            )
            time.sleep(5)
            return subprocess.run(
                ["systemctl", "is-active", "--quiet", service],
                check=False
            ).returncode == 0
        except Exception as e:
            logging.error(f"Khôi phục không thành công cho {service}: {e}")
            return False

    def send_alert(self, subject: str, body: str):
        email_conf = self.config.get("email", {})
        if not email_conf.get("enabled", False):
            return

        now = time.time()
        last_alert = self.cooldowns.get(subject, 0)
        if now - last_alert < self.config["monitoring"]["cooldown_period"]:
            return
        self.cooldowns[subject] = now

        try:
            msg = MIMEMultipart()
            msg["From"] = email_conf["username"]
            msg["To"] = ", ".join(email_conf["to_addresses"])
            msg["Subject"] = subject
            msg.attach(MIMEText(body, "plain"))

            with smtplib.SMTP(email_conf["smtp_server"], email_conf["smtp_port"]) as server:
                server.starttls()
                server.login(email_conf["username"], email_conf["password"])
                server.send_message(msg)

            logging.info(f"Đã gửi cảnh báo: {subject}")
        except Exception as e:
            logging.error(f"Gửi cảnh báo không thành công: {e}")

    def monitor_once(self):
        metrics = self.get_metrics()
        services = self.check_services()

        logging.info("Thông số hệ thống: " + str(metrics))

        for key, value in metrics.items():
            if value > self.config["thresholds"][key]:
                msg = f"{key} ở mức {value}% vượt qua ngưỡng {self.config['thresholds'][key]}%"
                logging.warning(msg)
                self.send_alert("Ngưỡng hệ thống bị vượt", msg)

        for service, is_active in services.items():
            if not is_active:
                logging.error(f"Dịch vụ không hoạt động: {service}")
                for _ in range(self.config["monitoring"]["recovery_attempts"]):
                    if self.attempt_recovery(service):
                        logging.info(f"Dịch vụ {service} đã phục hồi thành công")
                        break
                else:
                    self.send_alert("Dịch vụ không hoạt động", f"Khôi phục {service} không thành công")

    def run(self):
        interval = self.config["monitoring"]["interval"]
        while True:
            self.monitor_once()
            time.sleep(interval)


def main():
    parser = argparse.ArgumentParser(description="Giám sát hệ thống")
    parser.add_argument("--config", default="monitor_config.json", help="Đường dẫn đến file cấu hình")
    parser.add_argument("--once", action="store_true", help="Chạy một lần và thoát")
    parser.add_argument("--verbose", action="store_true", help="Bật ghi log gỡ lỗi")
    args = parser.parse_args()

    monitor = SystemMonitor(args.config)
    if args.once:
        monitor.monitor_once()
    else:
        monitor.run()

if __name__ == "__main__":
    main()

File cấu hình (monitor_config.json)

json Copy
{
    "thresholds": {
        "cpu_percent": 85.0,
        "memory_percent": 90.0,
        "disk_percent": 85.0,
        "load_average": 8.0
    },
    "services": [
        "nginx",
        "mysql",
        "docker",
        "redis-server"
    ],
    "email": {
        "enabled": true,
        "smtp_server": "smtp.gmail.com",
        "smtp_port": 587,
        "username": "your-email@gmail.com",
        "password": "your-app-password",
        "to_addresses": ["admin@yourcompany.com"]
    },
    "monitoring": {
        "interval": 60,
        "recovery_attempts": 3,
        "cooldown_period": 300
    }
}

Ví dụ về dịch vụ Systemd

ini Copy
[Unit]
Description=Giám sát hệ thống thông minh
After=network.target

[Service]
Type=simple
User=root
ExecStart=/usr/bin/python3 /opt/system-monitor/system_monitor.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Kết luận

Script này cung cấp:

  • Giám sát theo thời gian thực CPU, bộ nhớ, đĩa và tải trung bình
  • Giám sát dịch vụ với khả năng khởi động lại tự động
  • Ngưỡng và cảnh báo có thể cấu hình thông qua JSON
  • Thông báo qua email với thời gian chờ để tránh spam
  • Tích hợp Systemd cho việc thực thi nền đáng tin cậy

Các script tự động hóa như thế này là nền tảng của các thực hành DevOps. Chúng đảm bảo tính bền vững của hệ thống, giảm thời gian chết và giải phóng kỹ sư khỏi những công việc lặp đi lặp lại.

Mẹo chuyên nghiệp: Luôn thử nghiệm trong môi trường staging trước khi triển khai trên môi trường sản xuất.


Bài viết này được viết lần đầu bằng tiếng Bulgaria và được dịch sang tiếng Anh cho cộng đồng dev.to.

Đọc phiên bản gốc bằng tiếng Bulgaria: DevOps автоматизация със скриптове

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào