ansible常用模块

lineinfile

正则匹配,更改某个关键参数值
insertbefore匹配内容在前面添加
insertafter匹配内容在后面添加
删除某一行内容

 - name: seline modify enforcing
      lineinfile:
         dest: /etc/selinux/config
         regexp: '^SELINUX='
         line: 'SELINUX=enforcing'

如果匹配到,引用line这一行作为替换。如果没有匹配到,则完全引用line这一行作为添加

    - name: Fully quoted a line
      lineinfile:
         dest: /opt/playbook/test/testfile
         state: present
         regexp: '^%wheel'
         line: '%wheel  ALL=(ALL)       NOPASSWD: ALL'

      tags:
        - testfile

blockinfile

在指定的文件中插入”一段文本”,默认是末尾,常见用法是用来分发公钥

文件中某行后插入多行,如下

[root@ansible] /opt/software$ ansible test[1:2] -m blockinfile -a 'dest=/usr/local/kafka/config/zookeeper.properties insertafter=maxClientCnxns block="tickTime=2000\ninitLimit=10\nsyncLimit=5"'

delegate_to

任务委派

在对一组服务器 server_group1 执行操作过程中,需要在另外一台机器 A 上执行一个操作,比如在 A 服务器上添加一条 hosts 记录,这些操作必须要在一个 playbook 联动完成。也就是是说 A 服务器这个操作与 server_group1 组上的服务器有依赖关系。Ansible 默认只会在定义好的一组服务器上执行相同的操作,这个特性对于执行批处理是非常有用的。但如果在这过程中需要同时对另外 1 台机器执行操作时,就需要用到 Ansible 的任务委派功能(delegate_to)

下面描述下我的场景,如我要在192.168.1.1 服务器添加一个hosts 记录 "1.1.1.1 www.abc.com" ,同时也要把这个hosts 记录写到192.168.1.2

ansible hosts 192.168.1.1 文件内容

[all]
192.168.1.1

ansible task 文件内容(192.168.1.1.yml):

---

- name: add host record
shell: "echo "1.1.1.1 www.abc.com" >> /etc/hosts"



- name: add host record
shell: "echo "1.1.1.1 www.abc.com" >> /etc/hosts"
delegate_to: 192.168.1.2

# 添加上面这一行,就可以了

执行playbook

ansible-playbook -i 192.168.1.1.host 192.168.1.1.yml

 

local_action

本地操作

Ansible 默认只会对控制机器执行操作,但如果在这个过程中需要在 Ansible 本机执行操作呢?除了可以使用 delegate_to功能之外,还可以使用 local_action 关键字。

- name: add host record to center server 
  local_action: shell 'echo "192.168.1.100 test.xyz.com " >> /etc/hosts'
当然您也可以使用 connection:local 方法,如下:

- name: add host record to center server 
 shell: 'echo "192.168.1.100 test.xyz.com " >> /etc/hosts'
 connection: local   
 # delegate_to: localhost

register

- name: echo date 
 command: date 
 register: date_output 
 
- name: echo date_output 
 command: echo "30"
 when: date_output.stdout.split(' ')[2] == "30"

serial

批量执行

可以是数字

- name: test play
  hosts: webservers
  serial: 2
  gather_facts: False
  tasks:
  - name: task one
    comand: hostname
  - name: task two
    command: hostname

可以是百分比

- name: test play
  hosts: webservers
  serial: "30%"

可以是列表

- name: test play
  hosts: webservers
  serial:
  - 1
  - 5
  - 10

- name: test play
  hosts: webservers
  serial:
  - "10%"
  - "20%"
  - "100%"

可以混合使用

- name: test play
  hosts: webservers
  serial:
  - 1
  - 5
  - "20%"

max_fail_percentage

如果在执行中,10台服务器中有三台以上失败,剧本任务将停止,实际失败机器必须大于这个百分比时,tasks才会被中止. 等于时是不会中止tasks的.

- hosts: webservers
  max_fail_percentage: 30
  serial: 10

run_once

在一个主机上面只执行一次这个任务

---
# ...

  tasks:

    # ...

    - command: /opt/application/upgrade_db.py
      run_once: true

    # ...

添加在”delegat_to”选项对中来定义要执行的主机:

- command: /opt/application/upgrade_db.py
  run_once: true
  delegate_to: web01.example.org

当”run_once” 没有和”delegate_to”一起使用,这个任务将会被清单指定的第一个主机执行,类似于

- command: /opt/application/upgrade_db.py
  when: inventory_hostname == webservers[0]

fetch

将远程主机中的文件拷贝到ansible机器中,和copy模块的作用刚刚相反,并且在保存的时候使用hostname来进行保存,当文件不存在的时候,会出现错误,除非设置了选项fail_on_missing为yes,flat=yes这个选项很有用,他可以将文件直接拉到ansible机器的目录下,不好说,看下面的例子就明白了

