Ubuntu服务器长期靠手动敲命令维护,迟早会出问题。补丁漏打、配置漂移、多台机器重复操作、半夜被报警叫起来处理磁盘写满,这些场景的根源都是没有把运维动作自动化。自动化管理的核心不是装一堆花哨工具,而是把重复的、可标准化的操作固化成脚本和配置,让服务器自己按预期运行。下面直接讲具体怎么落地。

用Ansible统一配置多台服务器

如果你管理超过三台Ubuntu服务器,第一件事就是部署Ansible。它通过SSH工作,不需要在目标机器上装agent,符合Ubuntu默认环境。先在控制机上安装:

sudo apt update && sudo apt install -y ansible

然后编辑inventory文件,把服务器分组:

[web]
192.168.1.10
192.168.1.11

[db]
192.168.1.20 ansible_user=deploy ansible_ssh_private_key_file=/home/deploy/.ssh/id_ed25519

接下来写playbook。比如统一所有web服务器安装Nginx并推送配置文件,同时确保时区、locale、内核参数一致:

- hosts: web
  become: yes
  vars:
    nginx_worker_connections: 4096
  tasks:
    - name: 安装Nginx
      apt:
        name: nginx
        state: latest
        update_cache: yes

    - name: 推送Nginx主配置
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'
      notify: reload nginx

    - name: 设置时区为Asia/Shanghai
      timezone:
        name: Asia/Shanghai

    - name: 调整文件描述符限制
      pam_limits:
        domain: "*"
        limit_type: soft
        limit_item: nofile
        value: "65535"

  handlers:
    - name: reload nginx
      systemd:
        name: nginx
        state: reloaded

Ansible的幂等性保证你可以反复执行同一个playbook而不会产生副作用。配置漂移的问题用git管理playbook目录,每次修改都走版本记录,然后定期跑一遍playbook把实际状态拉回期望状态。这比手动登录每台机器改配置可靠得多。

无人值守的自动安全更新

Ubuntu默认的unattended-upgrades只对部分安全源生效,而且经常因为配置不完整而漏掉关键补丁。建议显式配置:

sudo apt install -y unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgrades

然后编辑/etc/apt/apt.conf.d/50unattended-upgrades,把Ubuntu所有更新源都打开:

Unattended-Upgrade::Allowed-Origins {
    "${distro_id}:${distro_codename}";
    "${distro_id}:${distro_codename}-security";
    "${distro_id}ESMApps:${distro_codename}-apps-security";
    "${distro_id}ESM:${distro_codename}-infra-security";
    "${distro_id}:${distro_codename}-updates";
};
Unattended-Upgrade::AutoFixInterruptedDpkg "true";
Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Unattended-Upgrade::Automatic-Reboot "false";
Unattended-Upgrade::Automatic-Reboot-Time "03:00";

生产环境不建议自动重启,但内核补丁不重启不生效。可以配合needrestart检查哪些服务需要重启,然后安排维护窗口统一处理。自动更新日志在/var/log/unattended-upgrades/,建议用logrotate控制大小,并配置监控告警抓取“ERROR”关键字。

systemd timer替代cron做定时任务

cron的问题在于没有依赖管理、没有失败重试、日志分散。Ubuntu 20.04以后systemd timer已经足够成熟,建议把重要定时任务迁过去。比如每天凌晨备份数据库,先写一个service单元:

[Unit]
Description=MySQL daily backup
After=mysql.service

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/mysql_backup.sh
StandardOutput=append:/var/log/mysql_backup.log
StandardError=append:/var/log/mysql_backup_error.log

再写timer单元:

[Unit]
Description=Run MySQL backup daily at 2:30

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
Unit=mysql-backup.service

[Install]
WantedBy=timers.target

启用并启动timer:

sudo systemctl daemon-reload
sudo systemctl enable mysql-backup.timer
sudo systemctl start mysql-backup.timer
sudo systemctl list-timers --all

Persistent=true保证如果服务器在任务计划时间关机了,开机后会补跑。systemd timer还能设置随机延迟、单调计时器、失败后重启策略,比cron灵活得多。

集中日志管理与磁盘防爆

Ubuntu服务器磁盘写满最常见的原因就是日志没管好。journald默认限制比较宽松,先收紧:

sudo mkdir -p /etc/systemd/journald.conf.d
sudo tee /etc/systemd/journald.conf.d/size.conf <<'EOF'
[Journal]
SystemMaxUse=500M
SystemMaxFileSize=100M
MaxRetentionSec=2week
Compress=yes
EOF
sudo systemctl restart systemd-journald

应用日志用logrotate控制。很多软件自带的logrotate配置不够细,建议在/etc/logrotate.d/下统一覆盖。比如Nginx:

/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        if [ -f /var/run/nginx.pid ]; then
            kill -USR1 `cat /var/run/nginx.pid`
        fi
    endscript
}

如果服务器数量多,单机日志管理只是兜底,真正要做的是把日志集中到Loki或ELK。Ubuntu上推荐用rsyslog转发到中央日志服务器,配置简单:

