4. 医疗容器镜像仓库运维

镜像仓库是医疗容器平台的“药品库”:它既保存应用制品,也承载合规证据。Harbor 作为主流企业级仓库,在医疗场景中通常需要同时满足高可用、内容可信、分级管控、跨院区同步与可审计清理。本节围绕这五件事展开,重点讲清“怎么部署、怎么验、怎么分级、怎么同步清理、坏了怎么查”。

一、Harbor 高可用部署:共享后端 + 无状态前端

Harbor 的高可用不是把单机容器多起几个副本,而是把有状态组件与无状态组件分开。核心判断是:哪些组件必须共享同一份数据,哪些可以水平扩展。典型生产部署采用“双 Harbor 实例 + 外部共享 PostgreSQL + 外部 Redis + 共享对象存储(S3/MinIO)+ 外部负载均衡”的结构。两个 Harbor 实例本身无状态,镜像层数据落在对象存储,元数据落在 PostgreSQL,会话与缓存落在 Redis,任意实例故障时流量可切到另一实例。

部署时先准备外部依赖,再安装 Harbor。以下为示例参数(非实测结果,仅作教学参考):PostgreSQL 14 主备、Redis 7 哨兵、MinIO 四节点纠删码、Harbor 2.10 双实例。安装时通过 harbor.yml 指向外部组件,关键片段如下:

database:
  type: external
  external:
    host: pg-harbor.med.local
    port: 5432
    username: harbor
    password: <secret>
    sslmode: require
external_redis:
  host: redis-harbor.med.local:26379
  password: <secret>
  sentinel_master_set: mymaster
storage_service:
  s3:
    accesskey: harbor-ak
    secretkey: <secret>
    region: cn-north-1
    bucket: harbor-registry
    endpoint: https://minio.med.local

验证高可用不能只看页面能打开。应做三项检查:其一,停掉一台 Harbor 实例,通过 VIP 持续 docker login 与 docker push,确认无中断;其二,检查两个实例的 harbor_db 连接是否指向同一 PostgreSQL,避免“双主写坏元数据”;其三,确认对象存储桶被两实例共同读写,镜像层不重复。若使用 Keepalived + HAProxy,VIP 漂移时间应控制在秒级,并配置健康检查路径 /api/v2.0/health。

二、镜像签名与漏洞扫描:把“可信”变成可验证

医疗镜像的合规要求通常包括“来源可信”和“已知漏洞可控”。Harbor 集成 Trivy 做漏洞扫描,集成 Notary/Cosign 做签名。扫描解决“这个镜像里有什么”,签名解决“这个镜像是不是我们构建的”。两者缺一不可。

扫描策略建议按项目配置:对 prod 项目开启“推送时自动扫描”,并设置阻断策略——存在 Critical 漏洞的镜像不允许被部署。示例判断逻辑:Trivy 扫描结果中 CRITICAL 数量大于 0 时,Harbor 将该 artifact 标记为不可拉取,配合准入控制器拒绝工作负载。签名方面,若采用 Cosign,构建流水线在推送后执行 cosign sign,部署前用 cosign verify 校验。示例命令:

cosign sign --key cosign.key harbor.med.local/prod/emr-api:v1.8.2
cosign verify --key cosign.pub harbor.med.local/prod/emr-api:v1.8.2

结果判读要明确:cosign verify 返回 0 且输出签名者身份,才视为通过;返回非 0 或提示 no matching signatures,说明镜像未签名或被篡改,应阻断发布。漏洞扫描结果则要看“可修复漏洞”与“不可修复漏洞”的区分,不能只盯总数。

三、医疗镜像分级分类管理:按数据敏感度与业务等级分

医疗镜像不能“一锅端”。建议按两个维度分级:数据敏感度(是否含患者隐私、是否含诊疗数据)与业务连续性等级(是否影响挂号、收费、急诊、手术)。据此把项目划分为四级:L1 核心诊疗、L2 关键业务、L3 一般业务、L4 工具与测试。不同级别对应不同的扫描阈值、签名要求、保留周期与同步范围。

例如 L1 项目要求:必须签名、Critical 漏洞为 0、保留最近 20 个版本、禁止跨公网同步;L4 项目可放宽为:建议签名、High 漏洞可接受、保留 5 个版本。分级不是贴标签,而要落到 Harbor 的项目配置、机器人账号权限和复制策略上。下面用一张结构图表达分级与策略的对应关系。

