CI/CD 基础

共 31 题
📑 题目列表 31 题
#
★★★

1. CI 流水线中的依赖安全扫描(OWASP Dependency-Check/Snyk)

请说明在 CI 流水线中如何通过 OWASP Dependency-Check 或 Snyk 进行依赖安全扫描?

  • Dependency-Check 基于 NVD 漏洞库的扫描
  • Snyk 的漏洞库与许可证扫描
  • 扫描作为质量门禁与漏洞修复

OWASP Dependency-Check 通过 Maven 插件或独立工具扫描项目依赖,与 NVD 漏洞库比对,生成报告列出存在已知漏洞的依赖及其严重等级;Snyk 提供更全面的漏洞库、许可证合规与修复建议,并支持多种语言。在 CI 中,二者可作为流水线阶段:扫描依赖生成报告,若存在高危漏洞则阻断构建或发布,形成安全质量门禁。工程实践上应设定严重等级阈值、管理误报(如 Dependency-Check 的 suppression 文件),并持续更新漏洞库。

依赖安全扫描是供应链安全的核心,把漏洞发现提前到 CI,避免带漏洞发布。需区分"扫描"与"修复",扫描结果应可追踪和驱动升级。

#
★★★

2. SNAPSHOT 元数据、更新时间戳和 updatePolicy 如何影响可复现性,发布流水线应怎样锁定输入

SNAPSHOT 元数据、更新时间戳和 updatePolicy 如何影响可复现性,发布流水线应怎样锁定输入?

  • SNAPSHOT 元数据(maven-metadata.xml)与时间戳
  • updatePolicy 决定何时刷新 SNAPSHOT
  • 锁定输入保证可复现构建

SNAPSHOT 依赖的版本是动态的,Maven 通过 maven-metadata.xml 维护其时间戳与快照列表,updatePolicy(daily、always、never 等)决定本地缓存何时检查远程更新。由于 SNAPSHOT 内容可随时变化,同一构建在不同时间可能解析到不同版本,破坏可复现性。发布流水线应锁定输入:使用 RELEASE 版本、固定 SNAPSHOT 时间戳、设置 updatePolicy 为 never 或使用 dependencyManagement 锁定精确版本,确保构建输入确定。

Maven 的元数据与时间戳机制是 SNAPSHOT 可变性的来源,理解它才能设计可复现的发布流程。

#
★★★

3. Spring Boot 3.5+ 的 spring-boot-maven-plugin AOT 编译与 JVM 层 AOT 类加载(JEP 483)的边界

请说明 Spring Boot 3.5+ 的 spring-boot-maven-plugin AOT 编译与 JVM 层 AOT 类加载(JEP 483)的边界?

  • spring-boot-maven-plugin 的 AOT 处理
  • JEP 483 的 AOT 类加载(aot 缓存)
  • 框架级 AOT 与 JVM 级 AOT 的分工

Spring Boot 的 AOT 处理(process-aot)是框架层面的:在编译期分析应用上下文、生成 Bean 定义与反射元数据,属于"应用级 AOT"。JEP 483 是 JVM 层的 AOT 类加载(AOT 缓存),在 JVM 启动时加载预编译的类缓存,属于"运行时级 AOT"。二者边界:Spring Boot AOT 解决"配置与 Bean 的静态化",JEP 483 解决"类加载与解释的启动加速";二者可叠加,Spring Boot AOT 生成的原生配置文件便于 JVM/原生工具进一步 AOT 优化启动。

区分框架级与 JVM 级 AOT 有助于理解启动优化栈:一个是生成代码与元数据,一个是加速类加载与解释。

#
★★★

4. compile、runtime、provided 和 test 作用域如何影响传递依赖、编译类路径与最终制品

请说明 compile、runtime、provided 和 test 作用域如何影响传递依赖、编译类路径与最终制品?

  • 各作用域在编译类路径与运行类路径的可见性
  • 传递依赖的范围传播
  • 对最终制品(JAR 内容)的影响

各作用域在编译类路径与运行类路径的可见性不同:compile 两端都可见且会传递;runtime 仅运行时可见、编译不可见,会传递;provided 编译期可见、运行期由容器提供、不传递(也不打入 JAR);test 仅测试类路径可见、不传递。最终制品只包含 compile 与 runtime 依赖,provided 依赖(如 Servlet API)不打入 JAR,避免与容器类冲突。

作用域决定"依赖何时可见、是否传递、是否进制品"。正确使用可控制制品体积与避免类冲突。

#
★★★

5. 使用 mvn dependency:analyze 检测 Spring Boot 4.0 中未使用依赖的精度与误报场景

使用 mvn dependency:analyze 检测 Spring Boot 4.0 中未使用依赖的精度如何,有哪些误报场景?

  • dependency:analyze 的字节码分析原理
  • 误报场景(反射、SPI、配置类、注解)
  • 结合 Spring Boot 的特殊性

dependency:analyze 通过分析字节码对类文件的引用,报告"声明但未使用"与"使用但未声明"的依赖。但其精度有限,在 Spring Boot 场景下易误报:Spring 大量使用反射、配置类加载、@ImportSpringFactoriesLoaderMETA-INF/services 等非字节码直接引用,analyze 会把这些依赖误判为"未使用"。因此分析结果应结合单元测试与人工审查,不能直接删除依赖。

analyze 是"字节码级引用"分析,无法识别反射/SPI/配置加载等间接引用,这是误报根源。用于清理简单依赖可行,复杂 Spring 项目需谨慎。

#
★★★

6. CI/CD 中的测试金字塔(单元测试/集成测试/E2E 测试)

请说明 CI/CD 中的测试金字塔(单元测试、集成测试、E2E 测试)及其在流水线中的安排?

  • 测试金字塔的层级与数量分布
  • 各层测试的执行速度与成本
  • 在 CI 流水线中的阶段安排

测试金字塔是"越底层越多、越上层越少"的测试分层:底层是大量快速稳定的单元测试,中层是数量较少的集成测试(验证模块间、数据库、外部接口协作),顶层是少量慢而全面的 E2E 测试(端到端验证完整链路)。在 CI 中,单元测试在每次提交快速执行,集成测试在合并或每日运行,E2E 在发布前或特定环境运行。合理分层能最快反馈、控制成本与稳定性。

金字塔的平衡点在于"反馈速度与覆盖广度"的权衡。单元测试快而多,E2E 慢而贵,应避免倒金字塔(全 E2E)。

#
★★★

7. CI/CD 的基本概念与流水线模型

请说明 CI/CD 的基本概念与流水线模型?

  • CI(持续集成)与 CD(持续交付/部署)的区别
  • 流水线阶段模型(构建→测试→部署)
  • 流水线即代码

CI(持续集成)指频繁把代码合并到主干并自动构建、测试,尽早发现问题;CD(持续交付)指代码随时可部署到生产,持续部署则自动发布。流水线模型是一系列阶段(lint、build、test、package、deploy)的顺序执行,每个阶段有明确输入输出与质量门禁。现代 CI/CD 强调"流水线即代码"(Pipeline as Code),把流水线定义存入仓库,可版本化、可审查、可复现。

CI/CD 的核心是"自动化、快速反馈、可重复"。流水线模型把交付过程结构化,门禁保证质量。

#
★★★

8. Enforcer 的 dependencyConvergence 与 requireUpperBoundDeps 关注点有何不同,冲突应如何修复而非忽略

Enforcer 的 dependencyConvergence 与 requireUpperBoundDeps 关注点有何不同,冲突应如何修复而非忽略?

  • dependencyConvergence:要求依赖版本收敛一致
  • requireUpperBoundDeps:要求使用最高版本
  • 冲突的修复策略

dependencyConvergence 要求依赖树中同一构件只出现一个版本,若出现多个版本则失败,关注"版本一致性";requireUpperBoundDeps 要求解析出的版本不能低于被依赖方声明的最高版本,关注"版本不能回退",防止用了旧版本引发缺类。冲突修复应通过 dependencyManagement 显式锁定双方都兼容的版本,或升级/排除冲突依赖,而不是用 ignore 或加 dependency:exclude 掩盖问题,否则可能引入运行时 NoSuchMethodError

