目录

Ansible 从入门到放弃

Ansible 从入门到放弃

前言

运维自动化的发展历程以及技术应用

  1. 本地部署 On-Premises 如下都需要自己 部署/配置 以及维护。
  • Application
  • Data
  • Runtime
  • Middleware
  • OS
  • Virtualization
  • Servers
  • Storage
  • NetWorking
  1. 基础设施既服务 ( 如 阿里云 ) IaaS - Infrastructure as a Service 如下需要自己 部署/配置 以及维护。
  • Application
  • Data
  • Runtime
  • Middleware
  • OS
  1. 平台既服务 ( 如 阿里云- ACK 容器服务 ) PaaS - Platform as a Service 如下需要自己 部署/配置 以及维护。
  • Application
  • Data
  1. 软件既服务 ( 如 各类软件 微信、钉钉、邮箱 ) SaaS - Software as a Service 所有的服务软件都不需要自己维护, 直接使用既可。

ansible

ansible 简介

ansible 是基于 python2-paramiko 模块开发的自动化运维工具。 实现了批量系统配置, 批量程序部署, 批量运行命令等功能。ansible 是基于模块工作的, 本身没有批量部署的能力。真正具有批量部署的是 ansible 所运行的模块, ansible 只是提供了一种框架。

ansible 集合了众多运维工具( pupet、cfengine、chef、func、fabric、saltstack )的优点

  • ansible 发展史

    • ansible 作者是 Michael DeHaan 同时他也是 Cobbler 与 Func 作者。

    • 2012-03-09 发布 0.0.1 版本。

    • 2015-10-17 被 Red Hat 收购。

  • ansible 特性

    • 基于 Python 开发

    • 模块化: 调用特定的模块(如: Paramiko、PyYAML、jinja2 等), 完成特定的任务。

    • 支持自定义模块

    • 部署简单, 基于Linux内置的 PythonOpen-SSH 和另一个 agentless 组件.

    • 支持 PlayBook 编排任务

    • 幂等性: 任务重复执行等于只执行一次, 不会重复执行多次相同命令。

    • 无需代理不依赖PKI.

    • 支持多语言模块编写.

    • YAML格式编排任务,支持丰富的数据结构.

ansible 架构

  • ansible 主要组成部分:

    • ansible playbooks: 任务剧本(任务集), 通过编排定义ansible任务集合的配置文件, 由ansible 顺序依次执行, 文件通常是 JSON格式的YML文件。

    • Roles: 角色, 多个 ansilbe playbooks 的集合.

    • Inventory: ansible 管理主机的清单 默认为 /etc/ansible/hosts 文件。

    • Modules: ansible 执行命令的功能模块, 一般为ansible内置核心模块, 也可以自定义第三方模块.

    • plugins: ansible 功能插件, 是功能模块的补充. 如: 连接类型插件、循环插件、变量插件、过滤插件等等.

    • Api: 提供第三方程序调用的开放接口.

    • ansible: ansible 的客户端命令工具. 执行 ansible 命令的主要程序.

      • Ad-Hoc 用户执行单条或多条的 ansible 命令.

      • ansible playbook 通过编写编排文件 ansible 执行命令集合.

        • ansible playbook 执行过程 -> 将编排好的任务写入 ansible-playbook 编排文件中 -> 通过 ansible-playbook 命令拆分任务集合, 然后按照预定的顺序逐条执行ansible 命令.

ansible 安装

  • ansible 安装很简单, 也有很多种方式.

    • 安装 epel 源以后 执行 yum -y install ansible

    • 使用 源码包 进行 安装

    • 通过 git clone https://github.com/ansible/ansible 以后进行安装

    • 使用 pip 命令安装

1
2
3
4
5
6
7
8
9

[root@jicki ~]# ansible --version
ansible 2.9.10
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Apr  2 2020, 13:16:51) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]

  • ansible 相关说明

    • /etc/ansible/ansible.cfg 主配置文件, 配置ansible的工作特性.

    • /etc/ansible/hosts 主机清单.

    • /etc/ansible/roles/ 存放(roles)角色的目录.

    • /usr/bin/ansible 二进制执行文件, ansible 主程序.

    • /usr/bin/ansilbe-doc 配置文档, 模块功能查看工具.

    • /usr/bin/ansible-galaxy 用于上传/下载 roles 模块到官方平台的工具.

    • /usr/bin/ansible-playbook 自动化任务、编排剧本工具/usr/bin/ansible-pull 远程执行命令的工具.

    • /usr/bin/ansible-vault 文件(如: playbook 文件) 加密工具.

    • /usr/bin/ansible-console 基于 界面的用户交互执行工具.

/etc/ansible/hosts

创建秘钥 ssh-keygen -t rsa -f ~/.ssh/id_rsa -C "jicki"

拷贝秘钥到其他被控端 ssh-copy-id ip

主机清单文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# #号为注释

# 单主机 直接写入 ip 或 nameserver
192.168.168.10

# 非标准22端口可直接用 : 填入
192.168.168.10:999
db1.example.com:999


# []包含的为主机组 如下 
[webservers]
192.168.168.10
192.168.168.11
192.168.168.12
192.168.168.13


# 主机也支持 nameserver 如下
[dbservers]
db1.example.com
db2.example.com
db3.example.com
db4.example.com

# 主机支持 [1:10] 类型的多主机 如下 
[docker]
# 等同于 192.168.168.10 ~ 192.168.168.120
192.168.168.1[0:20]


# 主机也支持 [a:z] 类型的 nameserver 如下
[kubernetes]
# 等同于 master-a ~ master-c
master-[a:c]
# 等同于 node-c ~ node-g
node-[c:g]

  • 操作主机

    • -m 为指定模块 ping 为 模块名称

    • -k 为密码方式, 默认为 ssh-key 免密码方式登录

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# ansible 通过 单主机进行操作 ( -k 为用户密码方式, 默认为 ssh-key )
ansible 192.168.168.10 -m ping -k


# ansible 通过 ':' 组合进行操作
ansible "192.168.168.10:192.168.168.20" -m ping -k


# ansible 通过 通配符加主机 进行操作
ansible 192.168.168.* -m ping -k


# ansible 通过 hosts 组名称 进行操作
ansible webservers -m ping -k


# ansible 通过 ':' 组合组进行操作
ansible 'webservers:dbservers' -m ping -k


# ansible 通过 通配符 进行操作
ansible '*servers' -m ping -k


# ansible 通过 ':&' 逻辑与 (两个组中都包含的主机)
ansible 'webservers:&dbservers' -m ping -k


# ansible 通过 ':!' 逻辑非 (在webservers 但不在 dbservers的主机)
ansible 'webservers:!dbservers' -m ping -k


# ansible 也支持多逻辑的组合
ansible 'webservers:dbserver:&appserver:!ftpservers' -m ping -k


# ansible 也支持正则表达式
ansible '~(web|db)serever' -m ping -k


# ansible 通过 all 对 hosts 清单下所有主机进行操作
ansible all -m ping -k


# ansible 通过 通配符 对 hosts 清单下所有主机进行操作
ansible '*' -m ping -k

  • 输出结果
1
2
3
4
5
6
7
8
[root@jicki opt]# ansible all -m ping
10.0.3.13 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

/etc/ansible/ansible.cfg

ansible 主配置文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# defaults 为默认配置
[defaults]

# 主机清单的路径, 默认为如下
#inventory      = /etc/ansible/hosts

# 模块存放的路径 
#library        = /usr/share/my_modules/

# utils 模块存放路径
#module_utils   = /usr/share/my_module_utils/

# 远程主机脚本临时存放目录
#remote_tmp     = ~/.ansible/tmp

# 管理节点脚本临时存放目录 
#local_tmp      = ~/.ansible/tmp

# 插件的配置文件路径
#plugin_filters_cfg = /etc/ansible/plugin_filters.yml

# 执行并发数
#forks          = 5

# 异步任务查询间隔 单位秒
#poll_interval  = 15

# sudo 指定用户
#sudo_user      = root

# 运行 ansible 是否提示输入sudo密码
#ask_sudo_pass = True

# 运行 ansible 是否提示输入密码 同 -k
#ask_pass      = True

# 远程传输模式
#transport      = smart

# SSH 默认端口
#remote_port    = 22

# 模块运行默认语言环境
#module_lang    = C


# roles 存放路径
#roles_path    = /etc/ansible/roles

# 不检查 /root/.ssh/known_hosts 文件 建议取消
#host_key_checking = False


# ansible 操作日志路径 建议打开
#log_path = /var/log/ansible.log


ansible 相关操作

ansible 执行过程

  1. 加载配置文件 /etc/ansible/ansible.cfg.

  2. 加载对应的模块文件.

  3. 通过 ansible 将模块或命令生成对应的临时 py 文件, 并将该临时文件 传输至远程服务器的对应 执行用户 临时目录下 $HOME/.ansible/tmp/ansible-tmp-2123/xxx.py >文件.

  4. 对临时 py 文件授权 ( chmod u+x xx.py ).

  5. 执行 py 文件,并返回执行结果.

  6. 删除临时的 py 文件, sleep 0 退出.


  • 执行状态

    • 绿色: 执行操作成功并且不需要做更改的操作.

    • 黄色: 执行操作成功, 并且对目标主机进行了变更操作. 如 更改文件内容, 重启服务, 删除文件等.

    • 红色: 执行操作失败.


ansible-doc

  • 显示模块帮助

    • -l, --list 列出可用模块

    • -s, --snippet 显示指定模块的 playbook 片段

1
2
3
4
5
6
7
8
# 例子

ansible-doc -l

ansible-doc ping

ansible-doc -s ping


ansible

  • ansible <host-pattern> [-m module_name] [-a args]

    • host-pattern: 主机ip、主机名、主机组。

    • module_name: 模块的名称。如果不写 默认为 -m command

    • args: 模块的参数, 需要加上 -a 进行指定模块的参数。如: `ansible all -a ‘hostname’

    • -v、-vv、-vvv: 显示详细的命令输出日志, v 越多越详细。如: ansible all -m ping -vvv

    • --list: 显示主机的列表。 如: ansible all --list

    • -k / --ask-pass: 提示输入ssh连接密码, 默认为 ssh-key 认证。如: ansible all -m ping -k

    • -K / --ask-become-pass: 提示输入 sudo 的密码。

    • -C / --check: 检查命令操作, 并不会执行。如: ansible all -m ping -C

    • -T / --timeout: 执行命令的超时时间, 默认为 10s。如: ansible all -m ping -T=2

    • -u / --user: 执行远程操作的用户. 如: ansible all -m ping -u=root

    • -b / --become: 代替旧版的 sudo 切换。

ansible 常用模块

截止 2020-08-10 ansible 模块为 3387 个.


Command 模块

  • command 模块: 在远程主机上执行命令, 支持条件判断. ansible 默认模块, 可忽略 -m 参数直接操作. 注: command 模块 不支持 $VARNAME < > | ; & 等符号.

    • `ansible all -m command -a ‘systemctl stop docker’

    • `ansible all -a ‘docker ps -a’

    • ansible all -a 'removes=/opt/ansible df -h'

      • 如果 /opt/ansible 不存在 就不执行 df -h 操作, 如果 /opt/ansible 存在, 就执行 df -h 操作.
    • ansible all -a 'creates=/opt/ansible df -h'

      • 如果 /opt/ansible 不存在 就执行 df -h 操作, 如果存在 /opt/ansible 就不执行 df -h 操作.
    • ansible all -a 'chdir=/opt ls -lt'

      • 切换目录, 等于 cd /opt && ls -lt 操作

shell 模块

  • shell 模块: shell 模块支持 command 所有的操作, 而且支持 $VARNAME < > | ; & 等符号操作.

    • ansible all -m shell -a 'ps -ef|grep docker'

Script 模块

  • script 模块: 执行脚本的命令. 只需要调用 ansible 本机上的脚本就可以在所有的选择主机上面执行脚本中的内容.

    • ansible all -m script -a '/root/1.sh'

      • /root/1.sh 脚本只需要在 ansible 管理主机上既可.

Copy 模块

  • copy 模块: 拷贝文件到远程主机.

    • `ansible all -m copy -a ‘src=/root/xxx.txt dest=/root/1.txt backup=yes’

      • src: 原文件路径

      • dest: 目标主机路径

      • backup: 如果目标主机文件存在, 会先进行备份, 再进行覆盖.

    • ansible all -m copy -a 'src=/root/1.txt dest=/root/2.txt mode=0644 owner=jicki group=jicki'

      • mode: 修改权限

      • owner: 修改用户

      • group: 修改用户组

    • ansible all -m copy -a 'content="hello\nworld\n" dest=/root/2.txt'

      • content: 将内容写入到目标文件中.

Fetch 模块

  • fetch 模块: 将远程主机的文件, 下载到本机中, 下载成功会存放在以 主机 IP/名称 的文件夹中, 会包含原文件的整体路径. (只能下载单个文件, 不支持目录, 可先打包成压缩包, 再进行下载)

    • ansible all -m fetch -a 'src=/var/log/messages dest=/root/'

      • src: 远程主机的文件路径

      • dest: 本机的文件夹路径


File 模块

  • file 模块: 操作远程主机的文件. 如: 创建文件 touch、 删除文件 absent

    • ansible all -m file -a 'name=/root/1.txt owner=jicki group=jicki mode=0755 recurse=yes'

      • mode: 修改权限

      • owner: 修改用户

      • group: 修改用户组

      • recurse=yes: 递归, 指对目录递归授权.

    • ansible all -m file -a 'name=/root/1.txt state=touch'

      • destnamepath: 指定远程主机的文件路径.

      • state: 文件操作类型. ( 默认为 absent )

        • touch: 创建空文件.
        • directory: 创建文件夹.
        • absent: 递归删除文件夹/文件.
        • link: 创建软连接.
    • ansible all -m file -a 'src=/root/1.txt dest=/root/1.link state=link'

      • src: 源文件, 这里用于指定 软连接的源文件.

Cron 模块

  • cron 模块: 为远程主机添加定时任务.

    • ansible all -m cron -a 'weekday=1-5 job="echo date >> /root/1.txt" name=echocron'

      • day: 表示 天. 支持 ( 1-31, *, */2 ) 写法

      • hour: 表示 小时. 支持 ( 0-23, *, */2 ) 写法

      • minute: 表示 分钟. 支持 ( 0-59, *, */2 ) 写法

      • month: 表示 月. 支持 ( 1-12, *, */2 ) 写法

      • weekday: 表示 星期. 支持 ( 0-6, Sunday-Saturday, * )写法

      • job: 表示 计划任务的内容.

      • name: 表示 计划任务名称. 相同的计划任务名称会覆盖.

    • ansible all -m cron -a 'disabled=true job="echo date >> /root/1.txt" name=echocron'

      • disabled: 只是注释掉计划任务 并非删除.

        • trueyes : 关闭计划任务. 关闭计划任务 必须指定 jobname.
        • falseno: 重新打开计划任务. 必须指定 jobname.
    • ansible all -m cron -a 'name=echocron state=absent'

      • state
        • absent 删除计划任务. 删除计划任务 只需要指定 name 既可.

Yum 模块

  • yum 模块: 利用 yum 操作软件包, 如 安装、查询、卸载等.

    • ansible all -m yum -a 'name=sysstat state=present'

    • ansible all -m yum -a 'name=/tmp/sysstat-12.3.3-1.2.x86_64.rpm'

    • ansible all -m yum -a 'name=sysstat update_cache=yes disable_gpg_check=yes'

      • name: 软件包的名称, 或者rpm包, 远程服务器必须存在 rpm 包. 安装多个软件使用 , 号隔开. 如 name=sysstat,mysql,redis

      • state

        • presentinstalled: 安装软件. 默认为 present, 可不填 state=present .
        • absentremoved: 卸载/删除软件.
      • update_cache=yes: 更新 yum 缓存后 在安装软件.

      • disable_gpg_check=yes: 禁用 gpg 检查.

    • ansible all -m yum -a 'list=installed'

      • list: 列出安装包.

        • installed: 已安装的软件
        • updates: 可以升级的软件
        • available: 可以安装的软件
        • repos: yum 源

Service 模块

  • service: 软件服务管理模块. 启动、关闭、重启 等操作.

    • ansible all -m service -a 'name=vsftpd state=started enabled=yes'

      • name: 服务名称.

      • state

        • started: 启动服务.
        • stopped: 停止服务.
        • restarted: 重启服务.
        • reloaded: 重新加载配置.
      • enabled: 设置是否开机启动.

        • yes、true
        • no、false

User 模块

  • user: 管理系统用户的模块

    • ansible all -m user -a 'name=nginx shell=/sbin/nologin system=yes home=/var/nginx groups=root uid=80 comment="nginx service user"'

      • name: 用户名

      • shell: 指定用户的 shell 类型

      • system: 指定是否为 系统用户

      • home: 指定用户额外的home目录,默认为 /home/用户名 .

      • groups: 用户额外的 groups 组.

      • uid: 指定用户的 uid 号.

      • comment: 用户额外说明.

    • ansible all -m user -a 'name=nginx state=absent remove=yes'

      • state

        • present: 创建用户 (默认为present)
        • absent: 删除用户
      • remove: 是否删除 用户 home 目录.


Group 模块

  • group: 管理系统用户组的模块

    • ansible all -m group -a 'name=nginx system=yes gid=80'

      • name: 用户组名

      • system: 是否为系统用户组

      • gid: 指定 gid 号

      • state

        • present: 创建用户组 (默认为present)
        • absent: 删除用户组
    • ansible all -m group -a 'name=nginx state=absent'


ansible-galaxy

通过 https://galaxy.ansible.com/ 页面下载

ansible-galaxy 工具用于下载对应的roles

  • ansible-galaxy list geerlingguy.nginx

    • list: 查看本地的 roles 角色.
  • ansible-galaxy install geerlingguy.nginx

    • install: 下载 roles 角色. 会下载到 $HOME/.ansible/roles/ 目录下
  • ansible-galaxy remove geerlingguy.nginx

    • remove: 删除已下载的 roles 角色. 在目录中删除也可以.

ansible playbook

playbook 流程图


playbook 与 YAML 描述

  • playbook 由一个或多个 play 组成.

  • playbook 中 每个play 必须包含 hoststasks.

  • playbookYAML 语法编写.

    • YAML 约定以 --- 开头 和 开始不同的 play .

    • YAML# 作为注释.

    • YAML 必须统一缩进, 空格 与 tab 不能混用, 缩进的级别也必须相同, 同级缩进代表同样的级别.

    • YAML 文件内容 是大小写敏感的, 跟 Linux 一样区分大小写.

    • YAML key/value 形式可写在同一行也可以换行写. 同行使用 : 隔开.

    • YAML 一个完整的代码块功能最少包含2个元素. 如 name: task

    • YAML 一个 name 下只能包含一个 task

    • YAML - 开头的为列表, key/value 形式的为字典.

    • YAML 特性

      • 可读性好
      • 和脚本语言交互性好
      • 使用实现语言的数据类型
      • 一致性的信息模型
      • 易于实现
      • 基于流处理
      • 表达能力好, 扩展性强

playbook 核心元素

  • hosts : 远程主机列表 ( ip / 主机名 / 组名 )

  • tasks : 任务集, 任务列表, 有两种写法

    • action: module args : action: 模块名 参数

    • module: args : 模块名: 参数 (一般使用这种)

    • ignore_errors: True 当前 task 出错时仍然会向下执行

  • varniables : 内置变量或自定义变量在 playbook 文件中调用

  • templates : 模板, 可替换模板文件中的变量并实现一些简单逻辑的文件

  • handles : 与 notity 结合使用, 由特定条件触发的操作, 满足条件才执行, 否则不执行

  • tags : 标签 指定任务执行, 用于执行一个 playbook 中的部分代码. 主要用于测试.


ansible-playbook 命令

  • ansible-playbook

    • -C / --check : Check 检查脚本运行情况, 不会在远程服务器里运行.

    • --list-hosts : 列出运行此 任务 的主机.

    • --list-tasks : 列出任务组的具体任务列表.

    • --limit : 只对主机列表中的某台主机执行.

    • -v -vv -vvv : 显示详细的执行过程, v 越多就越详细.


ansible-playbook 变量

  • 变量名要求: 只允许使用 字母数字_ 组成, 而且只能以 字母开头.

  • 内置的公共变量:

    • 使用 ansible all -m setup 可以获取到主机的系统变量名称.

      • ansible all -m setup -a 'filter=*addresses*' , 可使用 filter 参数进行过滤.

  • 通过文件自定义变量:

    • /etc/ansible/hosts 文件中定义

      • 对主机组中的主机单独定义变量, 优先级高于公共变量.

      • 对主机组中的所有主机定义统一变量, 优先级低于对单独主机定义的变量.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

[appserver]
# 对单独主机 定义变量 node_id
10.0.3.13 node_id=13

# 对主机组 定义统一变量 domain_name
[appserver:vars]
domain_name=jicki.cn


  • 使用变量 就可以灵活配置不同主机的 hostname
1
2
3
4
5
6
7
8
---
- hosts: all
  remote_user: root

  tasks:
    - name: set hostname
      hostname: name={{ node_id }}.{{ domain_name }}


  • 通过命令行定义变量: 通过命令行定义的变量优先级是最高的

    • ansible-playbook -e varname=valur

  • playbook 文件里 定义变量.

    • 通过 {{ 变量名 }} 使用变量.

    • 通过 vars: 列表 定义多个 变量.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14

---
- hosts: all
  remote_user: root

  # 定义变量
  vars:
    - pkg_name: httpd 

  tasks:
    - name: install {{ pkg_name }}
      # 使用变量
      yum: name={{ pkg_name }}


  • 通过定义单独的变量文件 用于统一存放变量, 可避免变量的重复定义.

    • 定义单独的 变量文件, 只需要将所有变量以 key: value 形式写入到 yml 文件中既可.

    • playbook 文件中, 只需要使用 vars_files: 指定 yml 文件路径既可.


  • vars.yml 变量文件
1
2
3
4
---
pkg_name: httpd
file_name: jicki.cn

  • install.yml playbook 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
---
- hosts: all
  remote_user: root

  # 配置模板文件
  vars_files:
    # 指定文件的路径
    - vars.yml

  tasks:
    - name: install {{ pkg_name }}
      yum: name={{ pkg_name }}
    - name: create {{ file_name }} file
      file: name=/root/{{ file_name }}.txt state=touch

  • 执行 playbook 操作
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17

[root@jicki ansible]# ansible-playbook install.yml

PLAY [all] *******************************************************************************************************

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

TASK [install httpd] *********************************************************************************************
changed: [10.0.3.13]

TASK [create jicki.cn file] **************************************************************************************
changed: [10.0.3.13]

PLAY RECAP *******************************************************************************************************
10.0.3.13                  : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


