• 对于注定会优秀的人来说,他所需要的,只是时间!
  • 手懒得,必受贫穷,手勤的,必得富足----《圣经》
  • 帮助别人,成就自己。愿君在本站能真正有所收获!
  • 如果你在本站中发现任何问题,欢迎留言指正!
  • 宝剑锋从磨砺出,梅花香自苦寒来!

ansible-playbook编排使用tips

自动化运维 eryajf 1个月前 (08-19) 188°C 已收录 0个评论
本文预计阅读时间 32 分钟

0,常用变量

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

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

1,判断错误

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

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

然后定义剧本如下:

$ cat site.yaml

---
  - hosts: localhost
    tasks:
      - uri:
          url: "http://localhost/get_info"
          method: GET
        register: webpage
        failed_when: webpage.status != 200
      - debug:
          var: webpage

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

$ ansible-playbook site.yaml

[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] ********************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************
ok: [localhost]

TASK [uri] **************************************************************************************************************************************************************************
ok: [localhost]

TASK [debug] ************************************************************************************************************************************************************************
ok: [localhost] => {
    "webpage": {
        "changed": false,
        "connection": "close",
        "content_length": "44",
        "content_type": "application/json",
        "cookies": {},
        "cookies_string": "",
        "date": "Tue, 02 Jun 2020 06:30:53 GMT",
        "elapsed": 0,
        "failed": false,
        "failed_when_result": false,
        "json": {
            "result": "hello world!",
            "status": "success"
        },
        "msg": "OK (44 bytes)",
        "redirected": false,
        "server": "openresty",
        "status": 200,
        "url": "http://localhost/get_info"
    }
}

PLAY RECAP **************************************************************************************************************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

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

---
  - hosts: localhost
    tasks:
      - uri:
          url: "http://localhost/get_info"
          method: GET
        register: webpage
        failed_when: webpage.status != 200
      - fail:
          msg: "check status field"
        when: "'hello' not in webpage.json.result"

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

---
  - hosts: localhost
    tasks:
      - uri:
          url: "http://localhost/get_info"
          method: GET
          return_content: yes
        register: webpage
        failed_when: webpage.status != 200
      - fail:
          msg: "check status field"
        when: "'hello' not in webpage.content"

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

2,只跑一次

run_once: true

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

---
- name: "创建远程主机上的版本目录"
  file: path=/release/{{project}}/{{_version}} state=directory
  tags: deploy

- name: "将代码同步到远程主机版本目录"
  synchronize:
    src: /{{WORKSPACE}}/
    dest: /release/{{project}}/{{_version}}/
    delete: yes
  tags: deploy

- name: "将项目部署到生产目录"
  file: path=/data/www/{{project}} state=link src=/release/{{project}}/{{_version}}
  tags: deploy

- name: "使版本目录保持五个版本历史"
  script: chdir=/release/{{project}} keepfive.sh
  tags: deploy

- name: "生成远程版本号"
  shell: "ls /release/{{project}} > /release/{{project}}.log"
  tags: deploy

- name: "同步版本号到本地"
  synchronize: "src=/release/{{project}}.log dest=/root/.jenkins/version/{{JOB_NAME}}.log mode=pull"
  tags: deploy

- name: "执行自由脚本"
  script: chdir=/release/{{project}} free.sh
  tags: deploy

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

---
- name: "创建远程主机上的版本目录"
  file: path=/release/{{project}}/{{_version}} state=directory
  tags: deploy

- name: "将代码同步到远程主机版本目录"
  synchronize:
    src: /{{WORKSPACE}}/
    dest: /release/{{project}}/{{_version}}/
    delete: yes
  tags: deploy

- name: "将项目部署到生产目录"
  file: path=/data/www/{{project}} state=link src=/release/{{project}}/{{_version}}
  tags: deploy

- name: "使版本目录保持五个版本历史"
  script: chdir=/release/{{project}} keepfive.sh
  tags: deploy

- name: "生成远程版本号"
  shell: "ls /release/{{project}} > /release/{{project}}.log"
  run_once: true
  tags: deploy

- name: "同步版本号到本地"
  synchronize: "src=/release/{{project}}.log dest=/root/.jenkins/version/{{JOB_NAME}}.log mode=pull"
  run_once: true
  tags: deploy

- name: "执行自由脚本"
  script: chdir=/release/{{project}} free.sh
  tags: deploy

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

3,滚动更新

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

$ cat site.yml