如果没有flat=yes这个选项,原路径是/tmp/open-falcon-v0.2.1.tar.gz,目标路径是/opt/software/master1.hanli.com/tmp/open-falcon-v0.2.1.tar.gz

[root@ansible] /opt/software$ ansible all -m fetch -a "src=/tmp/open-falcon-v0.2.1.tar.gz dest=/opt/software/ " --limit master1.hanli.com
master1.hanli.com | CHANGED => {
    "changed": true, 
    "checksum": "bc3ee52425bf586533af624b78def9194ce27206", 
    "dest": "/opt/software/master1.hanli.com/tmp/open-falcon-v0.2.1.tar.gz", 
    "md5sum": "0a4805bc299af901178e80a54c84f382", 
    "remote_checksum": "bc3ee52425bf586533af624b78def9194ce27206", 
    "remote_md5sum": null
}

如果添加flat=yes选项,目标路径是这样/opt/software/open-falcon-v0.2.1.tar.gz,可能这种有时候使用起来比较方便,需要注意的是dest=/opt/software/路径后面有/

[root@ansible] /opt/software$ ansible all -m fetch -a "src=/tmp/open-falcon-v0.2.1.tar.gz dest=/opt/software/ flat=yes" --limit master1.hanli.com
master1.hanli.com | CHANGED => {
    "changed": true, 
    "checksum": "bc3ee52425bf586533af624b78def9194ce27206", 
    "dest": "/opt/software/open-falcon-v0.2.1.tar.gz", 
    "md5sum": "0a4805bc299af901178e80a54c84f382", 
    "remote_checksum": "bc3ee52425bf586533af624b78def9194ce27206", 
    "remote_md5sum": null
}

args

只有文件不存在的时候执行命令

- name: Run the command if the specified file does not exist.
  command: /usr/bin/make_database.sh arg1 arg2
  args:
    creates: /path/to/database

执行命令前先切换目录

- name: This command will change the working directory to somedir/ and will only run when /path/to/database doesn't exist.
  command: /usr/bin/make_database.sh arg1 arg2
  args:
    chdir: somedir/
    creates: /path/to/database

failed_when

命令不依赖返回状态码来判定是否执行失败,而是要查看命令返回内容来决定。
比如检查etcd集群的状态,如果命令返回的内容中包含failed,就判定这个任务失败

until 直到满足条件
retries 重试次数
delay 重试间隔时间

post_tasks:
    - name: test etcd health
      shell: |
        ETCDCTL_API=3 /usr/local/bin/etcdctl \
          --endpoints={% if https | bool %}https{% else %}http{% endif %}://{{ ansible_eth0.ipv4.address }}:2379 \
        {% if https | bool %}
          --cacert=/etc/kubernetes/pki/etcd/ca.pem \
          --cert=/etc/kubernetes/pki/etcd/server.pem \
          --key=/etc/kubernetes/pki/etcd/server-key.pem \
        {% endif %}
          endpoint health
      register: test_etcd_health
      changed_when: no
      failed_when: "'is healthy' not in test_etcd_health.stdout"
      retries:6
      delay: 4
      until: "'is healthy' in check_etcd_health.stdout"

register: xx
failed_when: xx.stdout.find("yy'") == -1   当xx的的输出里面没有yy的时候

changed_when

一般情况下,ansible 会自动判断模块执行状态,如果修改了远程主机状态则被判定为 change 状态,不过也可以自己决定达到 changed 状态的条件,示例如下:

- name: copy in nginx conf 
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf 
 
- name: validate nginx conf 
 shell: "/data/app/nginx/sbin/nginx -t"
 register: command_result 
 changed_when: command_result.stdout.find('successful')

命令返回中有“successful”字符串,则为 changed 状态,下面这个设定将永远也不会达到 changed 状态。

- name: validate nginx conf 
 shell: "/data/app/nginx/sbin/nginx -t"
 changed_when: false

fail

自定义失败信息

name: Check hostname
fail:
   msg: >
          请检查主机名是否正确
     
when: ansible_hostname != inventory_hostname_short

synchronize

如果想让控制机和远程机的目录中的文件相同,比如/etc/yum.repo.d目录。

注意src目的最后有/,delete是删除远程主机目录中的 控制机上src中没有的文件,也就说加上delete,就可以保证远程机和控制的文件一摸一样,而不会有多余的文件

ansible all -m synchronize -a "src=/etc/yum.repos.d/ dest=/etc/yum.repos.d delete=yes"

需要注意的是:必须在控制机和远程主机上安装rsync。

如果想让两台远程主机之间同步文件,比如从master1到master2,如下

---