两条规则角度不同:一个管"收敛",一个管"上限"。修复要基于依赖树定位冲突路径,选择正确版本。

#
★★

9. 多发行版 Jar 如何按运行时版本选择 META-INF/versions 内容,编译与测试应覆盖哪些 JDK

多发行版 Jar(Multi-Release JAR)如何按运行时版本选择 META-INF/versions 内容,编译与测试应覆盖哪些 JDK?

  • Multi-Release JAR(MR-JAR)机制
  • META-INF/versions/ 的版本选择
  • 编译与测试的 JDK 覆盖

MR-JAR 在 META-INF/versions/<n>/ 下放置针对特定 Java 版本的类,JVM 在运行时根据当前版本选择对应类,MANIFEST.MF 声明 Multi-Release: true。编译时需用 --release 或采用 --multi-release 打包,为不同版本生成不同类。测试应覆盖应用支持的最低 JDK 与较高 JDK,验证低版本用 fallback 类、高版本用专用类,避免忽略版本差异。

MR-JAR 让一个 jar 兼容多版本 JVM。测试覆盖需包含基线版本与目标新版本,确保各版本类路径正确。

#
★★

10. Jenkins 声明式 Pipeline 的 stage/agent/post 结构如何编写,post 阶段如何做清理与通知

请说明 Jenkins 声明式 Pipeline 的 stage/agent/post 结构如何编写,post 阶段如何做清理与通知?

  • 声明式 Pipeline 的 agent/stages/steps/post 结构
  • post 阶段的条件(always/success/failure)
  • 清理与通知(cleanup、通知)

Jenkins 声明式 Pipeline 顶层用 pipeline { agent ...; stages { stage('Build'){ steps{...} } }; post { ... } } 组织。agent 指定运行节点,stages 定义阶段,每个 stage 内的 steps 执行命令。post 定义阶段/流水线结束后的动作,可按 alwayssuccessfailure 等条件执行,常用于清理(删除临时文件、归档测试报告)与通知(发送 Slack/Email 通知构建结果)。

post 是声明式 Pipeline 中处理结果与清理的关键,保证无论成败都执行通知与资源清理。

#
★★

11. Jenkins 的 Shared Library 与复用

请说明 Jenkins 的 Shared Library 及其复用价值?

  • Shared Library 的目录结构与加载
  • 封装通用步骤/变量/函数
  • 跨 Pipeline 复用

Jenkins Shared Library 是一个可复用的脚本库,包含 vars/(全局变量/步骤)、src/(Groovy 类)等目录,通过配置 library 指令加载,供多个 Pipeline 复用。它把通用逻辑(如构建、部署、通知、版本管理)封装为共享步骤,避免在每个 Pipeline 重复实现,提升一致性与可维护性。

Shared Library 是 Jenkins 的"建库"机制,把最佳实践沉淀为可复用代码。需注意版本管理与测试。

#
★★

12. Servlet API 等 provided 依赖在可执行 Jar 与外部容器部署中边界不同,如何防止打包冲突

Servlet API 等 provided 依赖在可执行 Jar 与外部容器部署中的边界不同,如何防止打包冲突?

  • provided 依赖在可执行 Jar 与外部容器的差异
  • 可执行 Jar 是嵌入式容器,需包含 Servlet 实现
  • 外部容器部署时由容器提供,需排除

provided 依赖(如 Servlet API)在外部容器部署时由容器提供,不打入应用;但在可执行 Jar(嵌入式 Tomcat)场景,Spring Boot 应用内嵌容器,需要把 Servlet 实现纳入 JAR,因此 Spring Boot 的依赖管理对不同场景有不同处理。防止冲突的关键是:使用 Spring Boot 的统一依赖管理(starter 自动选择合适的 scope),避免手工引入 Servlet API 导致版本与容器不匹配,或在外部容器部署时用 provided 排除。

打包边界取决于部署形态。嵌入式容器需包含,外部容器需排除,Spring Boot 的 starter 封装了这种差异。

