Ansible

  1. 1. 运维自动化和 Ansible 简介
    1. 1.1. 云计算运维工程师核心技能
    2. 1.2. Ansible 特性
    3. 1.3. Ansible 架构
  2. 2. Ansible 安装和入门
    1. 2.1. Ansible 安装
    2. 2.2. Ansible 相关文件
      1. 2.2.1. Ansible 配置文件
      2. 2.2.2. Ansible 主配置文件
      3. 2.2.3. inventory 主机清单
    3. 2.3. Ansible 相关工具
      1. 2.3.1. ansible-doc
      2. 2.3.2. ansible
      3. 2.3.3. ansible-vault
      4. 2.3.4. ansible-console
      5. 2.3.5. ansible-galaxy
    4. 2.4. Ansible常用模块
      1. 2.4.1. Command 模块
      2. 2.4.2. Shell 模块
      3. 2.4.3. Script 模块
      4. 2.4.4. Copy 模块
      5. 2.4.5. Fetch 模块
      6. 2.4.6. File 模块
      7. 2.4.7. unarchive 模块
      8. 2.4.8. archive 模块
      9. 2.4.9. hostname 模块
      10. 2.4.10. corn 模块
      11. 2.4.11. yum 和 apt 模块
      12. 2.4.12. service 模块
      13. 2.4.13. user 模块
      14. 2.4.14. group 模块
      15. 2.4.15. lineinfile 模块
      16. 2.4.16. replace 模块
      17. 2.4.17. setup 模块
  3. 3. Playbook
    1. 3.1. playbook 介绍
    2. 3.2. playbook 核心组件
      1. 3.2.1. hosts 组件
      2. 3.2.2. remote_user 组件
      3. 3.2.3. task 列表和 action 组件
    3. 3.3. 运行 playbook
    4. 3.4. playbook 实战
      1. 3.4.1. playbook 创建 mysql 用户
      2. 3.4.2. playbook 安装 Nginx
      3. 3.4.3. playbook 安装 httpd
    5. 3.5. playbook 中使用 handlers 和 notify
    6. 3.6. playbook 中使用 tags
    7. 3.7. playbook 中使用变量
      1. 3.7.1. setup 模块中的变量
      2. 3.7.2. playbook 命令行中自定义变量
      3. 3.7.3. playbook 文件中自定义变量
      4. 3.7.4. 使用变量文件
      5. 3.7.5. 主机清单文件中定义变量
        1. 3.7.5.1. 主机变量
        2. 3.7.5.2. 组/公共变量
  4. 4. Template
    1. 4.1. jinja2 语言
  5. 5. Roles
  6. 6. 参考

Ansible is an open source IT automation engine that automates provisioning, configuration management, application deployment, orchestration, and many other IT processes.

运维自动化和 Ansible 简介

云计算运维工程师核心技能

相关工具:

  • 代码管理(SCM):GitHub,GitLab,BitBucket,SubVersion
  • 构建工具:Maven,Ant,Gradle
  • 自动部署:Capistrano,CodeDeploy
  • 持续集成(CI):jenkins,Travis
  • 配置管理:Ansible,SaltStack,Chef,Puppet
  • 容器:Docker,Podman,LXC,第三方厂商如AWS
  • 编排:Kubernetes,Core,Apache Mesos
  • 服务注册与发现:Zookeeper,etcd,Consul
  • 脚本语言:Python,Ruby,Shell
  • 日志管理:ELK,Logentries
  • 系统监控:Prometheus,Zabbix,Datadog,Graphite,Ganglia,Nagios
  • 性能监控:AppDynamics,New Relic,Splunk
  • 压力测试:jMeter,Blaze Meter,loader.io
  • 应用服务器:Tomcat,jBoss,IIS
  • Web服务器:Apache,Nginx
  • 数据库:MySQL,Oracle,PostgreSQL等关系型数据库;mongoDB,redis等NoSQL数据库
  • 项目管理(PM):jira,Asana,Taiga,Terllo,Basecamp,Pivotal Tracker