ansible-playbook template

  • template 是一个模块,并且只能用于 playbook 下.

  • templates 文件, 可嵌套脚本 ( 利用模板编程语言 Jinja2 编写 )

    • Jinja2 语言, 使用字面量.

      • 字符串: 使用单引号或双引号.

      • 数字: 整数, 浮点数.

      • 列表: [A1, A2, …]

      • 元组: (B1, B2, …)

      • 字典: {key1:value1, key2:value2, …}

      • 布尔值: true/false

      • 算术运算: +, -, *, /, //, %, **

      • 比较操作: ==, !=, >, >=, <, <=

      • 逻辑运算: and, or, not

      • 流表达式: for, if, when


  • templates 根据模板块文件动态生成对应的配置文件

    • templates 文件一般约定存放于 templates 目录下, 并且以 .j2 为后缀

    • templates 目录需要与 playbookyml 文件在同级目录中.

1
2
3
4
5
[root@jicki nginx]# tree .
.
|-- nginx.yml
`-- templates
    `-- nginx.conf.j2

算术运算

  • nginx.conf.j2 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
user nginx;
# 这里使用 环境变量 vcpus * 2 
worker_processes {{ ansible_processor_vcpus * 2 }};
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

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;

    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

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


  • nginx.yml playbook 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
---
- hosts: all
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx
    - name: template conf
      # 如果 yml 与 templates 目录同级, src 直接写.j2 文件
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      notify:
        - restart nginx
    - name: start nginx
      service: name=nginx state=started enabled=yes

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted


when 条件语句

  • when 条件语句 例子
1
2
3
4
5
6
[root@jicki nginx]# tree .
.
|-- nginx.yml
`-- templates
    |-- nginx.conf.centos7.j2
    `-- nginx.conf.centos8.j2

  • playbook 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
---
- hosts: all
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx
    - name: template centos 7 conf
      # 如果 yml 与 templates 目录同级, src 直接写.j2 文件
      template: src=nginx.conf.centos7.j2 dest=/etc/nginx/nginx.conf
      # 使用 when 语句进行判断 如果变量为 "7" 执行这个
      when: ansible_distribution_major_version == "7"
      notify:
        - restart nginx
    - name: template centos 8 conf
      # 如果 yml 与 templates 目录同级, src 直接写.j2 文件
      template: src=nginx.conf.centos8.j2 dest=/etc/nginx/nginx.conf
      # 使用 when 语句进行判断 如果变量为 "8" 执行这个
      when: ansible_distribution_major_version == "8"
      notify:
        - restart nginx
    - name: start nginx
      service: name=nginx state=started enabled=yes

  handlers:
    - name: restart nginx
      service: name=nginx state=restarted

  • 执行 playbook 文件

    • skipping 状态表示跳过执行这个 TASK .
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

[root@jicki nginx]# ansible-playbook nginx.yml

PLAY [all] *******************************************************************************************

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

TASK [install nginx] *********************************************************************************
ok: [10.0.3.13]

TASK [template centos 7 conf] ************************************************************************
changed: [10.0.3.13]

TASK [template centos 8 conf] ************************************************************************
skipping: [10.0.3.13]

TASK [start nginx] ***********************************************************************************
ok: [10.0.3.13]

RUNNING HANDLER [restart nginx] **********************************************************************
changed: [10.0.3.13]

PLAY RECAP *******************************************************************************************
10.0.3.13      : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0


迭代变量 with_tiems

  • 迭代 with_items 执行重复任务.

    • 对于迭代选项, 固定变量名为 item .
    • task 中使用 with_items 指定需要迭代的元素列表.
      • 元素列表 支持 字符串字典 .
  • playbook 文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
---
- hosts: all
  remote_user: root

  tasks:
    - name: create some files
      # {{ item }} 为特殊变量, 代表 with_items 列表中的内容
      file: name=/tmp/{{ item }} state=touch
      with_items:
        - file1
        - file2
        - file3
        - file4
    - name: install some software
      yum: name={{ item }}
      with_items:
        - htop
        - sl
        - hping3

代嵌套子变量 (字典)

  • 迭代嵌套子变量.

    • 对迭代中的变量进行嵌套关联的操作.
  • playbook 文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

---
- hosts: all
  remote_user: root

  tasks:
    - name: create some files
      # {{ item }} 为特殊变量, 代表 with_itmes 列表中的内容
      file: name=/tmp/{{ item }} state=touch
      with_items:
        - file1
        - file2
        - file3
        - file4

    - name: create some group
      group: name={{ item }}
      with_items:
        - j1
        - j2
        - j3
        - j4

    - name: create some user
      # 使用 item.key值 进行引用
      user: name={{ item.name }} group={{ item.group }}
      # 使用 字典 定义 嵌套的子 变量
      with_items:
        - { name: 'file1', group: 'j1' }
        - { name: 'file2', group: 'j2' }
        - { name: 'file3', group: 'j3' }
        - { name: 'file4', group: 'j4' }

    - name: permission some files
      file: name=/tmp/{{ item.name }} owner={{ item.name }} group={{ item.group }}
      with_items:
        - { file: 'file1', name: 'file1', group: 'j1' }
        - { file: 'file2', name: 'file2', group: 'j2' }
        - { file: 'file3', name: 'file3', group: 'j3' }
        - { file: 'file4', name: 'file4', group: 'j4' }


  • 执行 playbook 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[root@jicki ansible]# ansible-playbook file.yml

PLAY [all] *****************************************************************************************

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

TASK [create some files] ***************************************************************************
changed: [10.0.3.13] => (item=file1)
changed: [10.0.3.13] => (item=file2)
changed: [10.0.3.13] => (item=file3)
changed: [10.0.3.13] => (item=file4)

TASK [create some group] ***************************************************************************
changed: [10.0.3.13] => (item=j1)
changed: [10.0.3.13] => (item=j2)
changed: [10.0.3.13] => (item=j3)
changed: [10.0.3.13] => (item=j4)

