面试 · 对比辨析型
说出本质差异。每题含对比表 + 关键差异 + 适用场景。考察对相似技术/理念的深度区分能力,避免混淆使用。
子类 1:CI/CD 对比#
题目1:持续交付(Continuous Delivery)vs 持续部署(Continuous Deployment)#
问题: 这两个概念经常被混淆(都简写 CD),请明确区分 Continuous Delivery 和 Continuous Deployment。
| 维度 | Continuous Delivery 持续交付 | Continuous Deployment 持续部署 |
|---|---|---|
| 自动化范围 | 到"可发布"(每次 CI 通过 = 可发布候选) | 到"已发布"(CI 通过自动部署到生产) |
| 人工干预 | 需要"一键发布"按钮 | 完全无人值守 |
| 部署触发 | 人工点击 | CI 通过自动触发 |
| 适用场景 | 强合规、核心链路、schema 变更 | 高测试覆盖、有灰度+自动回滚 |
| 风险控制 | 业务方选择发布窗口 | 金丝雀分析 + 自动回滚兜底 |
| 团队信任 | 需要业务方对发布节奏有控制 | 需要团队对自动化测试和监控高度信任 |
关键差异: 核心区别在"prod 部署是否需要人工审批"。Continuous Delivery 保证代码随时可发布(每个 commit 都是一个可发布候选),但实际发布由人决定;Continuous Deployment 去掉人工审批,CI 通过就自动部署。Delivery 是"能力",Deployment 是"自动化程度"。
适用场景:
- Continuous Delivery:强合规行业、核心链路需业务方选发布窗口、schema 变更需人工评估兼容性、对测试覆盖率信心不足
- Continuous Deployment:互联网产品高频迭代、测试覆盖率高、有完善的金丝雀 + 自动回滚、监控能秒级发现问题
(三者的完整概念区分——含持续集成 CI 与本题两个 CD 的关系、混合模式、DORA Elite 特征——见「1-概念解释型·子类2·题目1」,此处只做两个 CD 的对比表,不重复。)
题目2:GitHub Actions vs GitLab CI vs Jenkins#
问题: 三大主流 CI 工具各有定位,请对比它们的架构、扩展性和适用场景。
| 维度 | GitHub Actions | GitLab CI | Jenkins |
|---|---|---|---|
| 架构 | SaaS 为主(含 self-hosted runner) | GitLab 内置(单体 + Runner) | 主节点 + Agent 分布式 |
| 配置语言 | YAML(.github/workflows) | YAML(.gitlab-ci.yml) | Groovy DSL(Jenkinsfile) |
| Runner 隔离 | 矩阵 + 容器化 job | Tag 选择 + 容器化 | Agent label + 节点池 |
| 生态 | Marketplace 海量 Action | 内置模板 + 第三方 | 插件生态最大(1800+) |
| 维护成本 | 低(SaaS 托管) | 中(GitLab 自管) | 高(主节点+Agent运维) |
| 跨云/跨地域 | runner 可部署任意云 | Runner 跨云支持 | Agent 跨云支持 |
| 国内可用性 | 不稳定(需自建 runner) | 自建版本可用 | 完全可控 |
| 学习曲线 | 低 | 中 | 高(Groovy+插件生态) |
关键差异: GitHub Actions 是"SaaS 优先 + 配置即代码",开箱即用但国内网络不稳定;GitLab CI 是"代码托管 + CI 一体化",单平台闭环但Runner 自管;Jenkins 是"老牌强大但维护重",插件生态最丰富但 Groovy DSL 学习曲线陡、主节点易成单点。
适用场景:
- GitHub Actions:开源项目、海外团队、SaaS 产品、希望零运维 CI、需要 Marketplace 生态
- GitLab CI:已用 GitLab 托管代码、希望单平台闭环、国内可用、需要内置 Container Registry 和部署功能
- Jenkins:已有大量 Jenkins 插件投入、复杂流水线逻辑(Groovy 灵活)、强合规要求自建、有专职运维团队
实战选型还要考虑:① 跨云场景(GitHub Actions runner + OIDC + 云厂商 credentials 是现代主流);② 国内场景(云效 Flow 是 GitLab CI 的国内替代,配置语言类似但有平台坑);③ 规模场景(500+ 流水线时 Jenkins 主节点压力、GitHub Actions 并发限制、GitLab CI Runner 调度)。
题目3:Helm vs Kustomize#
问题: K8s 应用打包的两大工具 Helm 和 Kustomize 走了不同路线,请对比它们的理念差异和适用场景。
| 维度 | Helm | Kustomize |
|---|---|---|
| 核心理念 | 模板引擎({{ }} 渲染) | Overlay 叠加(拿现成 yaml 打补丁) |
| 配置语言 | Go template + values.yaml | K8s 原生 YAML(无模板语言) |
| 学习曲线 | 中(要学 template 语法) | 低(K8s yaml 即配置) |
| 第三方 Chart 生态 | 巨大(kube-prometheus-stack 等) | 较小(主要业务场景) |
| 多环境差异 | values.yaml 覆盖 | Base + Overlay 分层 patch |
| 复杂逻辑 | 支持(if/range/list) | 不支持(纯声明式) |
| K8s 原生集成 | 无(需 helm CLI) | 有(kubectl -k) |
| 适合场景 | 装"不动"的基础设施 | 频繁迭代的业务服务 |
关键差异: Helm 是"模板 + 参数化",灵活但模板里可以有任意逻辑,复杂 chart 难读难调试;Kustomize 是"拿现成 yaml 打补丁",无模板语言,多环境差异通过 overlay patch 表达,新人看一眼就知道"这个环境跟 base 比多了什么"。
适用场景:
- Helm:安装第三方组件(cert-manager、kube-prometheus-stack、Karpenter、ArgoCD)、需要复杂参数化(如一个 chart 支持单机/HA/多区域部署)、社区有成熟 chart 可复用
- Kustomize:业务服务多环境部署(base + qa/pre/prod overlay)、需要看清"这个环境跟 base 的差异"、不希望引入模板语言复杂度、需要 K8s 原生工具链(kubectl -k)
实战常见组合:第三方组件用 Helm 装、业务服务用 Kustomize 管。GitOps 工具(ArgoCD/Flux)都同时支持两者。注意 ArgoCD 处理 Helm 是"helm template"渲染后 apply(不创建真 Helm release),Flux 的 helm-controller 是真 Helm install(创建真 release,支持 helm rollback)。这是 Argo vs Flux 的一个重要差异。
题目4:ArgoCD vs FluxCD#
问题: CNCF Graduated 的两大 GitOps 工具 ArgoCD 和 FluxCD 走了不同路线,请对比架构、同步语义和适用场景。
| 维度 | ArgoCD | FluxCD |
|---|---|---|
| 架构 | server-first(重 UI + API Server) | controller-first(五控制器解耦) |
| UI | 原生 Web UI(拓扑图/diff/rollback) | 无原生 UI(用 Grafana 或 Weave GitOps) |
| 同步语义 | 全局 resync(默认 180s) | per-resource interval(每个 CR 独立) |
| Helm 处理 | helm template(不创建真 release) | helm-controller 真 helm install(创建 release) |
| 多租户 | AppProject + 自有 RBAC(额外抽象) | K8s RBAC + impersonation(原生) |
| 多集群 | 中心化(一个 Argo 管 N 集群) | 联邦(每集群一个 Flux) |
| 批量部署 | ApplicationSet(Matrix Generator) | 目录结构 + substituteFrom |
| 镜像自动化 | argocd-image-updater(独立项目) | image-automation-controller(一等公民) |
| SOPS 集成 | 需要 CMP 插件(繁琐) | 原生支持(kustomize-controller 内置) |
| PR Preview | ApplicationSet PR Generator(强) | 需要外部工具辅助 |
关键差异: ArgoCD 是"server-first"重 UI 体验,开发同学能自助看 sync 状态;FluxCD 是"controller-first"无 UI 但架构干净。Helm 处理是最大差异——Argo 把 Helm 当模板引擎(helm template),Flux 创建真 Helm release 支持 helm rollback。多租户 Flux 用 K8s RBAC 原生隔离更干净,Argo 用 AppProject + 自有 RBAC 多一层抽象。多集群 Argo 中心化(主集群挂了全停),Flux 联邦(每集群独立)。
适用场景:
- ArgoCD:开发同学需要 UI 看部署状态、规模中小(<20 集群)、单云单 region、需要 PR preview 环境、不重度使用 Helm
- FluxCD:平台团队内部用、规模大(>20 集群)跨云跨 region、重度使用 Helm(需要真 release + post-renderer)、强合规要求 K8s 原生 RBAC 隔离、想嵌入 IDP 通过 CRD 编程
实战迁移建议:不要为了技术审美迁移。如果现有 ArgoCD 跑得稳、团队熟悉、扩展满足需求就继续用。迁移的触发条件是明确痛点:多集群网络打不通、Helm hook 问题长期解决不了、UI 维护成本太高、多租户权限模型撑不住。
子类 2:IaC 对比#
题目1:Terraform vs Ansible#
问题: Terraform 和 Ansible 都是 IaC 工具但定位不同,请对比它们的核心理念和分工。
| 维度 | Terraform | Ansible |
|---|---|---|
| 核心定位 | 基础设施编排(创建/销毁资源) | 配置管理(在已存在资源上配置) |
| 抽象层 | 云资源层(VPC/EC2/RDS) | OS 层(包/文件/服务) |
| 语言 | HCL(声明式 DSL) | YAML + Jinja2(声明式任务) |
| 状态管理 | state 文件(强状态) | 无状态(每次跑检测当前状态) |
| 执行模型 | plan → apply(先预览再执行) | 顺序执行 task(即时生效) |
| 并行 | 自动(资源依赖图) | 按 play 串行(可 fork 并行 host) |
| Agent | 无(通过云 API) | 无(SSH) |
| 适合场景 | 创建 VPC/子网/RDS/K8s 集群 | 装软件/改配置/批量运维 |
关键差异: Terraform 管"资源生命周期"——创建 VPC、子网、RDS 实例,state 文件记录当前真实状态,diff 出需要变更的部分。Ansible 管"主机内配置"——在已存在的机器上装包、改配置文件、重启服务,每次跑都检测当前状态并收敛。Terraform 是"造房子",Ansible 是"装修"。
适用场景:
- Terraform:云基础设施编排(VPC/子网/路由表/安全组/RDS/EKS 集群)、需要 plan 预览变更、需要 state 持久化跟踪、跨云资源管理
- Ansible:K8s 集群内应用配置(装 Docker、配置 kubelet)、批量主机运维(升级内核、改 sysctl)、配置文件分发、应急止血(批量重启服务)
实战中常组合使用:Terraform 创建 EKS 集群 → Ansible 在 worker 节点上配置监控 agent。但现代云原生趋势是"基础设施用 Terraform + 应用部署用 GitOps",Ansible 的角色逐渐被 K8s Operator/Init Container 替代。
题目2:Terraform vs Pulumi vs OpenTofu#
问题: 2023 年 HashiCorp 把 Terraform 改为 BSL 许可证后,IaC 格局变成三足鼎立。请深度对比三者。
| 维度 | Terraform | OpenTofu | Pulumi |
|---|---|---|---|
| 许可证 | BSL(非 OSI 开源) | MPL 2.0(OSI 开源) | Apache 2.0 |
| 语言 | HCL(DSL) | HCL(兼容 Terraform) | Go/Python/TS/JS/C#/Java/YAML |
| Provider 生态 | 最大(3000+) | 兼容 Terraform provider | Native + Bridge TF provider |
| 测试能力 | terraform test(1.6+ 原生框架,够用) | 同 Terraform | 通用语言单测(最强) |
| State 后端 | S3/Azure/GCS/HCP | 同 Terraform | Pulumi Cloud/S3/自建 |
| 商业支持 | HashiCorp Cloud | 社区(Spacelift/env0 第三方) | Pulumi Cloud |
| State 加密 | 依赖 backend(S3 SSE) | 原生支持(KMS/AES) | 依赖 backend |
| 适合团队 | 已有 HCL 投入 | 严格开源 + 想要新特性 | 强编程能力 + 想要类型/测试 |
关键差异:
- 语言哲学:Terraform/OpenTofu 用 HCL(声明式 DSL,无函数定义、无 class、无 loop),有意限制表达力以保持易读易审计;Pulumi 用通用编程语言,获得类型检查、IDE 补全、单测能力,但复杂逻辑写嗨了容易失控
- OpenTofu 独有特性:Early Variable Evaluation(module source 可用变量)、State Encryption(原生 KMS 加密)、Provider iteration(多 region 用 for_each 而非 alias)
- Pulumi 独有特性:Input/Output 异步模型(
pulumi.Output<string>不是字符串)、Component Resource(用 class 封装)、CrossGuard(用同语言写 policy) - OpenTofu 风险:Registry 分裂(大部分 provider 还在 registry.terraform.io)、和 Terraform 兼容性会慢慢裂开(1.8+ 新特性 Terraform 没有)
适用场景:
- Terraform:已有大量 HCL 投入、用 HashiCorp 全家桶(Vault/Consul/Nomad)、需要商业支持
- OpenTofu:严格开源要求、想要 state encryption 等新特性、团队已掌握 HCL、想从 Terraform 平滑迁移(改 CLI 名字即可)
- Pulumi:新项目、团队有强编程能力(Go/TS)、需要复杂逻辑表达、需要单测覆盖、K8s 为主(Pulumi K8s provider 体验优秀)
题目3:Ansible vs Shell 脚本#
问题: 很多团队用 Bash 脚本做运维自动化,Ansible 相比 Shell 脚本有什么本质优势?什么时候仍应该用 Shell?
| 维度 | Ansible | Shell 脚本 |
|---|---|---|
| 抽象层 | 声明式 task(state=present) | 命令式(apt install / rm) |
| 幂等性 | 模块内置(apt/service/file 都幂等) | 需要自己写(if exists / |
| 跨主机编排 | 原生(inventory + fork) | 要自己写 SSH 循环 |
| 错误处理 | task 级别 failed_when/retries | set -e + trap ERR |
| 模板 | Jinja2 | envsubst / heredoc |
| 可读性 | YAML 高 | 依赖脚本作者风格 |
| 学习曲线 | 中(要学 module + playbook 概念) | 低(会 bash 就能写) |
| 依赖 | Python + SSH | 仅 bash |
关键差异: Ansible 的核心价值是"声明式 + 幂等"——apt: name=nginx state=present 不管装没装过结果都一样;Shell 脚本要自己判断 dpkg -l | grep nginx || apt install nginx,第二次跑可能报错。Ansible 的 inventory + fork 原生支持跨主机编排,Shell 要自己写 SSH 循环 + 并行控制。Ansible 的模块化(role)让复用更容易,Shell 脚本长了就是意大利面。
适用场景:
- Ansible:多主机批量配置(装监控 agent、改 sysctl、分发证书)、需要幂等保证(多次跑结果一致)、需要审计(playbook 是 YAML 可 review)、团队多人协作(role 复用)
- Shell 脚本:临时应急止血(批量重启服务、清缓存)、单机简单操作、Ansible 模块覆盖不到的边角场景、CI 流水线里的胶水逻辑(git pull + build + push)
实战中常见错误是"用 Shell 写复杂运维逻辑"——条件分支爆炸、错误处理弱、半完成状态难恢复。判断标准:脚本超过 100 行或有 3 层以上 if/else 就该考虑 Ansible。
子类 3:可观测性对比#
题目1:EFK(Elasticsearch + Fluentd + Kibana)vs Loki + Promtail#
问题: 日志聚合的两大主流方案 EFK 和 Loki 走了不同路线,请对比它们的存储模型、成本和适用场景。
| 维度 | EFK(Elasticsearch + Fluentd + Kibana) | Loki + Promtail |
|---|---|---|
| 存储模型 | 全文索引(倒排索引) | 仅索引 label(不索引日志内容) |
| 查询语言 | KQL/Lucene(全文搜索) | LogQL(类似 PromQL + grep) |
| 存储成本 | 高(索引膨胀) | 低(只存日志原文 + label 索引) |
| 查询速度 | 全文搜索快 | 按时间范围+label 扫描,全文搜索慢 |
| 复杂度 | 高(ES 集群运维重) | 低(Loki 单二进制 + 对象存储) |
| K8s 原生集成 | 中(需要 Fluentd/Fluent Bit) | 高(Grafana 生态原生) |
| 高基数标签 | 支持(但成本爆炸) | 不支持(label 基数要控制) |
| 适合场景 | 需要全文搜索、复杂日志分析 | 云原生场景、成本敏感、按 label 查询 |
关键差异: EFK 对日志内容建倒排索引,查询快但存储成本高(索引可能比日志原文还大);Loki 只索引 label(如 app=backend, namespace=prod),日志原文压缩存对象存储(S3/OSS),查询时按 label + 时间范围扫描,全文搜索慢但成本低 10 倍。EFK 适合"我要搜某个关键字在哪些日志里",Loki 适合"我要看这个服务最近 1 小时的所有日志"。
适用场景:
- EFK:业务日志需要复杂全文搜索(如审计日志排查关键字)、已投入大量 ES 运维经验、对查询速度要求高、不差钱
- Loki:云原生 K8s 场景、成本敏感、按 label 查询为主(app=backend, env=prod)、与 Grafana/Prometheus 统一可观测性栈、日志量极大但查询模式简单
实战经验:大部分云原生团队的日志查询是"按服务+时间范围看日志",不是"全文搜索某个关键字"。Loki 的成本优势(同样日志量 Loki 是 EFK 的 1/5-1/10)让它在中小团队快速取代 EFK。但要注意 Loki 不适合高基数查询(不要把 user_id 当 label)。
题目2:Prometheus vs Datadog#
问题: 开源自建 Prometheus 和 SaaS 商业产品 Datadog 是可观测性的两大路线,请对比。
| 维度 | Prometheus(自建) | Datadog(SaaS) |
|---|---|---|
| 部署模式 | 自建(K8s 集群内) | SaaS(Agent 推送到 Datadog 云) |
| 成本模型 | 固定成本(机器+存储) | 按主机/按量计费(host × $15-50/月) |
| 指标存储 | 本地 TSDB(15-30 天) | 云端长期存储(15 个月) |
| 多云支持 | 需要联邦/remote_write | 原生(Agent 跨云推送) |
| AIOps | 无(需配合 Sloth/Robusta) | 内置异常检测 + Watchdog |
| 一站式 | 指标为主(日志/链路要另接) | 指标+日志+APM+RUM 全家桶 |
| 定制化 | 极强(PromQL + 自定义 exporter) | 中(标签+dashboard) |
| 数据主权 | 完全自有 | 数据在 Datadog 云(合规考虑) |
| 学习曲线 | 中(PromQL + 运维) | 低(Agent 装上就有数据) |
关键差异: Prometheus 是"自建+开源+按量不限",固定成本但需要运维投入,适合大规模场景(机器多时 SaaS 按主机计费会爆);Datadog 是"SaaS+一站式+开箱即用",按主机计费成本线性增长但零运维,适合小团队快速上手。Datadog 的 APM/RUM/AIOps 是 Prometheus 生态要拼凑多个组件才能达到的。
适用场景:
- Prometheus:大规模集群(100+ 节点,SaaS 按主机计费太贵)、数据主权要求(金融/政府)、已有多云可观测性栈投入、需要深度定制
- Datadog:小团队(<50 节点)零运维上手、需要一站式(指标+日志+APM+RUM)、预算充足、不想投入 SRE 维护监控栈
实战常见组合:核心监控用 Prometheus(自建可控)+ 应用 APM 用 Datadog(开箱即用)+ 日志用 Loki(成本低)。纯 Datadog 在 100+ 节点时月费可达 $5000+,自建 Prometheus 月成本 $200-400。
题目3:Jaeger vs Tempo#
问题: 分布式链路追踪的两大开源工具 Jaeger 和 Tempo(Grafana 生态)有什么区别?
| 维度 | Jaeger | Tempo |
|---|---|---|
| 起源 | Uber 开源 → CNCF | Grafana Labs |
| 存储模型 | 索引 trace(Elasticsearch/Cassandra) | 仅索引 trace_id(对象存储) |
| 查询方式 | 按 tag/service 搜索 trace | TraceQL 按 tag/属性/duration 搜索(2.0+),也支持 trace_id 直查 |
| 存储成本 | 高(索引膨胀) | 极低(对象存储) |
| 与 Grafana 集成 | 好(数据源) | 原生(Grafana 生态) |
| 与 Loki 关联 | 中(手动 trace_id 跳转) | 强(Grafana 一键下钻) |
| 与 Metrics 关联 | 中(exemplar) | 强(Grafana exemplar) |
| 适合场景 | 已有 ES/Cassandra、不用 Grafana 生态 | 已有 Grafana 栈 + 对象存储、成本敏感 |
关键差异: Jaeger 对 trace 建全量索引(Elasticsearch/Cassandra),按 service/tag/operation 搜索灵活,但索引存储成本高。Tempo 自 2.0(2023)起支持 TraceQL,可按 attribute/tag/duration 搜索 trace——"Tempo 不支持搜索"是早期印象,已过时。Tempo 真正的差异化在存储成本:它只对 trace_id 建索引、span 原文压缩存对象存储(S3/OSS),不建全量倒排索引,所以比 Jaeger 便宜约一个量级。设计上 Tempo 仍以"Metrics/Logs 发现问题 → Exemplar/trace_id 下钻到 Trace"为主流程,靠 Grafana 生态串联,TraceQL 是补充而非像 Jaeger 那样以搜索为中心。
适用场景:
- Jaeger:已有 Elasticsearch/Cassandra 投入、不用 Grafana 生态、想要成熟的搜索 UI 和 service 依赖图
- Tempo:已有 Grafana + Loki + Mimir 栈、成本敏感(对象存储比 ES 便宜约 10 倍)、查询以"从 metrics/logs 下钻到 trace"为主(TraceQL 兜底按属性搜索)
题目4:DaemonSet 采集 vs Sidecar 采集#
问题: K8s 场景下日志/监控采集有 DaemonSet 和 Sidecar 两种模式,请对比。
| 维度 | DaemonSet 采集 | Sidecar 采集 |
|---|---|---|
| 部署模式 | 每节点一个采集 agent | 每 Pod 一个采集容器 |
| 资源开销 | 低(节点级共享) | 高(每 Pod 一份) |
| 隔离性 | 弱(多 Pod 共享 agent) | 强(每 Pod 独立) |
| 配置灵活 | 低(节点级统一配置) | 高(每 Pod 可定制) |
| 故障影响 | agent 挂了影响整节点 | 单 sidecar 挂只影响一个 Pod |
| 适合场景 | 标准化日志采集(stdout/stderr) | 复杂采集(多文件、解析逻辑) |
关键差异: DaemonSet 是"节点级共享",一个 agent 采集该节点所有 Pod 的日志,资源开销低但配置统一;Sidecar 是"Pod 级独立",每个 Pod 注入一个采集容器,灵活但资源开销大。DaemonSet 适合标准化场景(采集 stdout/stderr),Sidecar 适合定制化场景(采集特定文件、复杂解析)。
适用场景:
- DaemonSet:标准化日志采集(Promtail/Fluent Bit 采集容器 stdout)、节点级监控(node-exporter)、资源敏感场景
- Sidecar:业务有特殊日志文件(不是 stdout 而是写到 /var/log/app.log)、需要复杂解析逻辑(如多行日志合并)、需要按 Pod 定制采集配置、OTel Collector 注入场景
实战趋势:DaemonSet 是主流(成本低、配置统一),Sidecar 用于特殊场景。Istio 等 service mesh 的 sidecar 注入是另一个维度(流量拦截),与采集 sidecar 不是一回事。
子类 4:理念对比#
题目1:DevOps vs SRE#
问题: DevOps 和 SRE 经常被并列提及,它们是替代关系还是互补关系?
| 维度 | DevOps | SRE(Site Reliability Engineering) |
|---|---|---|
| 起源 | 2009 DevOps Days | Google 内部实践(2003) |
| 定位 | 文化/理念/运动 | 工程方法论/岗位 |
| 核心关注 | 打破 Dev/Ops 部门墙 | 用软件工程方法解决运维问题 |
| 度量 | DORA 四指标 | SLI/SLO/错误预算 |
| 范围 | 全研发生命周期 | 可靠性+运维自动化 |
| 落地手段 | CI/CD/IaC/监控 | toil 消除/自动化/SLO 工程 |
| 关系 | 是 SRE 的文化基础 | 是 DevOps 在可靠性领域的具体实现 |
关键差异: DevOps 是"文化+理念",强调 Dev 和 Ops 协作,没有具体岗位定义;SRE 是"岗位+方法论",Google 定义了 SRE 的具体职责(SLI/SLO/错误预算/toil 限制/事故复盘)。SRE 是 DevOps 在可靠性领域的具体实现路径——DevOps 说"开发和运维要协作",SRE 说"具体怎么做(SLI 度量、错误预算控制发布、toil 消除)"。
适用场景:
- DevOps:所有团队的通用文化基础、没有专职 SRE 的小团队、希望提升研发效能
- SRE:有专职可靠性团队、核心业务对可用性要求高(99.9%+)、需要用量化方法管理可靠性
实战中常见演进路径:早期团队只有 DevOps 文化(开发兼运维)→ 业务增长后设立 SRE 岗位(专职可靠性)→ SRE 推动落地 SLO + 错误预算 + 自动化。Google 的"SRE 是 DevOps 的一种实现"是准确描述。
题目2:GitOps vs 传统 CI-CD 推送#
问题: GitOps(pull-based)和传统 CI/CD(push-based)在部署模型上有什么本质区别?
| 维度 | 传统 CI/CD 推送 | GitOps 拉取 |
|---|---|---|
| 谁持有 kubeconfig | CI Runner | 集群内 controller |
| 部署方向 | CI push 到集群 | Controller 从 Git pull |
| 状态收敛 | apply 完就走(无持续 reconcile) | 持续 reconcile(漂移自愈) |
| 回滚方式 | 重新跑流水线部署旧版 | git revert commit |
| 审计 | 流水线日志(分散) | git log(单一事实源) |
| 漂移检测 | 无 | selfHeal 自动纠正 |
| 凭据安全 | CI 持有集群 admin token | 集群内只读 Git 凭据 |
| 多集群扩展 | 每集群给 CI 配凭据 | 每集群装一次 controller |
关键差异: 核心区别在"谁持有 kubeconfig"。传统模式 CI 持有集群 admin token 执行 kubectl apply,apply 完就走,漂移没人管;GitOps 模式 controller 在集群内主动拉 Git 收敛,凭据不外泄,漂移自动纠正,回滚 = git revert。GitOps 的"单一事实源"是 Git,任何对集群的变更都必须通过 Git commit,手动 kubectl 改了会被 selfHeal 拉回。
适用场景:
- 传统 CI/CD 推送:临时部署、CI/CD 已深度集成、不需要漂移检测、小规模简单场景
- GitOps 拉取:生产环境、多集群、强合规要求审计、需要漂移自愈、希望回滚简单(git revert)
题目3:Monorepo vs Multirepo#
问题: 代码仓库组织有 Monorepo(单仓多服务)和 Multirepo(一服务一仓)两种模式,请对比。
| 维度 | Monorepo | Multirepo |
|---|---|---|
| 代码可见性 | 全局可见(改一处全局生效) | 隔离清晰(跨服务改多 PR) |
| 原子提交 | 支持(一个 commit 改多服务) | 不支持(多 PR 协调) |
| CI 粒度 | 粗(触发条件要过滤) | 细(每个 repo 独立 CI) |
| 权限管理 | 粗(统一权限) | 细(按 repo 分权) |
| 依赖管理 | 内部包直引 | 内部包要发布到 registry |
| 工具要求 | 高(Bazel/Nx/TurboRepo) | 低(标准 git) |
| 适合规模 | 大公司(Google/Meta) | 中小团队 |
关键差异: Monorepo 的核心价值是"原子提交"——跨服务重构一个 commit 改完,不会出现"A 服务改了 B 服务还没改"的中间状态;代价是 CI 要做路径过滤(不能改一个文件触发全量构建)、权限管理粗(所有人能看所有代码)。Multirepo 的核心价值是"隔离清晰"——每个服务独立 CI/权限/发布节奏;代价是跨服务改动要多 PR 协调、内部包要发 registry。
适用场景:
- Monorepo:大公司强工具链支持(Bazel/Nx)、需要原子跨服务重构、服务间强耦合、统一技术栈
- Multirepo:中小团队、服务间松耦合、不同服务不同技术栈、需要按服务分权
题目4:GitFlow vs TrunkBased Development#
问题: 分支模型的两大流派 GitFlow 和 Trunk-Based 各有什么特点?
| 维度 | GitFlow | Trunk-Based |
|---|---|---|
| 主分支 | main + develop + feature/release/hotfix | main(唯一长期分支) |
| 分支生命周期 | 长(feature 几天到几周) | 短(feature < 1 天) |
| 合并频率 | 低(按 release 周期) | 高(每天多次) |
| 发布分支 | 独立 release 分支 | main 直接发布或短 release branch |
| 适合规模 | 大团队 + 长发布周期 | 中小团队 + 持续部署 |
| 复杂度 | 高(多分支管理) | 低(main + 短 feature) |
| 配套要求 | release manager | 强 CI/CD + feature flag |
关键差异: GitFlow 有 develop/release/hotfix 多种长期分支,适合"按版本发布"的传统软件;Trunk-Based 只有 main 一个长期分支,feature 分支短命(< 1 天),适合"持续部署"的互联网产品。Trunk-Based 的核心是"频繁合并到 main + feature flag 控制功能开关",没有发布分支的概念。
适用场景:
- GitFlow:企业软件按版本发布(如 v1.0/v2.0)、需要支持多版本并行(hotfix 老版本)、大团队需要 release manager 协调
- Trunk-Based:互联网产品持续部署、小团队快速迭代、有完善的 CI/CD 和 feature flag 支持
现代云原生主流是 Trunk-Based + GitHub Flow(feature → MR → main,main 永远可发)。GitFlow 在 SaaS 场景已少见。
子类 5:安全对比#
题目1:Vault vs 云 KMS vs SOPS#
问题: 密钥管理的三大方案 Vault、云 KMS、SOPS 各有什么定位和适用场景?
| 维度 | HashiCorp Vault | 云 KMS(AWS KMS/阿里云 KMS) | SOPS(Mozilla) |
|---|---|---|---|
| 定位 | 完整密钥管理系统 | 加密原语服务(加解密 API) | 文件加密工具 |
| 密钥存储 | Vault 自己管(可加密存储) | 云厂商托管(HSM 保护) | 不存密钥(用 KMS/Vault 加密) |
| 动态密钥 | 支持(数据库临时账号) | 不支持 | 不支持 |
| 审计日志 | 完整(每次访问有日志) | CloudTrail 记录 API 调用 | 无(依赖 KMS 审计) |
| K8s 集成 | ESO + Kubernetes Auth | ESO + IRSA/Pod Identity | kustomize-controller 原生 |
| 运维复杂度 | 高(HA 部署 + Unseal) | 低(SaaS) | 低(无服务端) |
| 适合场景 | 复杂密钥管理 + 动态凭证 | 数据加密 + 签名 | GitOps yaml 加密 |
关键差异: Vault 是"完整密钥管理系统"——管理密钥生命周期、支持动态密钥(数据库临时账号)、有审计日志和 Policy,但运维重(HA + Unseal + Auto-unseal);云 KMS 是"加密原语服务"——只提供加解密 API,密钥本身在云厂商 HSM 里,简单但功能单一;SOPS 是"文件加密工具"——用 KMS/Vault 的密钥加密 yaml/json 文件,加密文件可以直接入 Git,GitOps controller 解密后 apply。
适用场景:
- Vault:需要动态密钥(数据库临时账号)、需要完整审计日志、跨云统一密钥管理、合规要求高
- 云 KMS:数据加密(S3 SSE-KMS)、镜像签名(Cosign 用 KMS)、应用层加密(ChaCha20 密钥托管)、简单场景
- SOPS:GitOps 仓库里的 Secret 加密(加密 yaml 入 Git)、配置文件加密、与 Flux 原生集成
实战常见组合:Vault 管理动态密钥(数据库账号)+ 云 KMS 做底层数据加密 + SOPS 加密 GitOps 里的少量静态 Secret。不要把所有密钥都塞 Vault——简单场景用云 KMS + SOPS 更轻量。
题目2:SAST vs DAST#
问题: 静态安全测试 SAST 和动态安全测试 DAST 各有什么优劣?
| 维度 | SAST(静态) | DAST(动态) |
|---|---|---|
| 测试对象 | 源代码 | 运行中的应用 |
| 执行阶段 | 开发/PR 阶段 | Staging 部署后 |
| 发现漏洞类型 | SQL 注入、XSS、硬编码密钥 | 运行时漏洞、配置错误、未授权访问 |
| 误报率 | 高(理论漏洞可能不可利用) | 低(已验证可利用) |
| 覆盖率 | 高(能扫所有代码路径) | 低(只能扫到有路由的接口) |
| 速度 | 快(分钟级) | 慢(小时级) |
| 依赖源码 | 是 | 否 |
| 业务逻辑漏洞 | 不能 | 部分(如未授权访问) |
关键差异: SAST 扫源代码发现"可能存在的漏洞"(误报高但覆盖广),DAST 扫运行时应用发现"真实可利用的漏洞"(误报低但覆盖窄)。SAST 是"白盒"(看代码),DAST 是"黑盒"(模拟攻击者)。两者互补——SAST 扫不出运行时配置错误,DAST 扫不出硬编码密钥。
适用场景:
- SAST:PR 阶段质量门禁、commit 钩子、IDE 实时提示、需要早发现
- DAST:Staging 部署后定期扫描、上线前安全验收、合规审计
题目3:PSP(PodSecurityPolicy)vs PSA(Pod Security Admission)#
问题: K8s 1.25 移除了 PodSecurityPolicy,替换为 Pod Security Admission。请对比两者。
| 维度 | PSP(已废弃) | PSA(替代) |
|---|---|---|
| K8s 版本 | < 1.25(1.25 移除) | ≥ 1.25 |
| 配置方式 | ClusterRole + PodSecurityPolicy CRD | Namespace label |
| 粒度 | 细(可配每个字段) | 粗(三个级别 privileged/baseline/restricted) |
| 灵活性 | 高(自定义规则) | 低(预置三档) |
| 维护成本 | 高(策略复杂易错) | 低(标签即配置) |
| 扩展 | 原生 | 配合 Kyverno/OPA 补细粒度 |
关键差异: PSP 用 ClusterRole + CRD 配置,可以精细控制每个字段(如"允许 hostNetwork 但禁止 hostPID"),但策略复杂易错、维护成本高;PSA 用 namespace label 配置三个级别(privileged 不限、baseline 禁已知高危、restricted 最严),简单但粒度粗。PSA 的理念是"简单 + 默认安全",复杂策略交给 Kyverno/OPA。
适用场景:
- PSA restricted:所有业务 namespace 默认配置(禁止 privileged、runAsNonRoot、readOnlyRootFilesystem)
- PSA baseline:基础设施 namespace(需要部分高危能力但有约束)
- PSA privileged:kube-system 等系统 namespace
- Kyverno/OPA:需要细粒度策略(如"只允许特定服务账号使用 hostNetwork")
迁移建议:K8s 1.25+ 必须从 PSP 迁到 PSA + Kyverno 组合,PSA 做基线 + Kyverno 做细粒度。
子类 6:服务网格对比#
题目1:Istio vs Linkerd#
问题: 两大主流服务网格 Istio 和 Linkerd 走了不同路线,请对比数据面、功能、运维成本和适用场景。(服务网格本身的概念——数据面/控制面、mTLS、sidecar vs ambient——见「1-概念·子类5」。)
| 维度 | Istio | Linkerd |
|---|---|---|
| 数据面代理 | Envoy(C++,功能全、重) | linkerd2-proxy(Rust 微代理,轻、专注) |
| 控制面 | istiod(单体,整合 Pilot/Citadel/Galley) | 多组件(destination/identity/proxy-injector) |
| 无 sidecar 模式 | Ambient(ztunnel + waypoint,2024 GA) | 暂无(专注 sidecar,主打轻量) |
| 功能广度 | 极全(L7 路由/故障注入/限流/多集群/WASM 扩展) | 聚焦核心(mTLS/负载均衡/重试/可观测),少而精 |
| 流量治理 | VirtualService + DestinationRule(强、复杂) | HTTPRoute/ServiceProfile(简单) |
| mTLS | 支持(可选,配置项多) | 默认自动开启,零配置 |
| 资源开销 | 较高(Envoy 每 Pod ~50-100MB) | 很低(Rust 代理 ~10MB) |
| 学习曲线 | 陡(CRD 多、概念多) | 平缓(开箱即用) |
| 生态/治理 | CNCF 毕业,社区最大,云厂商托管多 | CNCF 毕业,社区较小但口碑好 |
关键差异: Istio 是"功能最全但复杂"——Envoy 数据面能力强,VirtualService/DestinationRule 支持精细流量治理(金丝雀、PR 隔离、故障注入),代价是概念多、CRD 多、Envoy 资源开销大、排障链路长。Linkerd 是"轻量专注"——Rust 写的超轻微代理,mTLS 默认开、零配置,运维简单,但功能面窄(复杂 L7 路由、多集群、WASM 扩展这些 Istio 强项 Linkerd 弱或没有)。两者都是 CNCF 毕业项目。
适用场景:
- Istio:需要精细流量治理(金丝雀/灰度/PR 隔离强依赖 VirtualService+DestinationRule)、多集群/多租户、要 WASM/EnvoyFilter 深度扩展、团队有精力吃透复杂度、想用 ambient 省 sidecar 开销
- Linkerd:想要 mTLS + 基础可观测性但不想背 Istio 的复杂度、资源敏感、中小规模、"够用就好"优先运维简单
实战提示:选 Istio 往往不是因为"更好",而是因为需要它的高级流量能力(4-场景排查题里的 PR 隔离 baggage 路由、金丝雀 subset 都强依赖 Istio 的 VirtualService/DestinationRule)。如果只需要"给服务间加个 mTLS + 看看 golden metrics",Linkerd 的总拥有成本低得多。