SaltStack Reactor触发SLS时if调用自定义grain报错问题咨询
报错根因
这个问题的核心是对Salt Reactor的渲染上下文理解有误:Reactor SLS在Master上渲染时,上下文里的grains对象存的是Master本机的Grains数据,根本不是事件对应目标Minion的Grains。
你的Master上没配置environment这个自定义Grain,直接访问grains['environment']当然会报dict object has no attribute 'environment'的错。
你测试时用默认自带Grain能跑通,只是因为Master本身就存在这些内置Grain(比如os、kernel这类默认项),但这时候判断的是Master的属性,不是目标Minion的,逻辑本身是不成立的,只是刚好没触发键不存在的报错。
另外你在Reactor里写的saltutil.sync_grains是异步下发的任务,Reactor渲染整个SLS的时候根本不会等这个任务跑完,就算Minion后续同步了自定义Grain,渲染阶段也拿不到对应值。
修复方法
不要在Reactor的Jinja渲染阶段直接读取目标Minion的Grain做判断,可任选以下一种可行方案:
- 方案1:把判断逻辑下沉到Minion侧执行
直接把if判断从Reactor SLS中移除,将判断逻辑写到要执行的dummy_state或者实际业务State里。State是在Minion本地运行的,能正确读取到Minion自身的所有Grain(包括自定义的environment项),是最稳妥的方案。 - 方案2:必须在Reactor层判断的话,先主动拉取Minion的Grain数据
先调用Salt的Runner接口拉取目标Minion的Grain缓存,再做逻辑判断,参考写法:
如果Grain是刚通过sync_grains同步的,建议加短等待再拉缓存,或者使用实时获取Grain的接口,避免拿到旧缓存导致判断错误。sync_grains: local.saltutil.sync_grains: - tgt: {{ data['id'] }} # 拉取目标minion的grains缓存 {% set minion_grains = salt['saltutil.runner']('cache.grains', tgt=data['id']) %} {% if minion_grains.get(data['id'], {}).get('environment') in ["prod", "dev", "migr"] %} test_if_this_works: local.state.apply: - tgt: {{ data['id'] }} - arg: - dummy_state {% endif %}
内容的提问来源于stack exchange,提问作者Megazord
相关产品推荐
相关产品推荐