TASK [create some user] ****************************************************************************
changed: [10.0.3.13] => (item={u'group': u'j1', u'name': u'file1'})
changed: [10.0.3.13] => (item={u'group': u'j2', u'name': u'file2'})
changed: [10.0.3.13] => (item={u'group': u'j3', u'name': u'file3'})
changed: [10.0.3.13] => (item={u'group': u'j4', u'name': u'file4'})

TASK [permission some files] ***********************************************************************
changed: [10.0.3.13] => (item={u'group': u'j1', u'name': u'file1', u'file': u'file1'})
changed: [10.0.3.13] => (item={u'group': u'j2', u'name': u'file2', u'file': u'file2'})
changed: [10.0.3.13] => (item={u'group': u'j3', u'name': u'file3', u'file': u'file3'})
changed: [10.0.3.13] => (item={u'group': u'j4', u'name': u'file4', u'file': u'file4'})

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



流程控制、循环 for 与 if

  • for 循环

    • {% for 语句块 %} ... {% endfor %}

  • ansible-playbook 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
---
- hosts: all
  remote_user: root

  vars:
    # 列表的形式
    listen_port:
      - 80
      - 81
      - 82
    # 字典的形式
    service:
      - name: web1
        domain: jicki.cn
        port: 90
        user: nginx
        path: /var/www/html 
      - name: web2
        domain: jicki.cn
        port: 91
        user: nginx
        path: /var/www/html
      - name: web3
        domain: jicki.cn
        port: 92
        user: nginx
        path: /var/www/html

  tasks:
    - name: copy template conf
      template: src=for.conf.j2 dest=/root/for.conf
  • for.conf.j2 文件

    • {% for port in listen_port %} 语句 listen_port 为 playbook 中定义的 vars .
1
2
3
4
5
6
7
8
{% for port in listen_port %}

server {
   listen {{ port }}
}

{% endfor %}

  • 查看最终生成 for.conf 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[root@jicki ~]# cat /root/for.conf

server {
   listen 80
}


server {
   listen 81
}


server {
   listen 82
}


  • 字典形式
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
---
- hosts: all
  remote_user: root

  vars:
    # 字典的形式
    service:
      - name: web1
        domain: jicki.cn
        port: 90
        user: nginx
        path: /var/www/html
      - name: web2
        domain: jicki.cn
        port: 91
        user: nginx
        path: /var/www/html
      - name: web3
        domain: jicki.cn
        port: 92
        user: nginx
        path: /var/www/html

  tasks:
    - name: copy template conf
      template: src=nginx.conf.j2 dest=/root/nginx.conf
  • nginx.conf.j2 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{% for s in service %}
user {{ s.user }};
worker_processes {{ ansible_processor_vcpus + 2 }};
pid /run/nginx.pid;
    server {
        listen       {{ s.port }} default_server;
        listen       [::]:{{ s.port }} default_server;
        server_name  {{ s.name }}.{{ s.domain }};
        root         {{ s.path }};
    }

{% endfor %}

  • 查看生成后的 nginx.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

user nginx;
worker_processes 3;
pid /run/nginx.pid;
    server {
        listen       90 default_server;
        listen       [::]:90 default_server;
        server_name  web1.jicki.cn;
        root         /var/www/html;
    }

user nginx;
worker_processes 3;
pid /run/nginx.pid;
    server {
        listen       91 default_server;
        listen       [::]:91 default_server;
        server_name  web2.jicki.cn;
        root         /var/www/html;
    }

user nginx;
worker_processes 3;
pid /run/nginx.pid;
    server {
        listen       92 default_server;
        listen       [::]:92 default_server;
        server_name  web3.jicki.cn;
        root         /var/www/html;
    }

  • if 流程控制

    • {% if 语句块 %} ... {% else %} ... {% endif %}

  • playbook 文件

    • 其中 web1, web2 不没有 user 变量, web3 包含 user 变量.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

---
- hosts: all
  remote_user: root

  vars:
    # 字典的形式
    service:
      - name: web1
        domain: jicki.cn
        port: 90
        path: /var/www/html

      - name: web2
        domain: jicki.cn
        port: 91
        path: /var/www/html

      - name: web3
        domain: jicki.cn
        port: 92
        user: nginx
        path: /var/www/html

  tasks:
    - name: copy template conf
      template: src=nginx.conf.j2 dest=/root/nginx.conf

  • nginx.conf.j2 文件

    • {% if s.user is defined %} 判断 是否有 s.user 这个变量
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

{% for s in service %}

{% if s.user is defined %}
user {{ s.user }};
{% else %}
user root;
{% endif %}
worker_processes {{ ansible_processor_vcpus + 2 }};
pid /run/nginx.pid;
    server {
        listen       {{ s.port }} default_server;
        server_name  {{ s.name }}.{{ s.domain }};
        root         {{ s.path }};
    }

{% endfor %}

  • 查看生成后的 nginx.conf

    • 第一个 不包含 s.user 变量 所以 user root;
    • 第二个 不包含 s.user 变量 所以 user root;
    • 第三个 包含 s.user 变量 所以 user nginx; 等于变量值
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

user root;
worker_processes 3;
pid /run/nginx.pid;
    server {
        listen       90 default_server;
        server_name  web1.jicki.cn;
        root         /var/www/html;
    }


user root;
worker_processes 3;
pid /run/nginx.pid;
    server {
        listen       91 default_server;
        server_name  web2.jicki.cn;
        root         /var/www/html;
    }


user nginx;
worker_processes 3;
pid /run/nginx.pid;
    server {
        listen       92 default_server;
        server_name  web3.jicki.cn;
        root         /var/www/html;
    }



Example - tasks

  • 基础的例子
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
---
# 指定主机组
- hosts: all
  # 指定执行 用户
  remote_user: root

  # 任务
  tasks:
    # 任务的名称
    - name: ping server
      ping:
    - name: echo hostname
      # shell 为模块名, 后面等同于 -a '' 参数
      shell: hostname
    - name: touch file
      file: name=/tmp/file.txt state=touch
    - name: echo file
      shell: ls -l /tmp/file.txt

  • ansible-playbook hello.yml 运行 playbook

    • 输出如下:

      • ok : ok 表示没有任何更改, 绿色

      • changed : changed 表示有修改, 黄色

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
PLAY [all] **********************************************************

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

