aliibarznji/infralab
GitHub: aliibarznji/infralab
一个在笔记本上运行的微型数据中心实验环境,以生产级标准实践 AD 域管理、监控告警、备份恢复验证和事件响应全流程。
Stars: 0 | Forks: 0
# InfraLab
**一个微型数据中心,像对待生产环境一样认真对待。**
在一台笔记本上的四个主机:一个 Active Directory 域,配备了经过测试的告警规则的全栈监控,**按计划执行恢复和校验和验证**(而不是假定其有效)的加密备份,以及五次蓄意引发的事件——每一次都被检测、调查、解决,并记录了其根本原因。
这里的所有内容都是手工构建、故意破坏并如实记录的——包括一次最终没有确认根本原因的事件,以及这个实验室在哪些地方有意达不到生产标准的每一个细节。
**技术栈:** Windows Server 2022 · Ubuntu · Active Directory · DNS · DHCP · SMB · Prometheus · Grafana · Alertmanager · Blackbox Exporter · restic · systemd · PowerShell · Bash
## 架构
```
graph TB
subgraph HOST["VMware Workstation — Windows 11 host, 16 GB RAM"]
subgraph NET["VMnet2 · host-only · 192.168.56.0/24 · VMware DHCP disabled"]
DC["DC01 — .10
Windows Server 2022
AD DS · DNS · DHCP · SMB
windows_exporter"] MON["MON01 — .20
Ubuntu
Prometheus · Grafana
Alertmanager · Blackbox · alert-sink"] BKP["BKP01 — .30
Ubuntu
restic repository
backup + restore verification"] CLI["CLIENT01 — DHCP
Windows 11 Pro
domain member"] end end MON -->|"scrape :9182"| DC MON -->|"scrape :9100"| BKP MON -->|"probe: DNS SOA · TCP 53/445/88 · ICMP"| DC BKP -->|"CIFS via autofs"| DC CLI -->|"DHCP · DNS · Kerberos · SMB"| DC ``` | 角色 | 主机 | 用途 | |---|---|---| | Domain Controller | DC01 | 身份验证、名称解析、地址分配、文件服务 | | Monitoring | MON01 | 指标、仪表板、告警、探测、计划的健康检查 | | Backup | BKP01 | 加密、去重、自动化的异机备份,并带有经过验证的恢复功能 | | Workstation | CLIENT01 | 从最终用户的角度验证域 | VMware 自带的 DHCP 在实验室网络中被禁用——这是在任何 VM 存在之前做出的第一个配置决策。同一个网段上的两台 DHCP 服务器会产生间歇性的错误作用域租约,这些租约表现为随机的网络不稳定,而不是它们实际的配置错误。 完整的拓扑结构、IP 规划、域设计及其背后的原因: [`docs/architecture.md`](docs/architecture.md) ## 是什么让它超越了普通的家庭实验室 **1. 备份是被证明有效的,而不是假定的。** 一个每周执行的任务会恢复最新的快照,并将**每个文件**与源数据进行 SHA-256 比较。备份成功和恢复成功是独立的 Prometheus 指标,并具有独立的告警,因为一次备份可能顺利完成,但仍然无法恢复——而这正是一个单一的“备份正常”指标所掩盖的故障。 **2. 告警规则经过了单元测试。** 所有 16 条规则都由针对合成时间序列运行的 `promtool` 测试覆盖——在部署之前,每一条规则都被证明会在其阈值处触发,并在低于阈值时保持静默。这些测试首先在空规则文件下被观察到运行失败。 **3. 故障发布数据而不是删除数据。** 备份任务从 `EXIT` trap 中写入其指标,因此即使是失败的运行也会报告——并且从单独的状态文件中保留了上一次成功的时间戳。一个在失败时停止写入的简单脚本会使其时间序列变得陈旧,而与消失的时间序列进行比较的告警永远不会触发。监控系统旨在经受住其监控对象的故障。 **4. 五次事件被引发、检测和记录** ——包含真实的命令输出、包括死胡同,以及一次坦诚的“未得出明确结论”。 **5. 这个实验室与生产环境之间的差距被记录下来,而不是被隐藏。** 风险登记册列出了每一个已知的缺陷,及其发生的可能性、实际到位的缓解措施,以及生产环境会采取的替代方案。 ## 事件响应 每次事件都遵循完整的生命周期:故障 → 检测 → 调查 → 根本原因 → 修复 → 验证 → 预防。包含时间线和命令输出的完整记录在 [`docs/incidents/`](docs/incidents/) 中。 | ID | 事件 | 值得保留的发现 | |---|---|---| | [INC-001](docs/incidents/INC-001-dns-outage.md) | DC01 上的 DNS 服务停止 | 宕机被**掩盖**了:ping 正常,短名称仍然通过 NetBIOS/LLMNR 后备进行解析,而所有的 FQDN 查询都失败了。分别通过 IP、短名称和 FQDN 进行测试是隔离故障的关键——任何单一的测试都会给出错误的答案。 | | [INC-002](docs/incidents/INC-002-disk-capacity.md) | 磁盘容量耗尽 | 填满了专用卷,而不是系统盘——域控制器上满了的 `C:` 盘可能会损坏 AD 数据库。`WindowsDiskSpaceLow` 按设计在 85% 时触发。 | | [INC-003](docs/incidents/INC-003-stale-backup.md) | 备份源不可达 | 计划的测试(`umount`)被证明**在此主机上是不可能实现的**——autofs 在下一次访问时会重新挂载。取而代之的是关闭了 DC01,产生了真正的故障;挂载守卫拒绝备份空路径,而恢复需要零人工干预。 | | [INC-004](docs/incidents/INC-004-kerberos-time-skew.md) | Kerberos 时钟偏差 | 偏移了**客户端**的时钟,而不是 PDC Emulator 的时钟。随后 Kerberos 在确认的 5 分钟策略下容忍了约 19 分钟——经过了调查,排除了候选解释或将其列出,**根本原因被如实记录为未解决**,而不是强行得出一个漂亮的结论。 | | [INC-005](docs/incidents/INC-005-restore-mismatch.md) | 恢复验证失败 | 端到端驱动 `RestoreTestFailed` 贯穿 Alertmanager,期间完全没有触及 restic 仓库。还暴露了一个真正的限制:检查器无法区分备份后的编辑和损坏——已知、已记录,并且仅仅因为此数据集是静态的才被接受。 | 最深入的分析 INC-001 值得完整阅读: | 测试 | 结果 | 结论 | |---|---|---| | `ping 192.168.56.10` | 4/4 回复 | 主机和网络正常运行 | | `nslookup dc01.lab.local` | 超时 | 名称解析是发生故障的层 | | `dir \\192.168.56.10\CompanyShare` | 成功 | SMB 本身是健康的 | | `dir \\dc01\CompanyShare` | **成功** | 短名称解析*没有*使用 DNS | | `dir \\dc01.lab.local\CompanyShare` | 失败 | FQDN 需要 DNS——故障已隔离 | 预防不仅仅是重启服务:DNS 获得了故障时重启的恢复操作,一个 blackbox 探针现在会向服务器提出一个真实的 SOA 问题,而不是仅仅检查 53 端口是否打开,并且每日健康检查会验证恢复配置是否仍然有效——因为一个没有人去验证的设置,就是一个会悄无声息丢失的设置。 ## 监控与告警 | 层级 | 内容 | 方式 | |---|---|---| | 主机指标 | 三台服务器的 CPU、内存、磁盘、网络 | node_exporter、windows_exporter | | Windows 服务 | NTDS、DNS、DHCPServer、Netlogon | windows_exporter 服务收集器,停机 2m 时告警 | | 服务真实性 | DNS 是否真的*回答*了该区域的问题? | Blackbox DNS SOA 探测——对 53 端口的 TCP 检查只能证明有东西在监听,而这正是 INC-001 中的陷阱 | | 备份健康度 | 退出代码、上次成功时间、快照计数、挂载状态 | 通过 node_exporter textfile collector 的自定义指标 | | 恢复健康度 | 上次验证结果、比较的文件、不匹配数 | 独立的指标,独立的告警 | | 送达 | 每个通知都记录了其触发时间 | `alert-sink`,一个仅使用标准库的 webhook 接收器——一份事件记录所需的凭证,而 Alertmanager 的 UI 并不会保留这些 | 阈值是经过选择的,而不是默认的——每一个的理由都被记录了下来。`BackupStale` 在**25 小时触发,而不是 24 小时**:每日任务需要为运行时间差异留有余地,否则每次晚运行几分钟它都会告警,而一个可预测会触发的告警,就是人们学会去忽略的告警。`NodeDown` 告警会抑制同一主机的所有其他告警,因此通知是原因本身,而不是它的六个后果。 每个阈值的完整理由:[`docs/monitoring-policy.md`](docs/monitoring-policy.md) ## 备份与验证恢复 ``` \\DC01\CompanyShare ──CIFS via autofs──► BKP01:/mnt/dc01-share │ restic backup --tag dc01-share ▼ /var/backups/restic-repo encrypted · deduplicated · 7d/4w/6m retention ``` - **拉取,而不是推送。** BKP01 持有凭据并主动连接到 DC01;DC01 没有仓库的凭据,也没有写入其中的路径。文件服务器上的勒索软件可以触及源数据,但永远无法触及快照。 - **挂载守卫。** 一个未挂载的 CIFS 挂载点只是一个空目录,备份它会产生一个有效但为空的快照,这能满足所有的时效性检查,但什么也保护不了。相反,该任务拒绝运行——在 INC-003 中针对一个真正不可达的 DC01 证明了这一点。 - **滚动完整性检查。** 每次备份后执行 `restic check --read-data-subset=N/7`:每周一次完整的包数据验证,成本仅为每日成本的七分之一。 - **带有 `Persistent=true` 的 systemd 定时器**,从 cron 迁移而来是有记录的原因:cron 会静默跳过主机离线时错过的运行,而 BKP01 在 CLIENT01 运行时会关机以保持在内存预算之内。现在,错过的窗口会在下次启动时执行,而不是变成没有备份的一天。 - **凭据**存在于 root 拥有的 mode-600 文件中,通过路径引用——永远不会出现在任务定义、脚本正文中,或 `ps` 输出中。 完整的灾难恢复循环被端到端证明:从实时共享中删除文件,从快照中恢复,验证内容,复制回去,在 DC01 上确认。然后实现了自动化,这样即使所有人都不再关注它,它也会继续发生。策略与设计:[`docs/backup-policy.md`](docs/backup-policy.md) ## 安全决策 **共享 ACL 从默认设置开始重建。** `CompanyShare` 最初带有 `Everyone: Full Control` 权限。这变成了仅限 `LAB\IT-Team`——在**两层**上生效,因为有效的 SMB 访问权限是共享和 NTFS 权限的交集。 微妙之处在于:必须切断来自 `C:\` 的 NTFS 继承,因为父卷会传播 `Users: Read & Execute`,这会在共享 ACL 看起来完美锁定时,悄无声息地重新授予每个域用户读取访问权限。 验证过程暴露了一个真正具有教育意义的失败:更改之后,从 CLIENT01 读取正常,但写入返回了 *Access Denied*。`whoami /groups` 显示没有域组——会话 token 早于 `IT-Team` 组,并且**组成员身份在登录时被打包进 token 中,而不是实时刷新的**。注销,登录,恢复正常。读取之所以一直正常,仅仅是因为 SMB 会话已经建立;新的写入强制进行了全新的授权检查。症状显示“权限错误”,而实际上权限完全正确。 在其他方面:DC01 上的 metrics endpoint 通过防火墙限制为仅允许 collector 的地址访问(metrics endpoint 是一份详细的主机清单);blackbox 和 alert-sink 绑定到 loopback(一个暴露的 blackbox exporter 是一个现成的 SSRF 代理——`/probe?target=` 会根据指令连接到任何地方);实验室网段没有通往互联网的路由;如果 `Everyone` 再次出现在共享 ACL 上,每日健康检查会大声报错。 ## 运维文档 编写这些文档是为了让不是我的人也能运行这个实验室。 | | | |---|---| | [`docs/architecture.md`](docs/architecture.md) | 拓扑、网络和域设计、资源预算、背后的原因 | | [`docs/inventory.md`](docs/inventory.md) | 主机、服务、账户、计划任务、版本 | | [`docs/monitoring-policy.md`](docs/monitoring-policy.md) | 每个阈值及其为何设定为该数值;明确说明已知的缺陷 | | [`docs/backup-policy.md`](docs/backup-policy.md) | 范围、保留、验证,为什么快照不是备份 | | [`docs/risks.md`](docs/risks.md) | 风险登记册:已接受的风险、已到位的缓解措施、已关闭的风险 | | [`docs/incidents/`](docs/incidents/) | 五份完整的根本原因记录以及它们所遵循的模板 | | [`docs/changes/`](docs/changes/) | CHANGE-001 → 005:原因、风险、回滚、验证、结果 | | [`docs/runbooks/`](docs/runbooks/) | 六个操作手册:恢复、DNS 故障、磁盘满、DC 恢复、新主机上线 | 变更记录读起来像是一部构建历史,而不是快照——每一份都指出了它遗留的缺陷,以及后来的哪次变更修复了它。CHANGE-002 部署了仪表板但没有告警;随后 INC-001 恰恰证明了为什么这很重要;CHANGE-005 修复了它。 ## 验证 这里没有任何声明是没有经过可能失败的检查的: | 内容 | 如何证明 | |---|---| | 16 条告警规则 | `promtool check rules` + 针对合成时间序列的单元测试,首先观察到失败 | | 备份脚本 | shellcheck 干净;针对真正不可达的源测试了挂载守卫 | | 恢路径 | 每周进行全树 SHA-256 比较;通过破坏一次性恢复副本进行了负面测试 | | Windows 健康检查 | `-SelfTest` 断言渲染逻辑,包括对日志派生文本的 HTML 编码;验证在移除编码时会失败 | | 告警送达 | 每次触发都记录在带有时间戳的 alert-sink 日志中 | | 仓库规范性 | 没有提交过任何凭据——在整个 git 历史记录中进行了验证,而不仅仅是工作树 | ## 证据 十八张正在运行的实验室的截图,索引在 [`screenshots/README.md`](screenshots/README.md) 中——一切所依赖的 DHCP 配置、从用户角度看到的正常运行的域、每一个 Prometheus target 的运行状态、通过的备份和恢复,以及 alert-sink 日志实时捕获了三次事件的触发和解决,并带有事件记录中引用的时间戳。  *备份仪表板:距离上次成功备份的时间、上次运行结果、距离上次通过恢复测试的时间,以及挂载状态——备份和恢复被作为独立的信号进行追踪,因为备份可能会成功,但其恢复可能会失败。* ## 已知限制 特此声明——这是一个学习用的实验室,假装不是这样将是抹杀上述一切的最快方式。 - **单一域控制器。** DC01 发生故障会同时导致身份验证、DNS 和 DHCP 瘫痪。生产环境至少运行两个,位于不同的故障域中。 - **备份完全打破了 3-2-1 原则。** 一台物理笔记本电脑同时存放源数据和仓库。生产环境需要脱离设备和站点的副本,其中一份是不可变的。 - **该域使用 `.local`** ——这是为 mDNS 保留的;`.test` 才是正确的。在提升之后发现了这个问题,而修复它意味着重建林。被接受并记录在案:这是关于部署前代价极小、部署后代价高昂的决策中最清晰的一课。 - **AD 数据库没有被备份** ——只有文件共享被备份了。VM 快照覆盖了 DC01,但快照不是备份(策略文档解释了原因)。 - **时钟偏差告警是一个代理指标。** 此版本的 windows_exporter 暴露的是 NTP 往返延迟,而不是真正的偏移量——被记录为一个不完美的信号,而不是作为解决 INC-004 暴露问题的最终方案。 - **实验室级别的密码**,没有 PKI,没有集中式日志记录,健康检查日志尚未导出到 Prometheus——这些都是顺理成章的下一步补充。 包含可能性和生产环境补救措施的完整登记册:[`docs/risks.md`](docs/risks.md) ## 展现的技能 | 领域 | 证明 | |---|---| | Active Directory | 林部署、OU 设计、安全组、域加入、token 行为 | | Windows Server | DNS、DHCP、SMB、服务恢复、计划任务、事件日志分析 | | 访问控制 | 共享与 NTFS 的交集、继承陷阱、最小权限原则、从客户端进行验证 | | Linux 管理 | systemd 服务与定时器、autofs、CIFS、凭据文件规范 | | 监控 | Prometheus、Grafana、三种 exporter 类型、blackbox 探测、自定义指标 | | 告警工程 | 单元测试的规则、合理化的阈值、抑制、在故障中存活的指标设计 | | 备份与 DR | 加密去重备份、拉取架构、自动化的验证恢复 | | 事件响应 | 五次完整的 RCA 循环;分层故障隔离;对未解决发现的诚实处理 | | 变更管理 | 五份包含风险、回滚和验证的变更记录 | | 文档 | 策略、操作手册、风险登记册——为下一位运维者而写,而非为了作秀 | *作为一个独立的学习项目构建。不隶属于、也未被任何公司或组织认可或生产。凭据和仓库密码存储在本地,从未提交到源代码控制中。*
Windows Server 2022
AD DS · DNS · DHCP · SMB
windows_exporter"] MON["MON01 — .20
Ubuntu
Prometheus · Grafana
Alertmanager · Blackbox · alert-sink"] BKP["BKP01 — .30
Ubuntu
restic repository
backup + restore verification"] CLI["CLIENT01 — DHCP
Windows 11 Pro
domain member"] end end MON -->|"scrape :9182"| DC MON -->|"scrape :9100"| BKP MON -->|"probe: DNS SOA · TCP 53/445/88 · ICMP"| DC BKP -->|"CIFS via autofs"| DC CLI -->|"DHCP · DNS · Kerberos · SMB"| DC ``` | 角色 | 主机 | 用途 | |---|---|---| | Domain Controller | DC01 | 身份验证、名称解析、地址分配、文件服务 | | Monitoring | MON01 | 指标、仪表板、告警、探测、计划的健康检查 | | Backup | BKP01 | 加密、去重、自动化的异机备份,并带有经过验证的恢复功能 | | Workstation | CLIENT01 | 从最终用户的角度验证域 | VMware 自带的 DHCP 在实验室网络中被禁用——这是在任何 VM 存在之前做出的第一个配置决策。同一个网段上的两台 DHCP 服务器会产生间歇性的错误作用域租约,这些租约表现为随机的网络不稳定,而不是它们实际的配置错误。 完整的拓扑结构、IP 规划、域设计及其背后的原因: [`docs/architecture.md`](docs/architecture.md) ## 是什么让它超越了普通的家庭实验室 **1. 备份是被证明有效的,而不是假定的。** 一个每周执行的任务会恢复最新的快照,并将**每个文件**与源数据进行 SHA-256 比较。备份成功和恢复成功是独立的 Prometheus 指标,并具有独立的告警,因为一次备份可能顺利完成,但仍然无法恢复——而这正是一个单一的“备份正常”指标所掩盖的故障。 **2. 告警规则经过了单元测试。** 所有 16 条规则都由针对合成时间序列运行的 `promtool` 测试覆盖——在部署之前,每一条规则都被证明会在其阈值处触发,并在低于阈值时保持静默。这些测试首先在空规则文件下被观察到运行失败。 **3. 故障发布数据而不是删除数据。** 备份任务从 `EXIT` trap 中写入其指标,因此即使是失败的运行也会报告——并且从单独的状态文件中保留了上一次成功的时间戳。一个在失败时停止写入的简单脚本会使其时间序列变得陈旧,而与消失的时间序列进行比较的告警永远不会触发。监控系统旨在经受住其监控对象的故障。 **4. 五次事件被引发、检测和记录** ——包含真实的命令输出、包括死胡同,以及一次坦诚的“未得出明确结论”。 **5. 这个实验室与生产环境之间的差距被记录下来,而不是被隐藏。** 风险登记册列出了每一个已知的缺陷,及其发生的可能性、实际到位的缓解措施,以及生产环境会采取的替代方案。 ## 事件响应 每次事件都遵循完整的生命周期:故障 → 检测 → 调查 → 根本原因 → 修复 → 验证 → 预防。包含时间线和命令输出的完整记录在 [`docs/incidents/`](docs/incidents/) 中。 | ID | 事件 | 值得保留的发现 | |---|---|---| | [INC-001](docs/incidents/INC-001-dns-outage.md) | DC01 上的 DNS 服务停止 | 宕机被**掩盖**了:ping 正常,短名称仍然通过 NetBIOS/LLMNR 后备进行解析,而所有的 FQDN 查询都失败了。分别通过 IP、短名称和 FQDN 进行测试是隔离故障的关键——任何单一的测试都会给出错误的答案。 | | [INC-002](docs/incidents/INC-002-disk-capacity.md) | 磁盘容量耗尽 | 填满了专用卷,而不是系统盘——域控制器上满了的 `C:` 盘可能会损坏 AD 数据库。`WindowsDiskSpaceLow` 按设计在 85% 时触发。 | | [INC-003](docs/incidents/INC-003-stale-backup.md) | 备份源不可达 | 计划的测试(`umount`)被证明**在此主机上是不可能实现的**——autofs 在下一次访问时会重新挂载。取而代之的是关闭了 DC01,产生了真正的故障;挂载守卫拒绝备份空路径,而恢复需要零人工干预。 | | [INC-004](docs/incidents/INC-004-kerberos-time-skew.md) | Kerberos 时钟偏差 | 偏移了**客户端**的时钟,而不是 PDC Emulator 的时钟。随后 Kerberos 在确认的 5 分钟策略下容忍了约 19 分钟——经过了调查,排除了候选解释或将其列出,**根本原因被如实记录为未解决**,而不是强行得出一个漂亮的结论。 | | [INC-005](docs/incidents/INC-005-restore-mismatch.md) | 恢复验证失败 | 端到端驱动 `RestoreTestFailed` 贯穿 Alertmanager,期间完全没有触及 restic 仓库。还暴露了一个真正的限制:检查器无法区分备份后的编辑和损坏——已知、已记录,并且仅仅因为此数据集是静态的才被接受。 | 最深入的分析 INC-001 值得完整阅读: | 测试 | 结果 | 结论 | |---|---|---| | `ping 192.168.56.10` | 4/4 回复 | 主机和网络正常运行 | | `nslookup dc01.lab.local` | 超时 | 名称解析是发生故障的层 | | `dir \\192.168.56.10\CompanyShare` | 成功 | SMB 本身是健康的 | | `dir \\dc01\CompanyShare` | **成功** | 短名称解析*没有*使用 DNS | | `dir \\dc01.lab.local\CompanyShare` | 失败 | FQDN 需要 DNS——故障已隔离 | 预防不仅仅是重启服务:DNS 获得了故障时重启的恢复操作,一个 blackbox 探针现在会向服务器提出一个真实的 SOA 问题,而不是仅仅检查 53 端口是否打开,并且每日健康检查会验证恢复配置是否仍然有效——因为一个没有人去验证的设置,就是一个会悄无声息丢失的设置。 ## 监控与告警 | 层级 | 内容 | 方式 | |---|---|---| | 主机指标 | 三台服务器的 CPU、内存、磁盘、网络 | node_exporter、windows_exporter | | Windows 服务 | NTDS、DNS、DHCPServer、Netlogon | windows_exporter 服务收集器,停机 2m 时告警 | | 服务真实性 | DNS 是否真的*回答*了该区域的问题? | Blackbox DNS SOA 探测——对 53 端口的 TCP 检查只能证明有东西在监听,而这正是 INC-001 中的陷阱 | | 备份健康度 | 退出代码、上次成功时间、快照计数、挂载状态 | 通过 node_exporter textfile collector 的自定义指标 | | 恢复健康度 | 上次验证结果、比较的文件、不匹配数 | 独立的指标,独立的告警 | | 送达 | 每个通知都记录了其触发时间 | `alert-sink`,一个仅使用标准库的 webhook 接收器——一份事件记录所需的凭证,而 Alertmanager 的 UI 并不会保留这些 | 阈值是经过选择的,而不是默认的——每一个的理由都被记录了下来。`BackupStale` 在**25 小时触发,而不是 24 小时**:每日任务需要为运行时间差异留有余地,否则每次晚运行几分钟它都会告警,而一个可预测会触发的告警,就是人们学会去忽略的告警。`NodeDown` 告警会抑制同一主机的所有其他告警,因此通知是原因本身,而不是它的六个后果。 每个阈值的完整理由:[`docs/monitoring-policy.md`](docs/monitoring-policy.md) ## 备份与验证恢复 ``` \\DC01\CompanyShare ──CIFS via autofs──► BKP01:/mnt/dc01-share │ restic backup --tag dc01-share ▼ /var/backups/restic-repo encrypted · deduplicated · 7d/4w/6m retention ``` - **拉取,而不是推送。** BKP01 持有凭据并主动连接到 DC01;DC01 没有仓库的凭据,也没有写入其中的路径。文件服务器上的勒索软件可以触及源数据,但永远无法触及快照。 - **挂载守卫。** 一个未挂载的 CIFS 挂载点只是一个空目录,备份它会产生一个有效但为空的快照,这能满足所有的时效性检查,但什么也保护不了。相反,该任务拒绝运行——在 INC-003 中针对一个真正不可达的 DC01 证明了这一点。 - **滚动完整性检查。** 每次备份后执行 `restic check --read-data-subset=N/7`:每周一次完整的包数据验证,成本仅为每日成本的七分之一。 - **带有 `Persistent=true` 的 systemd 定时器**,从 cron 迁移而来是有记录的原因:cron 会静默跳过主机离线时错过的运行,而 BKP01 在 CLIENT01 运行时会关机以保持在内存预算之内。现在,错过的窗口会在下次启动时执行,而不是变成没有备份的一天。 - **凭据**存在于 root 拥有的 mode-600 文件中,通过路径引用——永远不会出现在任务定义、脚本正文中,或 `ps` 输出中。 完整的灾难恢复循环被端到端证明:从实时共享中删除文件,从快照中恢复,验证内容,复制回去,在 DC01 上确认。然后实现了自动化,这样即使所有人都不再关注它,它也会继续发生。策略与设计:[`docs/backup-policy.md`](docs/backup-policy.md) ## 安全决策 **共享 ACL 从默认设置开始重建。** `CompanyShare` 最初带有 `Everyone: Full Control` 权限。这变成了仅限 `LAB\IT-Team`——在**两层**上生效,因为有效的 SMB 访问权限是共享和 NTFS 权限的交集。 微妙之处在于:必须切断来自 `C:\` 的 NTFS 继承,因为父卷会传播 `Users: Read & Execute`,这会在共享 ACL 看起来完美锁定时,悄无声息地重新授予每个域用户读取访问权限。 验证过程暴露了一个真正具有教育意义的失败:更改之后,从 CLIENT01 读取正常,但写入返回了 *Access Denied*。`whoami /groups` 显示没有域组——会话 token 早于 `IT-Team` 组,并且**组成员身份在登录时被打包进 token 中,而不是实时刷新的**。注销,登录,恢复正常。读取之所以一直正常,仅仅是因为 SMB 会话已经建立;新的写入强制进行了全新的授权检查。症状显示“权限错误”,而实际上权限完全正确。 在其他方面:DC01 上的 metrics endpoint 通过防火墙限制为仅允许 collector 的地址访问(metrics endpoint 是一份详细的主机清单);blackbox 和 alert-sink 绑定到 loopback(一个暴露的 blackbox exporter 是一个现成的 SSRF 代理——`/probe?target=` 会根据指令连接到任何地方);实验室网段没有通往互联网的路由;如果 `Everyone` 再次出现在共享 ACL 上,每日健康检查会大声报错。 ## 运维文档 编写这些文档是为了让不是我的人也能运行这个实验室。 | | | |---|---| | [`docs/architecture.md`](docs/architecture.md) | 拓扑、网络和域设计、资源预算、背后的原因 | | [`docs/inventory.md`](docs/inventory.md) | 主机、服务、账户、计划任务、版本 | | [`docs/monitoring-policy.md`](docs/monitoring-policy.md) | 每个阈值及其为何设定为该数值;明确说明已知的缺陷 | | [`docs/backup-policy.md`](docs/backup-policy.md) | 范围、保留、验证,为什么快照不是备份 | | [`docs/risks.md`](docs/risks.md) | 风险登记册:已接受的风险、已到位的缓解措施、已关闭的风险 | | [`docs/incidents/`](docs/incidents/) | 五份完整的根本原因记录以及它们所遵循的模板 | | [`docs/changes/`](docs/changes/) | CHANGE-001 → 005:原因、风险、回滚、验证、结果 | | [`docs/runbooks/`](docs/runbooks/) | 六个操作手册:恢复、DNS 故障、磁盘满、DC 恢复、新主机上线 | 变更记录读起来像是一部构建历史,而不是快照——每一份都指出了它遗留的缺陷,以及后来的哪次变更修复了它。CHANGE-002 部署了仪表板但没有告警;随后 INC-001 恰恰证明了为什么这很重要;CHANGE-005 修复了它。 ## 验证 这里没有任何声明是没有经过可能失败的检查的: | 内容 | 如何证明 | |---|---| | 16 条告警规则 | `promtool check rules` + 针对合成时间序列的单元测试,首先观察到失败 | | 备份脚本 | shellcheck 干净;针对真正不可达的源测试了挂载守卫 | | 恢路径 | 每周进行全树 SHA-256 比较;通过破坏一次性恢复副本进行了负面测试 | | Windows 健康检查 | `-SelfTest` 断言渲染逻辑,包括对日志派生文本的 HTML 编码;验证在移除编码时会失败 | | 告警送达 | 每次触发都记录在带有时间戳的 alert-sink 日志中 | | 仓库规范性 | 没有提交过任何凭据——在整个 git 历史记录中进行了验证,而不仅仅是工作树 | ## 证据 十八张正在运行的实验室的截图,索引在 [`screenshots/README.md`](screenshots/README.md) 中——一切所依赖的 DHCP 配置、从用户角度看到的正常运行的域、每一个 Prometheus target 的运行状态、通过的备份和恢复,以及 alert-sink 日志实时捕获了三次事件的触发和解决,并带有事件记录中引用的时间戳。  *备份仪表板:距离上次成功备份的时间、上次运行结果、距离上次通过恢复测试的时间,以及挂载状态——备份和恢复被作为独立的信号进行追踪,因为备份可能会成功,但其恢复可能会失败。* ## 已知限制 特此声明——这是一个学习用的实验室,假装不是这样将是抹杀上述一切的最快方式。 - **单一域控制器。** DC01 发生故障会同时导致身份验证、DNS 和 DHCP 瘫痪。生产环境至少运行两个,位于不同的故障域中。 - **备份完全打破了 3-2-1 原则。** 一台物理笔记本电脑同时存放源数据和仓库。生产环境需要脱离设备和站点的副本,其中一份是不可变的。 - **该域使用 `.local`** ——这是为 mDNS 保留的;`.test` 才是正确的。在提升之后发现了这个问题,而修复它意味着重建林。被接受并记录在案:这是关于部署前代价极小、部署后代价高昂的决策中最清晰的一课。 - **AD 数据库没有被备份** ——只有文件共享被备份了。VM 快照覆盖了 DC01,但快照不是备份(策略文档解释了原因)。 - **时钟偏差告警是一个代理指标。** 此版本的 windows_exporter 暴露的是 NTP 往返延迟,而不是真正的偏移量——被记录为一个不完美的信号,而不是作为解决 INC-004 暴露问题的最终方案。 - **实验室级别的密码**,没有 PKI,没有集中式日志记录,健康检查日志尚未导出到 Prometheus——这些都是顺理成章的下一步补充。 包含可能性和生产环境补救措施的完整登记册:[`docs/risks.md`](docs/risks.md) ## 展现的技能 | 领域 | 证明 | |---|---| | Active Directory | 林部署、OU 设计、安全组、域加入、token 行为 | | Windows Server | DNS、DHCP、SMB、服务恢复、计划任务、事件日志分析 | | 访问控制 | 共享与 NTFS 的交集、继承陷阱、最小权限原则、从客户端进行验证 | | Linux 管理 | systemd 服务与定时器、autofs、CIFS、凭据文件规范 | | 监控 | Prometheus、Grafana、三种 exporter 类型、blackbox 探测、自定义指标 | | 告警工程 | 单元测试的规则、合理化的阈值、抑制、在故障中存活的指标设计 | | 备份与 DR | 加密去重备份、拉取架构、自动化的验证恢复 | | 事件响应 | 五次完整的 RCA 循环;分层故障隔离;对未解决发现的诚实处理 | | 变更管理 | 五份包含风险、回滚和验证的变更记录 | | 文档 | 策略、操作手册、风险登记册——为下一位运维者而写,而非为了作秀 | *作为一个独立的学习项目构建。不隶属于、也未被任何公司或组织认可或生产。凭据和仓库密码存储在本地,从未提交到源代码控制中。*
标签:Active Directory, AI合规, Libemu, Plaso, Terraform 安全, Windows Server, 基础架构, 应用安全, 数据备份, 监控告警, 自定义请求头, 运维