ansible_角色的使用

本章主要介绍ansible中角色的使用

  • 了解什么是角色
  • 独立地写一个角色
  • 使用角色
  • 系统自带角色地使用

1.了解角色

正常情况下,配置一个服务如 apache时,要做一系列的操作:安装、拷贝、启动服务等。如果要在不同的机器上重复配置此服务,需要重新执行这些操作。
为了简化这些重复劳动,可以把安装、拷贝、启动 服务等操作打包成一个整体,这个整体称为角色,如图34-1所示。


如果想在其他机器上安装并配置apache,只要调用此角色即可,这样就可以实现一次劳动、永久回报的效果。

一个角色本质上就是一个文件夹,此文件夹名就是角色名,此文件夹中包含许多文件,有的是用于执行各种模块的文件,有的是用于拷贝到被管理主机的jinj2模板文件,有的是定义的变量文件。

为了防止文件太多太乱,在此角色的文件夹中再创建一个个的子目录,用于存放不同的文 件。例如,jinja2模板放在templates目录中,普通的文件放在files目录中,变量文件放在vars目录中,执行模块的各个task放在tasks目录中等。角色目录中每个子目录的作用总结如表34-1所示。


所有的角色都放在一个目录中等待被调用,默认目录为ansible.cfg所在目录的roles目录, 如果要修改路径可以在ansible.cfg中用roles path选项指定。

本章实验都在/home/lduan/demo5下操作,先把demo5目录创建出来并把 ansible.cfg 和hosts拷贝进去,命令如下。
复制代码
[blab@node01 ~]$ mkdir demo5
[blab@node01 ~]$ cp ansible.cfg hosts demo5/
[blab@node01 ~]$ cd demo5/
[blab@node01 demo5]$
修改ansible.cfg,添加 roles path = ./roles,命令如下。
复制代码
[blab@node01 demo5]$ cat ansible.cfg 
[defaults]
inventory = ./hosts
command_warnings=False        //增加内容
roles_path = ./roles          //增加内容

[privilege_escalation]
become=True
become_method=sudo
become_user=root

[blab@node01 demo5]$

2.手把手创建一个角色

创建一个名称为apache的角色
复制代码
[blab@node01 demo5]$ ansible-galaxy init roles/apache
- Role roles/apache was created successfully
[blab@node01 demo5]$ ls roles/
apache
[blab@node01 demo5]$ 
这里apache就是一个角色,看一下apache 中的内容
复制代码
[blab@node01 demo5]$ ls roles/apache/
defaults  files  handlers  meta  README.md  tasks  templates  tests  vars
[blab@node01 demo5]$
里面有不少目录,如前面介绍的,这些目录分别用于存放不同的文件。回顾在上期内容 demo4目录中写好的hand-1.yaml的内容。
复制代码
[blab@node01 demo5]$ cat /home/blab/demo4/hand-1.yml 
---
- hosts: node03
  vars:
   myport: 80
  tasks:
  - name: task1安装http
    yum: name=httpd state=installed
  - name: tasks2拷贝配置文件
    template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  - name: task3启动httpd服务
    service: name=httpd state=started
  handlers:
  - name: restart httpd1
    service: name=httpd state=restarted
  - name: restart httpd2
    service: name=httpd state=restarted
[blab@node01 demo5]$ 

这个文件中包含了以下内容:

  1. vars中是定义变量地
  2. tasks中的代码是正常要执行的
  3. handler中的代码是被触发执行才会执行的
  4. httpd.conf.j2是引用的jinja2模板

下面把这个YAML文件中的内容拆分放在apache角色的不同目录中,把 tasks下的代码放在tasks目录中,把 handlers下的代码放在handlers目录中等。

把 tasks的内容写入roles/apache/tasks/main.yml 中
复制代码
[blab@node01 demo5]$ cat roles/apache/tasks/main.yml 
---
- name: task1 安装httpd
  yum: name=httpd state=installed
- name: task2 拷贝配置文件
  template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  notify: restart httpd1
- name: task3 启动httpd 服务
  service: name=httpd state=started
[blab@node01 demo5]$ 
把 handlers 的内容写入roles/apache/handlers/main.yml 中
复制代码
[blab@node01 demo5]$ cat roles/apache/handlers/main.yml 
---
- name: restart httpd1
  service: name=httpd state=restarted
- name: restart httpd2
  service: name=httpd state=restarted
[blab@node01 demo5]$
在roles/apache/tasks/main.yml 中,template模块拷贝的文件 http.conf.j2所在的目录是roles!apache/templates,所以先把需要的 httod.conf.i2据贝到 roles/apache/templates中
复制代码
[blab@node01 demo5]$ cp ../demo4/httpd.conf.j2 roles/apache/templates/
[blab@node01 demo5]$ ls roles/apache/templates/
httpd.conf.j2
[blab@node01 demo5]$ 
把变量myport写入roles/apache/vars/main.yml中
复制代码
[blab@node01 demo5]$ cat roles/apache/vars/main.yml 
---
myport: 8080
[blab@node01 demo5]$

这里把myport的值改为8080,原来的值为80,会使 httpd.conf.j2中的端口发生变化,从而会触发handler。
也可以不在roles/apache/vars/main.yml中定义变量,而是在playbook 中定义myport 变量,如果在角色的vars 和 playbook 中都定义了myport变量,且变量的值不同,则角色的 vars中定义的变量生效。

下面查看apache这个角色的结构
复制代码
[blab@node01 demo5]$ tree roles/apache/
roles/apache/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
│   └── httpd.conf.j2
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

8 directories, 9 files
[blab@node01 demo5]$

这样apache这个角色我们就算是最终写好了。

3.使用角色

角色写好之后,只要在playbook中直接调用即可,在playbook中的roles下调用,调用的语法如下。
复制代码
 roles:
 ‐ name: 名称1
 role: rolesname1
 ‐ name: 名称2
 role: rolesname2
复制代码
 roles:
 ‐ role: rolesname1
 ‐ role: rolesname2
下面写一个名称为test-role1.yaml的 playbook,里面调用apache这个角色
复制代码
[blab@node01 demo5]$ cat test-roles1.yml 
---
- hosts: node02
  roles:
  - role: apache
[blab@node01 demo5]$
运行此playbook
复制代码
[blab@node01 demo5]$ ansible-playbook test-roles1.yml 

PLAY [node02] ******************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node02]

TASK [apache : task1 安装httpd] **************************************************
changed: [node02]

TASK [apache : task2 拷贝配置文件] ***************************************************
changed: [node02]

TASK [apache : task3 启动httpd 服务] ***********************************************
changed: [node02]

RUNNING HANDLER [apache : restart httpd1] **************************************
changed: [node02]

PLAY RECAP *********************************************************************
node02                     : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@node01 demo5]$

这里是运行test-rolel vam1之后的完整结果,可以看到运行的结果与前面运行的结果一样。变量可以在角色的defaults. vars中定义,也可以在nlavbook中定义,优先级的顺序是: 角色的vars中定义的变量→playbook中定义的变量→角色的defaults 中定义的变量。
所以,如果同一个变量同时在这三个地方被定义了,则角色的vars中定义的变量生效。先把在roles/apache/vars/main.yml中定义变量myport 的那行注释掉,这个变量将在 playbook中定义,如下所示。

复制代码
[blab@node01 demo5]$ cat roles/apache/vars/main.yml 
---
myport: 8080
[blab@node01 demo5]$
修改test-tole1.yaml的内容如下
复制代码
[blab@node01 demo5]$ cat test-roles1.yml 
---
- hosts: node02
  vars:
   myport: 808
  roles:
  - role: apache
[blab@node01 demo5]$ 
运行此playbook
复制代码
[blab@node01 demo5]$ ansible-playbook test-roles1.yml 

PLAY [node02] ******************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node02]

TASK [apache : task1 安装httpd] **************************************************
ok: [node02]

TASK [apache : task2 拷贝配置文件] ***************************************************
ok: [node02]

TASK [apache : task3 启动httpd 服务] ***********************************************
ok: [node02]

PLAY RECAP *********************************************************************
node02                     : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[blab@node01 demo5]$
到node02上验证 httpd 开启的端口是多少
复制代码
[root@node02 ~]# netstat -napt | grep httpd
tcp6       0      0 :::8080                 :::*                    LISTEN      6297/httpd          
[root@node02 ~]#

可以看到。httpd现在使用的端口是8080

4.系统 自带的角色

除我们自己创建的角色外,系统中也包含了一些内置的角色。

在node02上切换到root 用户,然后安装软件包rhel-system-roles.noarch
复制代码
[root@node01 ~]# yum -y install rhel-system-roles.noarch  //root用户安装
[root@node01 ~]# su - blab  //切换用户
安装好这个软件包之后,在/usr/share/ansible/roles目录中会有许多角色,如图34-2所示。
下面演示rhel-system-roles.selinux这个角色,使用lduan用户把rhel-system-roles.selinux拷贝到demo5下的roles目录中
复制代码
[blab@node01 ~]$ cp -r  /usr/share/ansible/roles/rhel-system-roles.selinux/ /home/blab/demo5/
[blab@node01 ~]$ cd demo5
[blab@node01 demo5]$ ls
ansible.cfg  hosts  rhel-system-roles.selinux  roles  test-roles1.yml
[blab@node01 demo5]$ 
前面在讲解handlers时,为httpd 配置了其他端口808,但是因为SELinux的问题,我们临时把 SELinux关闭了
复制代码
[root@node02 ~]# setenforce 0    //临时关闭
[root@node02 ~]# getenforce        //查看是否关闭
Permissive
[root@node02 ~]# 

可以看到,node02上 SELinux的模式是Permissive。下面我们利用角色rhel-system-
roles.selinux把 node02上 SELinux的模式改为 Enforcing。

查看角色rhel-system-roles.selinux中默认的变量
复制代码
[blab@node01 demo5]$ cat rhel-system-roles.selinux/defaults/main.yml 
---
selinux_state: null
selinux_policy: null

# Set up empty lists for SELinux changes.
selinux_booleans: []
selinux_fcontexts: []
selinux_logins: []
selinux_ports: []
selinux_restore_dirs: []

# Purging local modifications is disabled by default.
selinux_all_purge: no
selinux_booleans_purge: no
selinux_fcontexts_purge: no
selinux_ports_purge: no
selinux_logins_purge: no
[blab@node01 demo5]$ 
其中第一个变量是selinux state,这个变量用于指定SELinux的模式,默认值设置为了 null。可以在playbook中定义这个变量,覆盖这个默认的变量值
复制代码
[blab@node01 demo5]$ cat test-role2.yml 
---
- hosts: node02
  vars:
   selinux_state: enforcing
  roles:
   - role: rhel-system-roles.selinux
[blab@node01 demo5]$
运行此playbook
复制代码
PLAY RECAP *********************************************************************
node02                     : ok=7    changed=1    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0   

[blab@node01 demo5]$ 
到 node02上查看验证,
复制代码
[root@node02 ~]# getenforce 
Enforcing
[root@node02 ~]# 

这里已经把 node02上 SELinux的模式改为了 Enforcing。

5.修改端口上下文

在介绍handler 时,可以通过变量myport随意修改端口。但是端口上下文不对,httpd是启动不起来的,所以当初把 node02上的 SELinux 临时关闭了。
下面介绍如何使用角色rhel-system-roles.selinux修改端口上下文。

