定时任务管理:cron 与 systemd timer 对比

概述 定时任务是运维自动化的基础组件——日志轮转、数据备份、证书续期、健康检查、报表生成,几乎每个运维场景都离不开定时执行。大多数人对定时任务的认知停留在 crontab -e 加一行 0 2 * * * /path/to/script.sh,但这在生产环境中远远不够:任务失败了谁通知?执行超时了谁处理?多台机器上的任务怎么协调?从 cron 到 systemd timer 到分布式调度,逐步梳理定时任务的管理实践。 参考来源:cron Wikipedia、systemd.timer 官方文档 一、cron 语法与局限 1.1 cron 表达式 cron 表达式由 5 个字段组成: ┌──────── 分钟 (0-59) │ ┌────── 小时 (0-23) │ │ ┌──── 日 (1-31) │ │ │ ┌── 月 (1-12) │ │ │ │ ┌ 星期 (0-7, 0和7都是周日) │ │ │ │ │ * * * * * command 表达式 含义 0 2 * * * 每天凌晨 2:00 */15 * * * * 每 15 分钟 0 */6 * * * 每 6 小时 0 0 * * 0 每周日 0:00 0 0 1 * * 每月 1 号 0:00 30 3-5 * * * 3:30, 4:30, 5:30 0 0 1 1,4,7,10 * 每季度首月 1 号 @reboot 系统启动时 @daily / @midnight 每天 0:00 @weekly 每周日 0:00 @monthly 每月 1 号 0:00 @yearly / @annually 每年 1 月 1 日 0:00 1....

March 18, 2024 · 15 分钟 · 3009 字 · 徐保金

Docker 镜像优化:从 1GB 到 50MB

镜像过大的危害 很多团队在容器化初期不太关注镜像体积,一个 Spring Boot 应用镜像动辄 800MB-1.2GB,一个 Go 应用也常有 700MB+。镜像过大带来的问题远不止"占点磁盘": 拉取慢,部署延迟高:在 CI/CD 流水线或弹性扩容场景下,节点需要先拉取镜像再启动容器。1GB 的镜像在百兆内网下载需要 80 秒以上,而 50MB 的镜像仅需 4 秒。对于 HPA 自动扩容场景,这意味着故障恢复窗口被拉长。 安全攻击面大:基础镜像里包含了大量你根本用不到的系统工具(curl、wget、gcc、bash 等)。攻击者一旦拿到容器 shell,这些工具就是横向移动的跳板。镜像越小,攻击面越窄。 存储成本累积:一个镜像 1GB,每天构建 5 次、保留 30 天就是 150GB。10 个微服务就是 1.5TB。 Harbor / Registry 的存储成本和备份成本随之飙升。 构建缓存效率低:大镜像的每一层都更大,构建缓存命中后的加载也更慢,拖慢整体 CI 流水线。 本文参考 Docker 官方多阶段构建文档 多阶段构建(Multi-stage Build) 为什么需要多阶段构建 传统 Dockerfile 的关键问题是:构建工具和运行时环境混在同一个镜像里。 以 Go 应用为例,编译需要 go 工具链和 gcc,但运行时只需要一个二进制文件。如果用 golang:1.22 做基础镜像,最终镜像里会带上整个 Go SDK(约 800MB+),而你的应用二进制可能只有 15MB。 多阶段构建允许在一个 Dockerfile 中定义多个 FROM,每个 FROM 开始一个新阶段,最终镜像只保留最后一个阶段的内容。 多阶段构建语法 # ===== 阶段1:构建阶段 ===== FROM golang:1....

March 14, 2024 · 4 分钟 · 766 字 · 徐保金

kubectl 生产力指南:插件与别名

概述 kubectl 是 Kubernetes 管理员最常用的工具,但大多数人只用了它 20% 的功能。每天敲几十遍 kubectl get pods -n production,却不知道一行别名就能省掉一半字符;遇到问题只知道 kubectl describe 和 kubectl logs,却不知道 krew 插件能一键排查网络、资源、证书问题。本文逐步梳理 kubectl 的生产力提升工具链,从别名到插件到交互式工具,让你的 K8s 日常操作效率翻倍。 参考来源:kubectl 官方文档、krew 官网 一、kubectl 别名配置 1.1 基础别名 # ~/.bashrc 或 ~/.zshrc # 基础缩写 alias k='kubectl' alias kg='kubectl get' alias kd='kubectl describe' alias kdel='kubectl delete' alias ke='kubectl exec' alias kl='kubectl logs' alias kf='kubectl apply -f' alias kdf='kubectl delete -f' alias kr='kubectl run' # 常用资源缩写 alias kgp='kubectl get pods' alias kgs='kubectl get svc' alias kgn='kubectl get nodes' alias kgd='kubectl get deployments' alias kgsec='kubectl get secrets' alias kgcm='kubectl get configmaps' alias kging='kubectl get ingress' alias kgns='kubectl get namespaces' alias kgpv='kubectl get pv' alias kgpvc='kubectl get pvc' alias kdsa='kubectl describe sa' # 宽输出 + 自定义列 alias kgpw='kubectl get pods -o wide' alias kgsw='kubectl get svc -o wide' alias kgnw='kubectl get nodes -o wide' # watch 模式 alias kgpw='watch -n 2 kubectl get pods -o wide' alias kgnw='watch -n 5 kubectl get nodes -o wide' # 所有命名空间 alias kgpa='kubectl get pods --all-namespaces' alias kgsa='kubectl get svc --all-namespaces' # YAML 输出 alias kgpy='kubectl get pods -o yaml' alias kgsy='kubectl get svc -o yaml' 1....

March 12, 2024 · 14 分钟 · 2784 字 · 徐保金

CI/CD 流水线设计:GitHub Actions 实战

CI/CD 是现代软件交付的命脉。手动构建、手动部署不仅效率低下,更是事故的温床——“在我机器上能跑"的悲剧几乎都源于缺乏自动化流水线。GitHub Actions 作为 GitHub 原生的 CI/CD 平台,与代码仓库无缝集成,免费额度对开源项目友好,已成为最流行的 CI/CD 工具之一。从核心概念出发,结合 Go 项目和 Hugo 站点两个实战场景,完整讲解流水线设计。 参考来源:GitHub Actions 官方文档 一、GitHub Actions 核心概念 GitHub Actions 的架构围绕五个概念展开,理解它们的关系是设计流水线的基础: Workflow(工作流) │ ├── Job A(任务) │ ├── Step 1 → Action: checkout 代码 │ ├── Step 2 → Action: setup Go 环境 │ └── Step 3 → Shell: go test ./... │ └── Job B(任务) ├── Step 1 → Action: 下载构建产物 └── Step 2 → Shell: 部署到服务器 概念 说明 类比 Workflow 一个 ....

March 7, 2024 · 8 分钟 · 1580 字 · 徐保金

日志监控体系:Loki + Promtail 部署

为什么选择 Loki 传统 ELK(Elasticsearch + Logstash + Kibana)方案虽然功能强大,但存在两个核心痛点: 存储成本高:Elasticsearch 将日志全文索引化,每条日志的索引膨胀可达原始数据的 3-5 倍 运维复杂:ES 集群扩缩容、分片再平衡、索引生命周期管理复杂,生产集群维护成本高 Loki 由 Grafana Labs 开源,设计理念是"像 Prometheus 那样做日志"。它只对日志的标签(Labels)做索引,不对日志正文建索引,通过 LogQL 进行全文检索。这种设计使存储成本降低 10 倍以上。 本文基于 Loki 3.x,参考 Loki 官方文档 Loki vs ELK 对比 维度 ELK (Elasticsearch) Loki 索引方式 全文倒排索引 仅索引标签,正文不索引 存储成本 高(索引膨胀 3-5x) 低(标签索引 + 压缩正文) 查询语言 Lucene Query / KQL LogQL(类 PromQL 语法) 扩展性 水平扩展,分片复杂 微服务模式,组件独立扩展 适用场景 全文检索、复杂分析 日志监控、指标化查询、与 Grafana 联动 资源消耗 高(JVM,内存大) 低(Go 编写,内存友好) Loki 并非要完全替代 ES。如果你的核心需求是全文检索和复杂文本分析,ES 仍是更好的选择。但对于 SRE 日志监控、指标告警、排障定位这类场景,Loki + Grafana 的组合在成本和效率上优势明显。...

