使用ansible在大规模(几百台以上规模比较容易遭遇)部署机器的时候,有时候会碰到ansible进程hang在某个点上,这个点不必定每次都同样。
研究了一个下午,发现hang住的时候,CI/CD的agent上并无报错日志,被执行host上也没有ansible的日志输出,而且不管等待多长时间也不会退出。git
期初怀疑是版本问题,由于以前线上一直用的2.7版本,最近刚切换到2.9,可是实际上这个部署的job在使用2.9版本的时候已经成功过很多次。而后检查CI/CD上部署job的VCS配置,发现虽然有更新,可是并无什么很大的可能明显致使这种状况发生的changes。github
启动google大法,发现ansible的github上有人提过一个issue,一个很老的2017年9月的issue,https://github.com/ansible/ansible/issues/30411
这个issue最后一个comment是提交了一个PR(居然是20天前刚提交的),这个PR给task执行增长了一个硬超时,已经merge,虽然没有解释为何会hang住,可是起码提供了一个解决方案。并且里面的comments提到了一个关键的复现方法,一个简单的"df"命令就可让ansible进程hang住。
因而我找了两台机器,装了nfs,client端挂载了server端的一个目录,而后把server端的nfs进程stop掉,这时候在client中执行"df"命令,效果等同于进程hang住,原理也很简单,由于nfs连接断掉了,"df"在等待返回,等不到就“假死”在那里。
再而后,我配置了一个只有一条shell命令的ansible playbook,让多台机器(其中包括了这个nfs client节点)同时运行,结果果真是ansible在执行到这个nfs client节点的时候hang住不再动了,而且若是我从新启动nfs server端,ansible当即就回正常执行完,说明ansible进程没有“死”,只是一直在“等待”。shell
如今在回过头来思考,结论应该是批量开机器的时候,由于咱们用的是AWS,在规模很大的状况下,常常有实例会由于各类特例问题致使某些task挂起在机器上,而这个时候因为ansible没有超时机制,而且!最关键的来了,ansible没有收到任何错误值和返回值,因而就一直在“等待”,等到海枯石烂。
短时间的解决方法,若是是云平台,干掉那些“不正常”的机器,从新run一次job,通常都会解决。
长期的话,超时是一个可行的方案,并且ansible还须要真正的解决是并行问题,不要让一个机器的问题致使整个job的失败(某一个实例有问题,那就提示出来,其余的继续跑)。ide