前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Jenkins+Ansible架构迟早要遇到的问题|技术创作特训营第一期

Jenkins+Ansible架构迟早要遇到的问题|技术创作特训营第一期

原创
作者头像
金鹏
修改2023-08-24 02:31:20
8290
修改2023-08-24 02:31:20
举报
文章被收录于专栏:SDLC技术探究SDLC技术探究

1. 引言

最近在微信听书上听《万历十五年》,其中一节介绍了一位著名矛盾思想家/政治家——李贽,其以思想矛盾,个性开放,与时代格格不入著称,这也是我对他感兴趣的点。虽然不提倡向他那样一边跟寡妇妓女”勾搭“,一边骂世人知行不一,但是对鄙人的启发是,任何人和事物在某一段时间内都是相互矛盾的结合体。正所谓,福兮祸所依,祸兮福所倚,所以如果你觉得你的架构还挺稳定,那你的思想就挺危险;如果你觉得你很擅长Jenkins+Ansible,别得瑟,不妨看看下面我遇到的问题。

我们都知道,作为SRE/Devops/SDLC/Business Developer,当谈到自动化部署和配置管理时,想必对Jenkins 和 Ansible都不陌生,他们都是业界非常流行的开源工具。它们分别专注于不同的领域,但又可以结合使用来构建一个完整的持续集成和持续交付(CI/CD)管道。虽然现在基于Docker和K8S的CI/CD技术横行于世,但鄙人以为基于Jenkins+Ansible作为部署架构的公司因该也不在少数。鄙人曾利用此架构完成对几百个模块在上万台机器发布,在此抛砖引玉,分享一点浅薄的优化经验给那些在路上仍然裸奔的人。

2. 我们的架构是什么?

先介绍下架构,方便后面叙述问题。以Jenkins主从结构去控制管理中心节点和子节点,主节点和子节点利用ssh链接,子节点的主控节点使用Ansible管理子节点的集群机器,当然其ssh密钥是不同的,是定期更新的。在安全层面,安全策略也是点对点访问,以避免引发事故。在这里,Jenkins的主要作用就是负责管理和调度命令到集群的agent去执行和回收结果。Ansible主要用于负责分发指令,回调执行结果。

图1 部署架构
图1 部署架构

3. 这样的架构会有哪些问题?

当你的集群规模比较小,或者部署不够复杂时可能不会遇到这些问题,但是一旦随着业务的复杂,部署模块的增多,集群规模成倍扩增,部署指令的复杂,下面问题多少都会碰到。

3.1. 当一条指令执行2小时,会怎样?

图2 ssh断开和Ansible轮询执行结果
图2 ssh断开和Ansible轮询执行结果

你有没有遇到过这个问题,当你要去部署一个模块,这个模块需要优雅部署,这意味着我们首先需要流量的熔断,再等待已经负载的流量褪去,接下来执行我们的部署流程。好巧不巧,这些流程需要被发布系统管理;在优雅的过程中,这个服务的流量先从一个高点降到0或者我们能接受的范围,那么这个过程就会花费相当长的时间,可能1个小时或者两个小时,也就意味着你使用Playbook执行的命令需要经历这个复杂的场景,所以可能遇到的问题是,如果是同步执行,命令执行时间过长,ssh链接失去保活,如果是异步执行,那么你就要去轮训执行结果,这里也会遇到一个问题,ansible轮询结果时,非常耗节点CPU,再就是ssh频繁重联,尤其是批量部署多个机器(几十或者几百)。

那么需要怎么优化这个过程呢?

3.1.1. Ansible的异步

Ansible可以执行同步和异步的任务,让我们来了解一下Ansible的异步过程:

异步任务在Ansible中是指那些需要较长时间才能完成的任务,例如启动大规模的应用程序部署、升级操作系统等。在同步任务中,Ansible会等待每个任务完成后再继续执行下一个任务。而在异步任务中,Ansible会启动任务并立即继续执行下一个任务,而不必等待异步任务完成。让我门给个Ansible中处理异步任务例子先:

1.启动异步任务:通过在Playbook中使用async关键字,你可以指定一个任务作为异步任务。例如:

代码语言:yaml
复制
   - name: Start long-running task
     command: /path/to/long_task.sh
     async: 3600  # 指定任务超时时间(以秒为单位)
     poll: 0  # 指定异步任务轮询频率
     register: async_result

在这个例子中,async参数指定了任务的超时时间,poll参数指定了轮询任务状态的频率。

2.等待任务完成:在启动异步任务后,Ansible会继续执行下一个任务,但同时会为异步任务注册一个变量(这里是async_result)。你可以使用async_result变量来检查异步任务的状态。

3.轮询任务状态:使用async_status模块来轮询异步任务的状态,例如:

代码语言:yaml
复制
   - name: Wait for async task to complete
     async_status:
       jid: "{{ async_result.ansible_job_id }}"
     register: job_result
     until: job_result.finished
     retries: 30
     delay: 10

在这个例子中,async_status模块会检查异步任务的状态,直到任务完成为止。

4.处理任务结果:一旦异步任务完成,你可以使用相关的模块(例如debugnotify等)来处理任务的结果。例如:

代码语言:yaml
复制
   - name: Print async task result
     debug:
       var: job_result

所以Ansible的异步过程允许你在后台运行长时间运行的任务,而不会阻塞主要的Ansible执行流程。这对于处理复杂的、耗时的操作非常有用,但需要适当的设置和处理来确保任务的顺利执行和结果处理。

3.1.2. 优化ssh链接