February 29, 2024 · 6 分钟 · 1242 字 · 徐保金

Alertmanager 告警路由与抑制策略

在 Prometheus 生态中,Prometheus 负责根据告警规则产生告警,而 Alertmanager 负责告警的后续全生命周期管理:分组、路由、抑制、去重和通知发送。一个配置不当的 Alertmanager 会让值班人员在凌晨被海量重复告警淹没,而精心设计的路由与抑制策略能确保"正确的人、在正确的时间、收到正确的告警"。 参考来源:Prometheus 官方文档 — Alertmanager 一、Alertmanager 架构 Alertmanager 的处理流水线分为五个阶段: Prometheus 告警规则触发 │ ▼ ┌───────────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ 接收 Receive │ ──→ │ 分组 Group │ ──→ │ 路由 Route │ ──→ │ 抑制 Inhibit│ ──→ │ 去重 Dedup │ └───────────────┘ └───────────┘ └───────────┘ └───────────┘ └─────┬─────┘ │ ▼ ┌───────────────┐ │ 发送 Notify │ │ 邮件/微信/钉钉 │ └───────────────┘ 阶段 作用 关键配置 接收 接收来自 Prometheus 的告警 receivers 分组 将相同特征的告警合并为一批 group_by 路由 根据标签匹配决定告警去向 route、matchers 抑制 当某告警触发时,静默相关低优先级告警 inhibit_rules 去重 多个 Alertmanager 实例间的告警去重 HA 模式 + Gossip 发送 通过配置的渠道发送通知 webhook / email / 等 二、路由树设计 2....

February 27, 2024 · 6 分钟 · 1115 字 · 徐保金

Prometheus监控体系快速搭建

方案架构 Exporter → Prometheus(存储) → Grafana(可视化) ↓ Alertmanager(告警分发) Docker Compose 部署 version: '3.8' services: prometheus: image: prom/prometheus:v2.52.0 ports: ["9090:9090"] volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - ./rules:/etc/prometheus/rules - prom_data:/prometheus command: - '--storage.tsdb.retention.time=30d' restart: unless-stopped grafana: image: grafana/grafana:10.4.2 ports: ["3000:3000"] volumes: [grafana_data:/var/lib/grafana] restart: unless-stopped alertmanager: image: prom/alertmanager:v0.27.0 ports: ["9093:9093"] volumes: [./alertmanager.yml:/etc/alertmanager/config.yml] restart: unless-stopped node-exporter: image: prom/node-exporter:v1.8.1 ports: ["9100:9100"] restart: unless-stopped volumes: prom_data: grafana_data: 核心配置 # prometheus.yml global: scrape_interval: 15s evaluation_interval: 15s rule_files: - "rules/*.yml" alerting: alertmanagers: - static_configs: - targets: ['alertmanager:9093'] scrape_configs: - job_name: 'node' static_configs: - targets: ['node-exporter:9100'] 常用 PromQL # CPU 使用率 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) # 内存使用率 (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 # 磁盘使用率 (node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes * 100 告警规则示例 groups: - name: host-alerts rules: - alert: HighCPU expr: 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80 for: 5m labels: severity: warning annotations: summary: "CPU 使用率过高 ({{ $labels....

February 23, 2024 · 1 分钟 · 163 字 · 徐保金

Linux 日志管理:journald 与日志轮转

