写在前面
- Ansible的幂等性是对于模块(或playbook中的步骤)来谈的
- 大部分Ansible模块可以做到幂等
- 并不是所有Ansible模块都是幂等的,无法保证幂等性的模块如
shell
、command
- 本篇有很多说法只是基于作者个人浅薄的经验和思考,并无太多凭据;一家之言若有不妥,欢迎指出
Ansible 与 幂等
因为第一次接触Ansible就被安利说它是“幂等”的,但是一直没有搞清楚它究竟如何做到幂等。这样的“第一印象”反而让我走入了认识误区。
幂等
数学上,如果一个函数多次运算,得到的结果一致,则此函数具有幂等性(idempotent):
f(x)=f(f(x))
工程领域也经常引用此概念,但是并没有数学上那么严谨,一般认为 某项操作如果执行多次,得到的结果一致,则该操作具有幂等性
。
此处操作可引申为函数、请求、服务等。工程领域对幂等性更多强调其可重复执行[1]。
实现起来也各有不同。比如在交易领域,可以如此实现幂等:每笔交易持有一个全局id号,向服务发起交易请求需要携带此id,后端服务以此判断交易是否执行完成,并返回唯一执行结果[2]。
Ansible 幂等
Ansible 某些模块具有天然幂等性,具体指的是某些模块只是指定服务器将达到的最终状态,如
- tasks:
- name: remote option in remote config file
ini_file:
path: /some/path/config.ini
section: t_section
option: t_option
state: absent
将最终使远端的配置文件中没有 [t_section] t_option 项。而如果用 command
或 shell
执行 sed
命令,该命令会始终执行[3]。
所以,我们在使用 Ansible 时,应当尽量指定服务器的最终状态,而不是发出执行的指令。面向结果,而不是面向过程。
.retry 文件
每次在 Ansible-playbook 执行遇到失败时(部分 inventory 失败),系统会提示:
to retry, use: --limit @/path/to/my_playbook.retry
最初笔者以为这个 .retry 文件和 ansible 的幂等有关。但是打开文件之后,发现其实里面只有一个失败inventory的hostname。事实上,这个文件和幂等无关,只是在提醒用户,可以再次运行 ansible-playbook 并带上 --limit @/path/to/my_playbook.retry 以重试。
具体用法:
# my_playbook.yml
---
- hosts: inventory
tasks:
- name: I make you fail
- fail: msg="just make you fail"
# 第一次运行 playbook
ansible-playbook my_playbook.yml -i my_inventroy
# 抛出提示
fatal: [your_host]: FAILED! => {"changed": false, "msg": "just make you fail"}
to retry, use: --limit @/{path}/my_playbook.retry
# 重试
ansible-playbook my_playbook.yml -i my_inventroy --limit @/{path}/my_playbook.retry
当然,由于我们的 playbook 只能fail,重试多次还是不会成功滴,否则就有鬼了~
References: