第九章、ansible基于roles角色管理大项目

一、利用角色构造ansible playbook

随着开发更多的playbook,会发现有很多机会重复利用以前编写的playbook中的代码。或许,一个用于为某一应用配置MySQL数据库的play可以改变用途。通过利用不同的主机名、密码和用户来为另一个应用配置MySQL数据库。

但在现实中,这个play可能比较冗长且复杂,有许多包含或导入的文件,以及用于管理各种情况的任务和处理程序。将所有这些代码复制到另一playbook种可能并不简单。

ansible提供了一种方法,能以通用的方式更加轻松地重复利用ansible代码。可以在标准化目录结构中打包所有的任务、变量、文件、模板,以及调整基础架构或部署应用所需的其他资源。只需通过复制相关的目录,将角色从一个项目复制到另外一个项目。然后,只需从一个play调用该角色就能执行。

借助编写好的角色,可以从playbook中向角色传递调整其行为的变量,设置所有站点相关的主机名、IP地址、用户名,或其他在本地需要的具体详细信息。例如,部署数据库服务器的角色可能已编写为支持多个变量,这 些变量用于设置主机名、数据库管理员用户和密码,以及需要为安装进行自定义的其他参数。角色的作者也可以确保在选择不在play中设置变量值时,为这些变量设定合理的默认值。

ansible角色具有下列优点:

  1. 角色可以分组内容,从而与他人轻松共享代码
  2. 可以编写角色来定义系统类型的基本要素:Web服务器、数据库服务器、Git存储库,或满足其他用途
  3. 角色使得较大型项目更容易管理
  4. 角色可以由不同的管理员并行开发(可以由多个人分工合作完成部署)

除了自行编写、使用、重用和共享角色以外,还可以从其他来源获取角色。一些角色以及包含在rhel-system-rolses软件包中(安装后也就有很多系统角色了)。作为红帽企业Linux的一部分。还可以从ansible Galaxy网站获取由社区提供支持的许多角色(如部署nginx、lvs等)。

检查ANSIBLE角色结构

此时的角色是没有的

[student@server ansible]$ ls
a            get-pip.py.1    inventory.py   roles        var.yml
[student@server ansible]$ ls roles/
[student@server ansible]$ 

//手动定义

[student@server roles]$ ansible-galaxy init hh
- Role hh was created successfully
[student@server roles]$ ls hh/
defaults  files  handlers  meta  README.md  tasks  templates  tests  vars

ansible角色由字母和文件的标准化结构定义。顶级目录定义角色本身的名称(也就是roles本身)。文件整理到子目录中(定义的角色),子目录按照各个文件在角色中的用途进行命名,如tasks和handlers。files和templates子目录中包含其他YAML文件中的任务引用的文件。

扫描二维码关注公众号,回复: 14942156 查看本文章

//通过tree命令查看hh的树状图

[student@server roles]$ tree hh
hh
├── defaults
│   └── main.yml   ——角色默认定义的变量
├── files           ——指在调用角色时使用的静态文件,只用写相对路径
├── handlers        ——用来存放触发任务(notify)的目录
│   └── main.yml
├── meta            ——对角色的基础描述信息
│   └── main.yml
├── README.md       ——记录角色任何使用的帮助文档
├── tasks           ——需要执行的角色任务存放位置
│   └── main.yml
├── templates       ——存放模板,使用template来复制、一般用来启动服务或提前备份数据
├── tests           ——对角色执行进行测试
│   ├── inventory
│   └── test.yml
└── vars            ——经常使用的变量,比defaults变量优先级要高
    └── main.yml

8 directories, 8 files
  • Defaults:此目录中的main.yml文件包含角色变量的默认值,使用角色时可以覆盖这些默认值。这些变量的优先级较低,应该在play中更改和自定义。
  • Files:此目录包含由角色任务引用的静态文件
  • Handlers:此目录中的main.yml文件包含角色的处理程序定义,也就是触发器的内容
  • Meta:此目录中的main.yml文件包含与角色相关的信息,如作者、许可证、平台和可选的角色的依赖项。
  • Tasks:此目录中的mian.yml文件包含角色的任务定义。
  • Template: 此目录包含由角色任务引用的jinja2模板(j2模板)
  • Tests:此目录可以包含清单和test.yml剧本,可用于测试角色
  • Vars:此目录的main.yml文件定义角色的变量值,这些变量通常用于角色内部用途,这些变量的优先级较高,在playbook中使用时不应更改。