#
★★

13. Shade 插件重定位包名时如何处理服务提供者文件和反射配置,遗漏 transformer 会出现什么

Shade 插件重定位包名时如何处理服务提供者文件和反射配置,遗漏 transformer 会出现什么?

  • Shade 的 relocate(重定位)
  • META-INF/services 与反射配置的 transformer
  • ServicesResourceTransformer、ManifestResourceTransformer

Shade 重定位(relocate)改变依赖的包名以避免冲突,但 META-INF/services 里的服务接口名、META-INF/spring.factories 等反射/SPI 配置引用的类名不会自动跟着包名变化,需用 ServicesResourceTransformer 合并服务文件并修正类名,用 ManifestResourceTransformer 处理 MANIFEST。遗漏 transformer 会导致运行时 ServiceConfigurationError 或依赖注入找不到实现类,因为 SPI 配置指向了旧包名/未合并的类。

重定位是"改字节码和包名",但 SPI 配置、反射字符串是文本,需 transformer 同步改写,这是遗漏的常见坑。

#
★★

14. Surefire 与 Failsafe 分别绑定哪些生命周期阶段,集成测试失败后为何仍需要 post-integration-test

Surefire 与 Failsafe 分别绑定哪些生命周期阶段,集成测试失败后为何仍需要 post-integration-test?

  • Surefire 绑定 test 阶段
  • Failsafe 绑定 integration-test 与 verify 阶段
  • post-integration-test 的清理保证

Surefire 绑定 test 阶段执行单元测试;Failsafe 绑定 integration-test 阶段运行集成测试,verify 阶段汇总结果并判定失败。post-integration-test 阶段用于集成测试后的清理(如关闭数据库、释放资源、归档报告),即使集成测试失败,Maven 也会执行 post-integration-testverify 之前的清理,保证资源被释放、报告被生成,避免测试失败导致资源泄漏和反馈缺失。

Failsafe 与 post-integration-test 的配合确保"测试失败也走清理",这是集成测试可靠性的关键。

#
★★

15. dependencyManagement 只管理版本而不自动引入依赖意味着什么,子模块何时仍需声明 dependency

dependencyManagement 只管理版本而不自动引入依赖意味着什么,子模块何时仍需声明 dependency?

  • dependencyManagement 只提供版本,不引入依赖
  • 子模块需显式声明 dependency 才引入
  • 与继承的默认行为

dependencyManagement 只在父 POM 中声明"如果使用该依赖,用哪个版本",它本身不把依赖加到任何模块的类路径。子模块若想使用该依赖,仍需在自身 <dependencies> 中显式声明(可不写版本),Maven 才会引入。这意味着它只约束版本、不决定依赖存在性,避免整个依赖树被父 POM 意外塞满。

理解"只管理版本、不引入依赖"是正确使用 dependencyManagement 的关键,避免误以为声明了版本就会生效。

#
★★

16. maven-compiler-plugin 的 release 参数为何优于只设置 source 和 target,它如何约束平台 API

maven-compiler-plugin 的 release 参数为何优于只设置 source 和 target,它如何约束平台 API?

  • source/target 只控制字节码版本
  • release 同时约束平台 API(--release)
  • 避免使用高于目标版本的 API

source/target 只控制生成的字节码版本(语法),但编译时仍使用当前 JDK 的 API,可能引用目标版本中不存在的类或方法,导致"编译通过但运行报错"。release 参数等价于 javac 的 --release,同时约束字节码版本与平台 API,使代码只能使用目标版本及以下的 API,确保在目标 JDK 上能运行。因此用 release 而非仅 source/target 更安全。

source/target 管语法,release 管"语法+API"。release 是更严格的版本约束,避免运行时缺类。

#
★★

17. optional 依赖与 exclusion 分别由库作者和使用者控制什么,滥用排除会造成哪些运行时缺类

optional 依赖与 exclusion 分别由库作者和使用者控制什么,滥用排除会造成哪些运行时缺类?

  • optional:库作者声明不传递的依赖
  • exclusion:使用者排除传递依赖
  • 滥用排除导致缺类

