Ansible playbook 使用介绍

环境信息

  • Centos 7
  • ansible 2.9.27

Playbook 语法示例

ansible playbook 使用的是 YAML 格式的语法。

---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted

playbook 由一个或多个 play 组成。它的内容是一个以 play 为元素的列表。以上示例仅包含一个 play

每一个 play 中包含了一个 tasks 列表,tasks 列表中的每个 task 在其对应的 hosts依次执行即一个 task 执行完毕,下一个 task 才会执行

在运行 playbook 的过程中,如果一个 host 执行 task 失败,这个 host 将从整个 playbook 中移除。如果发生执行失败的情况,需要修正 playbook 中的错误,重新执行。

playbook 基础

主机与用户

play 中一般都需要选择要操作的目标主机,也可能需要指明以哪个用户身份来执行 tasks

  • hosts 一个或多个组或主机的 patterns,以 , 分割
  • remote_user 用户名。
---
- hosts: webservers
remote_user: root

在每一个 task 中,也可以定义自己的远程账号

- hosts: webservers
remote_user: root
tasks:
- name: test connection
ping:
remote_user: user1

sudo 提权操作

在需要提权操作的场景下,需要切换到更高权限的用户,可以使用 become 指令。become 可以在全局(play)级别使用或者 task 级别使用。

如果要提权到其他用户而非 root,可以使用指令 become_user

---
- hosts: master-nodes
become: yes
tasks:
- name: ping
ping:

- name: cat authorize
command: cat /root/.ssh/authorized_keys
become: yes
become_user: centos

变量

task 中可以使用变量。假设在 vars 那里定义了变量,可以这样使用它:

- hosts: webservers
vars:
http_port: 80
max_clients: 200
tasks:
- name: create a web for port {{ http_port }}
template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ http_port }}

playbook 执行之前,默认会执行 setup 收集目标主机的 facts 信息,这是 play 中默认的第一个 task

# ansible-playbook test.yml 

PLAY [k8s-master-nodes] ******************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************

ok: [k8s-master1]

ok: [k8s-master3]

ok: [k8s-master2]

playbook 中的 task 可以使用 facts 中的变量的值

# ansible k8s-master-nodes[0] -m setup -a "filter=ansible_distribution"

k8s-master1 | SUCCESS => {
"ansible_facts": {
"ansible_distribution": "CentOS Linux",
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false
}

# cat test.yml
---
- hosts: k8s-master-nodes
# become: yes
tasks:
- name: ping
ping:

- name: test os distribution
debug:
msg: "This is Centos"
when: ansible_distribution == "CentOS Linux"



# ansible-playbook test.yml

PLAY [k8s-master-nodes] ******************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************

ok: [k8s-master1]

ok: [k8s-master3]

ok: [k8s-master2]

TASK [ping] *************************************************************************************************************************************
ok: [k8s-master2]
ok: [k8s-master1]
ok: [k8s-master3]

TASK [test os distribution] *********************************************************************************************************************
ok: [k8s-master1] => {
"msg": "This is Centos"
}
ok: [k8s-master2] => {
"msg": "This is Centos"
}
ok: [k8s-master3] => {
"msg": "This is Centos"
}

PLAY RECAP **************************************************************************************************************************************
k8s-master1 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
k8s-master2 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
k8s-master3 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

handlers

handlers 中定义了在发生改动时执行的操作。

Handlers 也是一些 task 的列表,通过名字来引用,它们和一般的 task 并没有什么区别。Handlers 是由通知者进行 notify, 如果没有被 notify,handlers 不会执行。不管有多少个通知者进行了 notify,等到 play 中的所有 task 执行完成之后,handlers 也只会被执行一次。

handlers 会按照声明的顺序执行

Handlers 最佳的应用场景是用来重启服务,或者触发系统重启操作

notify

(当发生改动时)notify actions 会在 playbook 的每一个 task 结束时被触发,而且即使有多个不同的 task 通知改动的发生, notify actions 只会被触发一次。

- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache

module

palybook 中的每个 task 都是为了运行某个 module。在 task 中配置 module,是以 module: options 的格式

- hosts: webservers
tasks:
- name: test connection
ping:
- name: make sure apache is running
service: name=httpd state=running
- name: disable selinux
shell: setenforce 0

ansible playbook 常用模块参考

iptables

ansible iptables 模块官方文档

  • iptables 模块用于配置 Linux iptables 防火墙 [1]
  • iptables 模块只修改当前系统生效的 iptables 规则(动态),不会将规则写入 iptables 服务的配置文件以实现静态(持久)配置,它的行为和 iptables 命令相同

iptables 模块参数参考 [1]

参数 说明 示例
action rule 是被 append 到最后还是插入到最前面。
默认 append
如果 rule 已经存在,不会做变更
chain 要操作的 chain。
可以是自定义的 chain 或者默认存在的 chain 如 INPUT, FORWARD, OUTPUT, PREROUTING, POSTROUTING, SECMARK or CONNSECMARK
table This option specifies the packet matching table which the command should operate on
chain_management If true and state is present, the chain will be created if needed.
If true and state is absent, the chain will be deleted if the only other parameter passed are chain and optionally table. 默认为 false
comment 规则的注释说明
ctstate
list / elements=string
A list of the connection states to match in the conntrack module.
Possible values are INVALID, NEW, ESTABLISHED, RELATED, UNTRACKED, SNAT, DNAT.
Default: []
source Source specification
destination
string
Destination specification.
Address can be either a network name, a hostname, a network IP address (with /mask), or a plain IP address.
Hostnames will be resolved once only, before the rule is submitted to the kernel. Please note that specifying any name to be resolved with a remote query such as DNS is a really bad idea.
The mask can be either a network mask or a plain number, specifying the number of 1’s at the left side of the network mask. Thus, a mask of 24 is equivalent to 255.255.255.0. A ! argument before the address specification inverts the sense of the address.
destination_port
string
Destination port or port range specification
destination_ports
list / elements=string
This specifies multiple destination port numbers or port ranges to match in the multiport module
dst_range
string
Specifies the destination IP range to match in the iprange module.
source_port Source port or port range specification.
flush
boolean
Flushes the specified table and chain of all rules.
If no chain is specified then the entire table is purged.
默认值 false
jump This specifies the target of the rule
protocol The protocol of the rule or of the packet to check.
The specified protocol can be one of tcp, udp, udplite, icmp, ipv6-icmp or icmpv6, esp, ah, sctp or the special keyword all
rule_num Insert the rule as the given rule number.
This works only with action=insert.

lineinfile

lineinfile 用于以下场景:

  • 确定文件中存在特定的一行,替换存在的行
  • 修改文件中特定的一行

常用参数:

参数 说明 示例
state 指定的行是否应该存在。
- absent
- present 默认值
path
aliases: dest, destfile, name
required
要修改的目标文件
line
aliases: value
要插入或者替换修改的行
state=present 时为必须参数
如果 backrefs=true,可以使用 regexp 正则表达式捕获的值,使用 \g<1>\g<2> 的方式引用捕获到的内容
backup
boolean
默认值 false 。是否创建备份文件

修改防火墙中某个 IP 示例

- name: Modify iptables rule in /etc/sysconfig/iptables
hosts: nginx_1
become: yes
tasks:

- name: Replace the IP address in iptables rule
lineinfile:
path: /etc/sysconfig/iptables
regexp: (.*)18\.32\.100\.90(.*)
line: \g<1>180.232.100.99\g<2>

state: present
backup: yes
backrefs: true

参考链接

ansible 官方文档
Ansible中文权威指南

脚注