目录
- 写在前面
- [7 Ansible 进阶](#7 Ansible 进阶)
-
- [7.1 流程控制](#7.1 流程控制)
-
- [7.1.1 handlers触发器与notify](#7.1.1 handlers触发器与notify)
-
- [7.1.1.1 未使用handlers](#7.1.1.1 未使用handlers)
- [7.1.1.2 使用handlers](#7.1.1.2 使用handlers)
- [7.1.2 when判断](#7.1.2 when判断)
-
- [7.1.2.1 when的语法](#7.1.2.1 when的语法)
- [7.1.2.2 when判断主机名选择模块输出](#7.1.2.2 when判断主机名选择模块输出)
- [7.1.2.3 when结合register变量](#7.1.2.3 when结合register变量)
- [7.1.3 loop/with_items循环](#7.1.3 loop/with_items循环)
-
- [7.1.3.1 with_items案例](#7.1.3.1 with_items案例)
- [7.1.3.1 loop案例](#7.1.3.1 loop案例)
-
- [7.1.3.1.1 单变量的情况](#7.1.3.1.1 单变量的情况)
- [7.1.3.1.2 多变量的情况](#7.1.3.1.2 多变量的情况)
- [7.2 剧本调试](#7.2 剧本调试)
-
- [7.2.1 检查语法&单步执行](#7.2.1 检查语法&单步执行)
- [7.2.2 tag标签](#7.2.2 tag标签)
- [7.2.3 忽略错误](#7.2.3 忽略错误)
- [7.3 Jinja2模板(template模块)](#7.3 Jinja2模板(template模块))
-
- [7.3.1 template和copy的区别](#7.3.1 template和copy的区别)
- [7.3.2 motd案例(同facts变量部分案例)](#7.3.2 motd案例(同facts变量部分案例))
- [7.3.3 判断案例](#7.3.3 判断案例)
- [7.3.4 循环案例](#7.3.4 循环案例)
- [7.4 include 文件包含](#7.4 include 文件包含)
- [7.5 Roles角色(重点)](#7.5 Roles角色(重点))
-
- [7.5.1 Roles概述](#7.5.1 Roles概述)
- [7.5.2 Roles 案例](#7.5.2 Roles 案例)
-
- [7.5.2.1 创建目录结构](#7.5.2.1 创建目录结构)
- [7.5.2.2 创建hosts文件](#7.5.2.2 创建hosts文件)
- [7.5.2.3 书写任务tasks/main.yanl](#7.5.2.3 书写任务tasks/main.yanl)
- [7.5.2.4 书写模板templates/exports.j2](#7.5.2.4 书写模板templates/exports.j2)
- [7.5.2.5 书写变量group_vars/all/main.yaml](#7.5.2.5 书写变量group_vars/all/main.yaml)
- [7.5.2.6 编写触发器handlers/main.yaml](#7.5.2.6 编写触发器handlers/main.yaml)
- [7.5.2.7 编写top.yaml](#7.5.2.7 编写top.yaml)
- [7.5.2.8 再次查看完善后的目录结构](#7.5.2.8 再次查看完善后的目录结构)
- [7.5.2.9 测试](#7.5.2.9 测试)
- [7.5.2.10 运行并测试](#7.5.2.10 运行并测试)
- [7.6 Vault](#7.6 Vault)
- [7.7 Galaxy](#7.7 Galaxy)
- [7.8 Ansible优化](#7.8 Ansible优化)
写在前面
这是Ansible系列第五篇,内容为Ansible进阶,包含了流程控制、Roles角色、加密优化调优等。
序号连续上篇笔记 Ansible04-Ansible Vars变量详解
回顾一下Ansible架构:
7 Ansible 进阶
7.1 流程控制
7.1.1 handlers触发器与notify
- 定义一个
handlers触发点
,进行检测,若检测到变化(一般是配置文件),则执行notify
定义的操作。 - 一般用于检测服务状态的变化,如重启。
- handler实际上就是一个
tasks
列表,只是关注于资源的变化。 - 格式注意:写在playbook的最后,不然handlers下所有内容都会被识别为handlers
notify
中的action仅在play最后被触发。
notify中调用handlers定义的操作。
7.1.1.1 未使用handlers
shell
# 编写playbook,未使用handlers
[root@manager playbook]# cat 11.handlers.yaml
- hosts: storage
gather_facts: no
tasks:
- name: 分发配置文件
copy:
src: exports
dest: /etc/exports
backup: yes
- name: 重启服务
systemd:
name: nfs-server
state: reloaded
# 测试-第一次
[root@manager playbook]# ansible-playbook 11.handler.yaml
PLAY [storage] ********************************************************************************************
TASK [分发配置文件] ***************************************************************************************
changed: [192.168.100.150]
TASK [重启服务] *******************************************************************************************
changed: [192.168.100.150]
PLAY RECAP ************************************************************************************************
192.168.100.150 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 测试-第二次
[root@manager playbook]# ansible-playbook 11.handler.yaml
PLAY [storage] ********************************************************************************************
TASK [分发配置文件] ***************************************************************************************
ok: [192.168.100.150]
TASK [重启服务] *******************************************************************************************
changed: [192.168.100.150]
PLAY RECAP ************************************************************************************************
192.168.100.150 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
以上的例子可以发现,copy模块在未检测到文件变化后,不会再发送,即不changed
而systemd模块的重启服务却是每次执行playbook都会执行一次nfs-server的重启
7.1.1.2 使用handlers
- 使用方法:
- 在需要检测的模块下,
并列
的添加上notify
。 - 在playbook的最下方添加
handlers
模块,其中name
为notify
设置的value。
yaml
.....
notify:
- value
handlers:
- name: value
<Module操作>
.....
- 示例:
shell
# 编写playbook
[root@manager playbook]# cat 11.handlers.yaml
- hosts: storage
gather_facts: no
tasks:
- name: 分发配置文件
copy:
src: exports
dest: /etc/exports
backup: yes
notify:
- needrestart
handlers:
- name: needrestart
systemd:
name: nfs-server
state: reloaded
# 测试1-配置文件没修改时
[root@manager playbook]# ansible-playbook 11.handlers.yaml
PLAY [storage] ********************************************************************************************
TASK [分发配置文件] ***************************************************************************************
ok: [192.168.100.150]
PLAY RECAP ************************************************************************************************
192.168.100.150 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 测试2-文件发生变化时
[root@manager playbook]# ansible-playbook 11.handlers.yaml
PLAY [storage] ********************************************************************************************
TASK [分发配置文件] ***************************************************************************************
changed: [192.168.100.150]
RUNNING HANDLER [needrestart] *****************************************************************************
changed: [192.168.100.150]
PLAY RECAP ************************************************************************************************
192.168.100.150 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
以上可以发现,在notify
检测的模块不是changed
时,不会触发handlers
的内容;
若检测到changed
,则执行handlers
中对应notify
和- name
匹配的模块内容。
7.1.2 when判断
- 用于给运行的tasks设置条件
- when进行判断,满足/不满足条件就执行相应的模块
- 一般与变量一起用,尤其是facts变量和register变量
- 可以使用的判断的符号:
==
: 等于!=
:不等于is match
:匹配is not match
:不匹配
ansible_hostname is match ("front|backup") 类似grep的正则
ansible_hostname is not match ("front|backup") 排除,取反
7.1.2.1 when的语法
yaml
- hosts: xxx
tasks:
- name: yyy
<Module>
when: # 多条件判断
- 条件1
- 条件2
- name: zzz
<Module>
when: 条件 # 单条件判断
- 多条件相当于
and
- 如果多条件需要
or
:when: 条件1 or 条件2
7.1.2.2 when判断主机名选择模块输出
shell
# 编写playbook
[root@manager playbook]# cat 12.when.yaml
- hosts: manager,front
tasks:
- name: manager call manager
debug:
msg: manager
when: ansible_hostname == "manager"
- name: front call front
debug:
msg: front
when: ansible_hostname == "front"
# 测试
[root@manager playbook]# ansible-playbook 12.when.yaml
PLAY [manager,front] **************************************************************************************
TASK [Gathering Facts] ************************************************************************************
ok: [192.168.100.151]
ok: [192.168.100.148]
TASK [manager call manager] *******************************************************************************
ok: [192.168.100.151] => {
"msg": "manager"
}
skipping: [192.168.100.148]
TASK [front call front] ***********************************************************************************
skipping: [192.168.100.151]
ok: [192.168.100.148] => {
"msg": "front"
}
PLAY RECAP ************************************************************************************************
192.168.100.148 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
192.168.100.151 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
# 可以发现,只有对应主机才输出debug模块的值
7.1.2.3 when结合register变量
register变量是将shell或command模块的结果保存为变量。
shell
- name: echo date #执行了一个 date 命令,register 关键字将 date 命令的输出存储到 date_output 变量名
command: date
register: date_output
- name: echo date_output #用 when 对关键字对分析后的进行判断,如果匹配,则执行这个 task,不匹配就不执行
command: echo "30"
when: date_output.stdout.split(' ')[2] == "30"
- 第 1 个 task 执行了 date 命令,register 关键字将 date 命令的输出存储到 date_output 变量名。
- 第 2 个 task 对输出进行分析,并使用 when 对关键字对分析后的进行判断
- 如果匹配,则执行这个 task,不匹配就不执行。
- 因为
register 获取到的输出内容
都是字符串
,而 ansible 又是 python 写的,可以使用python 字符串的方法
对其做处理,比如使用的 split,还可以使用 find 方法。
7.1.3 loop/with_items循环
- ansible内有两种循环:
- with_*: with_items
对迭代项的引用
,固定变量名为"item",使用with_item属性给定要迭代的元素。 - loop:
等价于with_list,遍历数组(列表)。loop中,每个元素都以列表的方式去定义;
列表有多少个元素,就循环执行Module多少次。
每轮循环中,都会将本次迭代的列表元素保存在控制变量item
中。
- with_*: with_items
- 用于批量创建、添加、启动、重启
7.1.3.1 with_items案例
标准循环关键字:"with_items"
对迭代项的引用,固定变量名为"item",使用with_item属性给定要迭代的元素
分发nfs配置文件并循环重启rpcbind和nfs-server服务:
shell
# 编写playbook
[root@manager playbook]# cat 13.with_items.yaml
- hosts: storage
gather_facts: no
tasks:
- name: 分发配置文件
copy:
src: exports
dest: /etc/exports
backup: yes
- name: 重启rpcbind和nfs-server
systemd:
name: "{{ item }}"
state: restarted
with_items:
- rpcbind
- nfs-server
# 测试
[root@manager playbook]# ansible-playbook 13.with_items.yaml
PLAY [storage] ********************************************************************************************
TASK [分发配置文件] ***************************************************************************************
ok: [192.168.100.150]
TASK [重启rpcbind和nfs-server] ****************************************************************************
changed: [192.168.100.150] => (item=rpcbind)
changed: [192.168.100.150] => (item=nfs-server)
PLAY RECAP ************************************************************************************************
192.168.100.150 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
7.1.3.1 loop案例
7.1.3.1.1 单变量的情况
这种情况,loop和with_items相同
分发nfs配置文件并循环重启rpcbind和nfs-server服务:
shell
[root@manager playbook]# cat 13.loop.yaml
- hosts: storage
gather_facts: no
tasks:
- name: 分发配置文件
copy:
src: exports
dest: /etc/exports
backup: yes
- name: 重启rpcbind和nfs-server
systemd:
name: "{{ item }}"
state: restarted
loop: #仅将with_items修改为了loop
- rpcbind
- nfs-server
# 测试
[root@manager playbook]# ansible-playbook 13.loop.yaml
PLAY [storage] ********************************************************************************************
TASK [分发配置文件] ***************************************************************************************
ok: [192.168.100.150]
TASK [重启rpcbind和nfs-server] ****************************************************************************
changed: [192.168.100.150] => (item=rpcbind)
changed: [192.168.100.150] => (item=nfs-server)
PLAY RECAP ************************************************************************************************
192.168.100.150 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
7.1.3.1.2 多变量的情况
循环新建用户和uuid
shell
# 创建playbook
[root@manager playbook]# cat 14.loop2.yaml
- hosts: front
gather_facts: false
tasks:
- name: add user
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
shell: /bin/bash
state: present
loop:
- { name: "loop1" , uid: 53101}
- { name: "loop2" , uid: 53102}
- { name: "loop3" , uid: 53103}
# 测试:
[root@manager playbook]# ansible-playbook 14.loop2.yaml
PLAY [front] **********************************************************************************************
TASK [add user] *******************************************************************************************
changed: [192.168.100.148] => (item={'name': 'loop1', 'uid': 53101})
changed: [192.168.100.148] => (item={'name': 'loop2', 'uid': 53102})
changed: [192.168.100.148] => (item={'name': 'loop3', 'uid': 53103})
PLAY RECAP ************************************************************************************************
192.168.100.148 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
7.2 剧本调试
7.2.1 检查语法&单步执行
-C/--check
模拟运行,不作出改变,一些变量可能会提示报错,因为-C没有真正运行剧本.--syntax-check
只做语法检查,不运行.--step
单步运行.y
执行这个task,n
忽略这个task,c
自动运行
7.2.2 tag标签
为tasks中的不同任务定一个tag,这样可以在执行剧本的时候-t
指定执行哪个tag部分的任务
shell
# 编写playbook
[root@manager playbook]# cat 15.tag.yaml
- hosts: storage
gather_facts: no
tasks:
- name: 4. 启动服务rpcbind
systemd:
name: rpcbind
enabled: yes
state: restarted
tags: #添加tags
- rpcrestart
- name: 5. 启动服务nfs
systemd:
name: nfs-server
enabled: yes
state: reloaded
tags: #添加tags
- nfsreload
# 测试
[root@manager playbook]# ansible-playbook -t nfsreload 15.tag.yaml
PLAY [storage] ********************************************************************************************
TASK [5. 启动服务nfs] *************************************************************************************
changed: [192.168.100.150]
PLAY RECAP ************************************************************************************************
192.168.100.150 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
7.2.3 忽略错误
运行剧本的时候,因为重复运行导致的错误提示,并发是真的错误.
比如:目录已经存在,用户已经存在.
在这种情况下,我们可以通过ignore_errors忽略错误,让剧本可以继续运行.
shell
# 在需要忽略错误的模块下加
- hosts: xxx
tasks:
- name: yyy
<Module>
ignore_errors: true #yes/no也可以
7.3 Jinja2模板(template模块)
如果需要在分发文件时使用变量,就需要用到template模块
。根据模板文件
动态生成配置文件
。
templates文件
必须存放在templates目录
中,以.j2
结尾。
若需要直接使用templates文件而不指定路径,就需要使playbook文件
和templates目录同级
。
template模块
会自动在playbook同级的templates目录
中找对应的模板文件。
7.3.1 template和copy的区别
template模块传输时,会将变量解析成对应的值,类似shell脚本的双引号功能。
copy模块传输时,直接传送文件内容,类似shell脚本的单引号功能。
7.3.2 motd案例(同facts变量部分案例)
- 批量修改系统/etc/motd文件(登陆时自动显示的文件)
- 输出主机名
- 内存大小
- ip
- 发行版本
- cpu数量
- 核心数量
shell
#playbook编写
[root@manager playbook]# cat 10.change_moted.yaml
- hosts: front
tasks:
- name: template分发motd
template:
src: templates/motd.j2
dest: /etc/motd
backup: yes
# - name: cp分发motd
# copy:
# src: templates/motd.j2
# dest: /etc/motd
# backup: yes
# motd.j2模板编写
[root@manager templates]# cat motd.j2
welcome to Linux-{{ ansible_hostname }}
--------------------------------------------
主机名: {{ ansible_hostname }}
ip地址: {{ ansible_default_ipv4.address }}
内存大小: {{ ansible_memtotal_mb }}
CPU数量: {{ ansible_processor_vcpus }}
核心总数: {{ ansible_processor_cores }}
发行版本: {{ ansible_distribution }}
#运行
[root@manager playbook]# ansible-playbook 10.change_moted.yaml
PLAY [front] **********************************************************************************************
TASK [Gathering Facts] ************************************************************************************
ok: [192.168.100.148]
TASK [template分发motd] ***********************************************************************************
changed: [192.168.100.148]
PLAY RECAP ************************************************************************************************
192.168.100.148 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 测试
[root@manager playbook]# ssh root@front
welcome to Linux-front
--------------------------------------------
主机名: front
ip地址: 192.168.100.148
内存大小: 3640
CPU数量: 2
核心总数: 2
发行版本: CentOS
### copy模块推送的文件的测试
[root@manager playbook]# ssh root@front
welcome to Linux-{{ ansible_hostname }}
--------------------------------------------
主机名: {{ ansible_hostname }}
ip地址: {{ ansible_default_ipv4.address }}
内存大小: {{ ansible_memtotal_mb }}
CPU数量: {{ ansible_processor_vcpus }}
核心总数: {{ ansible_processor_cores }}
发行版本: {{ ansible_distribution }}
template和copy模块的区别:
copy仅仅传输数据,复制文件;
template 传输数据,复制文件的时候,文件中的
变量会被解析和运行
.
7.3.3 判断案例
在模板文件中,也可以用到if判断。
- 格式:
shell
{% if vhost.port is undefined %} # 单分支
http_port=80
{% elif vhost.port == 81 %} # 多分支
http_port=81
{% else %}
http_port = 83
{% endif %}
根据主机名,生成不同的文件
shell
# 编写模板文件
[root@manager playbook]# cat templates/template-if.j2
{% if ansible_hostname == "front" %}
state front
{% elif ansible_hostname == "storage" %}
state storage
{% endif %}
# 编写playbook
[root@manager playbook]# cat 16.template-if.yaml
- hosts: front,storage
tasks:
- name: if的template
template:
src: templates/template-if.j2
dest: /tmp/template-if.conf
# 结构
templates/
└── template-if.j2
16.template-if.yaml
# 运行
[root@manager playbook]# ansible-playbook 16.template-if.yaml
PLAY [front,storage] **************************************************************************
TASK [Gathering Facts] ************************************************************************
ok: [192.168.100.148]
ok: [192.168.100.150]
TASK [if的template] ***************************************************************************
changed: [192.168.100.150]
changed: [192.168.100.148]
PLAY RECAP ************************************************************************************
192.168.100.148 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.100.150 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 测试
[root@manager playbook]# ansible front -m shell -a "cat /tmp/template-if.conf"
192.168.100.148 | CHANGED | rc=0 >>
state front
[root@manager playbook]# ansible storage -m shell -a "cat /tmp/template-if.conf"
192.168.100.150 | CHANGED | rc=0 >>
state storage
7.3.4 循环案例
模板文件中同样有循环
- 格式:
shell
{% for xxx in yyy %} #类似python
server {
listen {{ xxx.listen }}
}
{% endfor %}
配置server.conf 到front /tmp目录
shell
{% for ip in [1,2,3,4,5,6] %}
10.0.0.{{ ip }}
{% endfor %}
# 也可以
{% for ip in range(2,11) %}
10.0.0.{{ ip }}
{%endfor%}
# 总之是python的语法
7.4 include 文件包含
1个ansible剧本内容过多,涉及到多个play(- host:web),可读性变弱,不方便调试.
于是人们想出把单个大的剧本拆分为多个,小的剧本.
多个小的剧本可以通过include功能合并使用.
这时候可以通过include_tasks
的功能把多个剧本文件合并在一起,让剧本变成多个方便阅读与维护.
shell
# 小playbook
- name: xxx
<Module>
- name: yyy
<Module>
...
#汇总的playbook
- hosts: xxx
tasks:
- include_tasks: yyy.yaml
7.5 Roles角色(重点)
- ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。
- 是一套剧本目录结构的要求与标准,让我们书写剧本的时候,把剧本的内容和需要的文件,按照目录要求,分门别类存储.
- roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。
- roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷的include它们的一种机制。
roles的本质是规定了1套目录结构,用于书写剧本
官网链接:https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_reuse_roles.html
7.5.1 Roles概述
-
Roles目录结构:
-
目录解释:
shell
roles: <--所有的角色必须放在roles目录下,这个目录可以自定义位置,默认的位置在/etc/ansible/roles
project: <--具体的角色项目名称,比如nginx、nfs
files: <--无需个性化的文件,copy或script模块可以直接调用。
templates: <--用来存放jinjia2模板,template模块会自动在此目录中寻找jinjia2模板文件。
tasks: <--playbook中tasks部分。此文件可以使用include包含其它的位于此目录的task文件。必须有main.yml
main.yml
handlers: <--playbook中handlers部分,当前角色中触发条件时执行的动作。必须有main.yml
main.yml
vars(group_vars): <--playbook中vats部分,当前角色用到的变量。必须有main.yml。(group_vars是所有roles都可用)
main.yml
defaults: <--当前角色设定默认变量。必须有main.yml
main.yml
meta: <--此角色的特殊设定及其依赖关系。必须有main.yml
main.yml
# roles/example_role/files/ 所有文件,都将可存放在这里
# roles/example_role/templates/ 所有模板都存放在这里
# roles/example_role/tasks/main.yml: 主函数,包括在其中的所有任务将被执行
# roles/example_role/handlers/main.yml:所有包括其中的 handlers 将被执行
# roles/example_role/vars/main.yml: 所有包括在其中的变量将在roles中生效
# roles/example_role/meta/main.yml: roles所有依赖将被正常登入
7.5.2 Roles 案例
修改之前的nfs配置playbook,符合roles的要求
- 分析:
- 设置
roles
对应的目录名。 - 根据原始的playbook,拆分成
tasks
、templates
、vars
、handlers
、top.yaml
。
7.5.2.1 创建目录结构
shell
[root@manager playbook]# mkdir roles-all
[root@manager playbook]# cd roles-all/
[root@manager roles-all]# mkdir roles01
[root@manager roles-all]# cd roles01/
[root@manager roles01]# touch top.yaml
[root@manager roles01]# touch hosts
[root@manager roles01]# mkdir -p nfs-server/{files,templates,tasks,handlers} group_vars
[root@manager roles01]# mkdir group_vars/all
[root@manager roles01]# cd ..
[root@manager roles-all]# tree -F
.
└── roles01/
├── group_vars/
│ └── all/
├── hosts
├── nfs-server/
│ ├── files/
│ ├── handlers/
│ ├── tasks/
│ └── templates/
└── top.yaml
7.5.2.2 创建hosts文件
shell
[root@manager roles01]# cp /etc/ansible/hosts .
cp: overwrite './hosts'? y
[root@manager roles01]# cat hosts
[front]
192.168.100.148 ansible_user=root ansible_password=Huawei@123 ansible_port=22
[storage]
192.168.100.150 ansible_user=root ansible_password=Huawei@123 ansible_port=22
[backup]
192.168.100.149 ansible_user=root ansible_password=Huawei@123 ansible_port=22
[data:children]
storage
backup
[docker]
192.168.100.141 ansible_user=root ansible_password=Huawei@123 ansible_port=22
[manager]
192.168.100.151
7.5.2.3 书写任务tasks/main.yanl
shell
[root@manager roles01]# cat nfs-server/tasks/main.yaml
- name: 1. 部署nfs-utils,rpcbind
yum:
name: nfs-utils,rpcbind
state: present
tags:
- 01.install
- name: 2. 修改配置文件
template:
src: exports.j2 #不需要写路径,role根据j2自动在templates目录下寻找对应的文件
dest: /etc/exports
backup: yes
notify:
- restart_nfs-server
tags:
- 02.conf
- name: 3. 创建共享目录并修改所有者
file:
path: "{{nfs_server_dir}}"
state: directory
owner: "{{nfs_user}}"
group: "{{nfs_user}}"
tags:
- 03.dir
- name: 4. 启动服务rpcbind
systemd:
name: "{{item}}"
enabled: yes
state: started
loop:
- rpcbind
tags:
- 04.start_srv
7.5.2.4 书写模板templates/exports.j2
shell
cat nfs-server/templates/exports.j2
#author: {{author}}
#/nfsupload 192.168.100.0/24(rw,all_squash)
{{ nfs_server_dir }} 192.168.100.0/24(rw,all_squash)
7.5.2.5 书写变量group_vars/all/main.yaml
shell
[root@manager roles01]# cat group_vars/all/main.yaml
author: tassel
nfs_server_dir: /nfsupload
nfs_user: nobody
7.5.2.6 编写触发器handlers/main.yaml
shell
[root@manager roles01]# cat nfs-server/handlers/main.yaml
- name: restart_nfs-server
systemd:
name: nfs-server
enabled: yes
state: restarted
7.5.2.7 编写top.yaml
shell
[root@manager roles01]# cat top.yaml
- hosts: storage
roles:
- role: nfs-server
#- hosts: yyy
# roles:
# - role: zzz
7.5.2.8 再次查看完善后的目录结构
shell
[root@manager roles01]# tree -F
.
├── group_vars/
│ └── all/
│ └── main.yaml
├── hosts
├── nfs-server/
│ ├── files/
│ ├── handlers/
│ │ └── main.yaml
│ ├── tasks/
│ │ └── main.yaml
│ └── templates/
│ └── exports.j2
└── top.yaml
7 directories, 6 files
7.5.2.9 测试
shell
[root@manager roles01]# ansible-playbook -i hosts -C top.yaml
PLAY [storage] ********************************************************************************************
TASK [Gathering Facts] ************************************************************************************
ok: [192.168.100.150]
TASK [nfs-server : 1. 部署nfs-utils,rpcbind] *************************************************************
ok: [192.168.100.150]
TASK [nfs-server : 2. 修改配置文件] ***********************************************************************
changed: [192.168.100.150]
TASK [nfs-server : 3. 创建共享目录并修改所有者] ***********************************************************
ok: [192.168.100.150]
TASK [nfs-server : 4. 启动服务rpcbind] ********************************************************************
ok: [192.168.100.150] => (item=rpcbind)
RUNNING HANDLER [nfs-server : restart_nfs-server] *********************************************************
changed: [192.168.100.150]
PLAY RECAP ************************************************************************************************
192.168.100.150 : ok=6 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
7.5.2.10 运行并测试
shell
[root@manager roles01]# ansible-playbook -i hosts top.yaml
PLAY [storage] ********************************************************************************************
TASK [Gathering Facts] ************************************************************************************
ok: [192.168.100.150]
TASK [nfs-server : 1. 部署nfs-utils,rpcbind] *************************************************************
ok: [192.168.100.150]
TASK [nfs-server : 2. 修改配置文件] ***********************************************************************
changed: [192.168.100.150]
TASK [nfs-server : 3. 创建共享目录并修改所有者] ***********************************************************
ok: [192.168.100.150]
TASK [nfs-server : 4. 启动服务rpcbind] ********************************************************************
ok: [192.168.100.150] => (item=rpcbind)
RUNNING HANDLER [nfs-server : restart_nfs-server] *********************************************************
changed: [192.168.100.150]
PLAY RECAP ************************************************************************************************
192.168.100.150 : ok=6 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
################
[root@manager roles01]# ansible storage -m shell -a "cat /etc/exports"
192.168.100.150 | CHANGED | rc=0 >>
#author: tassel
#/nfsupload 192.168.100.0/24(rw,all_squash)
/nfsupload 192.168.100.0/24(rw,all_squash)
[root@manager roles01]# ansible storage -m shell -a "showmount -e"
192.168.100.150 | CHANGED | rc=0 >>
Export list for storage:
/nfsupload 192.168.100.0/24
7.6 Vault
ansible-vault用于加密敏感信息
- hosts文件
- 变量文件
shell
#进行加密
ansible-vault encrypt <文件>
###
[root@manager roles01]# ansible-vault encrypt hosts.cyp
New Vault password:
Confirm New Vault password:
Encryption successful
[root@manager roles01]# cat hosts.cyp
$ANSIBLE_VAULT;1.1;AES256
62623831396464393263383030343163336535383830643337313339356661366537383035643933
6135666137613233636438343364336632346564646362650a336331383263613836363537663666
61656634383233653462393138633566633363383334636231353737366131663361353762303565
3666636530616338660a353034666463666139643136323263353835393863613062666165336263
32356538633930326266393938613864333033636635333761663538383035313337656537376465
32396533353766396633343566396463613264643534393764303733633833616362643737386262
63376233363630623230343339313637356432333535363132303236383831623736306461656164
66376139633365323931353665346136643939353233663733373530336536633537333238666430
36336138393335393834663232313030346661353161333262356432323631643336303964363339
37613662326339326532376665626462386566616463643632663930393837393031633334393939
38363538396435303834616436303736333032623036303536313737666263313331623766343134
36383730663366363465313833373930623865643932306235346436663331663966373432373566
37633935656432353462633438356232376535663231626662376466333836383932343234336261
65303835663437396662306238616435396535653734333234646562333361333337343633393533
33383965643465386162306135363630326566643637643037666635303963623639656164663061
66373938366463336632356134316265383234663130333162343636353933383933306132633436
38666438633763656231316532333065343366303230326136333836303136303965363833343234
63333865643864363439313462313262326566643139346635346663386163613663386631386263
34613630313935373233633466353430616564376334303636356435393230376561663162626234
64383138666531303932623434323936613939613636346130646135306531326161633161633865
33653439306637343362376364653433363962303838366165306264313439613535316330376263
33353864656539356235353331633762626565356366636133326530343636656464396637633337
32653030326631373731346230633064306333623732623934306230383231383361393236353362
65363434613937616539386664326635333862393666316666633036396132613566653264633162
6135
#进行使用
ansible或ansible-playbook --ask-vault-pass <正常即可>
###
[root@manager roles01]# ansible --ask-vault-pass -i hosts.cyp storage -m ping
Vault password:
192.168.100.150 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
#彻底解密
ansible-vault decrypt <文件名>
###
[root@manager roles01]# ansible-vault decrypt hosts.cyp
Vault password:
Decryption successful
7.7 Galaxy
实际上就是别人写好的roles
shell
[root@manager roles-all]# ansible-galaxy collection install nginxinc.nginx_core
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Downloading https://galaxy.ansible.com/api/v3/plugin/ansible/content/published/collections/artifacts/nginxinc-nginx_core-0.8.0.tar.gz to /root/.ansible/tmp/ansible-local-276848dtjz1k/tmpt7vv8eud/nginxinc-nginx_core-0.8.0-ipinsxaa
Installing 'nginxinc.nginx_core:0.8.0' to '/root/.ansible/collections/ansible_collections/nginxinc/nginx_core'
nginxinc.nginx_core:0.8.0 was installed successfully
'ansible.posix:1.5.4' is already installed, skipping.
'community.crypto:2.15.0' is already installed, skipping.
'community.general:7.3.0' is already installed, skipping.
[root@manager roles-all]# cp -r /root/.ansible/collections/ansible_collections/nginxinc/* .
[root@manager roles-all]# ls
nginx_core roles01
[root@manager roles-all]# tree -F nginx_core/
...
7.8 Ansible优化
-
性能 :
- ssh连接速度优化,关闭UseDNS,GSSAPIAuthcation ...
- 不要让ansible运行交互式的命令,非要用使用命令的非交互模式.
- 需要使用ans,yum安装软件,可以自建本地yum仓库,然后ans安装.(自建yum源,自己制作 - 的rpm包)
- 调整ansible并发数量( -f 调整并发数量 默认是5
ansible.cfg
forks=5
,实际调整 - 根据负载情况.) - 给ansible配置缓存(redis),队列.缓存facts.
- 给主机进行分组操作与管理.
- 关闭gather_facts,如果不用facts变量可以关闭, 剧本中: gather_facts: false
配置文件: gathering = explicit
- 关闭host,key,check 一般使用密码认证的时候需要关闭,如果不关闭 ansible
配置文件 host_key_checking = False
-
安全 :
- 配置sudo用户
ans ALL=(ALL) NOPASSWD: ALL
密码是1,ssh端口是 22 - 配合堡垒机一起使用
- 用户--->堡垒机---->ansible
- 用户的密码,进行加密( hash, ansible-vault)
- 配置sudo用户
-
sudo配置:
shell
# Ansible-Client
## 修改配置文件
[root@manager roles-all]# visudo
[root@manager roles-all]# tail -1 /etc/sudoers
ans ALL=(ALL) NOPASSWD: ALL
## 创建用户
[root@manager roles-all]# useradd ans
[root@manager roles-all]# passwd ans
# Ansible-Server
## /etc/ansible/ansible.cfg
[defaults]
sudo_user = ans
sudo_user = ans #被管理端上具有sudo权限的用户nopasswd: ALL
remote_user = ans #被管理端使用的用户,不指定默认是当前用户/root
remote_port = 22 #被管理端ssh端口号
host_key_checking = False
host_key_checking = False
log_path = /var/log/ansible.log
[privilege_escalation]
become=True #开启sudo功能
become_method=sudo #使用sudo命令
become_user=root #普通用户切换为root