概述 日志是系统运维的眼睛。从内核消息到应用日志、从安全审计到性能分析,日志贯穿了故障排查的每个环节。现代 Linux 采用 journald 作为系统日志守护进程,配合 logrotate 进行日志轮转,构成了完整的日志管理基础设施。本文深入 journald 的原理与配置、journalctl 的高级查询技巧、日志轮转策略、远程日志收集方案以及实战分析案例。 journald 原理 架构概览 journald 是 systemd 的系统日志组件,取代了传统的 syslog(rsyslog)。它接收来自内核、系统服务和应用程序的日志,统一存储为结构化的二进制格式。 [内核日志] [systemd 服务] [应用程序] │ │ │ ▼ ▼ ▼ [kmsg] [sd_journal_print] [syslog()/stdout] │ │ │ └──────────┬───────┴──────────┬───────┘ ▼ ▼ [journald] [/dev/log] │ ┌──────────┼──────────┐ ▼ ▼ ▼ [持久日志] [运行时日志] [转发到 syslog] /var/log/ /run/log/ /var/log/ journal/ journal/ messages 日志存储模式 # 查看当前存储模式 $ cat /etc/systemd/journald.conf | grep Storage #Storage=auto # 三种模式: # auto(默认): /var/log/journal 存在则持久化,否则仅内存 # persistent: 强制持久化(自动创建 /var/log/journal) # volatile: 仅内存(/run/log/journal) 模式 存储位置 重启后保留 适用场景 persistent /var/log/journal 是 生产环境 auto /var/log/journal 或 /run/log/journal 取决于目录 默认 volatile /run/log/journal 否 临时系统/安全要求 日志大小控制 # /etc/systemd/journald....

February 14, 2024 · 10 分钟 · 2022 字 · 徐保金

systemd 服务管理深度指南

systemd 架构概述 systemd 是现代 Linux 发行版的事实标准 init 系统,从 2015 年起已取代 SysVinit 成为绝大多数主流发行版的默认 init。它不只是"启动服务的工具",而是一个完整的系统和服务管理器。 核心 unit 类型 systemd 通过 unit(单元)来管理系统资源,每种 unit 类型对应一种资源: unit 类型 扩展名 作用 service .service 系统服务(守护进程) socket .socket IPC 套接字(支持套接字激活) timer .timer 定时任务(替代 cron) target .target 服务组(类似传统 runlevel) mount .mount 文件系统挂载点 device .device 内核设备 path .path 文件路径监控(文件出现时触发服务) slice .slice cgroup 资源分配层级 target 与传统 runlevel 的映射 # 查看当前默认 target systemctl get-default # 通常输出: multi-user.target(对应 runlevel 3,多用户命令行模式) # 切换到图形界面(对应 runlevel 5) sudo systemctl isolate graphical....

February 13, 2024 · 5 分钟 · 935 字 · 徐保金

Docker Compose 生产环境实战指南

概述 很多团队对 Docker Compose 的认知停留在"本地开发环境编排工具"。但事实上,在中小规模生产场景(单节点或少量节点)下,Compose 依然是性价比极高的方案。它语法简洁、学习成本低、不需要一整套 K8s 集群运维能力,就能完成多服务编排、依赖管理、健康检查、资源限制等核心工作。 本文不重复 Compose 基础语法,而是聚焦生产环境中的真实痛点:服务依赖怎么管才不会启动雪崩、健康检查怎么写才靠谱、密钥怎么不硬编码进 compose 文件、日志怎么不把磁盘写满、什么时候该从 Compose 迁移到 K8s。 本文基于 Docker Compose V2(docker compose 子命令),V1(docker-compose 独立二进制)已停止维护。参考 Compose 规范 多服务编排 生产级 Compose 文件结构 一个典型的生产环境应用至少包含:应用服务、数据库、缓存、反向代理。下面是一个完整的 Web 应用编排示例: # docker-compose.yml name: myapp services: # ========== 反向代理 ========== nginx: image: nginx:1.25-alpine container_name: myapp-nginx restart: unless-stopped ports: - "80:80" - "443:443" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/conf.d:/etc/nginx/conf.d:ro - cert_data:/etc/letsencrypt:ro - log_data:/var/log/nginx depends_on: web: condition: service_healthy networks: - frontend logging: driver: json-file options: max-size: "10m" max-file: "3" # ========== 应用服务 ========== web: build: context: ....

February 7, 2024 · 8 分钟 · 1653 字 · 徐保金