查看角色 rhel-system-roles.selinux中默认的变量
复制代码
[blab@node01 demo5]$ cat rhel-system-roles.selinux/defaults/main.yml 
---
selinux_state: null
selinux_policy: null

# Set up empty lists for SELinux changes.
selinux_booleans: []
selinux_fcontexts: []
selinux_logins: []
selinux_ports: []
selinux_restore_dirs: []

# Purging local modifications is disabled by default.
selinux_all_purge: no
selinux_booleans_purge: no
selinux_fcontexts_purge: no
selinux_ports_purge: no
selinux_logins_purge: no
[blab@node01 demo5]$ 

这里变量selinux_ports是一个列表,里面的元素需要定义多个变量,但是变量名是什么我们现在还不清楚。

用vim 编辑器打开roles/rhel-system-roles.selinux/tasks/main.yml,大概第116行是用于定义端口上下文
复制代码
[blab@node01 demo5]$ vim rhel-system-roles.selinux/tasks/main.yml 

114 - name: Set an SELinux label on a port
115   seport:
116     ports: "{{ item.ports }}"
117     proto: "{{ item.proto | default('tcp') }}"
118     setype: "{{ item.setype }}"
119     state: "{{ item.state | default('present') }}"
120   with_items: "{{ selinux_ports }}"

这里只截取了部分代码,可以看到循环列表selinux ports中的4个变量。其中 proto和 state有默认值,ports和setvpe没有默认值,所以我们在定义列表selinux ports时,至少要在列表的元素中定义ports和 setype这两个变量。

修改test-role1.yml的内容
复制代码
[blab@node01 demo5]$ cat test-roles1.yml 
---
- hosts: node02
  vars:
   myport: 808
   selinux_ports:
   - ports: "{{myport}}"
     setype: http_port_t
  roles:
  - role: rhel-system-roles.selinux
  - role: apache
[blab@node01 demo5]$ 

这里定义了一个变量myport的值为808,然后定义了一个列表selinux_ports。这个列表中只有一个元素,元素中有两个变量ports和 setype。其中 ports这个变量引用myport 的值,记得要用双引号引起来,setype的值被设置为了http_port_t。

注释:roles/apache/vars/main.yml 中的变量 否则会因为优先级的问题导致端口号不能更改
复制代码
[blab@node01 demo5]$ cat roles/apache/vars/main.yml 
---
#myport: 8080
[blab@node01 demo5]$ 
运行此 playbook
复制代码
[blab@node01 demo5]$ ansible-playbook test-roles1.yml 

PLAY RECAP *********************************************************************
node02                     : ok=10   changed=1    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0   

[blab@node01 demo5]$
然后到node02上检查httpd所使用的端口
复制代码
[root@node02 ~]# netstat -napt | grep httpd
tcp6       0      0 :::808                  :::*                    LISTEN      13421/httpd         
[root@node02 ~]# 

可以看到,httpd此时使用的端口是808。

相关推荐
孙克旭_2 天前
day051-ansible循环、判断与jinja2模板
linux·运维·服务器·网络·ansible
leo__5205 天前
自动化运维:使用Ansible简化日常任务
运维·自动化·ansible
风清再凯10 天前
自动化工具ansible,以及playbook剧本
运维·自动化·ansible
IT乌鸦坐飞机10 天前
ansible部署数据库服务随机启动并创建用户和设置用户有完全权限
数据库·ansible·centos7
遇见火星23 天前
如何使用Ansible一键部署MinIO集群?
ansible
粥周粥23 天前
ANSIBLE
ansible
码农101号23 天前
Linux中ansible模块补充和playbook讲解
linux·运维·ansible
码农101号23 天前
Linux的Ansible软件基础使用讲解和ssh远程连接
ansible
烟雨书信24 天前
ANSIBLE运维自动化管理端部署
运维·自动化·ansible
碎碎-li24 天前
ANSIBLE(运维自动化)
运维·自动化·ansible