optional 由库作者设置,表示该依赖在使用者处不传递(如可选功能),使用者需自行引入;exclusion 由使用者设置,从传递依赖中排除某个依赖。前者的控制权在库作者,后者的控制权在使用者。滥用 exclusion 会排除掉实际被运行时需要的类,导致 NoClassDefFoundErrorClassNotFoundException 等运行时缺类,因为排除粒度太粗或基于不准确假设。

optional 是"发布者声明可选",exclusion 是"消费方裁剪"。裁剪需基于准确的依赖树,过度排除会引入运行时风险。

#
★★

18. pluginManagement 与直接声明 plugin 的执行效果有何不同,父 POM 如何安全提供默认配置

pluginManagement 与直接声明 plugin 的执行效果有何不同,父 POM 如何安全提供默认配置?

  • pluginManagement 提供默认配置但不执行
  • 直接声明 plugin 会执行
  • 父 POM 安全提供默认配置

pluginManagement 只提供插件的版本与默认配置,但不会自动执行插件;子模块需在 <build><plugins> 中直接声明该插件才会执行,此时继承 pluginManagement 的版本与配置。直接声明的 plugin 会被执行。父 POM 用 pluginManagement 可安全提供默认配置(版本、常用参数),子模块按需声明执行,实现"统一默认、按需启用",避免默认执行所有插件。

pluginManagement 是"配置仓库",直接声明是"启用"。理解二者差异避免插件意外执行或未执行。

#
★★

19. renovate/dependabot 与依赖自动升级

请说明 Renovate/Dependabot 如何实现依赖自动升级?

  • Dependabot/Renovate 的自动依赖更新
  • 版本分组、升级策略与 PR 触发
  • 自动升级与 CI 验证

Dependabot 与 Renovate 是自动依赖升级工具,扫描仓库的依赖清单(如 pom.xml、package.json),发现新版本后自动创建升级 PR,并可在 PR 中触发 CI 验证。它们支持版本分组、忽略策略、更新频率配置,能把依赖升级的"发现+提交+验证"流程自动化。工程实践上应配置升级策略(避免大版本突变)、配合 CI 测试与 Enforcer 规则,确保升级安全性。

依赖自动升级把"维护依赖最新、修复漏洞"从人工变为自动,但需 CI 验证与策略控制配合。

#
★★

20. 使用 BOM(Bill of Materials)

请说明如何使用 Maven BOM(Bill of Materials)管理依赖版本?

  • BOM 的定义与 import
  • spring-boot-dependencies 等平台 BOM
  • 统一版本与覆盖

使用 BOM 时,在 dependencyManagement 中用 <scope>import</scope> 引入 BOM,即可继承其声明的所有依赖版本,无需逐条写版本。Spring Boot 的 spring-boot-dependencies 管理整个 Spring 生态版本,其他平台 BOM 类似。引入后可覆盖 BOM 中某依赖版本(用 dependencyManagement 显式声明),但需注意冲突。BOM 让依赖版本管理集中、可复用、易升级。

BOM 是"版本管理制品",import 继承其版本。多 BOM 引入时需注意同一坐标的覆盖顺序。

#
★★

21. 依赖调解的最近路径规则在深度相同的候选版本间如何决胜,POM 声明顺序为何会影响结果

依赖调解的最近路径规则在深度相同的候选版本间如何决胜,POM 声明顺序为何会影响结果?

  • 最近路径优先
  • 深度相同时先声明者优先
  • POM 声明顺序的影响

Maven 依赖调解默认"最近路径优先":选择路径最短的版本。当多个候选版本路径深度相同时,采用"先声明者优先"(first declaration wins),即依赖树中先出现的版本被选中。因此父 POM 或模块中 <dependencyManagement><dependencies> 的声明顺序会影响最终解析的版本,进而影响类路径内容。理解顺序影响有助于预判冲突结果。

决定胜负的先是深度,后是声明顺序。顺序敏感导致同样的依赖不同顺序可能解析不同版本,这正是可复现性要留意之处。

#

22. 制品管理(Nexus/Artifactory/Docker Registry)

