ansible-playbook基础
创建一个yml文件
[root@node2 ansible]# vim hello.yml
---
- hosts: master
remote_user: root
tasks:
- name: hello
command: hostname
[root@node2 ansible]# ansible-playbook hello.yml # 执行yml文件
1、ansible-vault:
管理加密解密yml文件
[root@node2 ansible]# ansible-vault encrypt hello.yml # 加密之后不能运行,解密之后才能运行
New Vault password:
Confirm New Vault password:
Encryption successful
[root@node2 ansible]# cat hello.yml
$ANSIBLE_VAULT;1.1;AES256
30326166353266666235363733626436316536316337356336336230303037663132623435633639
6235343133373466326334373833663334336665626562630a323830633034313933363264356430
63366362313930323632396137663736613431343261656461333362393661333166636335343735
3332343535636663630a376261663136653663383161613834346130616463363930373436643434
65613865653463343161353061623139393865353536326564636630643462373037376630633065
30356161326533326433623963353365336230666534633861336466366130323966663834366439
61343439666365343766383862613935363938633531383136343439663166663039336161346666
66313765613366353938623139343531333964313237386464363232303665613334373564626266
34356533303931616462666639336165316238363362336562353535306331376537
[root@node2 ansible]# ansible-vault decrypt hello.yml # 解密yml文件
Vault password:
Decryption successful
[root@node2 ansible]# ansible-vault view hello.yml # 查看加密的yml文件
Vault password:
[root@node2 ansible]# ansible-vault rekey hello.yml # 修改加密后的yml文件的口令
Vault password:
New Vault password:
Confirm New Vault password:
Rekey successful
[root@node2 ansible]# ansible-vault edit hello.yml # 修改yml文件内容
Vault password:
2、ansible-console
Ansible-console是Ansible为用户提供的一款交互式工具。
[root@node2 ansible]# ansible-console
Welcome to the ansible console.
Type help or ? to list commands.
root@all (3)[f:5]$
root@all (3)[f:5]$
root@all (3)[f:5]$
root@all (3)[f:5]$ cd master # 切换到其他主机组(或者某台主机)
root@master (2)[f:5]$ forks 6 # 设置并发执行的主机数量
root@all (3)[f:5]$ exit # 退出
root@master (2)[f:6]$ command hostname # 执行hostname命令
10.0.0.7 | CHANGED | rc=0 >>
node3
10.0.0.1 | CHANGED | rc=0 >>
node1
用户名@/etc/ansible/hosts内的所有主机 (数量) 【并发执行5台服务器】
playbook是由一个或者多个“play”组成的剧本。play的主要功能在于将事先归并为一族的主机装扮为事先通过ansible中的task定义好的角色。实质上task无非是调用ansible的一个module,将多个play组织在一个playbook中。
Playbook可以通过YAML格式进行描述定义,可以定制配置,按照指定的操作步骤有序执行,支持同步和异步方式。
3、YAML介绍
YAML是一种可读性高的用来表达资料序列的格式(仍是一种标记语言)。
YAML具有以下主要特性:
-
可读性高:YAML的语法简洁直观,使用空格来表达层次结构,使得文件更容易阅读和理解。
-
数据序列化:YAML是一种数据序列化语言,可以配合大多数编程语言使用,用于在人和计算机之间交换数据。
-
使用缩进表示层级关系:YAML使用缩进表示数据的层级关系,这使得数据的结构一目了然。
-
大小写敏感:YAML对大小写敏感,这意味着相同的标识符,大小写的不同会被视为两个不同的标识符。
-
支持多种数据类型:YAML支持对象、数组和纯量等多种数据类型。
-
易于实现:YAML的设计使得它在实现上相对简单。
-
基于流的处理:YAML可以基于流来处理,这意味着它可以一次处理一个数据项,而不是整个文件。
-
扩展性好:YAML的表达能力强,扩展性好,可以表示复杂的数据结构。
-
与脚本语言的交互性好:YAML和脚本语言的交互性好,可以方便地与各种编程语言结合使用。
YAML语法特点:
-
YAML 中的属性和值都是大小写敏感的。
-
在单一档案中,可以连续用若干个(----)区分多个档案,(...)表示档案结尾。
-
缩进的空格数不重要,只要相同层级的元素左对齐即可。
-
禁止使用 tab 缩进,只能使用空格。
-
使用 # 注释。
-
字符串可以不用引号标注。
-
k/v的值可同行写也可换行写,同行使用:分隔
-
v可是字符串,也可以是另一个列表。(列表使用“-”开头)
YAML 支持以下几种数据类型:
-
对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary);字典通常是由多个键值对组成
-
数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
-
纯量(scalars):单个的、不可再分的值
4、Playbook的核心元素主要包括:
-
Hosts:Playbook配置文件作用的主机。
-
Tasks:任务列表,由模板定义的操作列表。
-
Variables:内置的或者自定义的变量(在playbook的调用)。
-
Templates:模板,可替换模板文件中的变量实现一些逻辑简单的任务。
-
Handlers:由特定条件触发的操作,满足条件才执行,否则不执行。
-
Roles:用于层次性、结构化地组织Playbook,能根据层次型结构自动装载变量文件、Tasks以及Handlers等。
-
标签(tags):是一种非常有用的功能,它允许用户指定哪些任务应该在执行Playbook时运行,哪些任务应该被跳过。标签可以应用于单个任务或整个Playbook。通过在任务或Playbook上添加标签,用户可以在执行Playbook时使用
--tags
参数来指定要运行的标签。例如,如果一个任务被标记为webserver
,那么可以使用--tags "webserver"
来仅运行该任务。
补充:
ansible-playbook -C xxx.yaml # 对配置文件不做任何处理,校验是否正确
---
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: create new file
file: name=/data/newfile state=touch
- name: create new user
user: name=hanxu system=yes shell=/sbin/nologin
- name: install package
yum: name=httpd
- name: copy html file
copy: src=/var/www/html/index.html dest=/var/www/html backup=yes # 首先在自己服务器上写入index.html;backup=yes是为了给原有的index.html进行备份
- name: start service
service: name=httpd state=started enabled=yes
# 注释:一个模块对应一个action(也就是一个name不能对应两个service)
- name: copy html file
copy: src=/var/www/html/index.html dest=/var/www/html backup=yes
- name: copy test file
copy: src=/var/www/html/test.html dest=/var/www/html backup=yes
[root@node2 ansible]# ansible-playbook -C file.yml
PLAY [10.0.0.1] *************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************
ok: [10.0.0.1]
TASK [create new file] *******************************************************************************************
ok: [10.0.0.1]
TASK [create new user] *******************************************************************************************
changed: [10.0.0.1]
TASK [install package] *******************************************************************************************
changed: [10.0.0.1]
TASK [start service] *********************************************************************************************
changed: [10.0.0.1]
PLAY RECAP *******************************************************************************************************
10.0.0.1 : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@node2 ansible]# ansible-playbook file.yml # 执行yaml文件命令
[root@node2 ansible]# ansible 10.0.0.1 -a "ls /data"
10.0.0.1 | CHANGED | rc=0 >>
name
newfile
[root@node2 ansible]# ansible 10.0.0.1 -a 'getent passwd haa'
10.0.0.1 | CHANGED | rc=0 >>
haa:x:994:990::/home/haa:/sbin/nologin
[root@node2 ansible]# ansible 10.0.0.1 -m shell -a 'ss -tln | grep 80'
5、playbook的基础组件
remote_user:可用于Host和task中,也可通过指定其sudo的方式在远程主机上执行任务,其可用于play全局和某任务;
Task列表通常指的是一组需要完成的任务,这些任务可能涉及到不同的活动和操作。task list中的各任务按次序逐个在hosts中指定所有主机上执行,在运行自下而下某playbook时,若中途发生错误,所有已执行任务都将回滚。Task的目的是使用指定的参数执行模块,而在模块参数可以使用变量。模块执行是幂等的,这意味着多次执行是安全的。
Action通常指的是模块执行的动作。
格式: 模块:参数(所要执行的命令)
如果命令或者脚本的退出码不为0,可以使用以下方式代替。
tasks: - name: run this command and ignore the result shell: /usr/bin/somecommand || /bin/true
或者使用ignore_error来忽略
tasks: - name: run this command and ignore the result shell: /usr/bin/somecommand ignore_error: True
playbook的常见选项:
-
-i INVENTORY:指定要操作的主机清单。清单可以是文件、主机组或动态清单。
-
--limit LIMIT:仅对匹配限制的主机执行任务。限制可以是主机名、组名或标签。
-
-t TAGS:仅执行具有匹配标签的任务。标签可以是单个标签或标签列表。
-
-e EXTRA_VARS:设置额外的变量来传递给任务。变量可以是键值对或 YAML 字典。
-
-k:启用密钥文件身份验证。
-
--ask-pass:提示输入密钥文件的密码。
-
-K:启用 Kerberos 身份验证。
-
-u USER:以指定用户身份运行任务。
-
-s SUBCOMMAND:运行指定的子命令。有效的子命令包括:“gather”、“converge”、“help”和“list”。
-
--syntax-check:检查剧本的语法,但不执行任何任务。
-
-v:启用详细输出。
-
-vv:启用非常详细的输出。
-
--diff:在收敛之前显示要进行的更改。
-
--check:在执行任务之前检查任务。
-
--become:以指定用户身份执行任务。
-
--become-method METHOD:指定用于提升特权的方法。有效的选项包括:“sudo”、“su”和“pbrun”。
-
--become-user USER:指定用于提升特权的用户。
[root@node2 ~]# ansible master -a 'getent passwd haa' --limit 10.0.0.1 # 限制执行的主机
10.0.0.1 | CHANGED | rc=0 >>
haa:x:994:990::/home/haa:/sbin/nologin
[root@node2 ~]# ansible master -a 'getent passwd haa' --limit 10.0.0.1 -vv # 查看详细信息
[root@node2 ansible]# ansible-playbook file.yml --list-host # 列出配置文件主机
6、handlers和notify结合使用出发条件
Handlers是一组task列表,它们与前述的task并无本质区别,但只有在关注的资源发生变化时才会被执行。
Notify是一个action,它可以在每个play的最后被触发,避免了多次有改变发生时每次都执行指定的操作,而是在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。
vim http.yml
---
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: install package
yum: name=httpd
- name: copy conf file
copy: src=files/httpd.conf dest=/etc/httpd/conf backup=yes
- name: start service
service: name=httpd state=started enabled=yes
# 我的端口修改为81
[root@node1 html]# ss -ntl | grep 81
LISTEN 0 128 [::]:81 [::]:*
# 如果再次修改端口号,可能不会生效,因此需要使用handler
---
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: install package
yum: name=httpd state=installed
- name: copy conf file
copy: src=files/httpd.conf dest=/etc/httpd/conf backup=yes
notify: restart service
- name: start service
service: name=httpd state=started enabled=yes
handlers:
- name: restart service
service: name=httpd state=restarted enabled=yes
[root@node2 ansible]# ansible-playbook http.yml # 执行该文件
[root@node1 ~]# ss -ntl | grep 82 # 此时才生效
LISTEN 0 128 [::]:82 [::]:*
# handlers与notify的名称(restart service)需要一致;handlers下边可以添加多个内容
tags:只执行标签内容
---
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: install package
yum: name=httpd state=installed
- name: copy conf file
copy: src=files/httpd.conf dest=/etc/httpd/conf backup=yes
notify: restart service
- name: start service
service: name=httpd state=started enabled=yes
tags: rshttpd
handlers:
- name: restart service
service: name=httpd state=restarted enabled=yes
[root@node2 ansible]# ansible-playbook -t rshttpd http.yml
PLAY [10.0.0.1] *************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************
ok: [10.0.0.1]
TASK [start service] *********************************************************************************************
changed: [10.0.0.1]
PLAY RECAP *******************************************************************************************************
10.0.0.1 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@node2 ansible]# ansible 10.0.0.1 -m shell -a "ss -ntl | grep 82"
10.0.0.1 | CHANGED | rc=0 >>
LISTEN 0 128 [::]:82 [::]:*
[root@node2 ansible]# ansible 10.0.0.1 -m yum -a "name=httpd state=absent" # 卸载httpd服务
[root@node2 ansible]# ansible 10.0.0.1 -m shell -a "rpm -q httpd" # 检查是否卸载
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'. If you need to use command
because yum, dnf or zypper is insufficient you can add 'warn: false' to this command task or set
'command_warnings=False' in ansible.cfg to get rid of this message.
10.0.0.1 | FAILED | rc=1 >>
package httpd is not installednon-zero return code
7、Playbook中变量使用
变量名:仅能由字母、数字和下划线组成,且只能以字母开头。
变量来源:
1、ansible setup facts 远程主机的所有变量都可以直接调用。
[root@node2 ~]# ansible all -m setup -a 'filter=ansible_fqdn'
[root@node2 ~]# ansible all -m setup -a 'filter=ansible_hostname' # 查看主机名的部分信息
10.0.0.7 | SUCCESS => { "ansible_facts": { "ansible_hostname": "node3", "discovered_interpreter_python": "/usr/bin/python" }, "changed": false }
10.0.0.8 | SUCCESS => { "ansible_facts": { "ansible_hostname": "node2", "discovered_interpreter_python": "/usr/bin/python" }, "changed": false }
10.0.0.1 | SUCCESS => { "ansible_facts": { "ansible_hostname": "node1", "discovered_interpreter_python": "/usr/bin/python" }, e2 ~]# ansible all -m setup -a 'filter=ansible_*' # 支持通配符
[root@node2 ~]# ansible all -m setup -a 'filter=ansible_all_ipv4_addresses' # 显示所有的IPV4地址
2、在/etc/ansible/hosts中定义
普通变量:主机组中单独定义,优先级高于公共变量。
# 在/etc/ansisble/hosts中定义变量
[master]
10.0.0.1 http_port=81
10.0.0.7 http_port=82
[root@node2 ansible]# vim hostname.yml
---
- hosts: master
remote_user: root
tasks:
- name: set hostname
hostname: name={{ http_port}}.ansible
[root@node2 ansible]# ansible-playbook hostname.yml
公共组变量:针对主机组中所有主机定义的统一变量。
[master]
10.0.0.1 http_port=81
10.0.0.7 http_port=82
# 给组内所有的主机定义变量
[master:vars]
nodename=www
domainname=hahaha.com
[root@node2 ansible]# vim hostname.yml
---
- hosts: master
remote_user: root
tasks:
- name: set hostname
hostname: name={{nodename}}{{http_port}}.{{domainname}}
3、通过命令行指定变量,优先级最高。
[root@node2 ansible]# vim app.yml
---
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }}
- name: start service
service: name={{ pkname }} state=started enabled=yes
[root@node2 ansible]# ansible-playbook -e 'pkname=vsftpd' app.yml # 临时使用-e来定义变量内容
[root@node2 ansible]# ansible 10.0.0.1 -m shell -a 'ss -ntl | grep 21' # 检查一下是否执行成功
10.0.0.1 | CHANGED | rc=0 >>
LISTEN 0 32 [::]:21 [::]:*
# 如果变量不同,也可以设置多个变量
[root@node2 ansible]# vim app.yml
---
- hosts: 10.0.0.1
remote_user: root
tasks:
- name: install package
yum: name={{ pkname1 }}
- name: install package
yum: name={{ pkname2 }}
- name: start service
service: name={{ pkname }} state=started enabled=yes
[root@node2 ansible]# ansible-playbook -e 'pkname1=vsftpd pkname2=httpd' app.yml # 使用-e来定义变量内容
[root@node2 ~]# ansible 10.0.0.1 -m shell -a 'yum -y remove vsftpd' # 卸载安装的软件包
4、在playbook中定义变量
# 在脚本中定义变量并且指定
---
- hosts: 10.0.0.1
remote_user: root
vars:
- pkname1: httpd
- pkname2: vsftpd
tasks:
- name: install package
yum: name={{ pkname1 }}
- name: install package
yum: name={{ pkname2 }}
[root@node2 ansible]# ansible 10.0.0.1 -m shell -a 'rpm -q httpd vsftpd'
[WARNING]: Consider using the yum, dnf or zypper module rather than running 'rpm'. If you need to use command
because yum, dnf or zypper is insufficient you can add 'warn: false' to this command task or set
'command_warnings=False' in ansible.cfg to get rid of this message.
10.0.0.1 | CHANGED | rc=0 >>
httpd-2.4.6-99.el7.centos.1.x86_64
vsftpd-3.0.2-29.el7_9.x86_64