Ansible 特性

  • 模块化:调用特定的模块完成特定任务,支持自定义模块,可以使用任何编程语言编写模块
  • Paramiko(python 对 ssh 的实现),PyYAML,Jinja2(模板语言)三个关键模块
  • 基于Python语言实现
  • 部署简单,基于 python 和 SSH(默认已安装),agentless,无需代理不依赖 PKI(无需 SSL)
  • 安全,基于 OpenSSH
  • 幂等性:一个任务执行 1 遍和执行 n 遍效果一样,不因重复执行带来意外情况,此特性非绝对
  • 支持 playbook 编排任务,YAML 格式,编排任务,支持丰富的数据结构
  • 较强大的多层解决方案 role

Ansible 架构

ANSIBLE:组合 INVENTORY、API、MODULES、PLUGINS 的绿框,可以理解为是 ansible 命令工具,其为核心执行工具

  • ANSIBLE PLAYBOOKS:任务剧本(任务集),编排定义 Ansible 任务集的配置文件,由 Ansible 顺序依次执行,通常是 JSON 格式的 YML 文件
  • INVENTORY:Ansible 管理主机的清单 /etc/anaible/hosts
  • MODULES:Ansible 执行命令的功能模块,多数为内置核心模块,也可自定义
  • PLUGINS:模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
  • API:供第三方程序调用的应用程序编程接口

Ansible 安装和入门

Ansible 安装

1
$ dnf info ansible

EPEL 源的 rpm 包安装

1
$ yum install absible

除此以外还有编译安装,Git 方式安装,pip 方式安装等

确认安装:

1
$ ansible --version

Ansible 相关文件

Ansible 配置文件

  • /etc/ansible/ansible.cfg:主配置文件,配置 ansible 工作特性
  • /etc/ansible/hosts:主机清单文件,配置 ansible 管理的主机
  • /etc/ansible/roles/:存放角色的目录

Ansible 主配置文件

/etc/ansible/ansible.cfg 大部分的配置内容无需进行修改

1
2
3
4
5
6
7
8
9
10
11
12
13
[defaults]
#inventory = /etc/ansible/hosts # 主机列表配置文件
#library = /usr/share/my_modules/ # 库文件存放目录
#remote_tmp = $HOME/.ansible/tmp # 临时py命令文件存放在远程主机目录
#local_tmp = $HOME/.ansible/tmp # 本机的临时命令执行目录
#forks = 5 # 默认并发数,同时可以执行5次
#sudo_user = root # 默认sudo 用户
#ask_sudo_pass = True # 每次执行ansible命令是否询问ssh密码
#ask_pass = True # 每次执行ansible命令是否询问ssh口令
#remote_port = 22 # 远程主机的端口号(默认22)
host_key_checking = False # 检查对应服务器的host_key,建议取消注释
log_path = /var/log/ansible.log # 日志文件,建议启用
module_name = command # 默认模块,可以修改为shell模块

inventory 主机清单

ansible 的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在 inventory file 中将其分组命名。默认的 inventory file 为 /etc/ansible/hosts。inventory file 可以有多个,且也可以通过 Dynamic Inventory 来动态生成

inventory 文件遵顼 INI 文件风格,中括号中的字符为组名,可以将用一个主机同时归并到多个不同的组中,其外,当目标主机使用了非默认的 SSH 端口,还可以在主机名称之后使用冒号加端口号来说明。如果主机名称遵循相似的命名模式,还可以使用列表的方式标识各主机

1
2
3
4
5
6
7
8
9
10
mail.example.com

[webservers]
foo.example.com:2222
bar.example.com

[dbservers]
one.example.com
two.example.com
three.example.com
1
2
3
4
5
6
7
8
[webservers]
www[01:50].example.com

[dbservers]
db-[a:f].example.com

[appservers]
10.0.0.[1:100]

如果想配置目标主机,就不需要通过 SSH 协议连接本机,只需添加 ansible_connection=local 即可

1
2
3
4
5
6
[test]
10.0.0.8 ansible_connection=local # 指定本机连接,无需 ssh 配置

# ansible_connection=ssh # 默认配置 需要 StrictHostKeyChecking=no
10.0.0.7 ansible_connection=ssh ansible_port=2222 ansible_ssh_user=zhang ansible_ssh_pass=123456
10.0.0.6 ansible_connection=ssh ansible_ssh_user=root ansible_ssh_pass=123456

ansible_connection 不写的时候默认为 ssh,ansible_port 不写的时候默认为 22,ansible_ssh_user 不写的时候默认为当前用户,ansible_ssh_pass 不写的时候默认为 ssh 密钥

Ansible 相关工具

  • usr/bin/ansible:主程序,临时命令执行工具
  • usr/bin/ansible-doc:查看配置文档,模块工程查看工具,相当于 man
  • usr/bin/ansible-playbook:定制自动化任务,编排剧本工具,相当于脚本
  • usr/bin/ansible-pull:远程执行命令的工具
  • usr/bin/ansible-vault:文件加密工具
  • usr/bin/ansible-console:基于 Console 界面与用户交互的执行工具
  • usr/bin/ansible-galaxy:下载/上传优秀代码或 Role 模块的官网平台

利用 ansible 实现管理的主要方式:

  • Ad-Hoc 即利用 ansible 命令,主要用于临时命令使用场景
  • Ansible-playbook 主要用于长期规划好的,大型项目的场景,需要有前期的规划过程

ansible-doc

显示模块的帮助信息

1
2
3
ansible-doc [options] [module]
-l, --list # 列出所有模块
-s, --snippet # 显示指定模块的playbook示例
1
2
3
4
5
6
# 列出所有模块
$ ansible-doc -l
# 显示指定 ping 模块的帮助用法
$ ansible-doc ping
# 查看指定 ping 模块简要说明
$ ansible-doc -s ping

ansible

此工具通过 ssh 协议,实现对远程主机的配置管理,应用部署,任务执行等功能

格式:

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

选择说明:

1
2
3
4
5
6
7
8
9
10
11
--version              # 显示版本
-m module # 指定模块,默认为 command
-v # 详细过程 –vv -vvv更详细
--list-hosts # 显示主机列表,可简写 --list
-k, --ask-pass # 提示输入 ssh 连接密码,默认 Key 验证
-C, --check # 检查,并不执行
-T, --timeout=TIMEOUT # 执行命令的超时时间,默认 10s
-u, --user=REMOTE_USER # 执行远程执行的用户
-b, --become # 代替旧版的 sudo 切换
--become-user=USERNAME # 指定 sudo 的 runas 用户,默认为 root
-K, --ask-become-pass # 提示输入 sudo 时的口令

例:

1
$ ansible all --list-hosts
1
$ ansible all -m ping

也可以只有通配符等简单的模式匹配,如:

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
# ansible 的 Host-pattern
# All:表示所有 Inventory 中的所有主机
$ ansible all –m ping

# * :通配符
$ ansible "*" -m ping (*表示所有主机)
$ ansible 192.168.1.* -m ping
$ ansible "*srvs" -m ping

# 或关系 ":"
$ ansible "websrvs:appsrvs" -m ping
$ ansible “192.168.1.10:192.168.1.20” -m ping

# 逻辑与 ":&" 在 websrvs 组并且在 dbsrvs 组中的主机
$ ansible "websrvs:&dbsrvs" –m ping

# 逻辑非 ":!" 在 websrvs 组,但不在 dbsrvs 组中的主机 注意:此处为单引号
$ ansible 'websrvs:!dbsrvs' –m ping

# 综合逻辑
$ ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' –m ping

# 正则表达式
$ ansible "websrvs:&dbsrvs" –m ping
$ ansible "~(web|db).*\.foo\.com" –m ping
$ ansible 'kube*:etcd:!10.0.0.101' -a reboot;reboot

ansible命令执行过程

  1. 加载自己的配置文件,默认 /etc/ansible/ansible.cfg
  2. 加载自己对应的模块文件,如:command
  3. 通过 ansible 将模块或命令生成对应的临时 py 文件,并将该文件传输至远程服务器的对应执行用户 $HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY 文件
  4. 给文件 +x 执行
  5. 执行并返回结果
  6. 删除临时 py 文件,sleep 0 退出

执行状态:

  • 绿色:执行成功并且不需要做改变的操作
  • 黄色:执行成功并且对目标主机做变更
  • 红色:执行失败

ansible-vault

用于生成加密解密 yml 文件

1
$ ansible-vault [options] [create|decrypt|edit|encrypt|rekey|view] [vaultfile.yml]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 加密
$ anaible-vault encrypt test.yml

# 解密
$ anaible-vault decrypt test.yml

# 查看
$ anaible-vault view test.yml

# 编辑加密文件
$ anaible-vault edit test.yml

# 修改口令
$ anaible-vault rekey test.yml

# 创建新文件
$ anaible-vault create new.yml

ansible-console

此工具可交互执行命令,支持 tab,ansible 2.0+ 新增

ansible-galaxy

此工具会连接 https://galaxy.ansible.com 下面对应的 roles

1
2
3
4
5
6
7
8
# 列出所有已安装的 galaxy
$ ansible-galaxy list

# 安装 galaxy
$ ansible-galaxy install <galaxy_name>

# 删除 galaxy
$ ansible-galaxy remove <galaxy_name>

Ansible常用模块

Command 模块

1
2
3
4
$ ansible all -m command -a 'hostname'

zhangqiang-gen10plusv2 | CHANGED | rc=0 >>
zhangqiang-gen10plusv2

Command 模块是默认模块,即使不输入 command 也是默认的。可以在 /etc/ansible/ansible.cfg 下修改默认模块

需要注意的是,Command 模块不支持各种符号,例如 $ > 等,如果需要使用这些符号,需要使用 shell 模块

Shell 模块

与 Command 模块类似,但是支持各种符号,比如 * $ > 等

1
$ ansible all -m shell -a 'echo $HOSTNAME'

Script 模块

在远程主机上运行 ansible 服务器上的脚本(无需执行权限)

1
$ ansible all -m script -a "/data/test.sh"

Copy 模块

从 ansible 服务器主控制端复制文件到远程主机

1
2
3
4
5
6
7
8
9
10
11
# 如果目标存在,默认覆盖,此处指定先备份
$ ansible all -m copy -a "src=/etc/hosts dest=/tmp/hosts owner=user mode=600 backup=yes"

# 指定内容,直接生成目标文件
$ ansible all -m copy -a "content='hello world' dest=/tmp/test.txt"

# 复制 /etc 目录本身,注意 /etc/ 后面没有 /
$ ansible all -m copy -a "src=/etc dest=/tmp/etc"

# 复制 /etc/ 下的文件,不包括 /etc/ 目录本身,注意 /etc/ 后面有 /
$ ansible all -m copy -a "src=/etc/ dest=/tmp/etc"

Fetch 模块

从远程主机提取文件至 ansible 服务器主控制端,与 copy 模块相反,目前不支持目录

1
asible all -m fetch -a "src=/data/test.sh dest=/data/scripts"

File 模块

设置文件属性,创建软连接等

1
2
3
4
5
6
7
8
9
10
11
# 创建空文件
$ ansible all -m file -a "path=/tmp/test.txt state=touch"

# 创建目录
$ ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql mode=755"

# 创建软链接
$ ansible all -m file -a "path=/data/testfile path|dest|name=/data/testfile-link state=link"

# 递归修改目录属性
$ ansible all -m file -a "path=/data/mysql state=directory owner=mysql group=mysql mode=755 recurse=yes"

unarchive 模块

解包解压缩

2种用法

  1. 将 ansible 主机上的压缩包传到远程主机后解压缩至特定目录,设置 copy=yes,copy 参数默认为 yes,未来这个参数会被废弃
  2. 将远程主机上的压缩包解压缩至指定路径下,设置 copy=no
1
2
$ ansible all -m unarchive -a "src=/data/foo.tar.gz dest=/var/lib/foo owner=user group=bin mode=0777 copy=yes"
$ ansible all -m unarchive -a "src=https://example.com/foo.tar.gz dest=/usr/local/bin copy=no"

archive 模块

打包压缩保存在被管理节点

1
$ ansible all -m archive -a "path=/data/foo dest=/tmp/foo.zip format=zip owner=user mode=0777"

hostname 模块

管理主机名

1
2
$ ansible node1 -m hostname -a "name=webserver1"
$ ansible 10.0.0.1 -m hostname -a "name=example.com"

corn 模块

计划任务

支持时间:minute,hour,day,month,weekday

1
2
3
4
5
# 备份数据库脚本
$ cat /root/mysql_backup.sh

#!/bin/bash
mysqldump -A -F --single-transaction --master-data=2 -q -uroot |gzip >/data/mysql_backup/mysql_$(date +%F_%T).sql.gz
1
2
3
4
5
6
7
8
9
10
11
# 创建任务
$ ansible dbservers -m cron -a "name=mysql_backup minute=0 hour=1 user=root job=/root/mysql_backup.sh"

# 禁用任务
$ ansible dbservers -m cron -a "name=mysql_backup minute=0 hour=1 user=root job=/root/mysql_backup.sh disable=yes"

