一、jinja2模版
1、为什么需要这个模版呢
-
之前没有学习jinja2的时候,传输给被控节点的都是相同的配置文件,如果要配置一个httpd的话,那么这个就不能是相同的配置文件,会报错的,会监听通过一个ip
-
学习了jinja2之后,写一个jinja2模版,带有变量的,发送给被控主机,这样的话,被控主机会自动的识别到这些变量,转换为自己的ip地址,更加的灵活
-
更改的配置文件只需要更改一小部分的内容
-
jinja2模版用的就是setup变量,也就是事实变量,因此需要开启收集事实变量,默认是开启的
2、template模块(发送jinja2模版给被控主机的)
-
template模块是基于jinja2模版引擎的,会先解析jinja2模版的变量,能够自动的识别变量,变量不需要" "引号引起来,但是值的话,就需要单引号引起来了,因为不是变量,是字符串
-
jinja2模版格式
-
变量需要{{}} 不需要双引号,会自动的进行识别的
-
字符串需要单引号
-
# httpd.conf.j2 中的jinja2模版,不需要带
Listen {{ansible_ens160.ipv4.address}} 80[devops@master ansible]$ cat t1.yml
- hosts: mntasks:- template:src: ./httpd.conf.j2dest: /etc/httpd/conf/httpd.conf # 传输到被控节点上面# 不同的被控节点自动的识别到自己的变量,就不会造成一样的配置文件了,非常的灵活
2、jinja2模版语句
1、if判断(条件语句)
-
如果符合条件,就是什么,不符合条件,就不是什么
-
格式
{% if 条件判断 %}
语句块{% elif 条件判断 %}
语句块{% else %}
语句块{% endif %}
[devops@master ansible]$ cat t2.j2
{% if ansible_hostname == 'node1' %} # 主机等于node1话,就执行
"node1 is ok"
{% elif ansible_hostname == 'master' %} # 主机等于matser的话,就执行
"master is ok"
{% endif %}
[devops@master ansible]$ cat t2.yml
- hosts: mntasks:- template:src: ./t2.j2dest: /mnt/t2 # 写入到/mnt/t2这个文件里面去
2、for循环
-
就是跟魔方变量,配合使用,循环每一个主机
-
格式
{% for i in 循环体 %}
语句块
{% endfor %}
- node1主机上面的/mnt/hosts保存所有主机的ip和域名和主机名等信息
# groups.all 列出主机清单的中的所有主机
[devops@master ansible]$ cat t3.j2
{% for i in groups.all %}#hostvars[i] 获取指定主机的变量
{{hostvars[i].ansible_ens160.ipv4.address}} {{hostvars[i].ansible_fqdn}} {{hostvars[i].ansible_hostname}}
{% endfor %}
[devops@master ansible]$ cat t3.yml
- hosts: mntasks:- template:src: ./t3.j2dest: /mnt/t3
3、jinja2过滤器
1、default过滤器
-
当变量的值没有定义的时候,使用default定义的值
-
格式
# 前面是一个变量
"{{变量名|jinja2过滤器}}"
[devops@master test]$ cat default.yml
- hosts: alltasks:- debug:msg: "{{ qqq|default('default') }}"# 输出结果,没有定义这个变量,默认输出default定义的值
TASK [debug] **********************************************************************************
ok: [master] => {"msg": "default"
}
ok: [node1] => {"msg": "default"
}
2、dict2items过滤器
- loop可以使用字典
[devops@master test]$ cat dict2.yml
- hosts: allvars:users:user1:name: qqage: 10user2:name: wwage: 20tasks:- debug:msg: "{{item.value.name}}"loop: "{{users|dict2items}}" # dict2items过滤器,loop可以使用字典遍历# 输出信息
TASK [debug] **********************************************************************************
ok: [master] => (item={'key': 'user1', 'value': {'name': 'qq', 'age': 10}}) => {"msg": "qq"
}
ok: [master] => (item={'key': 'user2', 'value': {'name': 'ww', 'age': 20}}) => {"msg": "ww"
}
ok: [node1] => (item={'key': 'user1', 'value': {'name': 'qq', 'age': 10}}) => {"msg": "qq"
}
ok: [node1] => (item={'key': 'user2', 'value': {'name': 'ww', 'age': 20}}) => {"msg": "ww"
}
3、password_hash('sha512')过滤器
- 可以将密码进行加密,也就是登录的密码,进行加密
[devops@master test]$ cat passwd.yml
- hosts: node1vars:p1: "123"tasks:- user:name: ppstate: presentpassword: "{{p1|password_hash('sha512')}}" # 对这个变量,进行加密即可
二、角色
1、为什么需要角色
-
如果一个人,写了一个剧本,有很多的变量文件,想要拷贝到另外一个人的机器上面的话,很麻烦,有可能会少了几个变量而报错,因此的话,有了这个角色,就能具有很好的移植性
-
角色就是一个目录,变量文件,剧本,jinja2等等,都存放在这个里面
-
还有就是将剧本拆分成多个任务来完成,就不是之前都写在一个文件里面,效率高
2、角色的组成部分
-
files 存放一些非模版的配置文件,普通的文件,传输给被控节点的
-
template 用于存放jinja2模版文件,当角色使用相关的模版时,没有明确指出模版路径的话,默认使用此目录中的模版
-
tasks 剧本,main.yml,任务文件都存放在这个里面,也可以通过include的方式引入其他的任务文件,写在main.yml里面进行引用
-
handlers 存放监听的文件,触发的任务
-
vars 定义此角色要用到的变量,包含一个main.yml
-
meta 用于存放角色的元数据信息,属性,作者等
-
defaults 除了vars目录,也可以定义变量,优先级是最低的
3、角色的操作
1、创建角色和删除角色
# 在defaults里面创建的roles_path的作用就是,在引用一个角色时,会在这个目录下面去寻找角色
# 创建一个角色
[devops@master ansible]$ ansible-galaxy role init roles/apache
- Role roles/apache was created successfully
[devops@master ansible]$ ls roles/
apache# 直接删除这个目录即可,就是删除角色
2、编写一个httpd,自定义网页文件
# tasks任务里面的文件
[devops@master tasks]$ cat main.yml
---
# tasks file for roles/apache- yum:name: httpdstate: presentnotify: get_status
- copy:src: index.htmldest: /var/www/html/index.html
- template:src: httpd.conf.j2dest: /opt/httpd.conf
- firewalld:service: httppermanent: yesstate: enabledimmediate: yes
- service:name: "{{item}}"state: startedenabled: yesloop:- firewalld- httpd
- file:path: "{{http}}"state: touch# files存放网页文件的内容
[devops@master files]$ cat index.html
web# handlers触发任务的存放路径
[devops@master handlers]$ cat main.yml
---
# handlers file for roles/apache- name: get_statusshell: mkdir /opt/httpd# template存放的路径
[devops@master templates]$ cat httpd.conf.j2
Listen {{ansible_ens160.ipv4.address}} 80# vars定义的变量
[devops@master vars]$ cat main.yml
---
# vars file for roles/apache
http: /opt/file_http# 使用角色
[devops@master ansible]$ cat r_apache.yml
- hosts: node1roles:- apache
3、include_tasks
-
就是在tasks目录下面的main里面,不需要写很多,在tasks里面创建任务文件
-
使用include_tasks引用即可
-
避免任务过多
# 创建多个任务,然后include_tasks引入即可
[devops@master tasks]$ ls
copy.yml firewalld.yml main.yml template.yml[devops@master tasks]$ cat main.yml
---
# tasks file for roles/apache- yum:name: httpdstate: presentnotify: get_status
- include_tasks:file: copy.yml
- include_tasks:file: template.yml
- include_tasks:file: firewalld.yml
- service:name: "{{item}}"state: startedenabled: yesloop:- firewalld- httpd
- file:path: "{{http}}"state: touch# 执行结果
[devops@master ansible]$ ansible-playbook r_apache.yml PLAY [node1] **********************************************************************************TASK [Gathering Facts] ************************************************************************
ok: [node1]TASK [apache : yum] ***************************************************************************
changed: [node1]TASK [apache : include_tasks] *****************************************************************
included: /home/devops/ansible/roles/apache/tasks/copy.yml for node1TASK [apache : copy] **************************************************************************
ok: [node1]TASK [apache : include_tasks] *****************************************************************
included: /home/devops/ansible/roles/apache/tasks/template.yml for node1TASK [apache : template] **********************************************************************
changed: [node1]TASK [apache : include_tasks] *****************************************************************
included: /home/devops/ansible/roles/apache/tasks/firewalld.yml for node1TASK [apache : firewalld] *********************************************************************
ok: [node1]TASK [apache : service] ***********************************************************************
ok: [node1] => (item=firewalld)
changed: [node1] => (item=httpd)TASK [apache : file] **************************************************************************
changed: [node1]RUNNING HANDLER [apache : get_status] *********************************************************
changed: [node1]PLAY RECAP ************************************************************************************
node1 : ok=11 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
4、pre_tasks和post_tasks
-
pre_tasks在角色之前执行
-
post_tasks在角色之后执行
-
相当于是配置一个角色环境的操作
[devops@master ansible]$ cat r_apache.yml
- hosts: node1roles:- apachepre_tasks:- debug:msg: pre_taskspost_tasks:- debug:msg: post_tasks
4、下载角色的方法
1、从网上下载
-
https://galaxy.ansible.com/ui/standalone/roles/
-
-r是url文件,角色的url文件
# requirements.yml
# 直接从ansible galaxy上获取
- src: nginx# 从 GitHub 安装角色,并指定使用 'master' 分支,同时自定义角色安装后的名称
- src: https://github.com/bennojoy/nginxversion: mastername: nginx_role
- -p是指定下载角色的路径,保存在哪里,一般是roles目录下面
# 从网上下载一个角色
[devops@master ansible]$ ansible-galaxy role install heman021720.nginx-role -p roles/
2、从本地下载
yum -y install rhel-system-roles# 里面都是保存roles的目录,只需要cp到roles下面即可
[root@master roles]# pwd
/usr/share/ansible/roles
5、删除角色
-
第一个是直接删除角色的目录即可
-
第二个是先查看本地安装了哪些角色,然后在删除哪些
# 查找角色
[devops@master ansible]$ ansible-galaxy role list
# /home/devops/ansible/roles
- apache, (unknown version)
- heman021720.nginx-role, main# 删除角色
[devops@master ansible]$ ansible-galaxy role remove heman021720.nginx-role
- successfully removed heman021720.nginx-role
[devops@master ansible]$ ansible-galaxy role list
# /home/devops/ansible/roles
- apache, (unknown version)
6、查找角色
# 都是从网上找的
[devops@master ansible]$ ansible-galaxy role search nginx
三、集合
-
是包含多个角色的