14-ansible-role角色

官网文档
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html

为什么要用role

在 Ansible 中,Ansible Role(角色)是一种用于组织和重用 Ansible Playbook 代码的强大机制。

它可以将相关的任务、变量、模板、文件等组织在一起,形成一个独立的、可复用的单元,从而提高代码的可维护性和可扩展性。以下从多个方面详细解释 Ansible Role

1. 角色的作用

  • 代码复用:当需要在多个 Playbook 中执行相似的任务时,例如安装和配置 Web 服务器、数据库服务器等,可以将这些任务封装成角色,在不同的 Playbook 中重复使用,避免代码重复编写。
  • 提高可维护性:角色将相关的代码组织在一起,使得代码结构更加清晰。当需要修改某个功能时,只需要在对应的角色中进行修改,而不需要在多个 Playbook 中查找和修改代码。
  • 团队协作:角色可以让不同的团队成员负责不同的功能模块,每个成员专注于自己的角色开发和维护,提高开发效率和代码质量。

2. 角色的目录结构

一个标准的 Ansible Role 具有特定的目录结构,以下是一个典型的角色目录结构示例:

roles/
└── webserver/
    ├── defaults/
    │   └── main.yml
    ├── files/
    ├── handlers/
    │   └── main.yml
    ├── meta/
    │   └── main.yml
    ├── tasks/
    │   └── main.yml
    ├── templates/
    └── vars/
        └── main.yml
- mysqlcluster
  - defualts
  - files
  - xxx

各目录的作用如下:

  • defaults:包含角色的默认变量。这些变量具有最低的优先级,在运行时可以被其他地方定义的同名变量覆盖。
  • files:存放需要复制到目标主机的静态文件,例如配置文件、脚本等。
  • handlers:定义角色的处理程序(Handlers)。处理程序是在任务执行过程中被触发的特殊任务,通常用于重启服务等操作。
  • meta:包含角色的元数据,例如角色的依赖关系、作者信息等。
  • tasks:定义角色的主要任务。这些任务将按顺序执行,是角色的核心部分。
  • templates:存放 Jinja2 模板文件。模板文件可以根据变量动态生成配置文件。

    • nginx.conf
  • vars:包含角色的变量。这些变量的优先级高于 defaults 中的变量。

3. 角色的使用方法

定义角色

要定义一个角色,只需要按照上述目录结构创建相应的目录和文件,并在其中编写任务、变量、模板等代码。例如,在 tasks/main.yml 中定义角色的主要任务:

---
- name: Install Nginx
  apt:
    name: nginx
    state: present

- name: Start Nginx service
  systemd:
    name: nginx
    state: started
    enabled: yes

在 Playbook 中使用角色

在 Playbook 中,可以使用 roles 关键字引用角色。示例如下:

---
- name: Deploy Web Server
  hosts: web_servers
  #become: true
  roles:
    - webserver

在这个 Playbook 中,roles 部分引用了名为 webserver 的角色,Ansible 会自动执行该角色中定义的任务。

传递变量给角色

可以在 Playbook 中为角色传递变量,覆盖角色的默认变量。示例如下:

roles
  webserver/
    vars/
      main.yml 默认定义的变量
---
- name: Deploy Web Server
  hosts: web_servers
  become: true
  roles:
    - role: webserver
      vars:
        nginx_port: 8080

在这个例子中,为 webserver 角色传递了一个变量 nginx_port,并将其值设置为 8080。在角色中可以使用这个变量来动态配置 Nginx 的端口。

4. 角色的依赖关系

角色之间可以存在依赖关系,通过 meta/main.yml 文件来定义。例如,webserver 角色依赖于 common 角色,可以在 webserver/meta/main.yml 中定义依赖关系:

---
dependencies:
  - role: common

当使用 webserver 角色时,Ansible 会自动先执行 common 角色的任务。

5. 角色的分发和共享

Ansible Galaxy 是一个官方的角色库,你可以将自己开发的角色发布到 Ansible Galaxy 上,供其他用户下载和使用。同时,你也可以从 Ansible Galaxy 上下载其他用户共享的角色,方便快速搭建环境。例如,使用 ansible-galaxy 命令下载角色:

ansible-galaxy install geerlingguy.nginx
RHCE 几道题,下载redhat的角色,执行。

这将下载 geerlingguy 用户共享的 nginx 角色到本地。

通过使用 Ansible Role,可以将复杂的自动化任务分解为多个独立的、可复用的模块,提高 Ansible 代码的组织性和可维护性。

之前你部署的nfs、rsync、lsyncd、nginx是如何管理他们的palybook的?

想必是随便放在某一个文件夹里吧

而如果你部署这个备份方案的多个playbook,还使用到了一些额外的文件,如配置文件,网页文件,变量文件等等等,你该怎么管理?不能继续这样随便放,毫无章法吧。

role解决了什么问题

不用role,playbook完成部署。。

Ansible Role 解决了在使用 Ansible 进行自动化运维过程中遇到的诸多问题,以下从代码组织、复用性、可维护性、团队协作等多个方面详细阐述它所解决的问题。

1. 代码组织混乱问题

  • 缺乏结构化:在没有使用角色之前,Ansible Playbook 可能会变得非常庞大和复杂。当需要管理多个不同的服务或系统配置时,所有的任务、变量和模板都混杂在一个或几个 Playbook 文件中,代码结构不清晰,难以理解和管理。
  • Role 的解决方案:Role 提供了一种标准化的目录结构,将相关的任务、变量、模板、文件等组织在一起。例如,将与 Web 服务器相关的任务放在 tasks 目录,默认变量放在 defaults 目录,模板文件放在 templates 目录等。这样可以让代码结构更加清晰,易于导航和维护。j2

2. 代码复用性差问题

  • 重复编写代码:在多个 Playbook 中可能会有很多相似的任务,比如安装和配置 Nginx 服务,每次都需要在不同的 Playbook 中重复编写这些任务的代码,导致代码冗余。
  • Role 的解决方案:可以将这些通用的任务封装成一个 Role,例如创建一个 nginx Role。在不同的 Playbook 中,只需要简单地引用这个 Role 即可,避免了代码的重复编写,提高了代码的复用性。例如: ```yaml

  • name: Deploy Nginx on Server 1 hosts: server1 roles:

    • nginx
  • name: Deploy Nginx on Server 2 hosts: server2 roles:

    • nginx ```

3. 可维护性低问题

  • 修改困难:当代码重复且结构混乱时,一旦某个功能需要修改,比如修改 Nginx 的配置方式,就需要在多个 Playbook 中查找并修改相关代码,容易出现遗漏或不一致的情况,增加了维护的难度和风险。
  • Role 的解决方案:使用 Role 后,只需要在对应的 Role 中进行修改,所有引用该 Role 的 Playbook 都会自动应用这些修改。例如,如果要修改 nginx Role 中的配置任务,只需要在 nginx/tasks/main.yml 文件中进行修改,而不需要在每个使用该 Role 的 Playbook 中修改。

