Hyperledger Fabric Pod重启后Peer重复创建旧链码镜像如何解决
Hyperledger Fabric v2.4.x 版本默认Docker链码运行时的启动逻辑存在设计特性:Peer进程每次启动时,会遍历通道上所有已提交的历史链码版本,逐一校验本地是否存在dev-peer*命名格式的对应链码镜像,校验不通过就自动触发镜像构建流程。
在Docker-in-Docker部署模式下,如果未给内嵌Docker Daemon的数据目录挂载持久化存储,Pod重启后DinD环境内的历史镜像缓存会完全丢失,Peer检测不到旧镜像存在时,就会把所有历史版本的链码(包括早已升级弃用的版本)全部重新构建镜像,最终出现大量无用旧镜像堆积的现象。
方案1:关闭Peer启动自动构建链码镜像(推荐根治)
Fabric v2.4版本提供了官方配置项,可直接关闭启动阶段遍历构建所有历史链码镜像的逻辑,仅在链码首次被调用、且当前运行所需镜像不存在时,才构建对应版本的镜像:
- 若通过
core.yaml配置Peer,找到chaincode配置段,修改如下参数:
chaincode: docker: # 关闭启动时自动构建全量历史链码镜像 buildImages: false
- 若通过K8s环境变量注入Peer配置,直接给Peer容器添加对应环境变量即可:
CORE_CHAINCODE_DOCKER_BUILDIMAGES=false
配置生效后,Peer重启不会再触发无差别的旧链码镜像构建,从根源上杜绝无用镜像生成。
方案2:持久化DinD镜像缓存
给Pod内DinD容器的Docker数据目录(默认路径为/var/lib/docker)挂载持久化存储卷,Pod重启后历史构建的链码镜像缓存不会丢失,Peer校验时发现镜像已存在就不会重复执行构建。
该方案仅能避免重复构建行为,无法自动清理已弃用的旧版本链码镜像,需要配合清理规则使用。
方案3:配置镜像清理规则,限制留存规模
如果暂时无法调整上述配置,可通过主动清理的方式控制镜像总量:
- 配置Docker Daemon自动回收策略:给DinD启动命令添加回收参数,设置磁盘空间阈值,自动清理长期未使用的镜像,示例启动参数:
也可在DinD容器内添加定时任务,定期清理未使用的链码镜像,不会误删正在运行的链码和基础环境镜像:dockerd --storage-opt dm.min_free_space=10G --log-opt max-size=10m# 清理24小时内未被运行中容器引用的dev-peer前缀链码镜像 docker image prune -f --filter "until=24h" --filter "reference=dev-peer*" - 链码升级操作完成后,主动执行Peer自带的清理命令,移除已弃用旧版本链码的本地记录:
清理完成后Peer不会再识别到这些已弃用的旧版本链码,也就不会触发对应镜像的构建。# 替换为实际的通道名、链码名 peer lifecycle chaincode cleanup --channelID <对应通道名> --name <对应链码名>
方案4:替换链码运行时(长期生产方案)
Docker链码运行时是Fabric逐步淘汰的运行模式,生产环境可替换为外部链码运行时(Chaincode as a Service),由用户自行管理链码镜像的构建、发布和生命周期,Peer不会自动创建任何链码镜像,从架构层面彻底避免该问题。
注意:手动清理镜像时不要删除当前正在运行版本的链码镜像,否则会导致链码调用失败。
内容的提问来源于stack exchange,提问作者Akshay Sood