请说明制品管理(Nexus/Artifactory/Docker Registry)的作用?

  • 制品仓库的分类与职责
  • 二进制制品与镜像的存储
  • 制品生命周期与审计

制品管理涵盖二进制制品(JAR、WAR)与容器镜像的存储与分发。Nexus/Artifactory 是通用制品仓库(Maven 仓库、npm 等),托管、代理、缓存制品;Docker Registry(如 Harbor、Docker Hub)存储容器镜像。制品管理提供版本化存储、访问控制、审计与生命周期管理,是 CI/CD 与内部共享的基础。

制品管理是"交付物中心",保证制品可追溯、可复用、可审计。与私服、镜像仓库是同一概念的延伸。

#

23. 导入多个 BOM 出现同一坐标时如何解析版本,平台 BOM 与业务覆盖项应按什么顺序组织

导入多个 BOM 出现同一坐标时如何解析版本,平台 BOM 与业务覆盖项应按什么顺序组织?

  • 多 BOM 的版本覆盖顺序
  • dependencyManagement 中后声明者覆盖
  • 平台 BOM 与业务覆盖的组织

当多个 BOM 或 dependencyManagement 声明同一坐标版本时,Maven 按定义顺序,后声明的覆盖先声明的(同一 dependencyManagement 内)。因此组织顺序上,应把平台 BOM(如 Spring Boot)放在前面,业务或特殊覆盖项放在后面,让业务覆盖项生效。这种"先平台、后覆盖"的顺序保证默认版本来自平台,特例由业务显式覆盖。

顺序决定覆盖方向。理解"后者覆盖前者"可避免平台 BOM 版本被误覆盖或业务特例不生效。

#

24. 流水线即代码(Pipeline as Code)

请说明流水线即代码(Pipeline as Code)的概念与价值?

  • 流水线作为文件版本化
  • 可审查、可复现、可复用
  • 与代码评审/环境一致性

流水线即代码把 CI/CD 流水线定义(如 Jenkinsfile、GitHub Actions YAML、GitLab CI)作为代码存入仓库,随应用代码一起版本化、评审、分支管理。价值在于:流水线与代码一致可追溯、可审查(Merge Request 能看到流水线变更)、可复现(环境一致)、可复用(共享模板)。它把"部署流程"纳入版本控制,提升交付的规范与可靠性。

流水线即代码是对"配置漂移"的治理,让流水线的变更与代码变更一样受控。

#

25. 流水线超时与重试策略

请说明流水线超时与重试策略?

  • 阶段/流水线超时设置
  • 重试策略(幂等、退避)
  • 避免无限重试与资源浪费

流水线中的超时与重试用于应对任务卡死或瞬时失败:超时设置(如阶段 timeout)防止任务无限运行占用资源;重试策略(如声明式 Pipeline 的 retry、失败重跑)处理瞬时错误(网络抖动、依赖下载失败)。重试需保证幂等(重复执行不产生重复副作用),并采用退避避免风暴。工程设计上要区分"可重试的瞬时错误"与"不可重试的业务错误"。

超时与重试是流水线健壮性的保障。重试的前提是幂等与可恢复,避免无意义重试掩盖真实问题。

#

26. 流水线阶段(lint/test/build/package/deploy)

请说明流水线阶段(lint/test/build/package/deploy)及各阶段的作用?

  • 各阶段的职责划分
  • 阶段间的门禁与依赖
  • 阶段顺序与反馈速度

典型流水线阶段:lint(静态检查/代码规范)、test(单元/集成测试)、build(编译打包)、package(生成制品/镜像)、deploy(部署到环境)。各阶段按顺序执行,前序失败则终止,形成质量门禁。阶段划分让反馈最快(lint 最先发现低级问题)、制品可追踪、部署可控。合理划分阶段能提升 CI 效率与可维护性。

阶段是流水线的"关卡",每个阶段都有明确验收标准。快速失败、尽早反馈是阶段设计的核心。

#

27. 迁移 JDK 23 及以后版本时,为何应显式配置注解处理器路径,遗漏会让哪些生成代码消失