TASK [ping server] **************************************************
ok: [10.0.3.13]

TASK [echo hostname] ************************************************
changed: [10.0.3.13]

TASK [touch file] ***************************************************
changed: [10.0.3.13]

TASK [echo file] ****************************************************
changed: [10.0.3.13]


PLAY RECAP **********************************************************
10.0.3.13   : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


Example - handles

  • handlesnotity 结合的例子

    • 同一个name 下可以定义多个 notify 配置关联到不同的 handlers 中.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
- hosts: all
  remote_user: root

  tasks:
    - name: copy httpd.conf
      copy: src=/root/ansible/httpd.conf dest=/etc/httpd/conf/httpd.conf backup=yes
      # 关联多个触发器的写法
      notify:
        - restart httpd
        - check status httpd
        - check network port


  • 例子:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
---
- hosts: all
  remote_user: root

  tasks:
    - name: install httpd
      yum: name=httpd
    - name: copy httpd.conf
      copy: src=/root/ansible/httpd.conf dest=/etc/httpd/conf/httpd.conf backup=yes
      # 此任务 如果有变动会触发如下定义名称的触发器
      notify: restart httpd
    - name: start httpd
      service: name=httpd state=started enabled=yes

  # 触发器, 需要配置 notify 触发
  handlers:
    - name: restart httpd
      service: name=httpd state=restarted


  • ansible-playbook httpd.yml

    • 第一次执行输出如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18

PLAY [all] ********************************************************************************************************

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

TASK [install httpd] **********************************************************************************************
changed: [10.0.3.13]

TASK [copy httpd.conf] ********************************************************************************************
ok: [10.0.3.13]

TASK [start httpd] ************************************************************************************************
changed: [10.0.3.13]

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


  • 修改 httpd.conf 文件以后

    • 第二次执行输出如下:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22

PLAY [all] ********************************************************************************************************

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

TASK [install httpd] **********************************************************************************************
ok: [10.0.3.13]

TASK [copy httpd.conf] ********************************************************************************************
changed: [10.0.3.13]

TASK [start httpd] ************************************************************************************************
ok: [10.0.3.13]

RUNNING HANDLER [restart httpd] ***********************************************************************************
changed: [10.0.3.13]

PLAY RECAP ********************************************************************************************************
10.0.3.13                  : ok=5    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0



Example - tags

  • 基于 tags 的例子

    • 定义了 tags 后可通过定义的 tags 单独运行该 tags. 运行多个可用 , 号隔开.

    • 多个不同的任务 可以定义相同名称的 tags.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
---
- hosts: all
  remote_user: root

  tasks:
    - name: install httpd
      yum: name=httpd
    - name: copy httpd.conf
      copy: src=/root/ansible/httpd.conf dest=/etc/httpd/conf/httpd.conf backup=yes
      # 此任务 如果有变动会触发如下定义名称的触发器
      notify:
        - restart httpd
      # 定义标签
      tags: cpconf
    - name: start httpd
      service: name=httpd state=started enabled=yes
      # 定义标签
      tags: sthttpd

  # 触发器, 需要配置 notify 触发
  handlers:
    - name: restart httpd
      service: name=httpd state=restarted

  • 执行命令 -t 指定标签
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[root@jicki ansible]# ansible-playbook -t sthttpd httpd.yml

PLAY [all] ********************************************************************************************************

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

TASK [start httpd] ************************************************************************************************
changed: [10.0.3.13]

PLAY RECAP ********************************************************************************************************
10.0.3.13                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


ansible-vault

  • playbook 文件加密工具

  • ansible-vault encrypt hello.yml

    • encrypt: AES256 加密 ( 会提示输入密码 )

    • view: 加密的情况下 查看 原来的内容.

    • edit: 编辑加密的 playbook 文件.

    • decrypt: 解密.

    • rekey: 修改加密密码.


ansible-console

  • ansible-console: 可交互执行命令, 支持 Tab 键.
1
2
3
4
5
6
[root@jicki ~]# ansible-console
Welcome to the ansible console.
Type help or ? to list commands.

root@all (1)[f:5]$

  • root@all (1) [f:5]$

    • root: 当前执行用户.
    • all: 表示当前主机清单.
    • (1): 表示当前主机清单下包含 1 台主机.
    • [f:5]: 表示并发执行任务数为 5 个.

ansible Roles

  • Roles 既 (角色) 是 ansible v1.2 版本引入的新特性, 用于 层次性、结构化的组织 playbook.

  • Roles 能够根据层次结构自动加载- 变量文件、tasks、handler、template 文件等. 简单来讲就是将 这些文件归类到各自单独的文件目录中, 使 playbook 文件可以更好的通过 include 这些文件目录.

  • Roles 一般用于基于 主机构建服务 的场景中, 但也可以用于构建 守护进程 等场景.

  • Roles 官方定义默认的目录为 /etc/ansible/roles 下.

1
2
3
4
5
6
[root@jicki ansible]# tree .
.
|-- ansible.cfg
|-- hosts
`-- roles
    `-- nginx

