文章目录
- 一、Ansible的内置的或官方推荐创建的目录及文件
- 介绍
- roles目录解释
- 1、roles/自定义角色名目录下
- 2、roles/自定义角色名目录/tasks目录下
- 3、roles/自定义角色名目录/handlers目录下
- 4、roles/自定义角色名目录/templates目录下
- 5、roles/自定义项目名目录/files目录下
- 6、roles/自定义项目名目录/meta目录下
- 定义角色依赖的好处,何时需要定义角色依赖
- 好处
- 何时必须定义角色的依赖关系
- 何时不必要定义角色的依赖关系
- 二、使用`ansible-galaxy`创建角色的规范目录结构
- 什么是`ansible-galaxy`
- 使用方法
- 命令选项
- 如何使用`ansible-galaxy`创建role规范目录结构
- 使用Ansible roles的执行流程
- 三、案例-使用Ansible roles搭建Nginx负载均衡
- 创建角色规范目录
- 配置meta目录、files目录、templates目录
- meta目录定义角色依赖
- templates目录存放嵌入变量的Nginx主配置文件、Nginx网站应用负载均衡配置文件
- nginx.j2
- site.j2
- 编写tasks目录的playbook文件main.yaml
- ToDoHere???????????????
- 创建并编写项目入口文件
- 测试结果
- 四、案例-部署所有rsync-client和rsync-server服务
在Ansible中使用角色是一种模块化和重用配置的方法。角色允许你定义一系列的任务、文件、模板和变量,这些可以在不同的主机和项目中重用。下面是一个简单的示例,展示如何在Ansible
playbook中使用角色。首先,确保你已经创建了角色目录结构。一个典型的角色目录结构如下:
roles/
└── nginx/├── files/├── handlers/│ └── main.yml├── meta/│ └── main.yml├── tasks/│ └── main.yml├── templates/├── vars/└── defaults/└── main.yml
每个目录的作用如下:
- files/ :包含需要分发到远程主机的文件。
- handlers/ :定义了通知事件的处理器。
- meta/ :定义角色的依赖关系。
- tasks/ :定义角色的任务。
- templates/ :包含需要传输到远程主机的模板文件。
- vars/ :定义角色的变量。
- defaults/ :定义默认变量。
接下来,在你的playbook中使用角色。以下是一个示例playbook,它将 nginx 角色应用于 web_servers 主机组:
---
- hosts: web_serversbecome: yes # 使用管理员权限执行任务roles:- nginx
在这个playbook中:
- hosts: web_servers 指定了目标主机组。
- become: yes 表示使用管理员权限执行任务。
- roles: 指定了要应用的角色列表。
确保你的 nginx 角色已经正确定义在 roles/目录下,并且你的Ansible配置文件(通常是 ansible.cfg )正确指向了包含角色的目录。最后,运行你的playbook:
ansible-playbook your_playbook.yml
这将应用 nginx 角色到 web_servers 主机组中的所有主机。
一、Ansible的内置的或官方推荐创建的目录及文件
介绍
Ansible的内置目录结构和官方推荐的最佳实践可以帮助用户更好地组织和管理项目。以下是Ansible常见的目录及文件结构:
- Ansible项目目录结构
通常,Ansible项目会包含以下几个主要目录和文件:
- inventory: 存放主机清单文件,定义要管理的主机和组。
- playbooks: 存放Ansible Playbook文件的目录,Playbook用于定义要执行的任务。
- roles: 存放角色的目录,角色是用于组织Playbook的重用模块。
- tasks/: 存放任务文件。
- handlers/: 存放处理程序。
- templates/: 存放模板文件。
- files/: 存放静态文件。
- vars/: 存放变量文件。
- defaults/: 存放默认变量。
- group_vars/: 存放针对组的变量文件。
- host_vars/: 存放针对单个主机的变量文件。
- library/: 自定义模块的目录。
- filter_plugins/: 自定义过滤器的目录。
- README.md: 项目的说明文件。
- 官方推荐的目录
Ansible官方文档推荐的目录结构主要集中在以下几个方面:
- 组织性: 通过roles和playbooks的目录组织,可以更好地重用和维护代码。
- 可扩展性: 角色和目录结构使得项目更易于扩展和更新。
- 清晰性: 采用清晰的命名和结构,让其他开发人员更容易理解项目。
- 示例结构
一个典型的Ansible项目目录结构可能如下所示:
my-ansible-project/
├── inventory/
│ └── hosts.ini
├── playbooks/
│ └── site.yml
├── roles/
│ └── webserver/
│ ├── tasks/
│ │ └── main.yml
│ ├── handlers/
│ │ └── main.yml
│ ├── templates/
│ │ └── httpd.conf.j2
│ ├── files/
│ │ └── index.html
│ ├── vars/
│ │ └── main.yml
│ └── defaults/
│ └── main.yml
├── group_vars/
│ └── all.yml
├── host_vars/
│ └── host1.yml
├── library/
├── filter_plugins/
└── README.md
这样的结构可以提高代码的可读性和可维护性,方便团队协作。
注意:
如果要这样的结构的话,这里的playbooks目录下的site.yaml中是无法直接调用host_vars和group_vars中的变量的,除非使用include_vars
---
- name: 测试内置目录的主机清单识别,变量调用hosts: webserversbecome: notasks:- include_vars: ../group_vars/webservers- name: 测试是否可以直接调用变量debug:msg: "user:{{user}},id:{{id}}"
最好将site.yaml放于host_vars和grou_vars目录的同一层级中;或者host_vars和group_vars目录不在这个结构里创建,如果要定义主机或主机组的变量,可以直接在Ansible默认的/etc/ansible/host_vars和/etc/ansible/group_vars目录下定义;这样不管site.yaml是否在playbooks目录中,都可以直接调用的
[root@m01 ~]# tree ansible-project/ansible-project/
├── filter_plugins
├── group_vars
│ └── webservers
├── host_vars
├── inventory
│ └── hosts.ini
├── library
├── playbooks
├── READEME.md
├── roles
│ ├── roleA
│ │ ├── defaults
│ │ │ └── main.yml
│ │ ├── files
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── meta
│ │ │ └── main.yml
│ │ ├── README.md
│ │ ├── tasks
│ │ │ └── main.yml
│ │ ├── templates
│ │ ├── tests
│ │ │ ├── inventory
│ │ │ └── test.yml
│ │ └── vars
│ │ └── main.yml
│ └── roleB
│ ├── defaults
│ │ └── main.yml
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ ├── meta
│ │ └── main.yml
│ ├── README.md
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ ├── tests
│ │ ├── inventory
│ │ └── test.yml
│ └── vars
│ └── main.yml
└── site.yaml# 执行:
cd ansible-project
ansible-playbook site.yaml -i inventory/hosts.ini
roles目录解释
存放项目中Ansible的定义的多个角色里的规范内容
1、roles/自定义角色名目录下
存放单个角色里的要做的,且便于Ansilbe识别处理的规范的内容
2、roles/自定义角色名目录/tasks目录下
定义角色的任务文件——main.yaml;且文件必须命名为 main.yaml
;这个文件名是 Ansible 识别元数据的标准,其他名称不会被识别。
3、roles/自定义角色名目录/handlers目录下
定义通知事件的处理文件——main.yaml;且文件必须命名为 main.yaml
;这个文件名是 Ansible 识别元数据的标准,其他名称不会被识别。
4、roles/自定义角色名目录/templates目录下
定义Jinja2文件;包含需要传输到远程主机的模板文件
xxx1.j2
xxx2.j2
…
这样存放的好处是:
task目录下的任务文件中使用了template模块时,src的路径就可以直接写xxx1.j2就不用写全路径了
5、roles/自定义项目名目录/files目录下
包含需要分发到远程主机的除了JInja2的文件。
aaa1.txt
aass.conf
这样存放的好处是:
task目录下的任务文件中使用了copy等推送模块时,src的路径就可以直接写aaa.txt就不用写全路径了
6、roles/自定义项目名目录/meta目录下
定义当前角色所依赖的其他角色的文件——main.yaml;且文件必须命名为 main.yaml
;这个文件名是 Ansible 识别元数据的标准,其他名称不会被识别。
---
dependencies:- 所依赖的其他角色名
也就是说,执行当前角色的任务之前,需要先检查当前角色是否有依赖的角色,如果有,那么先执行它依赖的角色的任务,所有依赖的角色的任务都执行完了,再执行当前角色的任务
定义角色依赖的好处,何时需要定义角色依赖
在Ansible中定义角色依赖关系有以下几个好处:
好处
-
模块化管理:
- 通过将相关功能分散到不同的角色中,可以提高代码的可维护性和可重用性。依赖关系确保需要的角色能够自动被调用。
-
简化配置:
- 定义依赖关系可以减少重复配置。一个角色可以依赖于其他角色,从而避免在多个任务中重复编写相同的逻辑。
-
易于共享和协作:
- 在团队中工作时,明确的依赖关系可以帮助团队成员理解角色之间的关系,提高协作效率。
-
自动处理顺序:
- Ansible会自动处理依赖的执行顺序,确保依赖角色在主角色之前正确执行。
何时必须定义角色的依赖关系
-
功能依赖:
当一个角色的功能显然依赖于另一个角色时,例如,一个角色需要数据库角色来设置数据库,必须定义依赖关系。 -
公共资源:
如果多个角色使用相同的资源(如用户账户、配置文件等),则定义依赖关系确保这些资源先被创建或配置。
何时不必要定义角色的依赖关系
-
独立角色:
如果一个角色可以独立工作,不依赖于其他角色的功能,那么就不需要定义依赖关系。 -
简单任务:
对于一些简单的任务或脚本,仅执行单一功能的角色,可能没有必要引入依赖关系。 -
非直接依赖:
如果角色之间的关系并不直接导致功能上的依赖,可以不定义依赖。例如,角色A和角色B都可以独立于其他角色运行。
总之,定义角色依赖关系是为了确保角色之间的相互作用和功能完整性,但并不是所有情况下都需要。根据具体情况判断是否添加依赖关系,以保持角色的清晰性与简洁性。
dependencies:- { role: roleB }
在这种情况下,使用花括号 {}
是为了明确将其视为一个字典。虽然在这个特定的场景中,省略花括号也是合法的,但使用花括号可以提高可读性,尤其是在复杂结构或者需要传递额外参数时。
3、 其他写法
如果您的角色有多个依赖,您可以这样写:
dependencies:- role: roleB- role: roleC
*4、 带有版本约束的依赖
如果需要指定依赖角色的版本,可以使用以下格式:
dependencies:- { role: roleB, src: git+https://github.com/user/roleB.git, version: 'v1.0' }
meta/main.yml
中的dependencies
字段用于定义角色间的依赖关系。- 使用花括号是可选的,但可以提高可读性。
- 可定义多个依赖和版本约束。
二、使用ansible-galaxy
创建角色的规范目录结构
什么是ansible-galaxy
ansible-galaxy
命令用于管理Ansible角色,方便用户从Galaxy库中下载角色、初始化新角色等。它的出现是为了简化角色的管理和共享,提高用户的自动化工作效率。
使用方法
-
安装角色:
ansible-galaxy install <role_name>
用于安装指定的角色。
-
初始化角色:
ansible-galaxy init <role_name>
创建一个新的角色目录结构。
-
更新角色:
ansible-galaxy install -f <role_name>
强制更新已安装的角色。
-
移除角色:
ansible-galaxy remove <role_name>
删除指定的角色。
-
列出已安装角色:
ansible-galaxy list
显示当前环境中已安装的角色。
只会在默认目录中查找:
命令选项
install
: 安装角色。
init
: 初始化新角色。
remove
: 移除角色。list
: 列出已安装的角色。info
: 显示角色的详细信息。search
: 搜索Galaxy中的角色。dependencies
: 处理角色依赖。
这些选项提供了强大的功能,使用户能够方便地管理和使用Ansible角色,从而提升自动化管理的效率。
如何使用ansible-galaxy
创建role规范目录结构
mkdir roles
cd rolesansible-galaxy init roleA
j
使用Ansible roles的执行流程
注:
先寻找一个角色中的meta目录是否定义了依赖角色;如果有,那么先执行定义的依赖角色中的任务,这样依次递归执行
三、案例-使用Ansible roles搭建Nginx负载均衡
创建角色规范目录
# roles目录下创建名为loadBalance的角色规范目录
cd roles
ansible-galaxy init loadBalance
配置meta目录、files目录、templates目录
meta目录定义角色依赖
暂无功能上有依赖的角色
templates目录存放嵌入变量的Nginx主配置文件、Nginx网站应用负载均衡配置文件
nginx.j2
site.j2
编写tasks目录的playbook文件main.yaml
ToDoHere???????????????
创建并编写项目入口文件
touch site.yaml
---
- name: the project playhosts: allbecome: noroles:- {role: lb,when: ansible_hostname is match 'lb*'}
或
---
- name: the project playhosts: allbecome: noroles:- role: lbwhen: ansible_hostname is match 'lb*'
解释:
在Ansible中,- {role: lb,when: ansible_hostname is match 'lb*'}
是一个任务(task)的定义,它使用了Ansible的YAML语法。让我们分解一下这个语法:
-
-
:在Ansible的playbook中,这个符号表示一个新的任务的开始。 -
{}
:大括号用于定义一个字典(dictionary),在Ansible中,任务通常以字典的形式定义。 -
role: lb
:这是一个键值对(key-value pair),其中role
是键,lb
是值。在Ansible中,role
是一个特殊的关键字,用于指定要应用的角色。这里的lb
不是变量,而是一个硬编码的字符串,表示要应用的角色名称。 -
when: ansible_hostname is match 'lb*'
:这也是一个键值对,其中when
是键,ansible_hostname is match 'lb*'
是值。when
同样是Ansible中的特殊关键字,用于定义任务执行的条件。这里的条件是检查ansible_hostname
变量的值是否符合正则表达式'lb*'
。ansible_hostname
是一个变量,它在Ansible中自动设置为当前被管理主机的主机名。is match
是一个条件测试,用于检查左侧的变量是否匹配右侧的正则表达式。'lb*'
是一个正则表达式,*
表示任意数量的字符。
所以,这里的role
和when
不是变量,而是Ansible playbook语法中用于定义任务属性的特殊关键字。lb
和ansible_hostname is match 'lb*'
是与这些关键字关联的值,分别指定了要应用的角色和执行任务的条件。
通用语法可以表示为:
- {关键字1: 值1, 关键字2: 值2, ...}
在这个通用语法中,关键字是Ansible预定义的,比如role
和when
,而值则是根据你的具体需求来指定的。
在Ansible中,指定角色和条件的方式可以有多种写法。以下是一些替代写法:
- 使用
- name:
来指定任务名称,然后使用when:
条件语句:
- name: Apply lb role when hostname matches 'lb*'role: lbwhen: ansible_hostname is match('lb*')
- 使用
include_role
模块来引入角色,同时指定条件:
- include_role:name: lbwhen: ansible_hostname is match('lb*')
- 使用
import_role
模块来引入角色,然后使用when:
:
- import_role:name: lbwhen: ansible_hostname is match('lb*')
- 使用
block
来组合多个任务,并使用when:
条件语句:
- block:- role: lbwhen: ansible_hostname is match('lb*')
- 使用
with_items
来迭代一个列表,并对每个主机应用角色:
- role: lb
# when: ansible_hostname is match('lb*')with_items: "{{ groups['all'] }}"
- 使用
set_fact
来设置一个变量,然后使用这个变量在when:
中:
- name: Set fact for lb hostsset_fact:is_lb_host: "{{ ansible_hostname is match('lb*') }}"when: ansible_hostname is match('lb*')- role: lbwhen: is_lb_host
每种写法都有其适用场景,你可以根据你的具体需求和Ansible playbook的结构来选择最合适的写法。
当然,Ansible playbooks 提供了多种方式来实现相同的功能。以下是一些替代写法,用于定义角色分配和条件执行:
- 使用
when
关键字的另一种写法
- {role: lb, when: "'lb' in ansible_hostname"}
这里使用 'lb' in ansible_hostname
来检查主机名是否包含 lb
。
- 使用
with_items
和loop
来动态分配角色
- role: lbwhen: ansible_hostname in groups['lb_group']
这里假设你有一个名为 lb_group
的主机组,包含所有以 lb
开头的主机。
- 使用
include_role
模块
- name: Apply lb role to hostsinclude_role:name: lbwhen: ansible_hostname is match('lb*')
使用 include_role
模块可以更灵活地控制角色的包含。
- 使用
hosts
关键字指定特定的主机
- hosts: lb*roles:- lb
这里直接在 hosts
关键字中使用通配符来指定所有以 lb
开头的主机。
- 使用
with_items
循环
- name: Apply lb role to specific hostshosts: alltasks:- name: Apply lb rolerole: lbwhen: ansible_hostname in ['lba', 'lbb', 'lbc']
这里假设 lba
, lbb
, lbc
是特定的主机名。
- 使用
ansible_facts
变量
- name: Apply lb role based on facthosts: alltasks:- name: Set factset_fact:is_lb_host: "{{ ansible_hostname is match('lb*') }}"- name: Apply lb rolerole: lbwhen: is_lb_host
这里使用 set_fact
模块来设置一个事实变量,然后根据这个变量来决定是否执行角色。
- 使用
ansible_group
变量
- name: Apply lb role to hosts in lb_grouphosts: lb_grouproles:- lb
这里假设 lb_group
是一个包含所有以 lb
开头的主机的组。
这些替代写法提供了不同的方法来实现相同的功能,可以根据具体的需求和场景选择最合适的写法。
测试结果
ansible-playbook 入口文件位置
四、案例-部署所有rsync-client和rsync-server服务
注:
下面的写法有问题:
就算rsync-client写了ansible_hostname is match ‘web*’
由于rsync-server定义了依赖是rsync-client,且ansible_hostname == ‘backup’,所以执行rsync-server时跳转到rsync-client时仍然只会对backup主机执行任务
解决办法:
rsync-server可以不用定义rsync-client依赖
在入口文件这样写:
---
- name: project playhosts: allroles:- role: rsync-serverwhen: ansible_hostname == 'backup'- role: rsync-clientwhen: ansible_hostname is match 'web*'