---
  - hosts: remote
    tasks:
      - debug:
          msg: "this is task a"
      - debug:
          msg: "this is task b"

执行如上剧本看输出:

ansible-playbook -i test_hosts s.yaml

PLAY [remote] ***********************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************
ok: [10.3.22.90]
ok: [10.3.22.87]

TASK [debug] ************************************************************************************************************************************************************************
ok: [10.3.22.90] => {
    "msg": "this is task a"
}
ok: [10.3.22.87] => {
    "msg": "this is task a"
}

TASK [debug] ************************************************************************************************************************************************************************
ok: [10.3.22.90] => {
    "msg": "this is task b"
}
ok: [10.3.22.87] => {
    "msg": "this is task b"
}

PLAY RECAP **************************************************************************************************************************************************************************
10.3.22.87                 : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
10.3.22.90                 : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

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

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

---
  - hosts: remote
    serial: 1
    tasks:
      - debug:
          msg: "this is task a"
      - debug:
          msg: "this is task b"

执行结果如下:

ansible-playbook -i test_hosts s.yaml

PLAY [remote] ***********************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************
ok: [10.3.22.90]

TASK [debug] ************************************************************************************************************************************************************************
ok: [10.3.22.90] => {
    "msg": "this is task a"
}

TASK [debug] ************************************************************************************************************************************************************************
ok: [10.3.22.90] => {
    "msg": "this is task b"
}

PLAY [remote] ***********************************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************************************
ok: [10.3.22.87]

TASK [debug] ************************************************************************************************************************************************************************
ok: [10.3.22.87] => {
    "msg": "this is task a"
}

TASK [debug] ************************************************************************************************************************************************************************
ok: [10.3.22.87] => {
    "msg": "this is task b"
}

PLAY RECAP **************************************************************************************************************************************************************************
10.3.22.87                 : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
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失败。

---
  - hosts: remote
    serial: 1
    max_fail_percentage: 25
    tasks:
      - debug:
          msg: "this is task a"
      - debug:
          msg: "this is task b"

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

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

4,打印多行

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

$ cat test.yaml
---
- hosts: localhost
  connection: local
  vars:
    msg: |
       lookupd-tcp
        {{ node1 }}:4160
        {{ node2 }}:4160
        {{ node3 }}:4160
        lookupd-http
        {{ node1 }}:4161
        {{ node2 }}:4161
        {{ node3 }}:4161
        data-tcp
        {{ node1 }}:41501
        {{ node1 }}:41502
        {{ node2 }}:41501
        {{ node2 }}:41502
        {{ node3 }}:41501
        {{ node3 }}:41502
        data-http
        {{ node1 }}:41511
        {{ node1 }}:41512
        {{ node2 }}:41511
        {{ node2 }}:41512
        {{ node3 }}:41511
        {{ node3 }}:41512
  tasks:
    - name: test
      debug:
        msg: "{{ msg.split('\n') }}"

然后运行看下:

$ansible-playbook test.yaml -e "node1=10.3.0.0 node2=10.0.0.1 node3=10.0.0.2"
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [test] ********************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "lookupd-tcp",
        " 10.3.0.0:4160",
        " 10.0.0.1:4160",
        " 10.0.0.2:4160",
        " lookupd-http",
        " 10.3.0.0:4161",
        " 10.0.0.1:4161",
        " 10.0.0.2:4161",
        " data-tcp",
        " 10.3.0.0:41501",
        " 10.3.0.0:41502",
        " 10.0.0.1:41501",
        " 10.0.0.1:41502",
        " 10.0.0.2:41501",
        " 10.0.0.2:41502",
        " data-http",
        " 10.3.0.0:41511",
        " 10.3.0.0:41512",
        " 10.0.0.1:41511",
        " 10.0.0.1:41512",
        " 10.0.0.2:41511",
        " 10.0.0.2:41512",
        ""
    ]
}

PLAY RECAP *********************************************************************************************************************************************************************************************************************************************************************
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
扫码订阅本站,第一时间获得更新
微信扫描二维码,订阅我们网站的动态,另外不定时发送WordPress小技巧,你可以随时退订,欢迎订阅哦~

二丫讲梵 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明ansible-playbook编排使用tips
喜欢 (0)
[如果想支持本站,可支付宝赞助]
分享 (0)
eryajf
关于作者:
学无止境,我愿意无止境学。书山有路,我愿意举身投火,淬炼成金!永远不要忘记,激情的奋进,就是美好的未来!

您必须 登录 才能发表评论!