roles 目录结构

  • 目录结构说明

    • roles: - 所有的角色必须放在roles目录下, 这个目录可以自定义位置. 默认的位置在 /etc/ansible/roles
      • playbook.yml: - 剧本文件.
      • project: - 具体的角色项目名称, 比如 nginx、tomcat、php .
        • files: - 用于存放由copyscript 模块调用的文件.
        • templates: - 用于存放 Jinja2 模板, template 模块会自动在此目录中寻找 Jinja2 模板文件.
        • tasks: - 此目录应当包含一个main.yml文件, 用于定义此角色的任务列表, 此文件可以使用include包含其它的位于此目录的 task 文件.
        • handlers: - 此目录应当包含一个main.yml文件, 用于定义此角色中触发条件时执行的动作.
        • vars: - 此目录应当包含一个main.yml文件, 用于定义此角色用到的变量.
        • defaults: - 目录应当包含一个main.yml文件, 用于为当前角色设定默认变量.
        • meta: - 此目录应当包含一个main.yml文件, 用于定义此角色的特殊设定及其依赖关系.

  • roles - nginx
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[root@jicki roles]# tree .
.
`-- nginx
    |-- defaults
    |-- files
    |-- handlers
    |-- meta
    |-- tasks
    |-- templates
    `-- vars

  • 创建对应的文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[root@jicki ansible]# tree  roles/
roles/
`-- nginx
    |-- defaults
    |-- files
    |-- handlers
    |-- meta
    |-- tasks
    |   |-- group.yml
    |   |-- main.yml
    |   |-- restart.yml
    |   |-- start.yml
    |   |-- template.yml
    |   |-- user.yml
    |   `-- yum.yml
    |-- templates
    |   `-- nginx.conf.j2
    `-- vars

  • /etc/ansible/nginx_roles.yml 与 roles 同级
 1
 2
 3
 4
 5
 6
 7
 8
 9
10

---
- hosts: all
  remote_user: root

  # 选择 roles 属性
  roles:
      # 调用 role 目录. roles 同级的目录
    - role: nginx

  • /etc/ansible/roles/nginx/tasks/main.yml 入口文件 配置 task 执行顺序

    • 跨 roles 调用 tasks, 需要写 roles 目录级的全路径. 如:

      • -include: roles/httpd/tasks/copyfile.yml
1
2
3
4
5
6
- include: group.yml
- include: user.yml
- include: yum.yml
- include: template.yml
- include: start.yml

  • /etc/ansible/roles/nginx/tasks/group.yml 单独的 tasks 文件只写单独的内容 如下:
1
2
- name: create group
  group: name=nginx gid=80

  • 执行 /etc/ansible/nginx_roles.yml 文件
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

[root@jicki ansible]# ansible-playbook nginx_roles.yml

PLAY [all] ****************************************************************************************

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

TASK [nginx : create group] ***********************************************************************
changed: [10.0.3.13]

TASK [nginx : create user] ************************************************************************
changed: [10.0.3.13]

TASK [nginx : install package] ********************************************************************
changed: [10.0.3.13]

TASK [nginx : copy conf] **************************************************************************
changed: [10.0.3.13]

TASK [nginx : start service] **********************************************************************
changed: [10.0.3.13]

PLAY RECAP ****************************************************************************************
10.0.3.13   : ok=6    changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0



roles tags 标签

  • 在 playbook 文件中 对 roles 配置相应的 tags .
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
---
- hosts: all
  remote_user: root

  # 选择 roles 属性
  roles:
    # 配置相应的 tags 用 { } 引用
    - { role: nginx, tags: ['web', 'nginx'] }
    - { role: mysql, tags: ['db', 'mysql'] }
    - { role: redis, tags: ['db', 'redis'] }
    - { role: golang, tags: ['web', 'golang'] }
    - { role: app, tags: "app" }


  • 通过 ansible-playbook -t 参数指定 tags 进行单独调用

    • 如下指定 tags 为 web 的 role 执行. 为 nginx 和 golang
1
2
[root@jicki ansible]# ansible-playbook -t web playbook.yml


roles when 语句

  • 对 role 进行条件的判断.
    • ansible_distribution_major_version == "7"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
---
- hosts: all
  remote_user: root

  # 选择 roles 属性
  roles:
    # 配置相应的 tags 用 { } 引用
    - { role: nginx, tags: ['web', 'nginx'] }
    - { role: mysql, tags: ['db', 'mysql'] }
    - { role: redis, tags: ['db', 'redis'] }
    # 只针对 系统的 版本 为 7 的执行
    - { role: golang, tags: ['web', 'golang'], when: ansible_distribution_major_version == "7" }
    - { role: app, tags: "app" }


Example - roles

  • 一个综合的例子

  • roles 目录如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@jicki ansible]# tree .
.
|-- ansible.cfg
|-- hosts
|-- nginx_roles.yml
`-- roles
    `-- nginx
        |-- defaults
        |-- files
        |   `-- default.conf
        |-- handlers
        |   `-- main.yml
        |-- meta
        |-- tasks
        |   |-- copyfile.yml
        |   |-- group.yml
        |   |-- main.yml
        |   |-- start.yml
        |   |-- template.yml
        |   |-- user.yml
        |   `-- yum.yml
        |-- templates
        |   `-- nginx.conf.j2
        `-- vars
            `-- main.yml

  • nginx_roles.yml 文件
1
2
3
4
5
6
7
8
---
- hosts: all
  remote_user: root

  # 选择 roles 属性
  roles:
      # 调用 role 目录. roles 同级的目录
    - role: nginx

  • roles/tasks/main.yml 文件

    • 按照导入顺序执行如下 task
1
2
3
4
5
6
7
- include: group.yml
- include: user.yml
- include: yum.yml
- include: template.yml
- include: copyfile.yml
- include: start.yml

  • roles/tasks/template.yml 文件

    • template 文件引用了 notify
1
2
3
- name: copy conf
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
  notify: restart service
  • roles/tasks/copyfile.yml 文件

    • copyfile 文件引用了 变量, 以及引用了 files 目录下的文件
1
2
3
- name: copy conf
  copy: src=default.conf dest=/etc/nginx/conf.d/ owner={{ username }} group={{ groupname }}


  • roles/nginx/handlers/main.yml 文件

    • handlers 下必须包含一个 mian.yml 文件
1
2
- name: restart service
  service: name=nginx state=restarted

  • roles/nginx/vars/main.yml 文件

    • key/value 形式写入内容
1
2
3
username: nginx
groupname: nginx