1 基本语法
执行 deploy.yml
ansible-playbook deploy.yml
查看输出的细节
[root@controller ~]# ansible-playbook test.yml --verbose
Using /etc/ansible/ansible.cfg as config file
PLAY [test content] *******************************************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************************************************
ok: [192.168.143.192]
TASK [add content] ********************************************************************************************************************************************************************************************
changed: [192.168.143.192] => {"changed": true, "cmd": "echo \"Im awcloud\" >> /tmp/playbooktest.txt", "delta": "0:00:00.003959", "end": "2022-04-08 11:44:55.482102", "rc": 0, "start": "2022-04-08 11:44:55.478143", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
PLAY RECAP ****************************************************************************************************************************************************************************************************
192.168.143.192 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
查看该脚本影响哪些hosts
[root@controller ~]# ansible-playbook test.yml --list-hosts
playbook: test.yml
play #1 (web1): test content TAGS: []
pattern: ['web1']
hosts (1):
192.168.143.192
[root@controller ~]#
并行执行脚本
[root@controller ~]# ansible-playbook test.yml -f 10
PLAY [test content] *******************************************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************************************************
ok: [192.168.143.192]
TASK [add content] ********************************************************************************************************************************************************************************************
changed: [192.168.143.192]
PLAY RECAP ****************************************************************************************************************************************************************************************************
192.168.143.192 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2 基本结构
1.在什么机器上以什么身份执行
hosts
users
…
2.执行的任务是都有什么
tasks
3.善后的任务都有什么
handlers
例:
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
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
2.1 Tasks
tasks是从上到下顺序执行,如果中间发生错误,那么整个playbook会中止。修改文件后,再重新执行。
每一个task的对module的一次调用。使用不同的参数和变量而已。
每一个task最好有name属性,这个是供人读的,没有实际的操作。然后会在命令行里面输出,提示用户执行情况。
- 基本写法:
tasks:
- name: make sure apache is running
service: name=httpd state=running
当需要传入参数列表太长时,可以分隔到多行:
tasks:
- name: Copy ansible inventory file to client
copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
owner=root group=root mode=0644
或者用yml的字典传入参数
tasks:
- name: Copy ansible inventory file to client
copy:
src: /etc/ansible/hosts
dest: /etc/ansible/hosts
owner: root
group: root
mode: 0644
-
执行状态
每个action会调用一个module,在module中会去检查当前系统状态是否需要重新执行。如果本次执行了,那么action会得到返回值changed;
如果不需要执行,那么action得到返回值ok
例:
tasks:
- name: Copy the /etc/hosts
copy: src=/etc/hosts dest=/etc/hosts
# 第一次执行
[root@controller ~]# ansible-playbook test.yml
PLAY [test content] *******************************************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************************************************
ok: [192.168.143.194]
TASK [copy file] **********************************************************************************************************************************************************************************************
changed: [192.168.143.194]
PLAY RECAP ****************************************************************************************************************************************************************************************************
192.168.143.194 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 第二次执行
[root@controller ~]# ansible-playbook test.yml
PLAY [test content] *******************************************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************************************************
ok: [192.168.143.194]
TASK [copy file] **********************************************************************************************************************************************************************************************
ok: [192.168.143.194]
PLAY RECAP ****************************************************************************************************************************************************************************************************
192.168.143.194 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
由于第一次执行copy_hosts.yml的时候,已经拷贝过文件,那么ansible目标文件的状态避免重复执行.
2.2 Handler
主流的编程语言都会有event机制,那么handler就是playbook的event。
Handlers里面的每一个handler,也是对module的一次调用。而handlers与tasks不同,tasks会默认的按定义顺序执行每一个task,handlers则不会,它需要在tasks中被调用,才有可能被执行。
Tasks中的任务都是有状态的,changed或者ok。 在Ansible中,只在task的执行状态为changed的时候,才会执行该task调用的handler,这也是handler与普通的event机制不同的地方。
应用场景:
在tasks中修改了apache的配置文件。需要重起apache。此外还安装了apache的插件。那么还需要重起apache。像这样的应该场景中,重起apache就可以设计成一个handler.
一个handler最多只执行一次:在所有的任务里表执行之后执行,如果有多个task notify同一个handler,那么只执行一次。
例:
---
- hosts: lb
remote_user: root
vars:
random_number1: "{{ 10000 | random }}"
random_number2: "{{ 10000000000 | random }}"
tasks:
- name: Copy the /etc/hosts to /tmp/hosts.{{ random_number1 }}
copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number1 }}
notify:
- call in every action
- name: Copy the /etc/hosts to /tmp/hosts.\{\{ random_number2 \}\}
copy: src=/etc/hosts dest=/tmp/hosts.\{\{ random_number2 \}\}
notify:
- call in every action
handlers:
- name: call in every action
debug: msg="call in every action, but execute only one time"
输出
PLAY [test content] *******************************************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************************************************
ok: [192.168.143.194]
TASK [Copy the /etc/hosts to /tmp/hosts.7288] *****************************************************************************************************************************************************************
changed: [192.168.143.194]
TASK [Copy the /etc/hosts to /tmp/hosts.\ random_number2}}] ***************************************************************************************************************************************************
changed: [192.168.143.194]
RUNNING HANDLER [call in every action] ************************************************************************************************************************************************************************
ok: [192.168.143.194] => {
"msg": "call in every action, but execute only one time"
}
PLAY RECAP ****************************************************************************************************************************************************************************************************
192.168.143.194 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
3 Var
在Playbook中,通过vars关键字自定义变量,使用时用{{ }}引用以来即可。
使用方法
用户定义变量名为http_port,其值为为80。在tasks firewalld中,通过{{ http_port }}引用。
---
- hosts: web
vars:
http_port: 80
remote_user: root
tasks:
- name: insert firewalld rule for httpd
firewalld: port=\{\{ http_port \}\}/tcp permanent=true state=enabled immediate=yes
当变量比较多的时候,或者变量需要在多个playbook中重用的时候,可以把变量放到一个单独的文件中。通过关键字var_files把文件中定义的变量引入playbook中,使用变量的方法和在本文件中定义的变量相同。
- hosts: web
remote_user: root
vars_files:
- vars/server_vars.yml
tasks:
- name: insert firewalld rule for httpd
firewalld: port=\{\{ http_port \}\}/tcp permanent=true state=enabled immediate=yes
其中,vars/server_vars.yml的内容为:在这里插入代码片
http_port: 80
复杂变量
定义的语法如下
foo:
field1: one
field2: two
访问复杂变量中的子属性,可以利用中括号或者点号:
foo['field1']
foo.field1
陷阱:
某些时候YAML和Ansible Playbook的变量语法不能在一起好好工作了。这里仅发生在指冒号后面的值不能以{开头的时候,如果有必要以{开头,必须加上引号。总之在YAML值的定义中,如果提示YMAL语法错误,都可以尝试下加入引号来解决。
错误:
- hosts: app_servers
vars:
app_path: \{\{ base_path \}\}/22
修改:
- hosts: app_servers
vars:
app_path: "\{\{ base_path \}\}/22"
3.1 远程节点的系统变量(facts)
ansible会通过module setup来收集主机的系统信息,这些收集到的系统信息叫做facts,这些facts信息可以直接以变量的形式使用。
命令行上通过调用setup module命令可以查看可以引用的facts变量
ansible all -m setup -u root
使用方法
---
- hosts: all
user: root
tasks:
- name: echo system
shell: echo \{\{ ansible_os_family \}\}
- name install ntp on Debian linux
apt: name=git state=installed
when: ansible_os_family == "Debian"
- name install ntp on redhat linux
yum: name=git state=present
when: ansible_os_family == "RedHat"
3.2 文件模板中使用的变量
在playbook中定义的变量,可以直接在template中使用,同时facts变量也可以直接在template中使用,当然也包含在inventory里面定义的host和group变量。只要是在playbook中可以访问的变量,都可以在template文件中使用。
---
- hosts: web
vars:
http_port: 80
defined_name: "Hello My name is Jingjng"
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: Write the configuration file
template: src=templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify:
- restart apache
- name: Write the default index.html file
template: src=templates/index2.html.j2 dest=/var/www/html/index.html
- name: ensure apache is running
service: name=httpd state=started
- name: insert firewalld rule for httpd
firewalld: port=\{\{ http_port \}\}/tcp permanent=true state=enabled immediate=yes
handlers:
- name: restart apache
service: name=httpd state=restarted
3.3 命令行中传递变量
定义命令行变量
在release.yml文件里,hosts和user都定义为变量,需要从命令行传递变量值。
---
- hosts: '\{\{ hosts \}\}'
remote_user: '\{\{ user \}\}'
tasks:
- ...
使用命令行变量
ansible-playbook e33_var_in_command.yml --extra-vars "hosts=web user=root"
json格式传递参数:
ansible-playbook e33_var_in_command.yml --extra-vars "{'hosts':'vm-rhel7-1', 'user':'root'}"
还可以将参数放在文件里面:
ansible-playbook e33_var_in_command.yml --extra-vars "@vars.json"