# /etc/rsyslog.d/50-forward.conf
*.* @192.168.1.100:514

中央端用rsyslog或Grafana Loki接收,配合Promtail采集。日志集中后,磁盘写满的风险从业务服务器转移到了日志服务器,日志服务器再单独做容量规划和告警。

监控告警与自愈脚本

自动化管理不只是配置和部署,还包括自动发现异常并处理。基础监控用Prometheus node_exporter,Ubuntu上安装:

sudo apt install -y prometheus-node-exporter
sudo systemctl enable --now prometheus-node-exporter

告警规则至少覆盖CPU持续高负载、内存剩余不足、磁盘使用率超过85%、systemd服务失败、重启次数异常。Alertmanager收到告警后,可以触发webhook调用自愈脚本。

自愈脚本要非常克制,只处理明确无副作用的场景。比如磁盘使用率超过90%时自动清理可安全删除的缓存:

#!/bin/bash
# /usr/local/bin/auto_cleanup.sh
THRESHOLD=90
PARTITION="/"
USAGE=$(df -h "$PARTITION" | awk 'NR==2 {gsub("%","",$5); print $5}')

if [ "$USAGE" -ge "$THRESHOLD" ]; then
    # 清理apt缓存
    apt-get clean
    # 清理旧内核
    apt-get autoremove --purge -y
    # 清理journald
    journalctl --vacuum-size=200M
    # 清理临时文件
    find /tmp -type f -atime +7 -delete
    logger -t auto_cleanup "磁盘使用率${USAGE}%,已执行自动清理"
fi

把这个脚本接到systemd timer每30分钟跑一次,同时配合告警通知。注意自愈脚本必须记录日志,并且要有告警兜底,不能静默失败。

配置管理:把服务器当代码管

自动化配置的最高形式是基础设施即代码。除了Ansible,建议把服务器初始化也标准化。Ubuntu的cloud-init可以在首次启动时自动完成基础配置。创建/etc/cloud/cloud.cfg.d/99_custom.cfg:

#cloud-config
hostname: web-prod-01
manage_etc_hosts: true
users:
  - name: deploy
    sudo: ALL=(ALL) NOPASSWD:ALL
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...
packages:
  - htop
  - vim
  - curl
  - git
  - unattended-upgrades
package_update: true
package_upgrade: true
runcmd:
  - systemctl enable --now unattended-upgrades
  - sed -i 's/#Port 22/Port 2200/' /etc/ssh/sshd_config
  - systemctl restart sshd

这样新机器从镜像启动后自动完成用户创建、软件安装、安全基线配置。配合Ubuntu的autoinstall可以做全自动安装,把整个装机过程变成一条命令。

备份自动化与恢复验证

没有验证过的备份等于没有备份。自动化备份要包含恢复测试。数据库备份脚本示例:

#!/bin/bash
# /usr/local/bin/mysql_backup.sh
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=14

mkdir -p "$BACKUP_DIR"
mysqldump --single-transaction --quick --all-databases \
  | gzip > "$BACKUP_DIR/full_$DATE.sql.gz"

# 删除过期备份
find "$BACKUP_DIR" -name "full_*.sql.gz" -mtime +$RETENTION_DAYS -delete

# 记录备份大小
du -sh "$BACKUP_DIR/full_$DATE.sql.gz" | logger -t mysql_backup

恢复验证可以每周自动把最新备份恢复到一台测试实例,跑一条简单的数据完整性检查SQL,然后把结果发到监控系统。这个流程用GitLab CI或Jenkins做调度,比手动验证可靠。

SSH安全基线自动化

SSH是Ubuntu服务器最常被攻击的入口。自动化加固配置:

sudo tee /etc/ssh/sshd_config.d/99-hardening.conf <<'EOF'
Port 2200
PermitRootLogin prohibit-password
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers deploy
EOF
sudo systemctl restart sshd

配合fail2ban自动封禁暴力破解:

sudo apt install -y fail2ban
sudo tee /etc/fail2ban/jail.local <<'EOF'
[sshd]
enabled = true
port = 2200
maxretry = 3
bantime = 3600
findtime = 600
EOF
sudo systemctl enable --now fail2ban

这些配置都应该放进Ansible playbook,确保每台新机器自动应用。

自动化运维的落地顺序

不要试图一次性把所有东西都自动化。建议按这个顺序推进:先把所有服务器纳入Ansible管理,统一基础配置;然后配置自动安全更新和日志轮转,解决最紧急的补丁和磁盘问题;接着部署监控告警,让你知道什么时候出了问题;再逐步把备份、定时任务、自愈脚本迁移到自动化体系里。每一步都要有日志和告警,自动化不是把问题藏起来,而是让问题更快暴露、更快处理。Ubuntu服务器运维自动化管理的本质,是把你的运维经验固化成代码,让服务器按照你设定的规则自己运行,而不是每次出问题都靠人肉登录去救火。