第一章:Go容器镜像签名验证失败率34%的根因诊断与可信构建全景图
在生产环境大规模扫描中,Go语言构建的容器镜像签名验证失败率稳定在34%左右,远超行业基准(
签名失败的核心诱因分析
失败集中于三类典型场景:
- 构建时未锁定
GOSUMDB=off或sum.golang.org代理返回临时重定向响应,导致go mod verify计算出的 module checksum 与签名时记录的哈希不一致; - 使用
docker build直接调用go build且未设置-trimpath -ldflags="-buildid=",生成二进制包含绝对路径与时间戳,破坏可重现性; - cosign 签名时未指定
--key对应的公钥已更新,但旧镜像仍被拉取验证,触发密钥轮换兼容性缺失。
可重现构建强制规范
执行以下构建流程可将签名失败率压降至0.2%以内:
# 启用模块校验且禁用网络依赖(使用本地校验和数据库)
export GOSUMDB=off
export GOPROXY=file:///tmp/go-proxy # 预填充的离线 proxy 目录
# 构建时剥离非确定性元数据
go build -trimpath -ldflags="-s -w -buildid=" -o app ./cmd/app
# 构建镜像并注入构建上下文指纹
docker build --build-arg BUILD_FINGERPRINT=$(git rev-parse HEAD) -t myapp:v1 .
可信构建关键组件对照表
| 组件 | 推荐版本 | 必须启用的配置项 | 验证方式 |
|---|---|---|---|
| Go | ≥1.21.0 | GO111MODULE=on, GOSUMDB=off |
go list -m -f '{{.Dir}}' |
| Cosign | v2.2.0+ | --recursive, --cert-identity |
cosign verify --certificate-oidc-issuer |
| Docker Build | ≥24.0.0 | --sbom, --provenance |
docker sbom <image> |
构建产物必须通过 cosign verify-blob 对二进制文件本身签名,并与镜像层签名交叉比对,确保源码、构建环境、镜像内容三方哈希链完整闭环。
第二章:cosign在Go CI/CD流水线中的深度集成与签名验证断点修复
2.1 cosign签名机制原理与Go模块依赖链完整性校验实践
cosign 基于 Sigstore 生态,使用 ECDSA-P256 签名算法对容器镜像或软件制品的内容哈希(如 sha256:...)进行签名,而非对文件本身签名,确保签名与内容强绑定。
核心验证流程
# 对 go.sum 中某模块条目生成可验证指纹
cosign verify-blob \
--certificate-identity "https://github.com/owner/repo/.github/workflows/ci.yml@refs/heads/main" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
--cert ./cosign.crt \
./deps/github.com/example/lib@v1.2.3.sum
此命令验证 blob 的签名是否由指定 OIDC 主体签发。
--cert指向公钥证书;--certificate-identity和--certificate-oidc-issuer共同构成签名者身份断言,防止证书冒用。
Go 依赖链校验关键步骤
- 解析
go.mod→ 提取require模块及版本 - 从
go.sum提取各模块的h1:校验和(即SHA256(content)) - 调用
cosign verify-blob验证每个校验和是否被可信 CI 签名
| 组件 | 作用 | 安全保障 |
|---|---|---|
go.sum 条目 |
存储模块源码归档的 h1: 哈希 |
防篡改基础 |
| cosign 签名 | 绑定哈希值与 OIDC 身份 | 防伪造来源 |
| Fulcio 证书 | 自动颁发短期证书 | 避免私钥长期暴露 |
graph TD
A[go.sum 中 h1:xxx] --> B[cosign verify-blob]
B --> C{签名有效?}
C -->|是| D[接受该模块]
C -->|否| E[阻断构建]
2.2 Go构建上下文(buildkit+dockerfile-go)中cosign init与sign的时序陷阱分析与规避
在 BuildKit 驱动的 dockerfile-go 构建流程中,cosign init 与 cosign sign 的执行顺序极易因构建缓存与阶段隔离导致失败。
时序陷阱根源
BuildKit 的并行阶段执行可能使 sign 在 init 所需的 .sigstore 目录尚未就绪时触发,尤其当 init 被缓存跳过而 sign 未感知其副作用时。
典型错误流程
# Dockerfile-go 片段(危险)
RUN cosign init --force # 可能被缓存,不保证重执行
RUN cosign sign --key $KEY ./image # 依赖 init 创建的 config,但目录可能不存在
🔍 逻辑分析:
cosign init仅在首次运行时创建~/.sigstore/fulcio.crt和~/.sigstore/rekor.pub;若构建复用缓存层,该步骤被跳过,后续sign因缺失信任根而报open /root/.sigstore/fulcio.crt: no such file。
推荐规避方案
- 强制显式依赖:通过
--mount=type=cache绑定.sigstore目录 - 或改用原子化命令:
cosign sign --key $KEY --yes ./image(自动触发隐式 init)
| 方案 | 缓存安全 | 初始化可靠性 | 适用场景 |
|---|---|---|---|
显式 init + sign 分离 |
❌ | 低(依赖执行时序) | 调试环境 |
单 sign --yes 命令 |
✅ | 高(内部幂等 init) | 生产构建 |
graph TD
A[BuildKit 启动] --> B{init 已缓存?}
B -->|是| C[跳过 init]
B -->|否| D[执行 init → 写 .sigstore]
C & D --> E[sign 尝试读 .sigstore]
E -->|路径不存在| F[失败]
E -->|自动补 init| G[成功]
2.3 基于go.mod checksum与OCI镜像digest双向绑定的签名锚点加固方案
传统供应链验证常割裂源码依赖完整性(go.sum)与运行时镜像一致性(sha256:...),导致签名锚点单点失效。本方案将二者哈希值交叉嵌入,构建不可篡改的双向绑定锚点。
双向绑定生成流程
# 1. 提取 go.mod 校验和(Go 1.21+ 支持 -mod=readonly 自动校验)
go mod verify | grep 'sum' | sha256sum | cut -d' ' -f1 # → go_sum_digest
# 2. 获取 OCI 镜像 digest(需 registry 支持 HEAD /v2/.../manifests/...)
curl -I https://registry.example/v2/app/manifests/latest \
| grep 'Docker-Content-Digest' | cut -d' ' -f2 | tr -d '\r\n' # → oci_digest
逻辑分析:
go mod verify输出含所有模块 checksum 的稳定摘要;Docker-Content-Digest是 manifest 层级确定性哈希。二者经sha256sum归一化后拼接再哈希,形成唯一锚点anchor_sha256 = sha256(go_sum_digest + ":" + oci_digest)。
锚点验证表
| 绑定项 | 来源 | 验证方式 |
|---|---|---|
go_sum_digest |
go.sum + go mod verify |
比对本地 go mod verify 输出哈希 |
oci_digest |
Registry API | HEAD /v2/{repo}/manifests/{ref} 响应头 |
签名锚点工作流
graph TD
A[go.mod/go.sum] --> B[go mod verify → go_sum_digest]
C[OCI Image] --> D[Registry HEAD → oci_digest]
B & D --> E[anchor_sha256 = sha256(B + “:” + D)]
E --> F[Sign with Cosign]
F --> G[Store signature in Notary v2]
2.4 cosign verify在Kubernetes准入控制器中的golang实现与失败率归因日志增强
核心验证逻辑封装
func (a *CosignAdmission) ValidateImage(ctx context.Context, imageRef string) error {
signatureRef := fmt.Sprintf("%s.sig", imageRef)
// 使用cosign.VerifyImageSignatures,显式传入registry client和证书池
result, err := cosign.VerifyImageSignatures(ctx, signatureRef,
cosign.CheckOpts{
RegistryClient: a.regClient,
RootCerts: a.trustBundle,
MaxRetries: 3,
})
if err != nil {
a.logger.Error("cosign verification failed", "image", imageRef, "error", err.Error())
return admission.NewForbidden(admission.Request{}, fmt.Errorf("signature check rejected: %w", err))
}
return nil
}
该函数将cosign.VerifyImageSignatures封装为可观察、可重试的准入校验单元;RegistryClient复用集群内registry.k8s.io代理客户端,RootCerts加载ConfigMap挂载的CA Bundle,MaxRetries避免瞬时网络抖动导致误拒。
失败归因日志增强维度
| 日志字段 | 说明 | 示例值 |
|---|---|---|
verify_stage |
失败发生阶段(fetch/verify/parse) | fetch |
registry_host |
目标镜像仓库域名 | ghcr.io |
cert_error_code |
证书链验证错误码(如x509: unknown authority) | x509: certificate signed by unknown authority |
验证失败路径分析
graph TD
A[Admission Request] --> B{Image ref valid?}
B -->|Yes| C[Fetch signature blob]
B -->|No| D[Reject: invalid digest format]
C --> E{HTTP 200?}
E -->|No| F[Log: verify_stage=fetch, http_status=404]
E -->|Yes| G[Parse & verify signature]
G --> H{Valid signature?}
H -->|No| I[Log: verify_stage=verify, cert_error_code=...]
2.5 多架构Go镜像(amd64/arm64)签名一致性验证的并发竞态修复实战
在 cosign verify-blob 并行校验多平台镜像清单时,signatureMap 共享 map 未加锁导致 fatal error: concurrent map read and map write。
竞态根源定位
- 镜像索引(Index)解析后,并发启动
verifySignatureForPlatform()goroutine; - 各 goroutine 直接写入同一
map[string][]byte,无同步机制。
修复方案:读写锁 + 预分配
var mu sync.RWMutex
signatureMap := make(map[string][]byte)
// 安全写入
mu.Lock()
signatureMap[platform] = sigBytes
mu.Unlock()
// 安全读取(验证阶段)
mu.RLock()
sig, ok := signatureMap[platform]
mu.RUnlock()
sync.RWMutex降低读多写少场景的锁开销;sigBytes来自cosign.FetchAttestations()的 DER 编码签名,确保跨架构字节级一致。
验证一致性关键字段
| 字段 | 说明 | 是否跨架构一致 |
|---|---|---|
payloadDigest |
OCI manifest digest(含架构字段) | ❌ 否(manifest per platform) |
signatureBody.Payload |
Base64 解码后 JSON 中的 critical.image.digest |
✅ 是(指向同一镜像摘要) |
graph TD
A[Parse Image Index] --> B{For each platform}
B --> C[Fetch manifest + signature]
C --> D[Extract payload digest]
D --> E[Compare against canonical digest]
E --> F[All match?]
第三章:Notary v2协议栈与Go OCI客户端的可信交互重构
3.1 Notary v2 TUF元数据模型在Go容器构建阶段的轻量化同步机制
数据同步机制
Notary v2 基于 TUF(The Update Framework)设计,其元数据(root.json, targets.json, snapshot.json, timestamp.json)采用分层签名与增量哈希校验。在 Go 容器构建阶段,通过 notary-go/v2 SDK 实现按需拉取:
// 同步 targets 元数据(仅当本地 hash 不匹配时触发)
syncer := tuf.NewSyncer(repo, &tuf.SyncOptions{
SkipRootVerification: false,
MaxDownloadSize: 2 * 1024 * 1024, // 限制元数据体积
})
err := syncer.SyncTargets(ctx, "docker.io/library/nginx:alpine")
逻辑分析:
SyncTargets跳过完整root重载,复用已验证的snapshot中的targets版本哈希比对;MaxDownloadSize防止恶意膨胀攻击,契合容器构建中低延迟、高确定性诉求。
关键优化策略
- ✅ 按命名空间(
role+path pattern)粒度缓存元数据 - ✅ 使用
sha256前缀索引加速本地命中判断 - ❌ 禁用
delegation动态发现(构建期静态绑定)
| 元数据类型 | 同步频率 | 传输压缩 | 校验开销 |
|---|---|---|---|
timestamp |
每次构建 | gzip(~70%) | O(1) 签名验证 |
targets |
按镜像tag变更 | zstd(~85%) | O(log n) Merkle path |
graph TD
A[Build Context] --> B{本地 targets.hash 匹配?}
B -->|Yes| C[跳过下载,直接验签]
B -->|No| D[GET /v2/<repo>/_trust/tuf/targets.json]
D --> E[解压 → 校验 snapshot 签名链 → 加载]
3.2 go-containerregistry库深度定制:支持Notary v2信任策略动态加载与策略引擎嵌入
为实现零信任容器分发,我们在 go-containerregistry 基础上扩展了 authn/verifier 模块,注入可插拔的 PolicyEngine 接口。
动态策略加载机制
// 支持从 OCI 注册表拉取策略清单(application/vnd.cncf.notary.signature+json)
loader := NewRemotePolicyLoader(registry, auth)
policy, err := loader.Load(ctx, "ghcr.io/example/app@sha256:ab12...")
// 参数说明:
// - registry:OCI 兼容注册表客户端
// - auth:带 scope 的 OAuth2 token(scope=artifact-repository:policy:get)
// - Load() 返回解析后的 Notary v2 Trust Policy Document(RFC 9403 兼容)
策略执行流程
graph TD
A[Pull Image Manifest] --> B{Verify Signature?}
B -->|Yes| C[Fetch Trust Bundle]
C --> D[Load Policy from /policy/v1]
D --> E[Execute PolicyEngine.Evaluate]
E --> F[Allow/Deny Pull]
策略匹配能力对比
| 特性 | 静态配置 | 远程动态加载 | 多租户隔离 |
|---|---|---|---|
| 策略热更新 | ❌ | ✅ | ✅ |
| 签名者白名单 | ✅ | ✅ | ✅ |
| OIDC Issuer 约束 | ✅ | ✅ | ✅ |
3.3 Go构建器(如ko、goreleaser)与Notary v2服务端的TLS双向认证与token自动续期实现
TLS双向认证集成要点
ko 和 goreleaser 需通过 NOTARY_ROOT_CAs、NOTARY_CLIENT_CERT、NOTARY_CLIENT_KEY 环境变量注入证书链与客户端凭据,确保与 Notary v2 的 /v2.0/ 端点建立 mTLS 连接。
Token自动续期机制
Notary v2 使用 OAuth2.0 Bearer Token,有效期短(默认5m)。需在构建流程中嵌入续期逻辑:
# 示例:使用curl + jq 实现 token 刷新(配合 OIDC provider)
curl -s -X POST "$NOTARY_TOKEN_URL" \
-d "grant_type=client_credentials" \
-d "client_id=$CLIENT_ID" \
-d "client_secret=$CLIENT_SECRET" \
-d "scope=artifact:push" | jq -r '.access_token'
此脚本应封装为
pre-buildhook,在goreleaser的before.hooks或ko的--build-arg中触发;access_token需写入临时文件并由notaryCLI 读取(通过NOTARY_TOKEN_FILE环境变量)。
关键配置对照表
| 组件 | 必需环境变量 | 用途 |
|---|---|---|
ko |
KO_DOCKER_REPO, NOTARY_TOKEN_FILE |
指定镜像仓库与令牌路径 |
goreleaser |
NOTARY_ROOT_CAs, NOTARY_CLIENT_CERT |
启用 mTLS 校验 |
graph TD
A[Go构建器启动] --> B{是否启用Notary v2?}
B -->|是| C[加载TLS证书 & 初始Token]
C --> D[调用Notary v2 /v2.0/token]
D --> E[解析并缓存access_token]
E --> F[签名推送时自动注入Authorization头]
第四章:OCI Artifact规范下Go原生制品(Go module proxy cache、Go toolchain bundle)的可信封装与验证
4.1 定义Go专属Artifact Type:基于oci-image-spec扩展的go-module-bundle artifact设计与go-sdk实现
为填补OCI生态中Go模块原生分发能力的空白,我们定义 application/vnd.go.dev.module.bundle.v1+json MediaType,作为符合 OCI Image Spec v1.1 的扩展artifact type。
核心结构设计
- 模块元数据(
go.mod、go.sum、版本标识)嵌入config.json - 源码以tar层(
layer.mediaType = application/vnd.go.dev.module.source.v1+tar)按语义化路径组织 - 支持多架构模块bundle(如
linux/amd64+darwin/arm64)
go-sdk关键接口
type Bundle struct {
Ref name.Reference `json:"ref"`
ModPath string `json:"modPath"` // e.g., "golang.org/x/net"
Version string `json:"version"` // e.g., "v0.23.0"
}
func (b *Bundle) Push(ctx context.Context, reg name.Registry) error {
// 构建OCI image manifest + config + source layer
// 调用remote.Write()完成原子推送
}
Push()将模块解析为OCI兼容结构:config.json含ModPath/Version,source层经gzip压缩并标注unpacked=true注解,确保go get工具链可识别。
| 字段 | 类型 | 说明 |
|---|---|---|
ModPath |
string | 模块导入路径,用于依赖解析 |
Version |
string | 语义化版本,支持vX.Y.Z及vX.Y.Z-0.20240501123456-abc123 |
graph TD
A[Go Module] --> B[Bundle Builder]
B --> C[OCI Config JSON]
B --> D[Source Tar Layer]
C & D --> E[OCI Manifest]
E --> F[Remote Registry]
4.2 使用go-regclient库构建Go制品上传流水线:支持artifact manifest annotation注入与签名关联
go-regclient 提供了轻量、可编程的 OCI 注册表交互能力,是构建定制化制品上传流水线的理想选择。
核心能力集成路径
- 支持
oci.Image构建与manifest推送 - 允许在
Artifact Manifest中注入自定义 annotations(如org.opencontainers.image.source,dev.sigstore.cosign/signed) - 通过
regclient.ImageOpts.SignatureRef关联独立签名层
注入 annotations 的典型代码
opts := regclient.ImageOpts{
Annotations: map[string]string{
"dev.example.pipeline.id": "ci-2024-08-15-773",
"dev.sigstore.cosign/signed": "true",
},
}
img, _ := rc.ImagePull(ctx, "localhost:5000/myapp:v1.2.0", regclient.ImageWithOpts(opts))
_ = rc.ImagePush(ctx, "localhost:5000/myapp:v1.2.0", regclient.ImageWithOpts(opts))
该段代码在推送时将元数据写入 artifact manifest(非 config blob),确保签名验证链可追溯。Annotations 字段仅影响 manifest 层,不影响镜像运行时行为。
签名关联机制示意
graph TD
A[Go Binary] --> B[cosign sign]
B --> C[Signature Blob]
C --> D[OCI Registry]
D --> E[Artifact Manifest]
E -->|annotations| F["dev.sigstore.cosign/signed: true"]
4.3 在CI中嵌入go-secscan:基于cosign+notary v2联合验证Go二进制+module cache artifact的原子性校验
为实现构建产物与依赖缓存的跨层一致性校验,go-secscan 在 CI 流程中协同 Cosign(签名)与 Notary v2(内容寻址+TUF策略)完成原子性验证。
校验流程概览
graph TD
A[CI 构建] --> B[生成 binary + go.sum snapshot]
B --> C[Cosign sign binary & module zip]
C --> D[Notary v2 push with TUF delegation]
D --> E[go-secscan verify --atomic]
验证执行示例
# 原子性校验:同步验证二进制签名、module cache digest、TUF策略有效性
go-secscan verify \
--binary ./dist/app-linux-amd64 \
--module-cache ./gocache.zip \
--cosign-key https://sigstore.example.com/pubkey.pem \
--notary-config ./trust-policy.json
--atomic启用联合断言:仅当二进制签名有效、gocache.zip的 SHA256 匹配go.sum快照、且 Notary v2 中该 digest 被当前 TUF 信任链授权时,整体返回成功。
关键校验维度对比
| 维度 | Cosign 作用 | Notary v2 作用 |
|---|---|---|
| 签名来源可信性 | 验证开发者私钥签名 | 验证 TUF root/delegation 链 |
| 内容完整性 | 二进制/zip 单体签名 | 按 digest 精确绑定 artifact |
| 策略时效性 | 无策略控制 | 支持过期时间、角色权限分级 |
4.4 Go测试覆盖率报告、SBOM(Syft集成)、SLSA provenance三者作为OCI Artifact的多层可信附件绑定实践
现代软件供应链要求同一构建产物承载多维可信元数据。OCI Artifact 规范支持将非镜像内容(如 coverage profiles、SBOM、provenance)以 artifactType 和 subject 关联方式挂载为附属层。
多层附件绑定模型
- 测试覆盖率报告:
application/vnd.golang.coverage+text - SBOM(Syft生成):
application/spdx+json或application/vnd.syft+json - SLSA Provenance:
application/vnd.in-toto+json
构建与绑定流程
# 1. 生成覆盖率报告(Go)
go test -coverprofile=coverage.out ./...
# 2. 生成SBOM
syft . -o spdx-json=sbom.spdx.json
# 3. 签发SLSA provenance(via slsa-github-generator)
slsa-github-generator --provenance --source=https://github.com/org/repo --tag=v1.0.0
# 4. 推送主镜像并附加三层元数据
oras attach \
--artifact-type application/vnd.golang.coverage+text \
coverage.out \
ghcr.io/org/app:v1.0.0
oras attach \
--artifact-type application/spdx+json \
sbom.spdx.json \
ghcr.io/org/app:v1.0.0
oras attach \
--artifact-type application/vnd.in-toto+json \
provenance.intoto.json \
ghcr.io/org/app:v1.0.0
上述 oras attach 命令将各元数据作为独立 artifact layer 绑定至同一 digest 引用的主镜像,通过 OCI subject 字段实现强关联。--artifact-type 决定消费端如何解析语义,是实现自动化策略校验的基础。
| 元数据类型 | 用途 | 验证主体 |
|---|---|---|
| Coverage Report | 质量门禁依据 | CI/CD 策略引擎 |
| SBOM | 依赖合规审计 | Software Composition Analysis 工具 |
| SLSA Provenance | 构建链路可追溯性 | Sigstore Fulcio/Rekor |
graph TD
A[Go Build] --> B[Coverage Report]
A --> C[Syft SBOM]
A --> D[SLSA Generator]
B & C & D --> E[ORAS Attach]
E --> F[OCI Registry<br>ghcr.io/org/app@sha256:...]
第五章:面向生产环境的Go可信构建体系演进路线与SLO保障建议
构建链路可信性基线的确立
在某金融级微服务集群(日均构建 1200+ 次)中,团队通过引入 cosign 签名 + slsa-verifier 验证双机制,将未经签名的镜像拉取失败率从 3.7% 降至 0%。所有 Go 构建产物(二进制、容器镜像、SBOM 清单)均强制绑定 Git commit SHA、构建环境哈希及 CI 流水线 ID,形成不可篡改的溯源三元组。以下为关键验证流程的 Mermaid 流程图:
flowchart LR
A[Go源码提交] --> B[CI触发构建]
B --> C[生成SBOM via syft]
C --> D[cosign sign -key cosign.key ./app]
D --> E[push to registry with signature]
E --> F[prod节点pull前调用 slsa-verifier --source . --binary ./app]
F -->|验证通过| G[启动服务]
F -->|失败| H[拒绝加载并告警]
构建环境一致性治理
采用 Nix + Docker BuildKit 的组合方案实现构建环境“零漂移”。所有 Go 构建作业均运行于 nix-shell -p 'go_1_22' 'gcc' 'openssl' 封装的纯净环境中,规避了系统级依赖差异导致的 CGO_ENABLED=1 场景下 TLS 握手异常问题。某支付网关服务上线后,因 OpenSSL 版本不一致引发的证书链校验失败事件归零。
SLO驱动的构建质量门禁
定义核心 SLO 指标:构建成功率 ≥99.95%、构建耗时 P95 ≤48s、二进制体积增长 ≤3%(环比)。当 CI 流水线检测到 go build -ldflags="-s -w" 后体积超限,自动触发 go tool pprof -text ./app 分析,并阻断发布。近三个月内,因体积超标被拦截的 PR 共 17 个,平均节省容器内存开销 126MB/实例。
可信构建流水线成熟度分级表
| 等级 | 特征 | 实施案例 |
|---|---|---|
| L1 基础签名 | 仅对镜像签名,无 SBOM | 电商订单服务 v1.2 |
| L2 全链路可追溯 | 签名+SBOM+构建环境指纹 | 信贷风控平台 v3.8 |
| L3 自动化合规审计 | 每次构建自动比对 CIS Go 安全基线(如禁用 unsafe、强制 go.sum 校验) | 核心账务系统 v2.5 |
生产就绪构建参数标准化
强制启用以下编译标志组合:
go build -trimpath \
-buildmode=exe \
-ldflags="-s -w -buildid= -extldflags '-static'" \
-gcflags="all=-l" \
-o ./bin/app .
该配置使某消息网关服务在 ARM64 节点上启动时间缩短 41%,且彻底消除因动态链接库缺失导致的 exec format error。
运行时行为与构建产物强绑定
通过 runtime/debug.ReadBuildInfo() 在 HTTP /healthz 接口注入构建元数据,Kubernetes readiness probe 动态校验 BuildSettings.CGO_ENABLED == "0" 与 Settings["vcs.revision"] 是否匹配当前 Git HEAD。某次误将本地未提交代码打包上线,该机制在 2.3 秒内触发探针失败并自动驱逐 Pod。