医疗镜像分级分类与策略映射 分级维度:数据敏感度 × 业务连续性等级 L1 核心诊疗 急诊 / 手术 / 重症 含患者隐私数据 L2 关键业务 挂号 / 收费 / 报告 间接接触诊疗数据 L3 一般业务 办公 / 统计 / 门户 不含隐私数据 L4 工具与测试 CI 工具 / 临时验证 可快速重建 策略项 签名要求 漏洞阈值 保留版本 强制 Cosign Critical = 0 20 个 强制 Cosign Critical = 0 15 个 建议签名 High ≤ 5 10 个 可选 不阻断 5 个 同步与清理 同步范围 清理触发 审计要求 仅内网双活 保留策略 + 手动复核 全量操作留痕 内网 + 灾备 保留策略自动 关键操作留痕 按需同步 定期清理 常规日志 不同步 高频清理 无需审计

四、镜像同步与清理策略:既要“到得了”,也要“删得掉”

同步策略解决多院区、多集群的镜像分发。Harbor 的复制规则支持按项目、按标签、按名称过滤。医疗场景常见做法是:主中心作为源,灾备中心作为目标,采用“推模式”复制 L1/L2 项目;L3/L4 不复制,按需拉取。复制规则要设置过滤条件,例如只复制 v* 正式版本,排除 dev-* 与 test-*,避免测试镜像污染灾备仓库。同步完成后要检查复制任务的 status 与 success_rate,失败任务需查看目标端网络与认证。

清理策略解决存储膨胀。Harbor 提供“保留策略”和“垃圾回收”两层机制。保留策略按项目设置,例如“保留最近 20 个被推送的 artifact,且保留所有带 release- 标签的镜像”。垃圾回收则删除未被任何 manifest 引用的 blob。注意:删除 artifact 后必须执行 GC 才能释放对象存储空间,且 GC 期间仓库应停止写入或进入只读模式,避免误删正在上传的层。示例保留规则:

保留最近推送的 20 个 artifact
+ 保留标签匹配 release-* 的 artifact
+ 保留最近 30 天内被拉取过的 artifact

清理前建议先跑一次“模拟删除”,确认待删列表中没有 L1 正在使用的版本,再执行真实删除与 GC。医疗场景中,任何删除动作都应记录操作人、时间、项目与镜像摘要,便于追溯。

五、镜像仓库故障排查实战:从现象到根因

仓库故障通常表现为四类:登录失败、推送失败、拉取失败、复制失败。排查顺序应遵循“先看 Harbor 组件状态,再看外部依赖,最后看网络与证书”。常用入口包括:docker login 报错信息、Harbor 的 core/registry/jobservice 日志、PostgreSQL 连接数、Redis 哨兵状态、对象存储桶权限。

典型场景一:docker push 卡在 Pushing 后超时。先查 registry 日志是否有 blob upload 错误,再确认对象存储桶是否可写、S3 endpoint 是否可达。若两个 Harbor 实例中只有一个能写,说明共享存储配置不一致。典型场景二:docker login 返回 401 Unauthorized。先确认数据库连接是否正常,再检查 core 日志中是否有 failed to connect database;若数据库正常,则检查 Redis 会话是否丢失,导致 token 校验失败。典型场景三:复制任务持续失败。查看目标端是否可达、目标项目是否存在、机器人账号是否有推送权限,并核对复制规则中的标签过滤是否把目标版本排除。

排查时优先使用 Harbor 自带的健康检查接口 /api/v2.0/health,它会分别返回 database、redis、storage 等组件的状态,比逐台登录服务器更快定位是“仓库自身”还是“外部依赖”的问题。

最后强调一条运维原则:镜像仓库的高可用、签名、扫描、分级、同步与清理不是彼此独立的配置项,而是一条链。分级决定扫描阈值与签名要求,签名与扫描结果决定能否部署,同步范围决定灾备可用性,清理策略决定存储成本与合规留存。任何一环缺失,都会让“可信镜像”在某个环节失效。实际运维中应把这条链固化为流水线门禁与定期巡检项,而不是依赖人工记忆。