# 启用任务
$ ansible dbservers -m cron -a "name=mysql_backup minute=0 hour=1 user=root job=/root/mysql_backup.sh disable=no"

# 删除任务
$ ansible dbservers -m cron -a "name=mysql_backup minute=0 hour=1 user=root job=/root/mysql_backup.sh state=absent"

$ contab -l 查看计划任务

yum 和 apt 模块

  • yum 管理软件包,只支持 RHEL, CentOS, Fedora, Amazon Linux, Oracle Linux, Scientific Linux,不支持 Ubuntu, Debian 版本
  • apt 模块管理 Debian 相关版本的软件包
1
2
3
4
5
# 安装
$ ansible all -m yum -a "name=nginx state=present"

# 删除
$ ansible all -m yum -a "name=nginx state=absent"

service 模块

管理服务

1
2
3
4
5
6
7
8
9
10
11
# 停止服务
$ ansible all -m service -a 'name=httpd state=stopped'

# 启动服务,并设为开机自启
$ ansible all -m service -a 'name=httpd state=started enabled=yes'

# 重新加载
$ ansible all -m service -a 'name=httpd state=reloaded'

# 重启服务
$ ansible all -m service -a 'name=httpd state=restarted'

user 模块

管理用户

1
2
3
4
5
6
7
8
# home   指定家目录路径
# system 指定系统账号
# group 指定组
# remove 清除账户
# shell 指定shell类型

# 清空用户所有数据
$ ansible webserver -m user -a 'name=user1 state=absent remove=yes'

group 模块

管理组

1
2
3
4
5
# 创建组
$ ansible webserver -m group -a "name=testgroup system=yes"

# 删除组
$ ansible webserver -m group -a "name=testgroup state=absent"

lineinfile 模块

ansible 在使用 sed 替换时,经常会遇到需要转义的问题,而且 ansible 在遇到特殊符号进行替换时,存在问题,无法正常进行替换,其实在 ansible 自身提供了两个模块,lineinfile 模块和 replace 模块,可以方便的进行替换

一般在 ansible 当中去修改某个文件的单行进行替换的时候需要使用 lineinfile 模块

regexp 参数:使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最后面被匹配的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,那么这些行都会被删除

如果想进行多行匹配进行替换需要使用 replace 模块

  • 相当于 sed,可以修改文件内容
1
$ ansible webserver -m lineinfile -a "dest=/etc/httpd/conf/httpd.conf regexp='^Listen' line='Listen 8080'"

replace 模块

类似于 sed 指令,主要也是基于正则进行匹配和替换,建议使用

1
$ ansible all -m replace -a "path=/etc/fstab regexp='^(UUID.*)' replace='#\1'"

setup 模块

setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度,可以使用 gather_facts: no 来禁止 ansible 收集 facts 信息

1
2
$ ansible all -m setup
$ ansible all -m setup -a "filter=ansible_nodename*"

Playbook

playbook 介绍

playbook 是由一个或多个 play 组成的列表,play 的主要功能在于将预定义的一组主机,装扮成事先通过 ansible 中的 task 定义好的角色

Task 实际是调用 ansible 的一个 module,将多个 play 组织在一个 playbook 中,即可以让它们联合起来,按事先编排的机制执行预定义的动作

playbook 核心组件

playbook 核心组件
  • Hosts:执行的远程主机列表(应用在哪些主机上)
  • Tasks:任务集,由多个 task 的元素组成的列表实现,每个 task 是一个字典
  • Variables:内置变量或自定义变量在 playbook 中调用
  • Templates:模板,可替换模板文件中的变量并实现一些简单逻辑的文件
  • Handlersnotify:结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
  • tags:指定某条任务执行,用于选择运行 playbook 中的部分代码。ansible 具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过 tags 跳过此些代码片断
    • ansible-playbook -t tagsname useradd.yml
  • roles:角色,将 playbook 中的一些任务集合成一个角色,可以在 playbook 中调用,也可以在其他 playbook 中调用

hosts 组件

playbook 中的每一个 play 的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts 用于指定要执行指定任务的主机,须事先定义在主机清单中

1
2
3
4
5
6
7
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs # 或者,两个组的并集
Websrvs:&dbsrvs # 与,两个组的交集
webservers:!phoenix # 在websrvs组,但不在dbsrvs组
1
- hosts: websrvs:dbsrvs

remote_user 组件

可用于 Host 和 task 中。也可以通过指定其通过 sudo 的方式在远程主机上执行任务,其可用于 play 全局或某任务;此外,甚至可以在 sudo 时使用 sudo_user 指定 sudo 时切换的用户

1
2
3
4
5
6
7
8
9
- hosts: websrvs
remote_user: root # (可省略,默认为root) 以root身份连接

tasks: # 指定任务
- name: test connection
ping:
remote_user: testuser
sudo: yes # 默认sudo为root
sudo_user: zhang # sudo为zhang

task 列表和 action 组件

play 的主体部分是 task list,task list 中的各任务按次序逐个在 hosts 中指定的所有主机上执行,即在所有主机上完成第一个任务后,再开始第二个任务

task 的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致

每个 task 都应该有其 name,用于 playbook 的执行结果输出,建议其内容能清晰地描述任务执行步骤。如果未提供 name,则 action 的结果将用于输出

1
2
3
4
5
6
7
8
9
10
action: module arguments

# 建议使用
module: arguments

# eg.
- name: Ensure postgresql is at the latest version
ansible.builtin.yum:
name: postgresql
state: latest

运行 playbook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 运行playbook的方式
ansible-playbook <filename.yml> ... [options]

# 常见选项
--syntax-check # 检查语法
--check -C # 只检测可能会发生的改变,但不真正执行操作
--list-hosts # 列出运行任务的主机
--list-tags # 列出tag (列出标签)
--list-tasks # 列出task (列出任务)
--limit [主机列表] # 只针对主机列表中的主机执行
-v -vv -vvv # 显示过程

# 示例
ansible-playbook hello.yml --check # 只检测
ansible-playbook hello.yml --list-hosts # 显示运行任务的主机
ansible-playbook hello.yml --limit websrvs # 限制主机

playbook 实战

playbook 创建 mysql 用户

1
2
3
4
5
6
7
8
9
10
---
- hosts: dbsrvs
remote_user: root
gather_facts: no

tasks:
# 字典两种写法均可
- {name: Create group, group: name=mysql system=yes gid=306}
- name: Create mysql user
user: name=mysql shell=/sbin/nologin system=yes group=mysql uid=306 home=/data/mysql createhome=no

playbook 安装 Nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
---
- hosts: dbsrvs
remote_user: root
gather_facts: no

tasks:
- name: Add group nginx
group: name=nginx state=present
- name: Add user nginx
user: name=nginx group=nginx state=present
- name: Install Nginx
yum: name=nginx state=present
- name: Start Nginx
service: name=nginx state=started enabled=yes

playbook 安装 httpd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- hosts: websrvs
remote_user: root
gather_facts: no

tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
# - name: Modify config
# lineinfile: path=/etc/httpd/conf/httpd.conf regexp='^Listen' line='Listen 8080'
# - name: mkdir website dir
# file: path=/data/html state=directory
# - name: web html
# copy: src=files/index.html dest=/data/html/
- name: start service
service: name=httpd state=started enabled=yes

playbook 中使用 handlers 和 notify

handlers 本质是 task list,类似于 MySQL 中的触发器触发的行为,其中的 task 与前述的 task 并没有本质上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作

notify 对应的 action 可用于在每个 play 的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完后一次性的执行指定操作。而 notify 中列出的操作被称为 handler,即 notify 中调用 handler 中定义的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- hosts: websrvs
remote_user: root

tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
notify: restart httpd
- name: ensure apache is running
service: name=httpd state=started enabled=yes

handlers:
- name: restart httpd
service: name=httpd state=restarted
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- hosts: websrvs
remote_user: root

tasks:
- name: add group nginx
tags: user
user: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: Install Nginx
yum: name=nginx state=present
- name: config
copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
notify:
- Restart Nginx
- Check Nginx Process

handlers:
- name: Restart Nginx
service: name=nginx state=restarted enabled=yes
- name: Check Nginx process
shell: killall -0 nginx > /tmp/nginx.log

playbook 中使用 tags

在 playbook 文件中,可以利用 tags 组件,为特定 tasks 指定标签,当在执行 playbook 时,可以只执行特定 tags 的 tasks,而不是执行整个 playbook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# httpd.yml
- hosts: websrvs
remote_user: root