4. 团队协作难题

  • 协作冲突:在团队协作开发中,如果没有清晰的代码组织方式,不同成员可能会同时修改同一个 Playbook 文件,导致代码冲突和混乱。
  • Role 的解决方案:Role 可以让不同的团队成员负责不同的功能模块,每个成员专注于自己的 Role 开发和维护。例如,一个成员负责开发 webserver Role,另一个成员负责开发 database Role,这样可以减少代码冲突,提高团队协作效率。

5. 版本管理和分发问题

  • 难以管理版本:对于复杂的自动化项目,管理代码的版本和分发变得困难。不同的环境可能需要不同版本的代码,手动管理这些版本和分发代码容易出错。
  • Role 的解决方案:可以将 Role 发布到 Ansible Galaxy 等公共仓库或私有仓库中,方便进行版本管理和分发。其他用户可以根据需要下载和使用特定版本的 Role,同时可以使用版本控制工具(如 Git)对 Role 进行管理,确保代码的一致性和可追溯性。

6. 依赖管理问题

  • 依赖不清晰:在复杂的自动化场景中,一个任务可能依赖于其他任务或软件包,手动管理这些依赖关系容易出错,导致自动化脚本执行失败。
  • Role 的解决方案:Role 可以通过 meta/main.yml 文件清晰地定义依赖关系。例如,一个 webapp Role 可能依赖于 nginx Role 和 php Role,在 webapp/meta/main.yml 中可以明确指定这些依赖关系,Ansible 会自动处理这些依赖,确保任务按正确的顺序执行。
把单个的大剧本,拆分为小剧本,便于维护,修改、使用

完成解耦、结构更清晰、调试更方便

在实际的工作当中,一个完整的项目实际上是很多功能体的组合,如果将所有的功能写在一个playbook中会存在如代码耦合程度高、playbook长而维护成本大、灵活性低等一系列的问题。

使用roles能巧妙的解决这一系列的问题。

roles是ansible1.2版本后加入的新功能,适合于大项目playbook的编排架构。

该如何写role

编写 Ansible Role 时,采用正确的技巧和思路能显著提升角色的质量、可维护性和复用性。以下是编写 Ansible Role 的一些实用技巧和思路:

前期规划

明确功能边界

在开始编写 Role 之前,要精准定义该 Role 的功能。例如,如果要创建一个 nginx Role,就需明确它仅负责 Nginx 的安装、配置与启动,还是也涵盖虚拟主机的管理等。功能边界清晰,能避免 Role 过于庞大复杂,提高复用性。

分析依赖关系

确定 Role 所依赖的其他组件或角色。比如,安装 Nginx 可能依赖于特定版本的 OpenSSL,此时就要在 Role 中处理好这些依赖,确保安装过程顺利。

目录结构与文件编写

遵循标准目录结构

按照 Ansible 推荐的标准目录结构组织 Role,如下所示:

roles/
└── role_name/
    ├── defaults/
    │   └── main.yml
    ├── files/
    ├── handlers/
    │   └── main.yml
    ├── meta/
    │   └── main.yml
    ├── tasks/
    │   └── main.yml
    ├── templates/
    └── vars/
        └── main.yml

每个目录都有其特定用途,遵循此结构能让 Role 更易于理解和维护。

编写 defaults/main.yml

在该文件中定义 Role 的默认变量。这些变量应具有通用性,且易于被外部覆盖。例如:

# defaults/main.yml
nginx_port: 80
nginx_user: "www-data"

编写 tasks/main.yml

这是 Role 的核心文件,用于定义主要任务。任务应简洁明了,每个任务都要有清晰的描述。例如:

# tasks/main.yml
- name: Install Nginx
  apt:
    name: nginx
    state: present

- name: Start Nginx service
  systemd:
    name: nginx
    state: started
    enabled: yes

编写 handlers/main.yml

处理程序通常用于重启服务等操作,在配置文件变更时被触发。例如:

# handlers/main.yml
- name: Restart Nginx
  systemd:
    name: nginx
    state: restarted

编写 meta/main.yml

定义 Role 的元数据和依赖关系。例如:

# meta/main.yml
galaxy_info:
  author: your_name
  description: A role to install and configure Nginx
  license: MIT
  min_ansible_version: 2.9

dependencies:
  - role: common
    vars:
      some_variable: value

变量使用与管理

合理使用变量

变量能让 Role 更具灵活性。尽量使用变量来配置 Role 中的关键参数,如软件版本、端口号等。例如:

# tasks/main.yml
- name: Configure Nginx port
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  vars:
    nginx_port: "{{ nginx_port | default(80) }}"
  notify:
    - Restart Nginx

变量优先级管理

了解变量的优先级顺序,如命令行传递的变量优先级最高,defaults 中的变量优先级最低。合理利用这一特性,确保变量值符合预期。

模板使用

采用 Jinja2 模板

对于需要根据不同环境进行定制的配置文件,使用 Jinja2 模板。例如,nginx.conf.j2 模板文件:

# templates/nginx.conf.j2
server {
    listen {{ nginx_port }};
    server_name _;
    ...
}


# nginx.conf.j2
server{
    listen 80;
    server_name www.yuchaoit.cn;
    ...

}

错误处理与测试

错误处理

在任务中添加错误处理机制,如使用 ignore_errorsfailed_when 等参数。例如:

- name: 测试语法
  hosts: localhost
  tasks:
    # tasks/main.yml
    - name: Check Nginx configuration
      shell: nginx -t
      register: nginx_check
      ignore_errors: yes
    - name: 打印注册变量
      debug:
      msg: "{{nginx_check}}"
    - name: Fail if Nginx configuration is invalid
      fail:
        msg: "Nginx configuration is invalid"
      when: nginx_check.rc != 0

测试 Role

编写测试用例对 Role 进行测试。可以使用 Molecule 等工具来自动化测试过程,确保 Role 在不同环境下都能正常工作。

文档编写

详细文档说明

为 Role 编写详细的文档,包括 Role 的功能、使用方法、可用变量及默认值等。良好的文档能让其他用户更容易理解和使用你的 Role。例如:

# Nginx Role

## 功能
该 Role 用于在目标主机上安装、配置和启动 Nginx 服务。

## 使用方法
在 Playbook 中引用该 Role:
```yaml
- name: Deploy Nginx
  hosts: web_servers
  roles:
    - nginx

可用变量

变量名 默认值 描述
nginx_port 80 Nginx 监听端口
nginx_user www-data Nginx 运行用户

通过以上技巧和思路,你可以编写出高质量、可维护且复用性强的 Ansible Role。

ansible-role介绍

ansible.cfg

ansible.cfg 是 Ansible 的主配置文件,用于控制 Ansible 的默认行为。

它允许你自定义 Ansible 的运行方式,例如设置连接参数、调整并行任务数、指定默认路径等。以下是它的核心细节:


1. 配置文件的位置与优先级

Ansible 会按以下顺序查找 ansible.cfg找到的第一个有效文件会被使用

  1. 当前目录./ansible.cfg,剧本,hosts主机清单,相对路径的用法
  2. 用户家目录~/.ansible.cfg
  3. 全局配置/etc/ansible/ansible.cfg

2. 常见配置项

以下是 ansible.cfg 中最常用的配置选项:

基础配置

[defaults]
# 指定默认的 Inventory 文件路径
inventory = ./hosts

# 设置远程用户(默认为当前本地用户名)
remote_user = ubuntu

# 指定 SSH 私钥路径
private_key_file = ~/.ssh/id_rsa

# 是否检查主机密钥(生产环境建议为 True)
host_key_checking = False

# 并行任务数(默认 5,可调高以加速执行)
forks = 20

# 启用或禁用颜色输出
nocolor = 0

SSH 连接优化

[ssh_connection]
# SSH 超时时间(秒)
timeout = 30

# 启用持久连接(提升性能)
pipelining = True
control_path_dir = ~/.ansible/cp

权限提升

[privilege_escalation]
# 是否在远程主机上使用 sudo
become = True

# 默认的提权用户(如 root)
become_user = root

# 提权方法(支持 sudo/su/pbrun 等)
become_method = sudo

# 是否询问 sudo 密码
become_ask_pass = False

日志记录

[logging]
# 启用日志记录
log_path = /var/log/ansible.log

3. 配置示例

[defaults]
inventory = ./my_hosts
remote_user = admin
private_key_file = ~/.ssh/ansible_key
host_key_checking = False
forks = 15

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

[ssh_connection]
pipelining = True
timeout = 20

4. 覆盖默认配置

可以通过以下方式临时覆盖 ansible.cfg 的配置:

  • 命令行参数:例如 ansible-playbook -u user_name playbook.yml
  • 环境变量:例如 export ANSIBLE_FORKS=10
  • Playbook 中定义:在 Playbook 或 Role 中直接设置参数。

5. 注意事项

  1. 敏感信息:避免在 ansible.cfg 中直接存储密码,建议使用 ansible-vault 加密。
  2. 版本控制:如果团队协作,建议将项目相关的 ansible.cfg 添加到 .gitignore 中,防止覆盖他人配置。
  3. 调试配置:使用 ansible-config dump 命令查看当前生效的配置。

通过合理配置 ansible.cfg,可以显著提升 Ansible 的执行效率和易用性。建议根据实际需求调整参数,并在测试环境中验证后再应用到生产环境。

ansible.cfg参考配置

以下是一个综合性的 ansible.cfg 示例,包含常用配置项和优化参数,并附有详细注释。你可以根据实际需求调整配置:

# ansible.cfg - 综合配置示例

[defaults]
# --------------------------
# 基础配置
# --------------------------

# 默认 Inventory 文件路径
# /etc/ansible/hosts

inventory = ./hosts

# 默认远程用户(覆盖环境变量 ANSIBLE_REMOTE_USER)
remote_user = ansible_user

# SSH 私钥路径(如果使用密码认证则无需设置)
private_key_file = ~/.ssh/ansible_id_rsa

# 禁用 SSH 主机密钥检查(生产环境建议启用)
host_key_checking = False

# 并行任务数(根据主机性能调整)
# 根据cpu 2*n+1  
forks = 5

# 禁用颜色输出(调试时可设为 0)
nocolor = 0

# 默认模块路径(自定义模块存放位置)
# module_search_path = ~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules

# 是否显示跳过任务的摘要
display_skipped_hosts = True

# 超时设置(单位:秒)
timeout = 30

# --------------------------
# 错误处理与调试
# --------------------------

# 任务失败后是否继续执行
any_errors_fatal = False

# 允许任务失败百分比(0-100)
max_fail_percentage = 0

# 禁用警告
deprecation_warnings = False
command_warnings = False

# 允许重试文件
retry_files_enabled = True
retry_files_save_path = ./retry-files

[privilege_escalation]
# --------------------------
# 权限提升配置
# --------------------------

# 默认启用提权(sudo)
become = True

# 提权用户
become_user = root

# 提权方法(sudo/su/pbrun等)
become_method = sudo

# 是否询问 sudo 密码
# 方案客户端用户,paralles 免密sudo
become_ask_pass = False

# 提权后保留环境变量
become_flags = -E

[ssh_connection]
# --------------------------
# SSH 连接优化
# --------------------------

# 启用管道加速(禁用 requiretty 时使用)
pipelining = True

# 控制持久连接复用路径
control_path_dir = ~/.ansible/cp
control_path = %(directory)s/%%h-%%p-%%r

# SSH 参数优化
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ServerAliveInterval=15

# 禁用 SSH 压缩(网络带宽充足时可启用)
# compress = False

[persistent_connection]
# --------------------------
# 持久连接配置
# --------------------------

# 连接保持时间(秒)
connect_timeout = 30
command_timeout = 30

[galaxy]
# --------------------------
# Ansible Galaxy 配置
# --------------------------

# Galaxy 服务器地址
# server_list = galaxy.ansible.com, automation_hub_url

# 角色安装路径
roles_path = ~/.ansible/roles:/usr/share/ansible/roles

[logging]
# --------------------------
# 日志记录
# --------------------------

# 启用日志记录(需要写权限)
log_path = ./ansible.log

# 日志轮转(需配合外部工具如 logrotate)
# max_log_size = 1024000
# log_rotate = 7

[callback_profiles]
# --------------------------
# 回调插件配置
# --------------------------

# 启用任务计时插件
callback_whitelist = profile_tasks, timer

# 输出格式美化
# stdout_callback = yaml

[inventory]
# --------------------------
# Inventory 扩展配置
# --------------------------

# 启用动态 Inventory 缓存
cache = True
cache_plugin = jsonfile
cache_timeout = 86400  # 24 小时
cache_connection = ./inventory_cache

[selinux]
# --------------------------
# SELinux 特殊配置
# --------------------------

# 禁用 SELinux 相关模块的特殊处理
# special_context_filesystems = nfs, cifs, ...

[colors]
# --------------------------
# 输出颜色定制
# --------------------------

# 自定义颜色方案(调试使用)
# highlight = white
# verbose = blue
# warn = bright purple
# error = red
# debug = dark gray
# changed = yellow
# ok = green

[fact_caching]
# --------------------------
# Fact 缓存配置
# --------------------------

# 启用 Fact 缓存(提升执行速度)
fact_caching = jsonfile
fact_caching_connection = ./fact_cache
fact_caching_timeout = 86400  # 24 小时

配置说明与使用建议

  1. 文件存放位置

    • 建议将配置文件放在项目根目录,与 playbooks/hosts 文件同级
    • 优先级:当前目录 > 用户目录 > 全局配置
  2. 覆盖配置示例

    # 临时指定 Inventory 文件
    ansible-playbook -i production/hosts playbook.yml
    
    # 覆盖远程用户
    ansible-playbook -u deploy_user playbook.yml
    
    # 禁用提权
    ansible-playbook --become=no playbook.yml
    
  3. 性能优化重点

    • forks:根据控制机 CPU 和内存调整
    • pipelining:需在目标机 /etc/sudoers 中禁用 requiretty
    • fact_caching:适合基础设施变动少的场景
  4. 安全建议

    • 生产环境建议启用 host_key_checking
    • 敏感信息(如密码)建议使用 ansible-vault 加密
    • 日志文件(ansible.log)需定期清理
  5. 调试技巧

    # 查看最终生效的配置
    ansible-config dump --only-changed
    
    # 检查 SSH 连接
    ansible all -m ping -vvv
    

扩展场景配置

如果需要以下功能,可取消注释相应配置:

  • Galaxy 私有仓库:配置 server_list
  • 自定义模块/插件:配置 module_search_path
  • SELinux 特殊配置:调整 special_context_filesystems
  • 日志轮转:需配合系统 logrotate 工具

根据实际需求灵活调整即可!

roles配置目录

role、角色用于层次化、结构化的组织多个playbook。

role主要的作用是可以单独的通过一个有组织的结构、通过单独的目录管理如变量、文件、任务、模块、以及处理任务等,并且可以通过include导入使用这些目录。

roles主要依赖于目录的命名和摆放,默认tasks/main.yml是所有任务的人口,使用roles的过程也可以认为是目录规范化命名的过程。

roles每个目录下均由main.yml定义该功能的任务集,tasks/main.yml默认执行所有定义的任务;

roles目录建议放在ansible.cfg中”roles_path”定义的目录下。

[root@master-61 /etc/ansible/roles]#grep 'roles_path' /etc/ansible/ansible.cfg 
#roles_path    = /etc/ansible/roles

Role默认执行目录

Ansible 在运行 Playbook 时会自动在以下目录中查找 Role:

  • 当前 Playbook 所在目录的 ./roles/ 子目录。
  • 配置文件中指定的 roles_path(如 ~/.ansible/ansible.cfg 中的 roles_path)。

角色目录规划

Ansible Role 有一套标准的目录结构,它将不同类型的文件和配置项进行了合理的分类,使得角色的管理、维护和复用变得更加方便。以下是详细的角色目录规划及各部分的作用:

标准角色目录结构

roles/
└── <role_name>/
    ├── defaults/
    │   └── main.yml
    ├── files/
    ├── handlers/
    │   └── main.yml
    ├── meta/
    │   └── main.yml
    ├── tasks/
    │   └── main.yml
    ├── templates/
    ├── tests/
    │   ├── inventory
    │   └── test.yml
    └── vars/
        └── main.yml

各目录及文件说明

1. defaults 目录

  • 用途:存放角色的默认变量。这些变量具有最低的优先级,在运行时可以被其他地方定义的同名变量覆盖。通常用于设置一些通用的、可被用户自定义的参数。
  • 示例文件defaults/main.yml
    # 定义 Nginx 服务的默认监听端口
    nginx_port: 80
    # 定义 Nginx 运行的默认用户
    nginx_user: "www-data"
    

2. files 目录

  • 用途:存放需要复制到目标主机的静态文件,例如配置文件、脚本等。这些文件在复制过程中不会进行内容的动态替换。
  • 示例场景:如果你有一个自定义的 nginx.conf 文件需要部署到目标主机,可以将其放在该目录下。

3. handlers 目录

  • 用途:定义角色的处理程序(Handlers)。处理程序是在任务执行过程中被触发的特殊任务,通常用于重启服务、重新加载配置等操作。只有当与之关联的任务的状态为 changed 时,处理程序才会被执行。
  • 示例文件handlers/main.yml ```yaml
  • name: Restart Nginx systemd: name: nginx state: restarted ```

4. meta 目录

  • 用途:包含角色的元数据,如角色的作者信息、描述、依赖关系等。依赖关系的定义可以确保在使用该角色时,其依赖的其他角色会被先执行。
  • 示例文件meta/main.yml ```yaml galaxy_info: author: your_name description: A role to install and configure Nginx license: MIT min_ansible_version: 2.9

