5

ansible-playbook编排使用tips

 3 years ago
source link: http://www.eryajf.net/5173.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
本文预计阅读时间 32 分钟

0,常用变量

在日常配置编排过程中,我们经常需要用到一些内置的变量来进行一些判断或者配置的工作,这里整理一些常用的变量,以便于使用查阅。

  • 部署客户端主机名:ansible_hostname
  • 部署客户端主机IP:ansible_default_ipv4.address
  • 部署客户端主机详细信息:hostvars,返回主机详细信息,可以通过点操作定位具体需要的内容。

005BYqpgly1g1urv7np7gj31c00u04cv.jpg

1,判断错误

有时候我们在部署服务的时候,会针对一些服务状态进行检测,从而依据检测结果来判断是否将主机放回到负载列表当中,这里举一个web检测的例子,首先通过NGINX定义了一个返回值:

  1. $ curl localhost/get_info
  2. {"status":"success","result":"hello world!"}

然后定义剧本如下:

  1. $ cat site.yaml
  2. ---
  3. - hosts: localhost
  4. tasks:
  5. - uri:
  6. url: "http://localhost/get_info"
  7. method: GET
  8. register: webpage
  9. failed_when: webpage.status != 200
  10. - debug:
  11. var: webpage

这里使用本机进行验证此类功能,直接通过如下命令即可运行:

  1. $ ansible-playbook site.yaml
  2. [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
  3. PLAY [localhost] ********************************************************************************************************************************************************************
  4. TASK [Gathering Facts] **************************************************************************************************************************************************************
  5. ok: [localhost]
  6. TASK [uri] **************************************************************************************************************************************************************************
  7. ok: [localhost]
  8. TASK [debug] ************************************************************************************************************************************************************************
  9. ok: [localhost] => {
  10. "webpage": {
  11. "changed": false,
  12. "connection": "close",
  13. "content_length": "44",
  14. "content_type": "application/json",
  15. "cookies": {},
  16. "cookies_string": "",
  17. "date": "Tue, 02 Jun 2020 06:30:53 GMT",
  18. "elapsed": 0,
  19. "failed": false,
  20. "failed_when_result": false,
  21. "json": {
  22. "result": "hello world!",
  23. "status": "success"
  24. },
  25. "msg": "OK (44 bytes)",
  26. "redirected": false,
  27. "server": "openresty",
  28. "status": 200,
  29. "url": "http://localhost/get_info"
  30. }
  31. }
  32. PLAY RECAP **************************************************************************************************************************************************************************
  33. localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

上边通过输出的状态码进行判断,除此之外,还可以通过输出当中的具体内容匹配来进行判断,比如上边内容当中,我们看到对应的json字段里输出的返回内容,也可以根据具体内容来进行判断,此时调整剧本内容如下:

  1. ---
  2. - hosts: localhost
  3. tasks:
  4. - uri:
  5. url: "http://localhost/get_info"
  6. method: GET
  7. register: webpage
  8. failed_when: webpage.status != 200
  9. - fail:
  10. msg: "check status field"
  11. when: "'hello' not in webpage.json.result"

webpage.json.result可以将返回的内容定位到相应位置,然后再进行判断,当然不少时候也可以用如下方式判断:

  1. ---
  2. - hosts: localhost
  3. tasks:
  4. - uri:
  5. url: "http://localhost/get_info"
  6. method: GET
  7. return_content: yes
  8. register: webpage
  9. failed_when: webpage.status != 200
  10. - fail:
  11. msg: "check status field"
  12. when: "'hello' not in webpage.content"

多了一个参数 return_content: yes, 但需要注意的一个地方是:webpage.content中的json字段是无法展开的。

2,只跑一次

  1. run_once: true

有一些在列表中的任务,只需要跑一次就好,比如上线部署剧本中,发布列表可能有10台,那么如下步骤中,一些地方就不需要执行10次了,比如生成版本号以及同步到本地的两个步骤。

  1. ---
  2. - name: "创建远程主机上的版本目录"
  3. file: path=/release/{{project}}/{{_version}} state=directory
  4. tags: deploy
  5. - name: "将代码同步到远程主机版本目录"
  6. synchronize:
  7. src: /{{WORKSPACE}}/
  8. dest: /release/{{project}}/{{_version}}/
  9. delete: yes
  10. tags: deploy
  11. - name: "将项目部署到生产目录"
  12. file: path=/data/www/{{project}} state=link src=/release/{{project}}/{{_version}}
  13. tags: deploy
  14. - name: "使版本目录保持五个版本历史"
  15. script: chdir=/release/{{project}} keepfive.sh
  16. tags: deploy
  17. - name: "生成远程版本号"
  18. shell: "ls /release/{{project}} > /release/{{project}}.log"
  19. tags: deploy
  20. - name: "同步版本号到本地"
  21. synchronize: "src=/release/{{project}}.log dest=/root/.jenkins/version/{{JOB_NAME}}.log mode=pull"
  22. tags: deploy
  23. - name: "执行自由脚本"
  24. script: chdir=/release/{{project}} free.sh
  25. tags: deploy

通过添加 run_once: true可以定义对应的任务只执行一次:

  1. ---
  2. - name: "创建远程主机上的版本目录"
  3. file: path=/release/{{project}}/{{_version}} state=directory
  4. tags: deploy
  5. - name: "将代码同步到远程主机版本目录"
  6. synchronize:
  7. src: /{{WORKSPACE}}/
  8. dest: /release/{{project}}/{{_version}}/
  9. delete: yes
  10. tags: deploy
  11. - name: "将项目部署到生产目录"
  12. file: path=/data/www/{{project}} state=link src=/release/{{project}}/{{_version}}
  13. tags: deploy
  14. - name: "使版本目录保持五个版本历史"
  15. script: chdir=/release/{{project}} keepfive.sh
  16. tags: deploy
  17. - name: "生成远程版本号"
  18. shell: "ls /release/{{project}} > /release/{{project}}.log"
  19. run_once: true
  20. tags: deploy
  21. - name: "同步版本号到本地"
  22. synchronize: "src=/release/{{project}}.log dest=/root/.jenkins/version/{{JOB_NAME}}.log mode=pull"
  23. run_once: true
  24. tags: deploy
  25. - name: "执行自由脚本"
  26. script: chdir=/release/{{project}} free.sh
  27. tags: deploy

这样即便是发布了10台机器,那么版本号这两步也就只执行一次。

3,滚动更新

ansible默认情况下,执行剧本时是从剧本角度出发,每个任务在主机列表中逐一执行,有时候我们发布一些服务,需要一台一台从负载中摘出部署,然后放回去,这个时候,走默认的方向就不太合适了。用如下一个简单例子来说明:

  1. $ cat site.yml
  2. ---
  3. - hosts: remote
  4. tasks:
  5. - debug:
  6. msg: "this is task a"
  7. - debug:
  8. msg: "this is task b"

执行如上剧本看输出:

  1. ansible-playbook -i test_hosts s.yaml
  2. PLAY [remote] ***********************************************************************************************************************************************************************
  3. TASK [Gathering Facts] **************************************************************************************************************************************************************
  4. ok: [10.3.22.90]
  5. ok: [10.3.22.87]
  6. TASK [debug] ************************************************************************************************************************************************************************
  7. ok: [10.3.22.90] => {
  8. "msg": "this is task a"
  9. }
  10. ok: [10.3.22.87] => {
  11. "msg": "this is task a"
  12. }
  13. TASK [debug] ************************************************************************************************************************************************************************
  14. ok: [10.3.22.90] => {
  15. "msg": "this is task b"
  16. }
  17. ok: [10.3.22.87] => {
  18. "msg": "this is task b"
  19. }
  20. PLAY RECAP **************************************************************************************************************************************************************************
  21. 10.3.22.87 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
  22. 10.3.22.90 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

可以看到两个任务被分开,在两台主机上分别来执行。

ansible中的 serial就是用来控制任务执行数量的参数,上面的场景,我们可以把对应值设为1,剧本就会每台主机逐一执行了。

  1. ---
  2. - hosts: remote
  3. serial: 1
  4. tasks:
  5. - debug:
  6. msg: "this is task a"
  7. - debug:
  8. msg: "this is task b"

执行结果如下:

  1. ansible-playbook -i test_hosts s.yaml
  2. PLAY [remote] ***********************************************************************************************************************************************************************
  3. TASK [Gathering Facts] **************************************************************************************************************************************************************
  4. ok: [10.3.22.90]
  5. TASK [debug] ************************************************************************************************************************************************************************
  6. ok: [10.3.22.90] => {
  7. "msg": "this is task a"
  8. }
  9. TASK [debug] ************************************************************************************************************************************************************************
  10. ok: [10.3.22.90] => {
  11. "msg": "this is task b"
  12. }
  13. PLAY [remote] ***********************************************************************************************************************************************************************
  14. TASK [Gathering Facts] **************************************************************************************************************************************************************
  15. ok: [10.3.22.87]
  16. TASK [debug] ************************************************************************************************************************************************************************
  17. ok: [10.3.22.87] => {
  18. "msg": "this is task a"
  19. }
  20. TASK [debug] ************************************************************************************************************************************************************************
  21. ok: [10.3.22.87] => {
  22. "msg": "this is task b"
  23. }
  24. PLAY RECAP **************************************************************************************************************************************************************************
  25. 10.3.22.87 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
  26. 10.3.22.90 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

结果与上边的一对比就很容易理解这个参数的含义了。

除了定义 serial: 1,当然还可以定义更多,比如主机列表有30台,我们可以定义 serial: 5,就变成5台5台执行了。

在实际应用中,某些主机执行失败,只会中断当次构建,但不影响其他主机往后执行,这对我们来说并不安全,因为这可能会让没有走完发布流程的主机放回到负载列表中,因此,常常还有一个搭配使用的参数是:max_fail_percentage,表示当最大失败主机的比例达到多少时,ansible就让整个play失败。

  1. ---
  2. - hosts: remote
  3. serial: 1
  4. max_fail_percentage: 25
  5. tasks:
  6. - debug:
  7. msg: "this is task a"
  8. - debug:
  9. msg: "this is task b"

25是一个比例数据,表示构建列表中,如果有四分之一的失败,则会退出构建,如果我们希望一有失败就退出,则可以将之设为0。

注意:当serial: 1时,就不必再用 run_once: true,因为这种定义是无意义的。

4,打印多行

有时候我们在运行完一些任务之后,希望能够批量打印一些内容返回出来,此时可以使用如下方式进行打印:

  1. $ cat test.yaml
  2. ---
  3. - hosts: localhost
  4. connection: local
  5. vars:
  6. msg: |
  7. lookupd-tcp
  8. {{ node1 }}:4160
  9. {{ node2 }}:4160
  10. {{ node3 }}:4160
  11. lookupd-http
  12. {{ node1 }}:4161
  13. {{ node2 }}:4161
  14. {{ node3 }}:4161
  15. data-tcp
  16. {{ node1 }}:41501
  17. {{ node1 }}:41502
  18. {{ node2 }}:41501
  19. {{ node2 }}:41502
  20. {{ node3 }}:41501
  21. {{ node3 }}:41502
  22. data-http
  23. {{ node1 }}:41511
  24. {{ node1 }}:41512
  25. {{ node2 }}:41511
  26. {{ node2 }}:41512
  27. {{ node3 }}:41511
  28. {{ node3 }}:41512
  29. tasks:
  30. - name: test
  31. debug:
  32. msg: "{{ msg.split('\n') }}"

然后运行看下:

  1. $ansible-playbook test.yaml -e "node1=10.3.0.0 node2=10.0.0.1 node3=10.0.0.2"
  2. [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
  3. PLAY [localhost] ***************************************************************************************************************************************************************************************************************************************************************
  4. TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************************************************************
  5. ok: [localhost]
  6. TASK [test] ********************************************************************************************************************************************************************************************************************************************************************
  7. ok: [localhost] => {
  8. "msg": [
  9. "lookupd-tcp",
  10. " 10.3.0.0:4160",
  11. " 10.0.0.1:4160",
  12. " 10.0.0.2:4160",
  13. " lookupd-http",
  14. " 10.3.0.0:4161",
  15. " 10.0.0.1:4161",
  16. " 10.0.0.2:4161",
  17. " data-tcp",
  18. " 10.3.0.0:41501",
  19. " 10.3.0.0:41502",
  20. " 10.0.0.1:41501",
  21. " 10.0.0.1:41502",
  22. " 10.0.0.2:41501",
  23. " 10.0.0.2:41502",
  24. " data-http",
  25. " 10.3.0.0:41511",
  26. " 10.3.0.0:41512",
  27. " 10.0.0.1:41511",
  28. " 10.0.0.1:41512",
  29. " 10.0.0.2:41511",
  30. " 10.0.0.2:41512",
  31. ""
  32. ]
  33. }
  34. PLAY RECAP *********************************************************************************************************************************************************************************************************************************************************************
  35. localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

参考:https://www.it-swarm.dev/zh/action/ansible%E6%89%93%E5%8D%B0%E6%B6%88%E6%81%AF%E8%B0%83%E8%AF%95%EF%BC%9Amsg-line1-n-var2-n-line3-with-var3-var3%E2%80%9D/1056267943/


weinxin

二丫讲梵 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明ansible-playbook编排使用tips

Recommend

  • 64

    1.lookupsfile支持从外部数据拉取信息,例如从数据库里拉取信息,然后定义给一个变量的形式hosts:allgather_facts:truevars:contents:"{{lookup('file','/etc/sysconfig/network')}}"tasks:name:debuglookupsdebug:msg="T

  • 106

    使用ansible-playbook role方式部署jdk

  • 79

    playbook介绍一.为什么引入playbook我们完成一个任务,例如安装部署一个httpd服务,我们需要多个模块(一个模块也可以称之为task)提供功能来完成。而playbook就是组织多个task的容器,他的实质就是一个文件,有着特定的组织格式,它采用的语法格式是YAML(YetAnot...

  • 100

    目录结构:文件内容tasks目录下的“file.yml”文件,内容如下:tasks目录下的“main.yml”templates目录下的“nginx.conf.j2”{%ifnginx_use_proxy%}{%forproxyinnginx_proxies%}upstream{{proxy.name}}{server{{ansible_eth0.ipv4.address}}:{{proxy.po

  • 55

    playbook的基础组件name定义playbook或者task的名称hosts用于指定要执行指定任务的主机user用于指定远程主机上的执行任务的用户task任务列表vars定义变量vars_files定义变量文件notify任务执行结果如果是发生更改的则触发定义在handler的任务handlers用于当前关注...

  • 70

    此playbook的作用:通过指定标签(tags),来说明是安装tomcat7还是tomcat8main.yml:---- include: install_tomcat7.yml  tags: tomcat7- include: install_tomcat8.yml  tags:&...

  • 50

    playbook-剧本介绍playbooks是一个不同于使用Ansible命令行执行方式的模式,其功能更强大灵活。简单来说,playbook是一个非常简单的配置管理和多主机部署系统,不同于任何已经存在的模式,可作为一个适合部署复杂应用程序的基础。Playbook可以定制配置,可以按照指...

  • 51

    PlayBook介绍playbook是由一个或者多个play组成的列表,主要功能是将task定义好的角色归并为一组进行统一管理。playbooks本身组成部分有如下几份:1、tasks:任务,即调用模块完成的操作2、variables:变量3、templates:模板4、handlers:处理器,当条件满足时执...

  • 11

    Ansible最佳实践之使用CallBack插件分析Playbook执行性能 一个好的剧本,执行起来会很是丝滑,良好的执行体验让你甚至感觉不到执行了很久,哈…。——–山河已无恙 和小伙伴们分享一些分析Ansible回调插件的笔记

  • 4

    微信公众号:运维开发故事,作者:姜总一、ansible介绍Ansible Playbooks 提供了一个可重复、可重用、简单的配置管理和多机部署系统,非常适合部署复杂的应用程序。Ansible Playbook 是自动化任务的蓝图,这些任务...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK