chef-client始终使用旧版依赖cookbook未拉取服务端新版问题
问题根因
该现象是Chef依赖求解规则、本地缓存优先级、传递依赖约束三个机制共同作用的结果,具体逻辑:
common2能正常拉取1.0.1版本,核心原因是该cookbook从未在该节点运行过,本地无历史缓存版本,依赖求解时无历史版本干扰,会直接匹配Chef Server上符合无版本约束的最高可用版本。common1始终锁定1.0.0版本的触发点是basecookbook的旧版本传递依赖:- 节点首次bootstrap运行旧版test1时,会将当时匹配依赖规则的旧版
basecookbook拉取到本地缓存。你当前看到的无任何依赖的是最新版base,而本地缓存的旧版base在其metadata中实际声明了对common1 1.0.0的版本约束,该约束会作为传递依赖全局生效。 - Chef默认依赖求解器遵循「满足所有声明约束的前提下,优先使用本地已缓存版本」的策略。由于test1中对
base和common1都没有做显式版本限制,求解器会优先匹配本地已存的旧版base:旧版base携带的common1=1.0.0约束优先级高于无版本限制的common1依赖,求解器既不会主动升级本地缓存的base到最新无依赖版本(旧版本已经满足depends 'base'的无版本约束),也不会拉取更高版本的common1打破依赖匹配结果。 - 当你移除test1中对
base的依赖声明后,触发版本锁定的传递约束消失,common1不再有额外版本限制,求解器就会正常拉取最高可用的1.0.1版本。
- 节点首次bootstrap运行旧版test1时,会将当时匹配依赖规则的旧版
- 前期排查发现的bootstrap阶段版本干扰,本质不是运行列表的记忆功能,是首次运行时写入本地缓存的、带传递依赖约束的旧版cookbook被求解器优先选中导致的。
验证与修复方案
- 验证方式:清空节点本地cookbook缓存后重跑why-run即可确认,执行命令如下:
rm -rf /var/chef/cache/cookbooks/ chef-client -o test1 --why-run | egrep -- '- common'
清空缓存后如果common1正常拉取1.0.1、同时base被升级到最新无依赖版本,即可确认上述逻辑成立。
- 修复方式:不需要清空缓存的话,直接在test1的metadata.rb中显式声明common1的版本下限,比如
depends 'common1', '>= 1.0.1',给求解器明确的版本升级触发条件,强制求解器升级对应cookbook满足约束即可。
内容的提问来源于stack exchange,提问作者osexp2000
相关产品推荐
相关产品推荐

