第3章 Ansible 进阶
3.1 Ansible 的配置
3.1.1 可以配置什么
安装好Ansible后,通过 /etc/ansible/ansible.cfg 文件的内容和注释可以了解到所有可以配置的选项,下面距离我们常用的配置
#可以配置主机清单文件 inventory、extra模块放置的路径 library、远程主机的临时目录 remote_tmp,以及管理节点上的临时目录 local_tmp
inventory = /etc/ansible/hosts
library = /usr/share/my_modules/
remote_tmp = ~/.ansible/tmp
local_tmp = ~/.ansible/tmp
# 可以配置连接端口号 accelerate_port、超时时间等
accelerate_port = 5099
accelerate_timeout = 30
accelerate_connect_timeout = 5.0
3.1.2 Ansible 配置文件的优先级
优先级从高到低的排序
- ANSIBLE_CONFIG 配置的环境变量
- 当前目录的ansible.cfg
- 家目录下的 .ansible.cfg
- /etc/ansible/ansible.cfg
3.2 主机清单
主机清单(Host Inventory),它告诉Ansible 需要管理哪些主机,以及这些主机的分类和分组信息的文件。可以认为这是个文件版的CMDB系统。
Inventory的默认文件为 /etc/ansible/hosts ,可以通过 /etc/ansible/ansible.cfg 配置文件进行修改。此外,我们还可以通过 -i 参数来指定主机清单配置文件
ansible-playbook -i test.ini site.yml
当然我们也可以使用 --inventory-file 参数来进行指定。
3.2.1 远程主机的分组
在inventory文件中,可以通过 "[]" 符号给主机做分组。此外,分组还支持嵌套,如下。
mail.example.com
#简单的分组
[db]
one.example.com
two.example.com
[web]
www[01:50].example.com
#嵌套分组
[linuxserver:children]
db
web
3.2.2 设置连接参数
Ansible 可以在Inventory 文件中指定主机的连接参数,包括连接的方法、用户等。在Inventory中设置链接的参数如下,用空格分割多个参数
[targets]
localhost ansible_connect=local
other1.example.com ansible_connect=ssh ansible_user=root
other1.example.com ansible_connect=ssh ansible_user=pangcm
其他常用的连接参数如下
连接参数的值 | 连接参数的含义 |
---|---|
ansible_connection | SSH的连接方式,可以指定为 smart、ssh或者paramiko |
ansible_host | Ansible连接的主机地址,如果你要在Ansible中给主机起了一个不同的别名,那么需要使用这个参数 |
ansible_port | SSH端口号,默认为22 |
ansible_user | SSH连接时默认的用户名 |
ansible_ssh_pass | SSH连接时使用的密码,不建议用本参数存储明文密码,尽量使用values对密码进行加密存储 |
ansible_ssh_private_key_file | 基于key的SSH连接,使用的是private key 文件 |
ansible_ssh_common_args | 通过配置本参数指定SFTP、SCP和SSH默认的额外参数 |
以上的参数除了能够在Inventory文件中定义,还可以在playbook中定义或者通过变量的方式传入。
3.2.3 变量
Anible 支持在主机清单文件中指定变量,或者与主机清单文件同目录的特定子目录和文件中定义变量
- 主机清单文件中的变量
#为单个主机指定变量
[app]
host1 http_port=80
host2 http_port=81
#为一个组指定变量
[app:vars]
http_port=80
- 按目录结果存储的变量
假设主机清单文件为 /etc/ansible/hosts,那么相关的Host和Group变量可以放在 /etc/ansible/host_vars 和 /etc/ansible/group_vars 下同名目录中的文件,通常使用 yaml 文件。如下:
#host1的变量
/etc/ansible/host_vars/host1.yml
#app组的变量
/etc/ansible/group_vars/app.yml
这时候yaml文件存放的变量格式为 key:value 的形式,如下
---
hppt_port: 80
如果你的变量非常多,多到一个文件都存不下。那么你可以在同名目录下分开多个文件来存放变量,如下:
#host1的变量
/etc/ansible/host_vars/host/vars1.yml
/etc/ansible/host_vars/host/vars2.yml
3.3 Ansible 的脚本Playbook
3.3.1 Playbook的文件格式 YAML
Playbook是ANsible的脚本语言,使用的YAML格式。YAML和JSON类似,是一种数据表示格式,下面介绍一些关于YAML语言的基本知识。
# 文件开始符
---
# 数组list
- element1
- element2
- element3
#字典
key: value
#字典的嵌套
pangcm:
name: pangcm
job: ops
skill: ansible
# 字典和数组的嵌套
- pangcm1:
name: pangcm1
job: ops
skills:
- ansible
- linux
- python
- pangcm2:
name: pangcm2
job: ops
skills:
- ansible
- linux
- python
需要注意的地方,变量里面如果有冒号 ":" 时需要加上引号,变量以 "{" 开头时也要加上引号
foo: "foo:bar"
foo: "{{ variable }}"
3.3.2 执行Playbook的命令
执行Playbook需要使用单独的命令: ansible-playbook,常用的使用方法如下
# 基本使用方法
ansible-playbook deploy.yaml
# 查看输出西街
ansible-playbook deploy.yaml -v
# 查看脚本会影响哪些主机
ansible-playbook deploy.yaml --list-hosts
# 并行执行脚本(默认的并发数量为5)
ansible-playbook deploy.yaml -f 10
3.3.3 Playbook 的基本语法
最基本的Playbok脚本分为三个部分:
- 在什么机器以什么身份执行
- hosts
- user
- 执行的任务都有什么
- tasks
- 善后的任务都有什么
- handlers
下面针对这上面提到的三个部分做介绍
- 主机和用户
key | 含义 |
---|---|
hosts | 为主机的IP,或者主机组名,或者关键字all |
user | 在远程以哪个身份执行 |
become | 切换成其他用户执行,值为 yes或者no |
become_method | 与become一起使用,值可以为 "sudo/su/pfexec/doas" |
become_user | 与become一起用,默认为root,也可以是其他用户名 |
脚本里面使用become时,执行Playbook必须加参数 --ask-become-pass,提示用户输入 "sudo" 的密码。
ansible-playbook deploy.yaml --ask-become-pass
你也可以在Inventory中定义 ansible_sudo_pass 变量来避免每次都需要手工交互式地输入sudo密码。
- 任务列表
- 任务(task)是从上到下顺序执行的,如果中间发生错误,那么整个Playbook会中止。
- 每个任务都是对模块的一次调用,只是使用不用的参数和变量而已。
- 每个任务最好有 name 属性,这是供人读的,没有实际的操作。但是有这样的输出,我们能更好地知道执行的情况以及task的用途。
下面是一个简单的示例:
tasks:
# name 是可选的,建议使用
- name: make sure apache is running
service: name=httpd state=running
# 上面的参数使用的是 key=value的形式,也可以使用key:value的形式。
- name: copy ansible inventory file to client
copy:
src: /etc/ansible/hosts
dest: /etc/ansible/hosts
mode: 0644
任务中Action会调用一个模块,然后在模块中检查当前系统状态是否需要重新执行。如果本次执行了,那么Action返回的值为changed。如果不需要执行,那么返回的是ok。
- 响应事件handler
-
什么是handler
每个主流的编程语言都有Event机制,而handler就是Playbook的Event。Handlers里面每一个handler都是对模块的一次调用。但是和task任务不同,handler只有在它需要在任务中被调用的时候才有可能被执行。
前面提到,任务表中的任务都是有状态的:changed或者ok。在Ansible中,只有在任务的执行状态为changed的时候,才会执行该任务调用的handler。这也是handller和普通的Event机制不同的地方。 -
应用场景
什么情况下使用handler呢?如果你在任务中修改了Apache的配置文件,嘛呢需要重启Apache。如果你安装了一个Apache插件,那么也需要重启Apache。这时候,重启Apache就可以设计成一个handler。
一个handler最多只执行一次,并且在所有任务都执行完之后再执行。如果有多个任务调用(notify)同一个handler,那么只执行一次。
-
下面是一个示例,第一次执行的时候会触发两个handler,第二次执行的之后只会触发第二个handler。
---
- hosts: lb
remote_user: root
vars:
random_number: "{{ 10000 |random }}"
tasks:
- name: Copy the /etc/hosts to /tmp/hosts
copy: src=/etc/hosts dest=/tmp/hosts
notify:
- call by /tmp/hosts
- name: Copy the /etc/hosts to /tmp/hosts.{{ random_number }}
copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number }}
notify:
- call by /tmp/hosts.{{ random_number }}
handlers:
- name: call by /tmp/hosts.{{ random_number }}
debug: msg="call by /tmp/hosts.{{ random_number }} "
- name: call by /tmp/hosts
debug: msg="call first time"
这里需要注意的是handler的执行顺序是按照定义的顺序,而不是任务调用的顺序。就是说定义的时候顺序是 1,2,3;但是调用的时候是 3,2,1 ;但是最后执行的时候还是 1,2,3 的顺序。
3.3.4 变量
在Playbook中,常用的几种变量包括以下几种情况
- 在Playbook中用户自定义的变量
- 用户无须自定义,Ansible会在执行Playbook之前去远程主机搜集关于远程节点系统的信息变量
- 在文件模版中,可以直接使用上述两种变量
- 把任务的运行结果作为一个变量来使用,这个变量叫做注册变量
- 为了使Playbook更灵活、通用性更强,允许用户在执行Playbook时传入变量的值,这时候需要额外变量。
- 在Playbook中用户自定义的变量
用户在Playbook中使用变量时需要使用 "{{ }}" 引用起来即可。在Playbook中,我们可以使用vars关键字来定义变量,也可以使用var_files来引入变量文件。如下所示:
#使用vars来定义变量
- hosts: web
vars:
http_port: 80
tasks:
....
#使用var_files来引入变量文件
- hosts: web
var_files:
- vars/server_vars.yaml
tasks:
....
有时候我们需要使用变量的值不是简单的字符串或者数字,而是一个对象,这时候定义的语法如下,格式为YAML的字典格式。
---
- hosts: localhost
vars:
foo:
field1: one
field2: two
tasks:
- name: use vars
debug:
var=foo['field1'] #也可以foo.field1
要注意有些时候YAML和Ansible Playbook的变量语法不能在一起好好地工作。这通常发生在冒号后面的值有 "{" 开头的变量时,如果不加上引号,就很有可能报语法错误。
- 远程主机的系统变量(Facts)
Ansible 会通过模块 "setup" 来搜集主机的系统信息,这些收集到的系统信息叫做Facts.每个Playbook在执行前都会默认执行setup模块,所以这些Facts信息可以直接以变量的形式使用。
那么,我们怎么知道有那些Facts变量可以引用呢,我们可以使用setup模块来查看下:
ansible all -m setup -u root
在Playbook中,我们可以和使用普通变量一样来使用Facts变量。这里需要特别说明的是如何使用Facts中的复杂变量。答案是可以通过下面两种方式,如下:
#中括号
{{ ansible_ens3['ipv4']['address'] }}
#点号
{{ ansible_ens3.ipv4.address }}
收集Facts信息会消耗额外的时间,Ansible 的默认配置中要求搜集这些信息。如果要关闭,可以通过关键字 gather_facts来关闭。如下
- hosts: db
gather_facts: no
- 文件模版中使用的变量
template模块在Ansible中十分常用,而他在使用的时候有没有显示指定template文件中的值,所以有时候用户对template中使用的变量感到困惑,所以这里再重新强调下它的变量的使用。
template能直接使用再Playbook中定义的变量,也可以使用Facts变量,所有再Playbook中可以访问的变量,都可以再template文件中使用。通常template文件我们都是使用 j2作为后缀,因为这是使用jinja2的文件格式,里面的变量需要使用 "{{}}" 括起来。
- 把运行结果当作变量使用-注册变量
这时候就需要使用注册变量了,把执行的结果注册到变量中,给后面的任务使用。把执行结果注册到变量中的关键字是register,使用方法如下:
---
- hosts: web
tasks:
- name: exec shell
shell: ls
register: result
ignore_errors: True
- name: echo result
shell: echo "{{ result.stdout }}"
when: result.rc == 5
- name: debug result
debug: msg="{{ result.stdout }}"
注册变量经常和debug模块一起使用,这样可以得到更多的关于执行错误的信息,以帮助用户调试。
- 用命令行传递参数
为了使Playbook更灵活、通用性更强,允许用户在执行的时候传入变量的值,这时候就需要用到 "额外变量"。
使用命令行传递参数可以使用 --extra-vars 也可以使用简写 -e 。如下所示:
#在命令行中传值的方法
ansible-playbook test_var.yaml -e "host=web user=root"
#还可以使用json格式传递参数
ansible-playbook test_var.yaml -e "{'host':'web','user':'root'}"
#还可以将参数放在文件里面
ansible-playbook test_var.yaml -e "@vars.json"
上面的例子可以下面的playbook。
---
- hosts: localhost
tasks:
- name: show vars
debug: msg="host is {{ host }}, user is {{ user }}"
3.3.5 Playbook 也有逻辑控制语句
- when: 条件判断语句,类似编程语言中的if。
- loop: 循环语句,类似于编程语言中的while。
- block: 把几个任务组在一个代码块,以便针对一组操作的异常进行处理等操作。
- 条件判断语句when
有时候用户很有可能需要满足特定条件才去执行特定的步骤,如在某一特定的版本的系统上安装软件包。如下:
tasks:
#远程主机如果是debian,立刻关机
- name: "shutdown Debian systems"
command: /sbin/shutdown -t now
when: ansible_os_family == "Debian"
#根据Action的执行结果,来决定是否执行任务
- name: result is false
command: /bin/false
register: result
ignore_errors: True
- name: exec shell
shell: /bin/something
when: result | failed
- name: exec other shell
shell: /bin/something_else
when: result | success
#还可以使用 |int 对返回值的类型做转换,如下
- name: "只有在rhel7或者更新的版本上执行任务"
debug: "msg=hello pcm"
when: ansible_os_family == "RedHat" and ansible_lsb.major_release | int >= 6
除了上面的用法外,我们还可以使用条件表达式
---
- hosts: localhost
vars:
epic: true
tasks:
- name: "使用布尔表达式"
shell: echo "This is epic"
when: epic
- name: "布尔表达式前面可以加上not"
shell: echo "This is epic"
when: not epic
- name: "还可以判断变量有没有定义"
shell: echo "This is epic"
when: epic is not defined
- name: "还可以比较数值大小"
shell: echo "This is epic"
when: epic > 5
when除了能够用在task上,我们还会和Include或者Role一起来使用。
---
#当deploy为真时,执行deploy.yaml这个playbook。
- include: tasks/deploy.yaml
when: deploy
---
- hosts: web
#当update为真时,执行名为update的role
roles:
- { role: update, when: update}
- 循环语句 loop
"with_items" 可以用迭代list类型的变量,不仅支持简单的字符串列表,还可以支持哈希列表,如下:
#最简单的列表模式
- name: add serveral user
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
#如果在vars中定义了列表变量,还能这么操作
vars:
users: ['user1','user2']
tasks:
- name: add serveral user
user: name={{ item }} state=present groups=wheel
with_items: "{{ users }}"
#哈希列表这么用,可以使用具体的子项(字典列表)
- name: add serveral user
user: name={{ item.user }} state=present groups={{ item.group }}
with_items:
- {user: 'user1', group:'group1'}
- {user: 'user2', group:'group2'}
如果同事使用when和with_items(或其他循环声明),那么when声明会为每个条目单独判断一次
Ansible的循环和编程语言的一样,也能嵌套循环
下面嵌套的是列表
---
- hosts: localhost
tasks:
#使用with_nested,和python一样,可以使用 []来访问内层循环,也可以使用点号 "." 来访问。
- name: debug loop
debug: msg="username is {{ item[0] }},password is {{ item[1] }}"
with_nested:
- ['pcm1', 'pcm2']
- ['passwd1', 'passwd2', 'passwd3']
上面playbook执行的结果如下:
TASK [debug loop] ***************************************************************************************************************************************************************************
ok: [localhost] => (item=[u'pcm1', u'passwd1']) => {
"msg": "username is pcm1,password is passwd1"
}
ok: [localhost] => (item=[u'pcm1', u'passwd2']) => {
"msg": "username is pcm1,password is passwd2"
}
ok: [localhost] => (item=[u'pcm1', u'passwd3']) => {
"msg": "username is pcm1,password is passwd3"
}
ok: [localhost] => (item=[u'pcm2', u'passwd1']) => {
"msg": "username is pcm2,password is passwd1"
}
ok: [localhost] => (item=[u'pcm2', u'passwd2']) => {
"msg": "username is pcm2,password is passwd2"
}
ok: [localhost] => (item=[u'pcm2', u'passwd3']) => {
"msg": "username is pcm2,password is passwd3"
}
---
- hosts: localhost
tasks:
#使用with_dict,和python一样,可以使用 []来访问内层循环,也可以使用点号 "." 来访问。
- name: debug loop
debug: msg="username is {{ item[0] }},password is {{ item[1] }}"
with_nested:
- ['pcm1', 'pcm2']
- ['passwd1', 'passwd2', 'passwd3']
下面嵌套的是哈希表
---
- hosts: localhost
vars:
user:
- user1:
name: pcm1
age: 18
- user2:
name: pcm2
age: 20
tasks:
- name: print mans
debug: msg="User {{ item.key }} is {{ item.value.name }},age is {{ item.value.age }}"
with_dict: "{{ users }}"
对文件,我们也可以使用循环
tasks:
- name: "首先确认文件是存在的"
file: dest=/etc/fooapp state=directory
- name: "复制文件到远程目录上"
copy: "src={{ item }} dest=/etc/fooapp/ mode=600"
with_fileglob:
- /playbooks/files/fooapp/*
- 代码块 block
多个action组成块后,可以根据不同条件执行一段语句。好比编程语言中的函数。
---
- hosts: localhost
vars:
flag: true
tasks:
- block:
- name: action1
debug: msg="hello world"
- name: action2
debug: msg="hello ansible"
when: flag
block除了能和when组合在一起之外,还可以和rescue和always一起组合。效果可以类比python中的 try、except、finally 。如下:
---
- hosts: localhost
tasks:
- block:
- debug:
msg: 'I execute normally'
- command: /bin/false
- debug:
msg: 'I never execute, due to the above task failing'
rescue:
- debug:
msg: 'I caught an error'
- command: /bin/false
- debug:
msg: 'I also never execute'
always:
- debug:
msg: "This always executes"
3.3.6 重用 Playbook
Playbook支持两种重用机制,一种是重用单个静态Playbook嗯见,另外一种是重用特定功能的文件夹,类似于Python等编程语言中的包(Package)。
- include语句: 重用单个Playbook脚本,使用起来简单、直接
- role语句: 重用实现特定功能的Playbook文件夹,使用方法稍复杂,功能强大。role是Ansible更为推荐的重用和分享Playbook的方式。
1. include语句
include语句是基本的代码重用机制,主要重用任务,同时,include还可以将任务分割成多个文件,避免Playbook过于臃肿。
include的使用方法很简单,直接使用即可,如下:
#假设该文件名为main.yaml,下面调用deploy.yml的Playbook。
---
- hosts: localhost
tasks:
- include: deploy.yml
下面是deploy.yml的内容,只需要写上各个action即可。
- name: action1
debug: msg=action1
- name: action2
debug: msg=action2
如果我们想要引用Playbook的时候传入参数应该怎么操作呢?
#直接在行尾加上参数即可,用空格分割
- hosts: localhost
tasks:
- include: deploy.yml port=80
#也可以传入一个字典作为变量
- include: deploy.yml
vars:
user: pangcm
port: 80
#上面的字典也可以写成一串json
- { include: deploy.yml,user:pangcm,port=80 }
如果你在Playbook中已经定义了参数,那么就不需要传入了,直接在被调用的Playbook中使用即可。
---
- hosts: localhost
vars:
port: 80
tasks:
- include: deploy.yml
这里要注意 include 的位置,这是在tasks下的,也就是相当于一个大的action。如果放在和tasks同级,也就是全局include。我们不推荐这么做,因为它不支持嵌入include,而且很多的Playbook也无法使用,
---
- hosts: localhost
tasks:
...
- include: deploy.yml
include是场景不大的情况下还是挺好用的,但是如果引用多了这将很难管理,维护成本会变得很多。所以在使用更加灵活的重用机制时,建议使用下面的role.
2. role-Playbook 的 "Package"
Ansible好比编程语言中的include,role好比编程语言中的package。通常一个role由一组文件组成,形成一个完整的功能。如一个部署nginx的role,里面会包含若干playbook和文件。
Ansibe十分提倡在Playbook中使用role,并且提供了一个分享role的平台 ANsible Galaxy。在Galaxy上可以找到别人写好的role。
- role的目录结构
在Ansible中,通过遵循特定的目录结构,就可以实现对role的定义,具体遵循的目录结构是什么样子的呢?如下:
[root@xxx-test roles]# tree
.
├── deploy.yml
└── install-nginx
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
上面定义了一个名为install-nginx的role,用来安装nginx。Playbook文件中的deploy.yml调用这个role。上面的文件不要求全部拥有,看自己的实际需求。(以上目录我使用的是ansible-galaxy init install-nginx
创建的。)
下面解析下role目录的功能:
- defaults: 存放变量文件,存放在这里的变量优先级最低
- files: 存放普通文件,通常给copy模块使用
- handlers: 存放handler文件
- meta: 存放描述依赖关系role的文件
- tasks: 存放任务文件
- templates: 存放模版文件
- tests: 存放测试文件,用来测试整个role能否正常运行
- vars: 存放变量文件,优先级比defaults的高
role的子目录里面通常有main.yml文件,这是role的入口文件。整个role的入口文件为 tasks/main.yml。
此外,我们在使用下面的几个模块的时候,调用的文件不需要路径,直接使用文件名称即可:
- copy 或者script 使用 files 下的文件
- template 使用templates下的文件
- include 使用 tasks 下的文件。
- 在role中使用变量
在role中使用变量非常简单,直接使用 "{{}}" 括起来就可以使用了。我们先看下默认变量怎么使用,在 install-nginx/defaults/main.yml 文件中定义一个默认变量,然后输出。
var: "I am defalut vars"
在 install-nginx/tasks/main.yml 文件,也就是我们的role的入口文件中使用这个变量,直接输出。
---
- name: use var
debug: msg="{{ var }}"
最后,我们在 role的同级目录的文件 deploy.yml 中调用这个role:
---
- hosts: localhost
roles:
- install-nginx
最后调用这个playbook,看到输出了这个默认变量。
[root@xxx-test roles]# ansible-playbook deploy.yml
PLAY [localhost] ****************************************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************************
ok: [localhost]
TASK [install-nginx : use var] **************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "I am defalut vars"
}
PLAY RECAP **********************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
接下来,我们看下使用普通的变量看下,在 install-nginx/vars/main.yml 文件中定义个和defaults下同名变量,默认变量应该会被替换:
var: "I am a var vars dir"
执行结果如下,可以看到确实被替换了:
TASK [install-nginx : use var] *************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "I am a var vars dir"
}
除此之外,我们还可以在调用role的时候传入变量参数,如下:
---
- hosts: localhost
roles:
- { role: install-nginx,var: "I am a var in role" }
执行结果如下,可以看到这里传入的变量参数优先级高于在role里面定义的。
TASK [install-nginx : use var] *************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "I am a var in role"
}
此外,role还能使用在Inventory中定义的变量,执行Playbook时传入的变量等等。更多变量优先级的介绍后面会具体说明的。
- role和条件when一起执行,和include一样,role也经常和when搭档使用
---
#只有在RedHat系列的主机上才会执行操作
- hosts: localhost
roles:
- { role: install-nginx, when: "ansible_os_family == 'RedHat'" }
- role和任务的执行顺序
如果一个Playbook中同时出现role和任务,那么他们的调用顺序是怎样的呢?
答案是: pre_tasks > role > tasks >post_tasks.
3.3.7 用标签,实现执行Playbook中的部分任务
如果Playbook文件比较大,并且在执行的时候只是想执行部分功能,那么这个时候有没有解决方案呢?答案就是使用标签(tags)了.
下面我们有个playbook,并且打上了几个tag。
---
- hosts: localhost
tasks:
- name: "我是标签1"
debug: msg="first tag"
tags: first
- name: "我是标签2"
debug: msg="second tag"
tags: second
- name: "可以打多个标签,和前面的有同名的也没事,符合的就执行"
debug: msg="third tag"
tags:
- first
- second
执行的时候如果我们不加上任何参数,那么所有的标签对应的任务都会执行。如果我们要执行某个标签的任务,可以使用"-t" 参数指定:
ansible-playbook deploy.yml -t first
如果要跳过某些标签的任务,可以使用 "--skip-tags" 参数
ansible-playbook deploy.yml --skip-tags first
标签的名字是用户自定义的,但是如果把标签的名字定义为always,那么就有点特别了。只要在执行Playbook的时候,如果没有明确指定不执行always标签,那么always标签对应的任务就始终会被执行。
在指定执行某个标签的时候,我们可以使用 "tagged" "untagged" 和 "all" 来分别标志只执行有标签的任务、只执行没有标签的任务和执行全部任务。如下:
ansible-playbook deploy.yml -t tagged
标签除了能够在action中使用外,还能在include和role中使用标签。如下:
---
#include中使用
- include: foo.yml
tags: [web,foo]
#role中使用
roles:
- {role: webserver, port: 5000, tags: [web,foo]}
3.4 更多的Ansible模块
3.4.1 模块的分类
在Ansible模块文档上查看单个模块的时候,每一个模块文档的底部都会表示,这是"COre Module",还是"Extra Module"。
比如,yum就是一个Core模块,而archive就是一个Extra模块。
- Core模块(核心模块)
- 不需要额外下载和配置,安装Ansible后就可以直接使用的
- 比较常用的模块
- 经过严格测试的模块
- Extra模块(额外模块)
- 需要进行下载和额外配置才能使用
- 次常用的模块
- 还有可能存在bug的模块
3.4.2 Extra模块的使用方法
大概流程为下载Extra模块,修改配置文件或者环境变量。具体方法自行百度。
3.4.3 命令行查看模块的用法
通过命令 ansible-doc,可以查看模块的用法,如下:
ansible-doc yum
3.5 最佳使用方法
3.5.1 写Playbook的原则
Ansible为了降低Playbook的维护成本,提高Playbook的可维护性,提倡以下两个原则:
- 鼓励文件重用,尽量使用include和role避免重复代码。
- 尽量把大的文件分成小的文件
3.5.2 参考别人的Playbook
官方提供了一些比较常用的、经过测试的Playbook的例子
https://github.com/ansible/ansible-examples
此外,ansible还提供了一个Playbook的分享平台,平台上的例子是Ansible用户自己上传的
https://galaxy.ansible.com/