迁移 JDK 23 及以后版本时,为何应显式配置注解处理器路径,遗漏会让哪些生成代码消失?

  • JDK 23+ 的注解处理器默认路径变化
  • 显式配置 annotationProcessorPaths
  • 遗漏导致生成代码缺失(Lombok、MapStruct 等)

JDK 23 起,javac 对从类路径中隐式发现注解处理器(隐式注解处理)的行为发出弃用警告,官方推动显式声明处理器路径。工程实践上应在 maven-compiler-plugin 中显式配置 annotationProcessorPaths 声明使用的处理器(如 Lombok、MapStruct)。若不配置,在新的 JDK 环境下注解处理器可能不会运行,Lombok 生成的 getter/setter、MapStruct 映射实现等代码会缺失,导致编译错误或运行时找不到实现。

这是 JDK 对"类路径隐式发现处理器"行为弃用、推进显式声明的方向所致。显式声明处理器路径提升可复现性与明确性。

#

28. CI 中的 SBOM 生成与漏洞扫描

请说明 CI 中 SBOM 生成与漏洞扫描的流程?

  • SBOM(软件物料清单)的生成
  • 对 SBOM 进行漏洞扫描
  • 供应链安全与合规

SBOM 在 CI 中通过工具(如 CycloneDX、Syft)从依赖清单生成软件物料清单,列出所有组件与版本;随后可对 SBOM 进行漏洞扫描(对接漏洞库),识别已知漏洞。SBOM 生成与扫描形成供应链可见性与安全门禁,支持合规审计与漏洞响应。工程实践上应把 SBOM 作为制品发布并长期保存。

SBOM 是"成分清单",漏洞扫描是"基于成分的风险评估",二者结合是供应链安全的基础。

#

29. CI 中的镜像签名(Cosign/Sigstore)

请说明 CI 中的镜像签名(Cosign/Sigstore)的作用?

  • 镜像签名验证来源与完整性
  • Cosign/Sigstore 的签名与验证
  • 供应链安全与部署门禁

镜像签名(如 Cosign/Sigstore)在 CI 中对构建出的容器镜像进行密码学签名,并用签名记录来源与完整性。部署时验证签名,确保镜像未被篡改、来源可信,从而防止供应链攻击(如镜像投毒)。Sigstore 提供无密钥的签名基础设施(公钥/透明日志),Cosign 是常用签名工具。签名使镜像成为"可信交付物",可作为部署门禁。

签名解决"镜像可信"问题,与 SBOM(清单)、校验(完整性)互补,共同构成供应链安全。

#

30. 流水线通知(Slack/Email/Webhook)

请说明流水线通知(Slack/Email/Webhook)的实现方式?

  • 通知触发(构建结果/关键阶段)
  • Slack/Email/Webhook 集成
  • 通知与告警分级

流水线通知在构建结果或关键阶段(成功/失败/需人工确认)触发,通过 Slack Webhook、Email、通用 Webhook 等方式发送消息。实现上,在流水线的 post 或钩子阶段调用通知插件/脚本,传递构建状态、链接与摘要。通知应分级:失败通知团队、成功按需通知,避免噪音;关键发布需人工确认通知。

通知是 CI/CD 反馈闭环的一部分,让团队及时感知构建状态。合理分级避免"通知疲劳"。

#

31. 蓝绿部署(Blue-Green Deployment)

请说明蓝绿部署(Blue-Green Deployment)的策略?

  • 蓝绿两套环境与切换
  • 零停机、快速回滚
  • 资源成本与切换风险

蓝绿部署维护两套环境(蓝、绿),当前运行版本在蓝,新版本部署到绿,验证通过后把流量从蓝切换到绿,实现零停机发布;出问题可快速切回蓝(回滚)。优点是版本切换可控、回滚快速、灰度验证;缺点是资源成本翻倍(需两套环境),且切换瞬间可能产生连接/状态问题(需处理会话保持)。

蓝绿是"并行环境+一次性切换"的发布策略,与金丝雀(渐进流量)不同。适合快速回滚与无状态化应用。