上述问题中我们可以使用SSH长连接来解决频繁重连耗cpu的问题,因为建立SSH连接涉及加密协商和身份验证等步骤,因此长连接可以减少这些开销,提高连接的效率。在大多数情况下,SSH会话会在用户退出或超时时自动关闭,但可以通过配置来实现长连接。在SSH配置文件(通常位于/etc/ssh/sshd_config)中添加以下行可以延长会话的超时时间:

代码语言:shell
复制
ClientAliveInterval 120 #second
ClientAliveCountMax 1440 #second

上述配置会使服务器每120秒发送一个保活消息,如果在1440个保活消息(即2小时)内没有收到客户端的响应,则会终止会话。

另外一个参数是TCPKeepAlive, 可以通过在SSH客户端和服务器的SSH配置文件中启用TCP KeepAlive来确保底层TCP连接的活跃性。这可以在/etc/ssh/ssh_config(客户端)和/etc/ssh/sshd_config(服务器)中设置。

代码语言:txt
复制
TCPKeepAlive yes

最后一个要说的是SSH Multiplexing,这允许你在同一个连接上同时执行多个会话。这可以通过设置ControlPersist选项来实现,以及使用SSH配置文件中的mux选项。

代码语言:txt
复制
ControlPersist yes

另外可以修改ansible的配置文件,也可以达到类似效果:

代码语言:shell
复制
[ssh_connection]
pipelining = True           # 启用管道化,减少通信次数
control_path = ~/.ansible/cp/ansible-ssh-%%h-%%p-%%r  # 控制连接的路径,实现持久连接
ssh_args = -o ControlMaster=auto -o ControlPersist=30m  # 控制连接参数,控制持久连接的生命周期
[persistent_connection]
command_timeout = 3600 #持久化链接

3.1.3. 优化ansible代码

假如你还是使用2.9以下的版本,那么就需要考虑降低工作进程(Worker Process)列表检查频率,可以将其设置为500毫秒或者1秒,以避免频繁检查works列表,详情可以参考https://blog.csdn.net/avenger19/article/details/102858359,这里不作赘述。

另外一个是调整DEFAULT_INTERNAL_POLL_INTERVAL参数,降低结果处理轮询的频率,,详情可以参考:https://blog.csdn.net/avenger19/article/details/102860119,这里也不作赘述。

3.1.4. 让ansible起飞的plugin

随着问题和体量增加,就想着如何加速ansible,无意间发现一个神奇的插件Mitogen,据说可以提升1-7倍的速度。主要原理是通过高效的远程过程调用来取代 ansible 默认的嵌入式与纯 python shell 调用,它不会优化模块本身的执行效率,只会尽可能快的去执行模块获取返回(执行模块前也是有一系列连接,发送数据,传输渲染脚本等操作的)来提高整体的效率。这里是官网可以参考使用:https://mitogen.readthedocs.io/en/latest/howitworks.html。用了都说好。

3.2 Jenkins ansible plugin的bug?

鄙人所遇到的现象是,当有多个host分批异步执行时(ansible支持serial等场景),假设治理10个hosts,分2批,每批5个hosts,那么奇怪的现象就出现了,第一批跑完之后,第二批的inventory文件就被删除了,然而第一批的inventory文件还存在。后来审视了下plugin的源码:https://github.com/jenkinsci/ansible-plugin/blob/main/src/main/java/org/jenkinsci/plugins/ansible/InventoryContent.java,代码里的inventory是全局变量,在变更时没有加锁,后来在完成了修复。

3.3 如何回收执行结果?

因为playbook是task by task执行的,所以为了收集每个task的运行结果,我们当然少不了使用callback plugin。首先在playbook里定义了name的规范,例如:

代码语言:shell
复制
- name: STEPS-1 backup_package host_name mv_{{xxx}}_{{yyy}}

然后在callback plugin解析name,并拿到每个task的结果,callback到主节点分析处理。

4.写在最后

大明李贽生不逢时,好比现代人去了大明,不被抓去杀头,也要被看作怪胎,但是李贽就是李贽,别人说错了,也要坚信自己是对的,即使自己真的错了。因为矛盾的个体总有两面性,而非非黑即白。辩证看问题是基本逻辑,更需要长远而深邃地剖析,最后践行知行合一理念,那么你就有可能觉得本文不只是一篇教科书式的文章,而是在引导你前行。

【选题思路】

本文主要由听书所引发的一些做人做事的道理,引出对待工作对待自己的态度,进而引出问题,引导读者深入文章,再提出本人曾遇到过的一些问题,一一分析解答。最后总结,本文不是教科书,只是引导你去独立思考,付诸实践。

【写作提纲】

  1. 如何切题?——由个人经历引入并介绍当前的技术背景 2.先铺垫好路,让读者了解清楚架构,避免误入歧途 3.由问题切入,这样的架构会遇到什么问题,列举一些可能遇到的疑难问题,并一一剖析解答 4.总结升华主题。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 引言
  • 2. 我们的架构是什么?
  • 3. 这样的架构会有哪些问题?
    • 3.1. 当一条指令执行2小时,会怎样?
      • 3.1.1. Ansible的异步
      • 3.1.2. 优化ssh链接
      • 3.1.3. 优化ansible代码
      • 3.1.4. 让ansible起飞的plugin
    • 3.2 Jenkins ansible plugin的bug?
      • 3.3 如何回收执行结果?
      • 4.写在最后
      相关产品与服务
      持续集成
      CODING 持续集成(CODING Continuous Integration,CODING-CI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、NodeJS 等所有主流语言,并且支持 Docker 镜像的构建。图形化编排,高配集群多 Job 并行构建全面提速您的构建任务。支持主流的 Git 代码仓库,包括 CODING 代码托管、GitHub、GitLab 等。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档