一. Installation Guide
1.1 Installing Ansible on Ubuntu
| sudo apt update
sudo apt install software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
|
1.2 Structure of configuration dir
| /etc/ansible
├── ansible.cfg #主配置文件,配置ansible工作特性(一般无需修改)
├── hosts #主机清单(将被管理的主机放到此文件)
└── roles #存放角色的目录
|
二. Introduction to Ansible
Ansible 是新出现的自动化运维工具,有以下特征:
- 基于Python开发
- 集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点
- 实现了批量系统配置、批量程序部署、批量运行命令等功能。
- ansible是基于模块工作的,本身没有批量部署的能力。
- 真正具有批量部署的是ansible所运行的模块,ansible 只是提供一种框架。
ansible 框架主要包括:
1. connection plugins 连接插件:负责和被监控端实现通信;
2. host inventory:指定操作的主机,是一个配置文件里面定义监控的主机;
3. 各种模块核心模块、command模块、自定义模块;
4. 借助于插件完成记录日志邮件等功能;
5. playbook:剧本执行多个任务时,非必需可以让节点一次性运行多个任务。
ansible的架构:连接其他主机默认使用ssh协议
Ansible 主要组成部分:
- ansible playbooks:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible顺序依次执行,通常是JSON格式的YML文件
- inventory:Ansible管理主机的清单 /etc/anaible/hosts
- modules: Ansible执行命令的功能模块,多数为内置核心模块,也可自定义
- plugins: 模块功能的补充,如连接类型插件、循环插件、变量插件、过滤插件等,该功能不常用
- API: 供第三方程序调用的应用程序编程接口
- ansible: 组合INVENTORY、API、MODULES、PLUGINS的绿框,可以理解为是ansible命令工具,其为核心执行工具
ansible命令执行过程如下,也可以在命令中添加 -vvvvv参数查看执行过程。
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的主机一般称为主控端,中控,master或堡垒机
- 主控端Python版本需要2.6或以上
- 被控端Python版本小于2.4需要安装python-simplejson
- 被控端如开启SELinux需要安装libselinux-python
- windows不能做为主控端
- ansible不是服务,不会一直启动,只是需要的时候启动
2.1 Quick start
2.1.1 连接集群节点
| # 添加节点配置到 hosts
sudo tee -a /etc/ansible/hosts << EOF
master ansible_host=192.168.1.180 ansible_user=moloom ansible_ssh_port=7777
node1 ansible_host=192.168.1.181 ansible_user=moloom ansible_ssh_port=7777
node2 ansible_host=192.168.1.182 ansible_user=moloom ansible_ssh_port=7777
EOF
# 校验配置文件编写是否正确
ansible-inventory /etc/ansible/hosts --list
# 测试各节点是否能联通
ansible node1 -m ping -k
ansible node2 -m ping -k
|
2.1.2 运行 playbook
编辑文件 first_playbook.yaml
| - name: My first play
hosts: mohosts
tasks:
- name: Ping my hosts
ansible.builtin.ping:
- name: Print message
ansible.builtin.debug:
msg: Hello world!
|
运行 playbook
| ansible-playbook first_playbook.yaml -k
|
2.2 Inventory
Ansible 的主要功能在于批量的主机操作,inventory 就是存放要操作的主机节点的 IP 信息文件。为了方便结合环境,Ansible 还支持在 inventory 文件内对主机节点进行分组。
/etc/ansible/hosts 文件是 ansible 寻找 inventory 的默认文件。也可以通过 -i inventory.ini 命令行参数来指定 inventory 文件。
Ansible 的 inventory 支持两种文档格式 ==INI== 和 ==YAML== ,Ansible 的默认 inventory 文件就是 INI 格式。
inventory 的组名必须唯一,且区分大小写,最好不要有空格、连字符(-)以及用数字开头
2.2.1 INI 格式示例
| [a_xxx]
master ansible_host=192.168.1.180
node1 ansible_host=192.168.1.181
node2 ansible_host=192.168.1.182
[a_xxx:vars]
ansible_user=moloom
ansible_ssh_port=7777
ansible_ssh_pass=mo
ansible_sudo_pass=mo
ansible_sudo_exec=/bin
ansible_ssh_private_key_file=~/.ssh/
ansible_shell_type=bash
ansible_connection=ssh
ansible_python_interpreter=/usr/bin/python3.10
[metagroup_name_s:children]
a_xxx
b_xxx
c_xxx
[metagroup_name_s2]
a_xxxx
[metagroup_name_m:children]
metagroup_name_s
metagroup_name_s2
|
2.2.2 YAML 格式示例
| a_xxx:
hosts:
master:
ansible_host: 192.168.1.180
node1:
ansible_host: 192.168.1.181
node2:
ansible_host: 192.168.1.182
vars: # 定义变量,可以把一些字段相同的值放到 vars 下
ansible_user: moloom
ansible_ssh_port: 7777
ansible_ssh_pass: mo #ssh连接时的密码
ansible_sudo_pass: mo #使用sudo连接用户时的密码
ansible_sudo_exec: /bin #如果sudo命令不在默认路径,需要指定sudo命令路径
ansible_ssh_private_key_file: ~/.ssh/ #秘钥文件路径,秘钥文件如果不想使用ssh-agent管理时可以使用此选项
ansible_shell_type: bash #目标系统的shell的类型,默认sh
ansible_connection: ssh #SSH 连接的类型:local,ssh,paramiko
ansible_python_interpreter: /usr/bin/python3.10 # 指定 python 解释器版本,防止输出警告
metagroup_name_s:
children:
a_xxx:
b_xxx:
c_xxx:
metagroup_name_s2:
hosts:
a_xxxx:
metagroup_name_m:
children:
metagroup_name_s:
metagroup_name_s2:
|
Ansible 命令介绍。
| /usr/bin/ansible 主程序,临时命令执行工具
/usr/bin/ansible-doc 查看配置文档,模块功能查看工具
/usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
/usr/bin/ansible-playbook 定制自动化任务,编排剧本工具
/usr/bin/ansible-pull 远程执行命令的工具,推送命令至远程主机
/usr/bin/ansible-vault 文件加密工具
/usr/bin/ansible-console 基于Console界面与用户交互的执行工具
|
ansible 命令中的 Host-pattern 支持正则表达式
- 通配符 "*" 例:ansible "*" -m ping 表示所有主机
- 逻辑或 ":" ansible "websrvs:appsrvs" -m ping
- 逻辑与 ":&" ansible "websrvs:&dbsrvs" –m ping 在websrvs组并且在dbsrvs组中的主机
- 逻辑非 ":!" ansible 'websrvs:!dbsrvs' –m ping 在websrvs组,但不在dbsrvs组中的主机。注意:此处为单引号!!!
- 综合逻辑 ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' –m ping
- 正则 ansible "websrvs:&dbsrvs" –m ping , ansible "~(web|db).*\.magedu\.com" –m ping
2.3.1 Command ansible
| ansible Host-pattern [options]
-m --module #指定模块
-a module-args #指定模块参数,默认为 command
-b --become #代替旧版的 sudo 切换
-C --check #执行但不会改变,有点类似 k8s 的 --dry-run
-u --user #指定远程连接的用户
-f #启动的并发线程数
-K --ask-become-pass #提示输入 sudo 的口令
-i #指定 inventory 文件
-T --timeout #执行命令的超时时间,默认 10s
-v #打印详细信息,v越多,信息越详细,最多 5 个 v!!!!
--list-hosts #不执行命令,只输出受影响的主机节点名
--become-user #指定执行操作的用户,默认是 root
|
2.3.2 Command ansible-inventory
操作 inventory 的命令。
| ansible-inventory /etc/ansible/hosts --list #校验 inventory 文件格式
|
2.3.3 Command ansible-doc
这个命令相当于在查 ansible 的手册。
| ansible-doc <moduleName> [options] [resourcesName]
-l --list #列出所有模块
-s --snippet #只显示 playbook 相关说明
|
2.3.4 Command ansible-galaxy
官网资源:https://galaxy.ansible.com/ui/
| ansible-galaxy [options]
- list #列出安装了的 roles
- install #安装
- remove #删除
|
2.3.5 Command ansible-pull
推送命令至远程主机,效率无限提升。
2.3.6 Command ansible-playbook
| ansible-playbook <filename.yml> ... [options]
--check -C 只检测可能会发生的改变,但不真正执行操作;只检查语法,如果执行过程中出现问题,-C无法检测出来;执行playbook生成的文件不存在,后面的程序如果依赖这些文件,也会导致检测失败
--list-hosts 列出运行任务的主机
--list-tags 列出tag (列出标签)
--list-tasks 列出task (列出任务)
--limit 主机列表 只针对主机列表中的主机执行
-t #指定执行打了某个标签的 play 片段
|
2.3.7 Command ansible-vault
管理加密解密yml文件
| ansible-vault [options] [resourcesName]
- encrypt #加密
- decrypt #解密
- view #查看
- edit #编辑加密文件
- rekey #修改口令
- create #创建新文件
|
2.3.8 Command ansible-console
| ansible-console [host-pattern]
|
2.4. Ansible 常用模块
模块文档:https://docs.ansible.com/ansible/latest/module_plugin_guide/index.html
2.4.1 Command
Command 在远程主机执行命令,默认模块,可忽略-m选项。模块常用参数:
- chdir 进入到被管理的主机
- creates 如果 creates 中的文件或文件夹存在,值则不执行后面的命令,若不存在则执行
| # 示例
#查看 sshd 状态
ansible mohosts -a 'service sshd status'
#进入被管理主机某个目录,打印当前所在目录
ansible mohosts -a 'chdir=/tmp pwd'
#若 home 目录没有 calico,则打印 home 的所有文件
ansible mohosts -a 'creates=~/calico ls -l'
|
此命令不支持 $VARNAME < > | ; & 等!!!
2.4.2 Shell
Shell 在远程主机执行命令,与 Command 模块类似,但支持更复杂的命令。
| # 修改用户密码
ansible mohosts -m shell -a 'echo moo | passwd --stdin moloom'
# 运行复杂命令,如 awk 处理文件内容,复杂命令可能会失败,推荐写入脚本后复制到远程主机执行,再将结果拉回执行机器。
ansible mohosts -m shell -a "cat /tmp/stanley.md | awk -F'|' '{print $1,$2}' &> /tmp/example.txt"
|
2.4.2.1 修改配置文件,使 Shell 作为默认模块
| vim /etc/ansible/ansible.cfg
# 添加或修改以下内容
module_name = shell
|
2.4.3 Script
在远程主机上运行ansible服务器上的脚本
| ansible mohosts -m script -a /data/test.sh
|
2.4.4 Copy
从主控端复制文件到远程主机。模块常用参数:
- src 源文件,指定拷贝文件的本地路径 (如果有/ 则拷贝目录内容,比拷贝目录本身)
- dest 目标路径
- owner 所有者
- group 所属组
- mode 设置权限
- backup 是否备份目的地的文件
- content 文件内容
| # 如果目标存在,则备份要被覆盖的目的地文件
ansible mohosts -m copy -a "src=/root/test1.sh dest=/tmp/test2.sh owner=moloom mode=600 backup=yes"
# 指定内容,直接生成目标文件
ansible mohosts -m copy -a "content='test content\nxxx' dest=/tmp/test.txt"
|
2.4.5 Fetch
从远程主机提取文件至主控端,copy相反,目前不支持目录,可以先打包,再提取文件。
| # 生成每个被管理主机不同编号的目录,不会发生文件名冲突
ansible mohosts -m fetch -a 'src=/root/test.sh dest=/data/scripts'
# 先压缩,在传到本机,注意压缩包名称不要重复
ansible all -m shell -a 'tar jxvf test.tar.gz /root/test.sh'
ansible all -m fetch -a 'src=/root/test.tar.gz dest=/data/'
|
2.4.6 File
设置文件属性。参数如下:
- path 文件路径
- recurse 递归,一般在 state=directory 时用
- src 创建硬链接,软链接时,指定源目标,配合'state=link' 'state=hard' 设置软链接,硬链接
- state 状态,可选值:touch 创建文件、directory 创建文件夹、absent 删除作用、link 软连接、hard 硬连接。
| # 创建文件
ansible node1 -m file -a 'path=/app/test.txt state=touch'
# 创建目录
ansible node1 -m file -a "path=/data/testdir state=directory"
# 设置权限755
ansible node1 -m file -a "path=/root/test.sh owner=wang mode=755"
# 创建软链接
ansible node1 -m file -a 'src=/data/testfile dest=/data/testfile-link state=link'
|
2.4.7 Unarchive
解包解压缩。常见参数:
- copy deprecated! 默认 yes。值为 yes 会把压缩包传到远程主机后解压缩;若为 no,则会在远程主机上查找以 src 字段的值为文件
- src 源文件路径(可以是主控端/远程主机路径,远程路径需配合copy=no)
- dest 解压目标路径(强制参数)
- mode 设置解压后文件权限
- remote_src true 代表压缩包在远程主机上,false 代表压缩包在控制主机上
| # 从主控端解压文件到远程主机(默认copy=yes)
ansible node1 -m unarchive -a 'src=foo.tgz dest=/var/lib/foo'
# 解压远程主机上的压缩包并设置权限777
ansible node1 -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777'
# 解压远程主机上的压缩包到远程主机
ansible node1 -m unarchive -a 'src=~/2/1.tar.gz remote_src=true dest=/home/moloom/2'
|
2.4.8 Archive
远程主机目录打包压缩。参数说明:
- path 要打包的目录路径(强制)
- dest 生成的压缩包路径(强制)
- format 压缩格式(zip/tar/bz2/gz等)
- owner 设置文件属主
- mode 设置文件权限
| # 将/etc/sysconfig目录打包为bz2格式,并设置权限
ansible all -m archive -a 'path=/etc/sysconfig dest=/data/sysconfig.tar.bz2 format=bz2 owner=wang mode=0777'
|
2.4.9 Hostname
管理主机名。
| # 批量修改主机组名称
ansible node1 -m hostname -a "name=app.adong.com"
# 修改单个主机名
ansible 192.168.38.103 -m hostname -a "name=app2.adong.com"
|
2.4.10 Cron
管理计划任务(增强版)。参数说明:
- name 任务唯一标识(推荐)
- job 要执行的命令(强制)
- state absent表示删除任务
- disabled yes表示禁用任务(注释)
- 时间参数:minute/hour/day/month/weekday
| # 创建每5分钟时间同步任务
ansible mohosts -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.16.0.1 &>/dev/null' name=Synctime"
# 删除指定名称的任务
ansible mohosts -m cron -a 'state=absent name=Synctime'
# 创建被禁用的计划任务
ansible mohosts -m cron -a 'minute=*/10 job="/usr/sbin/ntpdate 172.30.0.100" name=synctime disabled=yes'
|
2.4.11 Service
服务管理。参数说明:
- name 服务名称(强制)
- state 服务状态:started/stopped/reloaded/restarted
- enabled 是否开机自启
| # 停止服务
ansible node1 -m service -a 'name=httpd state=stopped'
# 启动服务并设置开机自启
ansible node1 -m service -a 'name=httpd state=started enabled=yes'
# 重启服务
ansible node1 -m service -a 'name=httpd state=restarted'
|
2.4.12 User
用户管理。参数说明:
- append 在加入多个组(非 primary 组)时,是否追加还是覆盖设置,默认 false 覆盖
- name 用户名(强制)
- system 是否系统用户
- home 指定家目录
- group 主组
- shell 指定登录shell
- password 设置密码,密码必须是加密的,用 openssl passwd -1 加密
- remove 删除用户时同时删除家目录
- state absent表示删除用户
| # 创建测试用户
ansible mohosts -m user -a 'name=user1 comment="test user" uid=2048 home=/app/user1 group=root'
# 创建系统用户
ansible mohosts -m user -a 'name=sysuser1 system=yes home=/app/sysuser1'
# 彻底删除用户(包括家目录)
ansible mohosts -m user -a 'name=user1 state=absent remove=yes'
# 创建带密码的用户,密码必须是加密的
ansible mohosts -m user -a 'name=app uid=1188 system=yes home=/home/app groups=root shell=/sbin/nologin password="$6$randomsalt$IxDD3jeSOb5eB1CX5LBsqZFVkJdido3OUILO5Ifz5iwMuTS4XMS130MTSuDDl3aCI6WouIT9pzdK6cDmPw0vL0"' --become -K
|
2.4.13 Group
用户组管理,参数说明
- gid 指定组的gid
- name 组名
- state 添加 present、删除 absent 用户组
- non_unique 是否允许 gid 不唯一,默认 false
- force 是否强制执行用户组的修改操作,默认 false
- local 是否只在本地创建组(即不使用集中认证系统),默认 false
- system 是否是系统组,默认 false
用户组管理。
| # 创建系统组
ansible srv -m group -a "name=testgroup system=yes"
# 删除用户组
ansible srv -m group -a "name=testgroup state=absent"
|
2.4.14 Lineinfile
Ansible 在使用 sed 进行替换时,经常会遇到需要转移的问题,而且 Ansible 在遇到特殊符号进行替换时,存在问题,无法正常进行替换。Ansible 提供了两个模块: Lineinfile 和 Replace 模块用于进行替换功能。
| #把 master 解析的行更改成 222
ansible mohosts -m lineinfile -a "path=/etc/hosts regexp='master$' line='222'" --become -K
#更改回来
ansible mohosts -m lineinfile -a "path=/etc/hosts regexp='222' line='192.168.1.180 master'" --become -K
#删除 222 这行
ansible mohosts -m lineinfile -a "path=/etc/fstab regexp='222' state=absent" --become -K
|
2.4.15 Replace
类似 sed 命令,也支持正则。
| #把挂载的 swap 行给取消注释
ansible mohosts -m replace -a "path=/etc/fstab regexp='^#(/swap.*)' replace='\1'" --become -K
|
2.4.16 Setup
用于收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是主机较多时性能有点差,可以使用 gather_facts: no 来禁止 Ansible 收集 facts 信息。
| #收集 node1 的所有信息
ansible node1 -m setup
#获取指定的某个 key 信息
ansible node1 -m setup -a 'filter=ansible_processor'
|
2.5 Playbook
playbook 用于部署和配置托管节点,通过编写 playbook 来实现程序的自动化部署。
2.5.1 Playbook 核心元素
- Hosts 执行的远程主机列表(应用在哪些主机上)
- Tasks 任务集
- Variables 内置变量或自定义变量在playbook中调用
- Templates模板 可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers和notify结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
- tags标签 指定某条任务执行,用于选择运行playbook中的部分代码。 ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断 ansible-playbook -t tagsname useradd.yml
2.5.2 示例
2.5.3 notfy 和 handlers
notify 会在当前 task 结束时被触发,执行所指向的 handlers 中命令。
示例如下。
| - name: test notify and handlers
hosts: mohosts
gather_facts: no #取消收集信息
tasks:
- name: print 1
shell: echo 1 > 1.txt
notify: restarted cron
- name: print 2
shell: pwd >> 1.txt
- name: print service cron info
shell: service cron status >> 1.txt
- name: restart service cron
service: name=cron state=restarted
- name: print seperate
shell: echo "\nservice cron has restarted!\n" >> 1.txt
handlers:
- name: restarted cron
service: name=cron state=restarted
- name: Check cron process
shell: killall -0 cron >> 1.txt
|
tags 用于在 play 中添加标签,这样可以在 ansible-playbook 命令中添加参数 --tags mo 来指定执行某个 play 片段
示例:只会执行 print 2
ansible-playbook AnsibleProjects/playbook/test_notify_handlers.yaml --limit master -t mo,qq
| - name: test notify and handlers
hosts: mohosts
gather_facts: no #取消收集信息
tasks:
- name: print 1
shell: echo 1 > 1.txt
- name: print 2
shell: pwd >> 1.txt
tags: mo
- name: print 3
shell: echo 3 >> 1.txt
tags: qq
|
2.5.5 playbook 中的变量
变量命名:变量名仅能由字母、数字和下划线组成,且只能以字母开头。
2.5.5.1 变量来源
- setup,可以通过 setup 模块获取被控主机信息,这些信息都是变量,可以被引用。
- ansible 默认的 inventory 文件中定义的变量也可以被引用。
- 通过命令行指定变量,优先级是最高!
ansible-playbook –e varname=value。
- 在 playbook 中定义。
- 在独立的变量 YAML 文件中定义。
- 在 role 中定义。
2.5.5.2 定义变量
2.5.5.2.1 在 playbook 中定义
| - name: define the vars
hosts: mohosts
vars:
- var1: value1
- var2: value2
tasks:
- name: print 1
shell: echo {{ var1 }} > 1.txt
|
2.5.5.2.2 单独变量 yaml 文件
| #文件名 vars.yaml
var1: value11
var2: value22
|
| # playbook.yaml
- name: test
vars_files:
- /home/moloom/vars.yaml
tasks:
- name: print 1
shell: echo {{ var1 }} > 1.txt
|
2.5.5.2.3 在 INI 类型的 inventory 文件中定义变量
| [mohosts]
master ansible_host=192.168.1.180 #注意:在这定义的只有操作 master 时才能使用
[mohosts:vars] #在这定义的在操作 mohosts 组时都能用
ansible_user=moloom
ansible_ssh_port=7777
|
使用变量
| ansible master -a 'echo {{ ansible_host }} >> 1.txt'
|
2.5.5.2.4 在命令行定义临时变量
| ansible master -e 'ansible_host=192.168.1.181' -a 'echo {{ ansible_host }} >> 1.txt'
|
2.5.5.3 调用变量
通过{{ variable_name }} 调用变量,且变量名前后必须有空格,有时用“{{ variable_name }}”才生效。
2.5.6 Template 模版
template 有点类似编程语言一样,有数组、运算符、逻辑控制(for、if、when),根据 template 模块文件动态生成对应的配置文件,使用 jinja2 语法格式。
template文件必须存放于templates目录下,且以 .j2 结尾.
| ├── temnginx.yml
└── templates
└── nginx.conf.j2
|
2.5.6.1 基本语法
| Jinja2语言,使用字面量,有下面形式
字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and,or,not
流表达式:For,If,When
|
2.5.6.2 示例
| #示例:利用template 同步nginx配置文件
#vim temnginx.yml
- hosts: master
remote_user: root
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
# templates/nginx.conf.j2
worker_processes {{ ansible_processor_vcpu+2 }}
|
2.5.6.3 when 分支结构
需要将某个执行结果作为判断条件时使用。
| # 注意:在 when 语句后面取值不需要用双花括号 {{}} 。
- name: test when
hosts: master
gather_facts: no # 取消收集信息
tasks:
- name: Run /bin/false
command: /bin/false
register: result
ignore_errors: True
#第一个 task 执行失败时执行
- name: Run /bin/something if previous task failed
command: /bin/pwd
when: result is failed
#第一个 task 执行成功时执行
- name: Run /bin/something_else if previous task succeeded
command: /bin/something_else
when: result is succeeded
#第一个 task 被跳过时执行
- name: Run /bin/still/something_else if previous task was skipped
command: /bin/still/something_else
when: result is skipped
|
2.5.6.4 with_items
用于重复性执行任务。对迭代项的引用,固定变量名为"item"。
| # 注意:在 when 语句后面取值不需要用双花括号 {{}} 。
- name: test when
hosts: master
gather_facts: no # 取消收集信息
tasks:
- name: Run /bin/false
command: /bin/false
register: result
ignore_errors: True
#第一个 task 执行失败时执行
- name: Run /bin/something if previous task failed
command: /bin/pwd
when: result is failed
#第一个 task 执行成功时执行
- name: Run /bin/something_else if previous task succeeded
command: /bin/something_else
when: result is succeeded
#第一个 task 被跳过时执行
- name: Run /bin/still/something_else if previous task was skipped
command: /bin/still/something_else
when: result is skipped
#with_items 还可以嵌套子变量
- name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
|
2.5.6.5 条件分支语法 for 、if
示例
| # temnginx.yml
---
- hosts: testweb
remote_user: root
vars: # 调用变量
nginx_vhosts:
- listen: 8080 #列表 键值对
- server_name: 127.0.0.1
# templates/nginx.conf.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
{% if vhost.server_name is defined %}
server_name {{ vhost.server_name }}
{% endif %}
}
{% endfor %}
#生成的结果
server {
listen 8080
}
|
2.6 Roles
roles 是 1.2 版本引入的新特性,用于层次性、结构化地组织 playbook。roles 能够根据层次型结构自动装载变量文件、tasks 以及 handlers 等。roles 就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷地 include 它们的一种机制,类似于 docker compose 的编排技术。
2.6.1 通过 Roles 传递参数
当给一个主机应用角色的时候可以传递变量,然后在角色内使用这些变量。
| - hosts: master
roles:
- common #调用第一个 role
# 调用 foo_app_instance ,后面的 dir 和 port 是给 role 传参
- { role: foo_app_instance, dir: '/web/htdocs/a.com', port: 8080 }
|
2.6.2 条件使用 Roles
角色也可以条件调用。
| - hosts: master
roles:
# 当 when 后面的条件成立,才会调用 some_role
- { role: some_role, when: "ansible_os_family == 'RedHat'" }
|
2.6.3 Roles 目录结构
| roles/
└── projectName/ # 项目名称,以下每个目录必须至少有一个 main.yaml 文件!!!!
├── tasks/ # 定义 task, role 的基本元素
│ └── main.yaml
├── files/ # 存放由 copy 或 script 模块等调用的文件
│ └── main.yaml
├── vars/ # 定义变量
│ └── main.yaml
├── templates/ # template 模块查找所需要模板文件的目录
│ └── main.yaml
├── handlers/ # 其它的文件需要在此文件中通过 include 进行包含
│ └── main.yaml
├── default/ # 不常用,设定默认变量时使用此目录中的 main.yml 文件
│ └── main.yaml
└── meta/ # 用于定义此角色的特殊设定及其依赖关系;ansible 1.3 及其以后的版本才支持
└── main.yaml
|
2.6.4 示例
在 ubuntu 上安装 nginx。
2.6.4.1 目录结构
| ├── playbook.yaml
└── roles
├── nginx
│ ├── files
│ │ └── index.html
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ └── templates
│ └── nginx.conf.j2
└── nginx_uninstall
├── files
└── tasks
└── main.yml
|
2.6.4.2 创建 playbook.yml
| - hosts: master
become: yes
roles:
#- nginx #安装 nginx
- nginx_uninstall #卸载 nginx
|
2.6.4.3 roles/nginx/tasks/main.yml
| - name: Ensure Nginx is installed
apt:
name: nginx
state: present
update_cache: yes
- name: Copy Nginx configuration template
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Restart Nginx
- name: Copy index.html to default site
copy:
src: index.html
dest: /var/www/html/index.html
- name: Ensure Nginx is enabled and running
service:
name: nginx
state: started
enabled: yes
|
2.6.4.4 roles/nginx/files/index.html
| <!DOCTYPE html>
<html>
<head>
<title>Welcome to Nginx!</title>
</head>
<body>
<h1>Hello, World!</h1>
<p>This is the default page for Nginx on Ubuntu.</p>
</body>
</html>
|
2.6.4.5 roles/nginx/handlers/main.yml
| - name: Restart Nginx
service:
name: nginx
state: restarted
|
2.6.4.6 roles/nginx/templates/nginx.conf.j2
| user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
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;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
}
|
2.6.4.7 roles/nginx_uninstall/tasks/main.yml
| - name: Stop Nginx service
service:
name: nginx
state: stopped
enabled: no
- name: Remove Nginx package
apt:
name: nginx
state: absent
purge: yes # 彻底删除配置文件
autoremove: yes # 自动删除不再需要的依赖包
- name: Remove Nginx log files
file:
path: /var/log/nginx
state: absent
- name: Remove Nginx configuration files
file:
path: /etc/nginx
state: absent
- name: Remove Nginx web root directory
file:
path: /var/www/html
state: absent
|