1、在playbook中使用ansible角色

在playbook中使用角色非常简单。


  • name: test
    hosts: node1
    roles:
    • role1
    • role2

对于每个指定的角色,角色任务、角色处理程序、角色变量和角色依赖项将按照顺序导入到playbook中。角色中的任何copy、script(运行脚本)、template或include_tasks/import_tasks任务都可引用角色中相关的文件、模板或任务文件且无需相对或绝对路径名称。ansible将分别在角色的files、templates或tasks子目录中寻找他们。

注意
如果使用roles部分将角色导入到play中,这些角色会为该play定义的任何任务之前运行。

以下示例设置cy的角色变量a1和a2的值。
使用cy角色自定义变量时,任何defaults和vars变量的优先级都会被覆盖。
示例:
1、创建角色

[student@server roles]$ cd  /etc/ansible/roles
[student@server roles]$ ansible-galaxy  init  cy

2、在vars里给角色定义变量

[student@server roles]$ Vim  cy/vars/main.yml
---
# vars file for cy
a1: 11
a2: 22

3、在tasks目录中的main.yml中写角色的任务

[student@server roles]$ Vim  cy/tasks/main.yml
---
# tasks file for cy
- name: test
  debug:
    msg: "{
    
    { a1 }}"

4、在/etc/ansible/目录下创建一个test.yml的playbook来使用cy角色(这里才会标明对那台主机进行执行)

---
- name: test1
  hosts: node1
  roles:              //直接调用/var/main.yml变量
    - cy

此时会发现,我们能够调用角色vars目录下的main.yml定义的变量可以直接被调用
5、在test.yml的playbook中自定义变量

---
- name: test1
  hosts: node1
  roles:               
    - role: cy      //添加此参数可直接引用a1变量
      a1: 333

6、执行test.yml,就会发现test.yml中定义的a1变量覆盖了角色中vars目录中定义的变量,因为这种定义的优先级高于vars

输出结果为:a1=33

2、控制执行顺序

对于playbook中的每个play,任务按照任务列表中的顺序来执行,执行完所有任务后,将执行任何通知的处理程序。
在角色添加到play后,角色任务将添加到任务列表的开头。如果play中包含第二个角色,其任务列表添加到第一个角色之后(一般是先执行角色在执行普通任务)。

角色处理程序添加到play中的方式与角色任务添加到play中相同。每个play定义一个处理程序列表。角色处理程序先添加到处理程序列表,后跟play的handlers部分中定义的任何处理程序。

在某些情形中,可能需要在角色之前执行一些play任务。可以在play配置中添加pre_tasks部分,可以优先执行。列在此部分中的所有任务将在执行任何角色之前执行。如果这些任务中有任何一个通知了处理程序,则这些处理程序任务也在角色或普通任务之前执行。

此外,play也支持post_tasks关键字。这项任务是在play的普通任务和执行角色,他们通知的任何处理程序之后执行。

默认情况下:

tasks: 
roles:
先执行角色,然后在执行tasks

也就是这样理解:
pre_tasks:  在角色之前执行
post_tasks: 在角色之后执行

例子
如:

---
- name: test1
  hosts: node1
  pre_tasks:            //默认会第一个执行
    - name: debug1
      shell:
        cmd: echo aaa
      notify: cc
  roles:             # 第二个执行
    - cy

  post_tasks:
    - name: debug2      # 第三
      debug:
        msg: ooo
        
  handlers:
    - name: cc
      debug:
        msg: iii

执行该playbook,我们发现pre_tasks任务在角色之前执行的,而且触发器是在触发后马上执行的。
Post_tasks任务是在触发器和角色执行完成后,才来执行的。

3、导入角色任务

导入时需在role角色中已经定义好了变量,在导入时即可直接引用
除了将角色包含在play的roles部分中外,也可以使用普通任务将角色添加到play中,使用include_role模块可以动态包含角色,使用import_role模块可以静态导入角色。
如:

---
- name: test23
  hosts: node1
  tasks:
    - debug:
        msg: chenyufdsf

    - name: a task to include cy here
      include_role:                         //或者使用import_role
        name: cy

    - name: debug2
      debug:
        msg: 11111

这样引用的话也是按照顺序来执行的

定义清单的三种方式:

reles:
  -cy

roles:
  - role: cy

tasks: 
  - name: aa
       include_role:  
         name: cy

案例:
示例:创建和使用角色
根据下列要求,在/etc/ansible/roles中创建名为http的角色

1、部署yum仓库
2、安装httpd软件包
3、模板文件index.html.j2已存在,用户创建具有以下输出的文件/var/www/html/index.html:
Welcome to HOSTNAME on IPADDRESS
当index.html内容发生改变时,重启httpd服务
其中HOSTNAME是受控节点的完全合格域名,IPADDRESS则是受控节点的IP地址
按照上方所述,创建一个使用此角色的playbook /etc/ansible/newrole.yml,该playbook在所有主机上运行。

不想用之前的角色话,想在创建一个角色时,可使用
ansible-galaxy remove cy

1、创建http角色

[root@server roles]# ansible-galaxy init http
- Role http was created successfully
[root@server roles]# 

2、根据要求手动新建index.html.j2模板

[root@server roles]# cd http/templates/
[root@server templates]# ls
//调用事实变量,分别是完全合格域名和本机IP地址
[root@server templates]# vim index.html.j2
Welcome to {
   
   { ansible_fqdn }} on {
   
   { ansible_ens160.ipv4.address }}

3、在/etc/ansible/roles/http/tasks/main.yml书写角色任务内容

[root@server ansible]# vim /etc/ansible/roles/http/tasks/main.yml
---
# tasks file for http
- name: repo1
  yum_repository:
    file: server
    name: baseos
    description: rhel8
    baseurl: file:///mnt/BaseOS
    enabled: yes
    gpgcheck: no

- name: repo2
  yum_repository:
    file: server
    name: appstream
    description: RHEL8
    baseurl: file:///mnt/AppStream
    enabled: yes
    gpgcheck: no

- name: mount cdrom
  mount:
    src: /dev/cdrom
    path: /mnt
    fstype: iso9660
    state: mounted

- name: install httpd
  yum:
    name: httpd
    state: present

- name: cp file
  template:
    src: index.html.j2                 //这里写相对路径调用访问网页
    dest: /var/www/html/index.html     //保存到受控主机
  notify:                              //触发任务
    - restart httpd
 
- name: firewalld                    //开启防火墙
  firewalld:
    service: http
    state: enabled
    permanent: yes
    immediate: yes
    
- name: firewalld for http         //设置防火墙规则
  firewalld:
    service: http
    state: enabled
    permanent: yes

4、配置触发器handlers触发器

[root@server ansible]# vim /etc/ansible/roles/http/handlers/main.yml 
---
# handlers file for http
- name: restart httpd
  service:
    name: httpd
    state: restarted
    enabled: yes

5、书写/etc/ansible/newrole.yml playbook,运行http角色

[root@server ansible]# vim newrole.yml
---
- name: web station
  hosts: all
  roles:
     - http

6、执行该playbook

[root@server ansible]# ansible-playbook newrole.yml
PLAY [web station] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [node1]
ok: [node2]

TASK [http : repo1] ************************************************************
changed: [node1]
changed: [node2]

TASK [http : repo2] ************************************************************
changed: [node1]
changed: [node2]

TASK [http : mount cdrom] ******************************************************
changed: [node1]
changed: [node2]

TASK [install httpd] ***********************************************************
changed: [node2]
changed: [node1]

TASK [http : cp file] **********************************************************
changed: [node2]
changed: [node1]

TASK [http : firewalld] ********************************************************
changed: [node1]
changed: [node2]

RUNNING HANDLER [restart httpd] ************************************************
changed: [node1]
changed: [node2]

PLAY RECAP *********************************************************************
node1                      : ok=8    changed=7    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
node2                      : ok=8    changed=7    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

7、验证:

[root@server ansible]# curl http://node1.example.com
Welcome to node1.example.com on 172.16.30.10
[root@server ansible]# curl http://node2.example.com
Welcome to node2.example.com on 172.16.30.20

二、系统角色

1、自定义安装系统角色

[student@server roles]$ sudo yum -y install rhel-system-roles

2、rhel系统角色
常用的系统角色:

Rhel-system-roles.kdump 配置kdump崩溃恢复服务
Rhel-system-roles.network 配置网络接口
Rhel-system-roles.selinux 配置网络接口
Rhel-system-roles.selinux 配置和管理selinux(selinux模式 文件和端口上下文、布尔值 )
Rhel-system-roles.timesync 配置时钟同步
Rhel-system-roles.postfix 使用postfix服务将每个主机配置为邮件传输代理
Rhel-system-roles.firewall 配置主机的防火墙
Rhel-system-roles.tuned 配置tuned服务,以调优系统性能

3、RHEL系统角色位于/usr/share/ansible/roles/目录下

[student@server roles]$ ls | wc -l
36
[student@server roles]$ cp -a rhel-system-roles.selinux /home/student/ansible/roles/selinux
[student@server roles]$ cd /home/student/ansible/roles/
[student@server roles]$ ls
hh  selinux
//可以查看帮助文档
[student@server selinux]$ cat README.md
```yaml
selinux_all_purge: true


#### set SELinux policy type and mode

```yaml
selinux_policy: targeted
selinux_state: enforcing

示例:
安装 RHEL 系统角色软件包,并创建符合以下条件的playbook /etc/ansible/timesync.yml:
在所有受管节点上运行
使用 timesync 角色
配置该角色,以使用当前有效的 NTP 提供商
配置该角色,以使用时间服务器 classroom.example.com
配置该角色,以启用 iburst 参数
1、安装系统角色
dnf -y install rhel-system-roles

2、将时钟同步的系统角色复制到/etc/ansible/roles目录下,并重名了角色名为timesync
cp -r /usr/share/ansible/roles/rhel-system- roles.timesync/ /etc/asnible/roles/timesync
3、书写playbook,并执行。

[root@workstation ansible]$ vim timesync.yml
---
- name: set time sync
  hosts: all
  vars:  
    timesync_ntp_servers:
      - hostname: ansible.example.com
        iburst: yes
  roles:
    - timesync
[root@workstation ansible]$ ansible-playbook timesync.yml

三、从ansible-galaxy安装角色

ansible-galaxy install子命令从Ansible Galaxy下载角色(需要什么角色就从官网下载什么),并将它站桩到控制节点本地。
默认情况下,角色安装到用户的roles_path下的第一个可写目录中。根据ansible设置的默认roles_path,角色通常安装到用户的~/.ansible/roles目录。默认的roles_path可能会被当前的ansible配置文件或环境变量ANSIBLE_ROLES_PATH覆盖,这将影响ansible-galaxy的行为。
可以使用-p DIRECTORY选项,指定具体的目录来安装角色。

安装角色
1、首先在roles目录下书写一个playbook,把需要安装角色的路径定义到playbook中,下载完后可以放在终端中

[root@server roles]# vim /etc/ansible/roles/test.yml 
- name: haproxy
  src: file:///home/student/ansible/haproxy.tar.gz       //在本地中传输给受控主机

- name: phpinfo
  src: file:///home/student/ansible/phpinfo.tar.gz

其中src指定角色的来源,可以是本地的(file://),也可以是远程的(http:// )

2、使用ansible-galaxy命令安装角色

[root@server ansible]# ansible-galaxy install -r /etc/ansible/roles/test.yml -p /etc/ansible/roles/
- downloading role from file:///root/haproxy.tar.gz
- extracting haproxy to /etc/ansible/roles/haproxy
- haproxy was installed successfully
- downloading role from file:///root/phpinfo.tar.gz
- extracting phpinfo to /etc/ansible/roles/phpinfo
- phpinfo was installed successfully

3、在roles目录下查看安装好的角色
然后外面就可以根据里面的模块调用服务了

[root@server roles]# pwd
/etc/ansible/roles
[root@server roles]# ls
haproxy  phpinfo  test.yml

管理下载的角色
ansible-galaxy命令也可管理本地的角色,如位于playbook项目的roles目录中的角色。ansible-galaxy list子命令列出本地找到的角色。

[root@server ansible]# ansible-galaxy list
# /etc/ansible/roles
- haproxy, (unknown version)
- phpinfo, (unknown version)

可以使用ansible-galaxy remove子命令本地删除角色
[root@server ansible]# ansible-galaxy remove haproxy
- successfully removed haproxy
[root@server ansible]# ansible-galaxy list
# /etc/ansible/roles
- phpinfo, (unknown version)

猜你喜欢

转载自blog.csdn.net/cxyxt/article/details/127673716