tasks:
- name: Install httpd
yum: name=httpd state=present
tage: install
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
tags: conf
- name: start httpd service
tags: service
service: name=httpd state=started enabled=yes
1
2
# 指定执行install,conf 两个标签
$ ansible-playbook –t install,conf httpd.yml

playbook 中使用变量

仅能由字母,数字和下划线组成,且只能以字母开头

1
2
3
4
5
# 变量定义 eg.
http_port=80

# 变量调用方式 eg.
{{ http_port }}

setup 模块中的变量

setup 模块中的变量可以直接调用

ansible setup facts 远程主机的所有变量都可直接调用 (系统自带变量),setup 模块可以实现系统中很多系统信息的显示,可以返回每个主机的系统信息包括:版本、主机名、cpu、内存等

1
2
3
4
$ ansible all -m setup -a 'filter="ansible_nodename"'                   # 查询主机名
$ ansible all -m setup -a 'filter="ansible_memtotal_mb"' # 查询主机内存大小
$ ansible all -m setup -a 'filter="ansible_distribution_major_version"' # 查询系统版本
$ ansible all -m setup -a 'filter="ansible_processor_vcpus"' # 查询主机cpu个数
1
2
3
4
5
6
7
8
9
---
# var1.yaml
- hosts: all
remote_user: root
gather_facts: yes

tasks:
- name: Create log file
file: name=/data/{{ ansible_hostname }}.log state=touch owner=zhang mode=600
1
$ ansible-playbook var1.yaml

playbook 命令行中自定义变量

通过命令行指定变量,优先级最高

1
2
# 命令行赋值
$ ansible-playbook –e 'pkname=httpd' var2.yaml
1
2
3
4
5
6
7
8
9
---
# var2.yaml
- hosts: websrvs
remote_user: root
gather_facts: yes

tasks:
- name: Install package
yum: name={{ pkname }} state=present
1
$ ansible-playbook var2.yaml

playbook 文件中自定义变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
---
# var3.yaml
- hosts: websrvs
remote_user: root
gather_facts: yes
vars:
username: user1
groupname: group1

tasks:
- name: Create group
group: name={{ groupname }} state=present
- name: Create user
user: name={{ username }} group={{ groupname }} state=present
1
$ ansible-playbook var3.yaml

使用变量文件

可以在一个独立的 playbook 文件中定义变量,在另一个 playbook 文件中引用变量文件中的变量,比 playbook 中定义的变量优先级高

1
2
3
# var.yaml
service1: httpd
service2: nginx
1
2
3
4
5
6
7
8
9
10
11
12
# var4.yaml
- hosts: websrvs
remote_user: root
gather_facts: yes
vars_files:
- var.yaml

tasks:
- name: Create httpd log
file: name=/data/{{ service1 }}.log state=touch owner=zhang mode=600
- name: Create nginx log
file: name=/data/{{ service2 }}.log state=touch owner=zhang mode=600

主机清单文件中定义变量

主机变量
1
2
3
4
# vim /etc/ansible/hosts
[homeserver]
192.168.50.3 name=nuc
192.168.50.4 name=gen10plusv2
1
2
3
4
5
6
---
- hosts: homeserver

tasks:
- name: Rename hostname
hostname: name={{ name }}
组/公共变量

在 inventory 主机清单文件中赋予指定组内所有主机上的在 playbook 中可用的变量,如果和主机变量是同名,优先级低于主机变量

1
2
3
4
5
6
7
# vim /etc/ansible/hosts
[homeserver]
192.168.50.3 name=nuc
192.168.50.4 name=gen10plusv2

[homeserver:vars]
domain=tyokyo320.com
1
2
3
4
5
6
---
- hosts: homeserver

tasks:
- name: Rename hostname
hostname: name={{ name }}.{{ domain }}

Template

模板是一个文本文件,可以做为生成文件的模板,并且模板文件中还可以嵌套 jinja 语法

jinja2 语言

Jinja2 语言,使用字面量,有下面形式

  • 字符串:使用单引号或双引号
  • 数字:整数,浮点数
  • 列表:[item1, item2, …]
  • 元组:(item1, item2, …)
  • 字典:{key1:value1, key2:value2, …}
  • 布尔型:true/false
  • 算术运算:+, -, *, /, //, %, **
  • 比较操作:==, !=, >, >=, <, <=
  • 逻辑运算:and,or,not
  • 流表达式:For,If,When

Roles

参考