jinja2和角色管理和集合

一、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: mn
  tasks:
    - template:
        src: ./httpd.conf.j2
        dest: /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: mn
  tasks:
    - template:
        src: ./t2.j2
        dest: /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: mn
  tasks:
    - template:
        src: ./t3.j2
        dest: /mnt/t3

3、jinja2过滤器

  • 因为是过滤器,所以的话,就会有|这个符号的存在,前面是变量,后面是对这个变量进行过滤器的

1、default过滤器

  • 当变量的值没有定义的时候,使用default定义的值

  • 格式

# 前面是一个变量
"{{变量名|jinja2过滤器}}"


[devops@master test]$ cat default.yml 
- hosts: all
  tasks:
    - 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: all
  vars:
    users:
      user1:
        name: qq
        age: 10
      user2:
        name: ww
        age: 20
  tasks:
    - 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: node1
  vars:
    p1: "123"
  tasks:
    - user:
        name: pp
        state: present
        password: "{{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: httpd
    state: present
  notify: get_status
- copy:
    src: index.html
    dest: /var/www/html/index.html
- template:
    src: httpd.conf.j2
    dest: /opt/httpd.conf
- firewalld:
    service: http
    permanent: yes
    state: enabled
    immediate: yes
- service:
    name: "{{item}}"
    state: started
    enabled: yes
  loop:
    - 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_status
  shell: 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: node1
  roles:
    - 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: httpd
    state: present
  notify: get_status
- include_tasks:
    file: copy.yml
- include_tasks:
    file: template.yml
- include_tasks:
    file: firewalld.yml
- service:
    name: "{{item}}"
    state: started
    enabled: yes
  loop:
    - 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 node1

TASK [apache : copy] **************************************************************************
ok: [node1]

TASK [apache : include_tasks] *****************************************************************
included: /home/devops/ansible/roles/apache/tasks/template.yml for node1

TASK [apache : template] **********************************************************************
changed: [node1]

TASK [apache : include_tasks] *****************************************************************
included: /home/devops/ansible/roles/apache/tasks/firewalld.yml for node1

TASK [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: node1
  roles:
    - apache
  pre_tasks:
    - debug:
        msg: pre_tasks
  post_tasks:
    - debug:
        msg: post_tasks



4、下载角色的方法

1、从网上下载

# requirements.yml
# 直接从ansible galaxy上获取
- src: nginx

# 从 GitHub 安装角色,并指定使用 'master' 分支,同时自定义角色安装后的名称
- src: https://github.com/bennojoy/nginx
  version: master
  name: 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

三、集合

  • 是包含多个角色的

总结

  • when中的话,不需要{{}}就能自动的识别到变量,需要双引号

  • jinja2中的话需要{{}}才能识别到变量,但是不需要双引号

  • 因此的话,就是值的话都需要引号才行

posted @ 2025-09-28 14:12  乔的港口  阅读(11)  评论(0)    收藏  举报