dependencies:

  • role: common vars: some_variable: value ```

5. tasks 目录

  • 用途:定义角色的主要任务。这些任务将按顺序执行,是角色的核心部分。任务可以调用各种 Ansible 模块来完成具体的操作,如安装软件、创建文件等。
  • 示例文件tasks/main.yml ```yaml
  • name: Install Nginx apt: name: nginx state: present

  • name: Start Nginx service systemd: name: nginx state: started enabled: yes ```

6. templates 目录

  • 用途:存放 Jinja2 模板文件。模板文件可以根据变量动态生成配置文件,使得配置文件可以根据不同的环境或需求进行定制。
  • 示例场景:一个动态生成的 nginx.conf.j2 模板文件,根据 nginx_port 变量来设置监听端口。
    server {
      listen ;
      server_name _;
      ...
    }
    

7. tests 目录

  • 用途:用于存放角色的测试相关文件,包括测试用的清单文件(inventory)和测试 Playbook(test.yml)。可以使用工具如 Molecule 结合这些文件对角色进行自动化测试,确保角色在不同环境下都能正常工作。
  • 示例文件
    • tests/inventory:定义测试用的主机清单。
    • tests/test.yml:包含用于测试角色功能的任务。

8. vars 目录

  • 用途:包含角色的变量。这些变量的优先级高于 defaults 中的变量,但低于命令行传递的变量和在 Playbook 中定义的变量。通常用于设置一些与角色紧密相关,但又不适合作为默认值的变量。
  • 示例文件vars/main.yml
    # 定义 Nginx 配置文件的路径
    nginx_conf_path: "/etc/nginx/nginx.conf"
    

通过遵循这样的目录规划,你可以更清晰地组织 Ansible Role 的代码,提高角色的可维护性和复用性。

先来看一个role的结构化目录吧。

一个完整的roles是由task、handlers、files、vars、templates、meta等一系列目录组成,各目录存放不同的文件实现不同的功能,在调用时直接下文件名即可调用。

参考官网即可,且必须按照如下的目录格式来,不是随便定义的
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html#role-directory-structure

Ansible 角色具有定义的目录结构,其中包含八个主要的标准目录。您必须在每个角色中至少包含其中一个目录。您可以省略角色不使用的任何目录。例如如下的官网示例

# playbooks
site.yml
webservers.yml
fooservers.yml
roles/
    common/
        tasks/
        handlers/
        library/
        files/
        templates/
        vars/
        defaults/
        meta/
    webservers/
        tasks/
        defaults/
        meta/

默认情况下,Ansible 将在角色中的每个目录中main.yml查找相关内容的文件(也main.yamlmain):

  • tasks/main.yml- 角色执行的任务的主要列表。
  • handlers/main.yml- 处理程序,可以在此角色内部或外部使用。
  • library/my_module.py- 可在此角色中使用的模块(有关更多信息,请参阅在角色中嵌入模块和插件)。
  • defaults/main.yml- 角色的默认变量(有关更多信息,请参阅使用变量)。这些变量在所有可用变量中具有最低优先级,并且可以很容易地被任何其他变量(包括库存变量)覆盖。
  • vars/main.yml- 角色的其他变量(有关更多信息,请参阅使用变量)。
  • files/main.yml- 角色部署的文件。
  • templates/main.yml- 角色部署的模板。
  • meta/main.yml- 角色的元数据,包括角色依赖项。

role部署nginx

下面为你详细介绍使用 Ansible Role 部署 Nginx 的完整案例,包含角色的目录结构、各文件内容及使用方法。

1. 创建角色目录结构

首先,创建一个名为 nginx 的角色目录,其标准结构如下:

root@ansible-01:~/ansible_roles# mkdir -p  roles/{defaults,files,handlers,meta,tasks,templates,vars}

roles/
└── nginx/
    ├── defaults/
    │   └── main.yml
    ├── files/
    ├── handlers/
    │   └── main.yml
    ├── meta/
    │   └── main.yml
    ├── tasks/
    │   └── main.yml
    ├── templates/
    └── vars/
        └── main.yml

2. 编写各目录下的文件

defaults/main.yml

此文件用于定义角色的默认变量,可被外部变量覆盖。

# 定义 Nginx 监听端口
nginx_port: 35555
# 定义 Nginx 运行的用户
nginx_user: "www-data"

handlers/main.yml

该文件定义处理程序,在配置文件变更时触发服务重启。

- name: Restart Nginx
  systemd:
    name: nginx
    state: restarted

meta/main.yml

此文件包含角色的元数据和依赖关系。

galaxy_info:
  author: Your Name
  description: A role to install and configure Nginx
  license: MIT
  min_ansible_version: 2.9

dependencies: []

tasks/main.yml

这是角色的核心文件,定义主要任务。

- name: Update apt cache (for Ubuntu)
  apt:
    update_cache: yes
    cache_valid_time: 3600
  when: ansible_os_family == "Debian"

- name: Install Nginx (for Ubuntu)
  apt:
    name: nginx
    state: present
  when: ansible_os_family == "Debian"

- name: Install Nginx (for CentOS)
  yum:
    name: nginx
    state: present
  when: ansible_os_family == "RedHat"

- name: Create Nginx configuration from template
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify:
    - Restart Nginx

- name: Start Nginx service
  systemd:
    name: nginx
    state: started
    enabled: yes

templates/nginx.conf.j2

该模板文件根据变量动态生成 Nginx 配置文件。

user {{ nginx_user }};
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    server {
        listen       {{ nginx_port }};
        server_name  _;

        location / {
            root   /var/www/html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /var/www/html;
        }
    }
}

vars/main.yml

这里可定义一些特定于角色的变量。

# 定义 Nginx 配置文件的路径
nginx_conf_path: "/etc/nginx/nginx.conf"

3. 使用角色的 Playbook

创建一个 Playbook 文件(例如 deploy_nginx.yml)来使用这个角色。

启动钥匙,找到roles入口,启动

---
- name: 部署nginx的角色
  hosts: web
  become: true
  roles:
    - mynginx

4. 运行 Playbook

假设你的主机清单文件为 hosts.ini,包含 web_servers 主机组,可使用以下命令运行 Playbook:

ansible-playbook -i hosts.ini deploy_nginx.yml

说明

  • 兼容性:上述案例考虑了 Ubuntu(Debian 系)和 CentOS(RedHat 系)系统,根据 ansible_os_family 变量选择合适的包管理工具进行 Nginx 安装。
  • 变量覆盖:如果需要修改默认的 nginx_portnginx_user 变量,可以在 Playbook 中传递新的变量值,例如: ```yaml

  • name: Deploy Nginx hosts: web_servers become: true roles:
    • role: nginx vars: nginx_port: 8080 nginx_user: "nginxuser" ```

通过以上步骤,你可以使用 Ansible Role 方便地在多台主机上部署和配置 Nginx。

role综合案例

# yuchaoit.cn  ansible-role
site.yml                    # role入口
nfs_servers.yml             # role
rsync_servers.yml           # role
roles/                      # role规范目录结构
    nfs_servers/            # role具体名字
        tasks/              # 剧本任务
        handlers/           # 剧本里存放的handlers
        files/              # 如压缩文件,如需要拷贝的文件
        templates/          # 存放配置文件
        vars/               # 存放变量文件
    rsync_servers/
        tasks/
        handlers/
        files/
        templates/
        vars/

img

实践1:部署rsyncd服务

0.思路

1.写好剧本
2.创建角色的目录结构
3.拷贝需要操作的文件对应的结构目录下
4.拆分剧本

1.rsync剧本

纯剧本版,不拆分roles的方案。

- hosts: localhost
  vars:
    user_id: '4444'
    rsync_user: 'u_rsync'
  tasks:
  - name: 01_create_group
    group:
      name: "{{ rsync_user }}"
      gid: "{{ user_id }}"
  - name: 02_create_user
    user:
      name: "{{ rsync_user }}"
      uid: "{{user_id}}"
      group: "{{ rsync_user}}"
      create_home: no
      shell: /sbin/nologin

  # 3.创建数据目录且授权
  - name: 03_createUdata
    file:
      path: "{{ item }}"
      state: directory
      owner: "{{ rsync_user }}"
      group: "{{ rsync_user }}"
      mode: "0755"
    loop:
      - /data
      - /backup
  # 4.安装rsync软件
  - name: 04_install_rsync
    apt:
      name: rsync
      state: latest
  # 5.复制配置文件与密码文件
  - name: 05_copy_config
    copy:
      src: "{{ item.t_src }}"
      dest: /etc/
      mode: "{{ item.t_mode }}"
    notify:
      - restart_rsyncd
    loop:
      - { t_src: /script/rsyncd.conf,t_mode: '0644'}
      - { t_src: /script/rsync.passwd,t_mode: '0600'}

  # 6.启动服务
  - name: 06_start_rsync
    systemd:
      name: rsync
      state: started
      enabled: yes
  # 7.重启服务
  handlers:
    - name: restart_rsyncd
      systemd:
        name: rsyncd
        state: restarted

2.创建role结构目录

[root@master-61 /etc/ansible/roles]#mkdir -p  rsync_server/{tasks,handlers,files,templates,vars}
[root@master-61 /etc/ansible/roles]#tree
.
└── rsync_server
    ├── files
    ├── handlers
    ├── tasks
    ├── templates
    └── vars

6 directories, 0 files
[root@master-61 /etc/ansible/roles]#

3.创建playbook到tasks目录

任务么,就是安装rsync服务,生成main.yml即可

tasks/main.yml


- name: 01_create_group
  group:
    name: "{{ rsync_user }}"
    gid: "{{ user_id }}"
- name: 02_create_user
  user:
    name: "{{ rsync_user }}"
    uid: "{{user_id}}"
    group: "{{ rsync_user}}"
    create_home: no
    shell: /sbin/nologin

# 3.创建数据目录且授权
- name: 03_createUdata
  file:
    path: "{{ item }}"
    state: directory
    owner: "{{ rsync_user }}"
    group: "{{ rsync_user }}"
    mode: "0755"
  loop:
    - /data
    - /backup
# 4.安装rsync软件
- name: 04_install_rsync
  apt:
    name: rsync
    state: latest
# 5.复制配置文件与密码文件
- name: 05_copy_config
  copy:
    src: "{{ item.t_src }}"
    dest: /etc/
    mode: "{{ item.t_mode }}"
  notify:
    - restart_rsyncd
  loop:
    - { t_src: rsyncd.conf,t_mode: '0644'}
    - { t_src: rsync.passwd,t_mode: '0600'}

# 6.启动服务
- name: 06_start_rsync
  systemd:
    name: rsync
    state: started
    enabled: yes

4. 配置文件放入到files目录

files目录结构

[root@master-61 /etc/ansible/roles/rsync_server/tasks]#tree /etc/ansible/roles/rsync_server/
/etc/ansible/roles/rsync_server/
├── files
│   ├── rsyncd.conf
│   └── rsync.passwd
├── handlers
├── tasks
│   └── main.yml
├── templates
└── vars

5 directories, 3 files

Rsync.passwd

[root@master-61 /etc/ansible/roles/rsync_server]#cat files/rsync.passwd 
rsync_backup:yuchao666

rsyncd.conf

[root@master-61 /etc/ansible/roles/rsync_server]#cat files/rsyncd.conf
uid = u_rsync 
gid = u_rsync 
port = 873
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = rsync_backup
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log
[mybackup]
comment = chaoge rsync backup!
path = /backup
[data]
comment = yuchaoit.cn rsync!
path = /data

5.拆分handlers

rsync用到的handlers就是在修改完配置文件后,必须要重启这个任务

原本写在单个的大剧本中,现在可以单独写出来然后维护

[root@master-61 /etc/ansible/roles/rsync_server]#cat  handlers/main.yml
- name: restart_rsyncd
  systemd:
    name: rsyncd
    state: restarted

6.拆分vars

提取出安装rsync脚本中使用到的变量,如用户信息

[root@master-61 /etc/ansible/roles/rsync_server]#cat vars/main.yml 
user_id: '4444'
rsync_user: 'u_rsync'

7. 优化tasks任务文件main.yml

超哥教你写role的口诀

  • 该拆的全给拆开

  • 如何拆,以role提供的目录结构拆,对应着拆

    • 对应的目录填入对应的数据
    • 内容需要反复写的定义为变量
    • 如果要填写多个数据,如文件列表,可以写loop循环
# 1.创建www组
- name: 01_create_group
  group:
    name: "{{rsync_user}}"
    gid: "{{user_id}}"

# 2.创建www用户
- name: 02_create_user
  user:
    name: "{{rsync_user}}"
    uid: "{{user_id}}"
    group: "{{rsync_user}}"
    create_home: no
    shell: /sbin/nologin

# 3.创建数据目录并更改授权
- name: 03_create_data
  file:
    path: "{{item}}"
    state: directory
    owner: "{{rsync_user}}"
    group: "{{rsync_user}}"
    mode: '755'
  loop:
    - /data
    - /backup/


# 4.安装rsync软件
- name: 04_install_rsync
  yum:
    name: rsync
    state: latest

# 5.复制文件
- name: 05-copy config
  copy:
    src: "{{item.src}}"
    dest: /etc
    mode: "{{item.mode}}"

  notify:
    - restart rsyncd
  loop:
    - {src: rsyncd.conf,mode: '644'}
    - {src: rsync.passwd,mode: '600'}

# 6. 启动服务
- name: start service
  systemd:
    name: rsync
    state: started
    enabled: yes

8.编写启动role文件

  • 注意启动文件的路径,和roles平级
  • 最终是以tasks/main.yml作为入口
[root@master-61 /etc/ansible]#cat /etc/ansible/rsync_server.yml 
- hosts: backup
  roles:
    - rsync_server

9.检查roles所有文件

[root@master-61 /etc/ansible]#tree /etc/ansible/roles/rsync_server/
/etc/ansible/roles/rsync_server/
├── files
│   ├── rsyncd.conf
│   └── rsync.passwd
├── handlers
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
└── vars
    └── main.yml

5 directories, 5 files

10.调试运行role

[root@master-61 /etc/ansible]#ansible-playbook -C rsync_server.yml

实际执行,安装rsync服务

[root@master-61 /etc/ansible]#ansible-playbook  rsync_server.yml

至此,关于安装rsync服务的roles已经写好了,主要就是区别于纯手写plabook,解决纯playbook的问题

  • 提供files、handlers、tasks、vars单独放置各自需要的yaml
  • 把一个臃肿的大playbook,拆成小部分,分门别类的管理。

实践3: 部署nfs服务

1.思路

1.拷贝nfs服务端配置文件,生成templates目录下的j2模板文件,用于变量替换配置文件信息
2.编写handlers
3.编写tasks
4.编写vars
5.编写role启动文件

2.创建role目录结构

[root@master-61 /etc/ansible/roles]#mkdir nfs_server/{tasks,handlers,files,templates,vars} -p

3.创建jinja模板文件

[root@master-61 /etc/ansible/roles]#cat nfs_server/templates/exports.j2 
/data {{ server_ip }}(rw,sync)

4.创建变量文件

[root@master-61 /etc/ansible/roles]#cat nfs_server/vars/main.yml 
server_ip: '10.211.55.0/24'
nfs_user: "tnfs"
nfs_uid: 7777

5.编写handlers文件

[root@master-61 /etc/ansible/roles]#cat  nfs_server/handlers/main.yml
- name: restart_nfs
  systemd: 
    name: nfs-server
    state: restarted

6.编写tasks任务文件

[root@master-61 /etc/ansible/roles]#vim nfs_server/tasks/main.yml

# 1.创建www组
- name: 01-add group
  group:
    name: "{{nfs_user}} "
    gid: "{{nfs_uid}}"
# 2.创建www用户
- name: 02-useradd
  user: 
    name: "{{nfs_user}} " 
    create_home: no
    shell: /sbin/nologin
    uid: "{{nfs_uid}}"
# 3.安装nfs
- name: 03-nfs install
  apt: 
    name: nfs-server
    state: latest
# 4.拷贝配置文件 templates/exportfs.j2
# copy. files/exports
- name: 04-cp
  template:
    src: exports.j2
    dest: /etc/exports
  notify:
    - restart_nfs

# 5.创建数据目录且授权
- name: create data dir 
  file:
    path: "{{ item }}"
    state: directory
    owner: "{{nfs_user}}"
    group: "{{nfs_user}}"
    mode: '0755'
  loop:
    - /data
    - /backup

# 6. 启动rpcbind服务
- name: start rpcbind
  service:
    name: rpcbind
    state: started
    enabled: yes

# 7.启动nfs服务
- name: start nfs
  service: 
    name: nfs-server
    state: started
    enabled: yes

7.编写启动role文件

注意就是roles的值,和roles目录下的文件夹对应

[root@master-61 /etc/ansible/roles]#cat /etc/ansible/nfs_server.yml 
- hosts: nfs
  roles:
    - nfs_server

8.测试role执行

[root@master-61 /etc/ansible/roles]#ansible-playbook -C /etc/ansible/nfs_server.yml

总结roles角色用法

1.roles有固定的格式,需要创建固定的文件夹结构,以及每个文件夹都对应的固定的作用
2.写roles其实就是改造、拆分以前写的部署服务的playbook
3.最后就是注意细节,语法,别敲错了单词,出错了看日志报错,对应出错的文件,按照正确规则,编写即可
4.动手练习,完成rsyncd,nfs,sshd服务的部署,理解roles的用法

生产环境下的ansible-role

给大家看看于超老师维护的role,了解下为什么让你学role,以及给你讲解这些知识点,理解role的目录结构。

1.ansible总目录

image-20220514135803421

2.涉及的组件列表

也就30多个吧,花一个月把剧本全看明白就行了,没什么高级用法,都是超哥讲解的ansible模块,以及那些高级语法。

  • ansible模块
  • playbook语法、yaml、高级语法
  • role规范

image-20220514140646937

3.听超哥指挥,能打胜仗

我说的对吗 老铁们。

[汗]这个图的意思就是想告诉你们,工作里的运维部署内容,必然会更复杂,更多,但是只要你把课堂上讲的语法学会,作业做出来,就能搞定工作里的活。也就是我贴的这个图,里面的语法应该是能看懂的吧。

然后就是拿着这个剧本去部署公司的产品,出了问题,自己要会修改这个剧本

4.例如安装mysql的角色

以下是一个用于在生产环境中部署和配置 MySQL 的 Ansible Role 案例,包含了详细的目录结构、各文件内容及使用说明。

1. 角色目录结构

mkdir -p mysql/{defaults,files,handlers,mate,tasks,templates,vars}
roles/
└── mysql/
    ├── defaults/
    │   └── main.yml
    ├── files/
    ├── handlers/
    │   └── main.yml
    ├── meta/
    │   └── main.yml
    ├── tasks/
    │   └── main.yml
    ├── templates/
    └── vars/
        └── main.yml

2. 各目录及文件详细内容

defaults/main.yml

定义角色的默认变量,可在使用角色时被覆盖。

# MySQL 版本,可根据实际需求修改
mysql_version: 8.0
# MySQL root 用户密码
#mysql_root_password: "default_root_password"
# MySQL 数据目录
mysql_data_dir: "/var/lib/mysql"
# MySQL 配置文件路径
mysql_conf_path: "/etc/mysql/mysql.conf.d/mysqld.cnf"

handlers/main.yml

定义处理程序,用于在 MySQL 配置文件变更时重启服务。

- name: Restart MySQL
  systemd:
    name: mysql
    state: restarted

meta/main.yml

包含角色的元数据和依赖关系。

galaxy_info:
  author: Your Name
  description: A role to install and configure MySQL in production environment
  license: MIT
  min_ansible_version: 2.9

dependencies: []

tasks/main.yml

角色的核心任务文件,包含安装、配置和初始化 MySQL 的任务。

- name: Update apt cache (for Ubuntu)
  apt:
    update_cache: yes
    cache_valid_time: 3600
  when: ansible_os_family == "Debian"

- name: Install MySQL (for Ubuntu)
  apt:
    name: "mysql-server-{{ mysql_version }}"
    state: present
  when: ansible_os_family == "Debian"

- name: Install MySQL (for CentOS)
  yum:
    name: "mysql-server-{{ mysql_version }}"
    state: present
  when: ansible_os_family == "RedHat"

- name: Create MySQL configuration from template
  template:
    src: mysqld.cnf.j2
    dest: "{{ mysql_conf_path }}"
  notify:
    - Restart MySQL

- name: Start and enable MySQL service
  systemd:
    name: mysql
    state: started
    enabled: yes

templates/mysqld.cnf.j2

Jinja2 模板文件,用于生成 MySQL 配置文件。

[mysqld]
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = {{ mysql_data_dir }}
log-error       = /var/log/mysql/error.log
bind-address    = 0.0.0.0

# 字符集设置
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# 其他配置参数,可根据生产环境需求调整
max_connections = 200
innodb_buffer_pool_size = 512M

vars/main.yml

定义特定于角色的变量,可覆盖默认变量。

# 可根据实际情况添加更多特定变量

3. 使用该角色的 Playbook

创建一个名为 deploy_mysql.yml 的 Playbook 文件来使用这个角色。

---
- name: Deploy MySQL in production
  hosts: localhost
  become: true
  roles:
    - mysql

4. 运行 Playbook

假设你的主机清单文件为 hosts.ini,其中包含 mysql_servers 主机组,使用以下命令运行 Playbook:

ansible-playbook -i hosts.ini deploy_mysql.yml

注意事项和说明

  • 兼容性:该案例同时支持 Ubuntu(Debian 系)和 CentOS(RedHat 系)系统,根据 ansible_os_family 变量选择合适的包管理工具进行 MySQL 安装。
  • 密码安全:在实际生产环境中,建议使用 Ansible Vault 来加密敏感信息,如 mysql_root_password,以提高安全性。
  • 配置调整templates/mysqld.cnf.j2 中的配置参数可根据生产环境的具体需求进行调整,如 max_connectionsinnodb_buffer_pool_size 等。
  • 错误处理:在 tasks/main.yml 中,mysql_secure_installation 任务使用了 ignore_errors: true,这是因为在某些情况下,如已经进行过安全初始化,再次执行可能会报错。你可以根据实际情况调整错误处理逻辑。

通过以上步骤,你可以使用 Ansible Role 在生产环境中高效地部署和配置 MySQL。

image-20220514142724348

Jinja2

下面为你提供一个 Ansible Playbook 结合 Jinja2 的完整案例,此案例用于在多台服务器上部署并配置 Nginx,借助 Jinja2 模板动态生成 Nginx 配置文件。

1. 项目结构

ansible-project/
├── inventory.ini
├── nginx-playbook.yml
├── roles/
│   └── nginx/
│       ├── defaults/
│       │   └── main.yml
│       ├── templates/
│       │   └── nginx.conf.j2
│       └── tasks/
│           └── main.yml

2. 各文件详细内容

inventory.ini

该文件定义了目标主机列表。

[web_servers]
server1.example.com
server2.example.com

nginx-playbook.yml

这是主 Playbook 文件,用于调用 nginx 角色。

---
- name: Deploy and Configure Nginx
  hosts: web_servers
  become: true
  roles:
    - nginx

roles/nginx/defaults/main.yml

此文件定义了 nginx 角色的默认变量。

nginx_port: 80
nginx_server_name: _
nginx_root_dir: /var/www/html

roles/nginx/templates/nginx.conf.j2

这是 Jinja2 模板文件,用于生成 Nginx 配置文件。

user www-data;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    server {
        listen       {{ nginx_port }};
        server_name  {{ nginx_server_name }};

        location / {
            root   {{ nginx_root_dir }};
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   {{ nginx_root_dir }};
        }
    }
}

roles/nginx/tasks/main.yml

该文件定义了 nginx 角色的主要任务。

- name: Install Nginx
  apt:
    name: nginx
    state: present
  when: ansible_os_family == "Debian"

- name: Install Nginx
  yum:
    name: nginx
    state: present
  when: ansible_os_family == "RedHat"

- name: Generate Nginx configuration file
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify:
    - Restart Nginx

- name: Start and enable Nginx service
  systemd:
    name: nginx
    state: started
    enabled: yes

handlers:
  - name: Restart Nginx
    systemd:
      name: nginx
      state: restarted

3. 案例说明

  • 变量传递:在 roles/nginx/defaults/main.yml 中定义了默认变量,这些变量可在 Jinja2 模板 nginx.conf.j2 中使用。如果需要修改默认值,可在 Playbook 中通过 vars 关键字传递新的变量值。
  • 模板生成roles/nginx/tasks/main.yml 中的 template 模块会使用 Jinja2 引擎将 nginx.conf.j2 模板文件根据变量动态生成实际的 Nginx 配置文件,并复制到目标主机的 /etc/nginx/nginx.conf 路径。
  • 服务管理:使用 systemd 模块启动并启用 Nginx 服务,当配置文件发生变化时,会触发 Restart Nginx 处理程序重启服务。

4. 运行 Playbook

在项目根目录下,使用以下命令运行 Playbook:

ansible-playbook -i inventory.ini nginx-playbook.yml

通过这个案例,你可以看到如何利用 Ansible Playbook 结合 Jinja2 模板动态生成配置文件,实现自动化部署和配置。

Jinja2案例

以下是一个基于 Ansible + Jinja2 的 Web 服务器部署运维业务案例教程,包含完整的代码示例和操作说明:


案例目标

使用 Ansible Playbook 结合 Jinja2 模板:

  1. 自动化部署 Nginx Web 服务器
  2. 动态生成 Nginx 配置文件(含多环境支持)
  3. 管理网站静态资源

环境准备

组件 版本
Ansible 2.10+
Jinja2 内置(Ansible自带)
被管理节点 Ubuntu 20.04 x2

控制节点配置(ansible-control)

# 安装Ansible
pip install ansible

# 配置SSH免密登录(需提前生成密钥)
ssh-copy-id -i ~/.ssh/id_rsa.pub user@node1
ssh-copy-id -i ~/.ssh/id_rsa.pub user@node2

Ansible Playbook 结构

mkdir nginx-deploy
cd nginx-deploy
tree
├── inventory.ini          # 主机组定义
├── group_vars/             # 全局变量
│   └── all.yml             # 环境变量
├── roles/                  # 角色目录
│   ├── common/             # 通用任务
│   │   └── tasks/main.yml
│   └── nginx/              # Nginx角色
│       ├── defaults.yml    # 默认变量
│       ├── handlers/main.yml # 服务处理
│       └── tasks/main.yml    # 主要任务
└── site.yml                # 主Playbook

1. 配置 Inventory

inventory.ini

[webservers]
node1 ansible_host=192.168.1.100
node2 ansible_host=192.168.1.101

[nginx_servers:vars]
env = production  # 可设置为 development/test
domain = example.com
static_root = /var/www/example.com

2. 编写 Jinja2 模板

roles/nginx/templates/nginx.conf.j2

user  nginx;
worker_processes  auto;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    server {
        listen       {{ nginx_port }};
        server_name  {{ domain }}{% if env == 'production' %} .{{ domain }}{% endif %};

        location /static/ {
            root   {{ static_root }};
            expires max;
        }

        {% if env == 'production' %}
        location / {
            proxy_pass http://backend-server;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
        {% else %}
        location / {
            root   {{ static_root }};
        }
        {% endif %}
    }
}

3. 定义 Variables

group_vars/all.yml

nginx_port: 80

nginx_packages:
  - nginx
  - certbot

static_files:
  - index.html
  - style.css
  - script.js

roles/nginx/defaults.yml

nginx_conf_path: /etc/nginx/nginx.conf
ssl_cert_path: /etc/letsencrypt/live/{{ domain }}/fullchain.pem
ssl_key_path: /etc/letsencrypt/live/{{ domain }}/privkey.pem

4. 编写 Tasks

roles/nginx/tasks/main.yml

- name: Install Nginx packages
  ansible.builtin apt:
    name: "{{ item }}"
    state: present
  with_items: "{{ nginx_packages }}"

- name: Deploy static files
  ansible.builtin.copy:
    src: "{{ role_path }}/files/{{ item }}"
    dest: "{{ static_root }}/{{ item }}"
  with_items: "{{ static_files }}"

- name: Generate Nginx configuration
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: "{{ nginx_conf_path }}"
    owner: root
    group: root
    mode: '0644'

- name: Reload Nginx service
  ansible.builtin.service:
    name: nginx
    state: reloaded

5. 完整 Playbook

site.yml

- name: Deploy Nginx with Jinja2
  hosts: webservers
  become: yes
  roles:
    - common
    - nginx

6. 静态文件示例

roles/nginx/files/index.html

<!DOCTYPE html>
<html>
<head>
    <title>{{ domain }} - {{ env }}</title>
    <link rel="stylesheet" href="/static/style.css">
</head>
<body>
    <h1>Welcome to {{ domain }}!</h1>
    <script src="/static/script.js"></script>
</body>
</html>

7. 执行 Playbook

ansible-playbook site.yml -i inventory.ini

关键功能验证

  1. 动态配置生成

    cat /etc/nginx/nginx.conf | grep server_name
    # 输出: server_name example.com .example.com(生产环境)
    
  2. 静态文件部署

    ls /var/www/example.com/
    # 应显示 index.html style.css script.js
    
  3. 服务状态检查

    systemctl status nginx
    # 状态应为 active (running)
    

高级技巧扩展

  1. 多环境支持

    # 修改 inventory 中的 env 变量:
    ansible-playbook site.yml -i inventory.ini --extra-vars "env=staging"
    
  2. 条件判断模板

    
    
    
  3. 循环配置虚拟主机

    
    
    

总结

通过 Ansible + Jinja2 的组合可以实现:

  • 零接触部署:无需手动登录服务器
  • 配置一致性:消除人工操作的差异
  • 版本可控:所有配置文件版本化管理
  • 灵活扩展:轻松支持多环境/多站点部署

建议后续学习方向:

  1. Ansible Vault 加密敏感数据
  2. 结合 Git 实现配置版本控制
  3. 使用 AWX 构建可视化运维平台
Copyright © www.yuchaoit.cn 2025 all right reserved,powered by Gitbook作者:于超 2025-02-28 20:08:15

results matching ""

    No results matching ""