- hosts: master2.hanli.com
  tasks:
    - name: copy file from master1 to master2
      synchronize:
        src: /etc/sysctl.d/kubernetes.conf
        dest: /etc/sysctl.d/kubernetes.conf
      delegate_to: master1.hanli.com

如果在远程主机之间同步目录,比如从master1到master2,如下,

注意两个地方:

  • 目录结尾有/
  • 如果master2上没有 /etc/kubernetes/这个目录,需要提前创建好,貌似synchronize模块并没有一个参数可以自动创建
  • 经过测试,只需创建/etc/kubernetes/这个目录就行,不用创建/etc/kubernetes/cert/这个目录
---

- hosts: master2.hanli.com
  tasks:
    - name: copy file from master1 to master2
      synchronize:
        src: /etc/kubernetes/cert/
        dest: /etc/kubernetes/cert/
      delegate_to: master1.hanli.com

如果想在两台远程主机上同步文件,也可以使用scp命令

[root@ansible] ~$ ansible master1.hanli.com -m shell -a "scp /etc/sysctl.d/kubernetes.conf root@master2.hanli.com:/etc/sysctl.d/kubernetes.conf"

async+poll

async 等同于 命令行参数 -B

异步后台方式执行任务,并在指定的秒数后超时,超时会杀掉任务的进程。默认是同步,即保持长连接,它会等待所有执行完毕(即阻塞模式)。但有时候是没必要这样的,比如某些命令的执行时间比ssh的超时时间还长。如果不指定超时秒数,将以同步方式运行任务

poll 等同于 命令行参数 -P ,异步模式下轮训任务的时间间隔,默认10秒

ansible默认是同步模式,即先在一部分节点上执行一个任务(每一批节点的数量取决于fork进程数量),直到这一批所有节点上该任务完全执行完毕才会接入下一个批节点(数量取决于fork进程数量),直到所有节点将该任务都执行完毕,然后重新回到第一批节点开始执行第二个任务。依次类推,直到所有节点执行完所有任务,ansible端才会释放shell。也就是说在未执行完毕的时候,ansible是占用当前shell的,任务执行完毕后,释放shell了才可以输入其他命令做其他动作。

如果是异步模式,假如fork控制的并发进程数为5,远程控制节点为24个,则ansible一开始会将5个节点的任务扔在后台,并每隔一段时间去检查这些节点的任务完成情况,当某节点完成不会立即返回,而是继续等待直到5个进程都空闲了,才会将这5个节点的结果返回给ansible端,ansible会继续将下一批5个节点的任务扔在后台并每隔一段时间进行检查,依次类推,直到完成所有任务。

在异步模式下,如果设置的检查时间间隔为0,在将每一批节点的任务丢到后台后都会立即返回ansible,并立即将下一批节点的任务丢到后台,直到所有任务都丢到后台完成后,会返回ansible端,ansible会立即释放占用的shell。也就是说,此时ansible是不会管各个节点的任务执行情况的,不管执行成功还是失败。

因此,在轮训检查时间内,ansible仍然正在运行(尽管某批任务已经被放到后台执行了),当前shell进程仍被占用处于睡眠状态,只有指定的检查时间间隔为0,才会尽快将所有任务放到后台并释放shell。

需要注意3点:

1 .按批(例如每次5台全部完成一个任务才进入下一批的5台)完成任务的模式在ansible 2.0版本之后可以通过修改ansible的执行策略来改变(见后文),改变后会变成"前赴后继"的执行模式:当一个节点执行完一个任务会立即接入另一个节点,不再像默认情况一样等待这一批中的其他节点完成该任务。
2 .上面执行过程是默认的执行过程,如果开启了pipelining加速ansible执行效率,会省去sftp到远端的过程。
3 .信息收集任务是默认会执行的,但是可以设置禁用它。

debug

可以用来显示执行结果

  post_tasks:
    - name: Check etcd health
      shell: |
        ETCDCTL_API=3 /usr/local/bin/etcdctl \
          -- endpoints={% if https | bool %}https{% else %}http{% endif %}://{{ ansible_ens33.ipv4.address }}:2379 \
        {% if https | bool%}
          -- cacert=/etc/kubernetes/pki/etcd/ca.pem \
          -- cert=/etc/kubernetes/pki/etcd/server.pem \
          -- key=etc/kubernetes/pki/etcd/server-key.pem \
        {% endif %}
          endpoint health
      register: check_etcd_health
    - name: show health info
      debug: var=check_etcd_health  verbosity=0

meta

默认情况下handler会在所以task执行完成之后再以handler中定义的顺序执行(而不是task中notify的顺序),如果我们想在某个任务之后立即执行handler,可以使用meta模块

- name: Flush handlers to start docker
  meta: Flush_handlers
展开阅读全文

没有更多推荐了,返回首页