### Centos7 安装EPEL源
$$ yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -y
### 安装ansible
$$ yum install ansible -y
### 查看ansible版本
$$ ansible --version
ansible 2.9.23
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, Nov 16 2020, 22:23:17) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
### 修改主配置文件,取消某些选项注释
host_key_checking = False
log_path=/var/log/ansible.log
module_name = shell
/etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性(一般无需修改)
/etc/ansible/hosts 主机清单(将被管理的主机放到此文件)
/etc/ansible/roles/ 存放角色的目录
/usr/bin/ansible 主程序,命令执行文件
/usr/bin/ansible-doc 文档,查看ansible模块功能
/usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
/usr/bin/ansible-playbook 定制自动化任务,编排剧本工具
/usr/bin/ansible-pull 远程执行命令的工具
/usr/bin/ansible-vault 文件加密工具
/usr/bin/ansible-console 基于Console界面与用户交互的执行工具
### /etc/ansible/ansible.cfg
$$ vim /etc/ansible/ansible.cfg
[defaults]
# some basic default values...
#inventory = /etc/ansible/hosts # 主机清单文件
#library = /usr/share/my_modules/ # 库文件目录
#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_user = root # 默认root用户执行
#ask_sudo_pass = True # 每次执行ansible命令是否询问ssh密码
#ask_pass = True # 每次执行ansible命令是否询问ssh口令
#transport = smart
#remote_port = 22 # 端口
#module_lang = C
#module_set_locale = False
建议优化项
host_key_checking = False # 检查对应服务器的host_key,建议取消注释
log_path=/var/log/ansible.log # 日志文件,建议取消注释
module_name = command # 默认模块,建议修改成shell
### 主机清单中列举了需要批量操作的主机
主机清单格式:
1.未分组的主机,在任何组头之前指定
green.example.com
blue.example.com
192.168.100.1
192.168.100.10
2.对主机进行分组
[webservers]
alpha.example.org
beta.example.org
192.168.1.100
192.168.1.110
如果某些主机之间有一定规律,可以使用以下的方法,例如主机www.aa1.com到主机www.aa10.com
[webservers]
www.aa[1:10].com
### 用来显示模块帮助
### 格式
ansible-doc [-options] [-M MODULE_PATH]
-l --list 列出可用模块
-s --snippet 简单显示指定模块用法片段
### 示例
ansible-doc -l 列出所有模块
ansible-doc ping 查看指定模块帮助用法
ansible-doc -s ping 简单指定模块帮助用法
### 通过ssh协议,实现对远程主机的配置管理 应用部署 任务执行等功能
### 建议配置ansible端能基于密钥认证的方式来访问管理节点
# 生成密钥对
$$ ssh-keygen -t rsa -P ''
# 分发公钥
$$ ssh-copy-id -i /root/.ssh/id_rsa.pub [email protected]
### 格式
ansible <host-pattern> [-m module_name] [-a args]
ansible 主机列表 模块 参数
--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时的口令
### 示例
# 列出所有主机清单
$$ ansible all --list
# 列出web分组下的主机清单
$$ ansible web --list
# 使用ping模块检测主机状态
$$ ansible all -m ping
ansible的Host-pattern
### ansible的Host-pattern
All :表示所有Inventory中的所有主机
$$ ansible all –m ping
* :通配符
$$ ansible "*" -m ping (*表示所有主机)
$$ ansible 192.168.236.* -m ping
或关系 ":"
$$ ansible 'web:db' -m ping
$$ ansible “192.168.236.162:192.168.236.164” -m ping
逻辑与 ":&"
$$ ansible 'web:&db' –m ping
逻辑非 ":!"
$$ ansible 'websrvs:!dbsrvs' –m ping
也支持正则表达式
$$ ansible "~(web|db).*\.aaa\.com" –m ping
ansible命令执行过程
### 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退出
### 执行状态:
绿色:执行成功并且不需要做改变的操作
黄色:执行成功并且对目标主机做变更
红色:执行失败
### 执行状态的颜色修改:
$$ vim /etc/ansible/ansible.cfg
[colors]
#highlight = white
#verbose = blue
#warn = bright purple
#error = red
#debug = dark gray
#deprecate = purple
#skip = cyan
#unreachable = red
#ok = green
#changed = yellow
#diff_add = green
#diff_remove = red
#diff_lines = cyan
### 该工具会连接 https://galaxy.ansible.com 去下载相应的roles
### 示例
# 安装
$$ ansible-galaxy install geerlingguy.redis
# 卸载
$$ ansible-galaxy remove geerlingguy.redis
# 列出
$$ ansible-galaxy list
### 该工具用来将ansible的命令推送至远程
### 用来执行编写好的playbook任务
### 示例
# 编写一个简单的playbook
$$ cat test.yaml
# test yaml file
- hosts: web-test
remote_user: root
tasks:
- name: hello world
command: /usr/bin/wall hello world
# 执行(部分输出未进行排版)
$$ ansible-playbook test.yaml
192.168.236.162: ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
### 用于加密解密yaml文件
### 示例
# 加密 需要设置密码 加密后无法直接被运行
$$ ansible-vault encrypt test.yaml
# 解密
$$ ansible-vault decrypt test.yaml
# 查看
$$ ansible-vault view test.yaml
# 编辑
$$ ansible-vault edit test.yaml
# 修改密码
$$ ansible-vault rekey test.yaml
### 在远程主机上执行命令,此为默认模块,可忽略-m选项
### 该模块不支持$VARNAME < > | ; &等,需要使用shell模块
### 格式参数
$$ ansible-doc -s command
- name: Execute commands on targets
command:
argv: # 以列表而不是字符串的形式传递命令。使用'argv'来避免引用会被错误解释的值(例如"user name")。
# 只能提供字符串或列表形式,不能同时提供两者。必须提供其中一种。
chdir: # 在运行该命令之前,先切换到此目录。
cmd: # 要运行的命令
creates: # 如果文件名或者glob已经存在,则不会运行该步骤
free_form: # 命令模块使用自由形式的命令运行
removes: # 如果文件名或者glob存在,则会运行该步骤
stdin: # 设置命令的输入
stdin_add_newline: # 如果设置为' yes',则在stdin data后面附加一个换行符。
strip_empty_ends: # 删除输出末尾的空行
warn: # 启用或禁用任务警告。
### 示例 (在前面已经修改了ansible配置文件,将默认模块修改为shell了,因此这里需要指定模块名)
$$ ansible all -m command -a "ls"
$$ ansible all -m command -a "creates=anaconda-ks.cfg ls"
### 和command相似,支持$VARNAME < > | ; &等
### 格式参数
$$ ansible-doc -s shell
- name: Execute shell commands on targets
shell:
argv: # 以列表而不是字符串的形式传递命令。使用'argv'来避免引用会被错误解释的值(例如"user name")。
# 只能提供字符串或列表形式,不能同时提供两者。必须提供其中一种。
chdir: # 在运行该命令之前,先切换到此目录。
cmd: # 要运行的命令
creates: # 如果文件名或者glob已经存在,则不会运行该步骤
free_form: # 命令模块使用自由形式的命令运行
removes: # 如果文件名或者glob存在,则会运行该步骤
stdin: # 设置命令的输入
stdin_add_newline: # 如果设置为' yes',则在stdin data后面附加一个换行符。
strip_empty_ends: # 删除输出末尾的空行
warn: # 启用或禁用任务警告。
### 示例
$$ ansible all -a "remove=anaconda-ks.cfg ls"
$$ ansible all -a 'echo $HOSTNAME'
### 在远程主机上执行ansible端的脚本文件
### 格式参数
$$ ansible-doc -s script
- name: Runs a local script on a remote node after transferring it
script:
chdir: # 在运行该脚本之前,先切换到此目录。
cmd: # 本地脚本的路径,后面可接可选参数
creates: # 远程主机上若存在该文件,则不会运行该步骤
decrypt: # 对文件进行自动解密
executable: # 用来调用脚本的可执行文件的名称或路径。
free_form: # 本地脚本文件的路径,后面跟着可选参数。
removes: # 远程主机上若不存在该文件,则不会运行该步骤
### 示例
# 编写一个简单的脚本
$$ cat test.sh
#! /bin/bash
# Desc: 测试ansible的script模块
# Time:2021-07-12
NAME=$HOSTNAME
echo "My hostname is ${NAME}"
# ansible端执行
$$ ansible all -m script -a test.sh
### 从ansible端拷贝文件到远程主机
### 格式参数
$$ ansible-doc -s copy
- name: Copy files to remote locations
copy:
attributes: # 执行完后的文件或者目录应该具有的属性(lsattr查看权限),默认是=
backup: # 创建一个包含时间戳信息的备份文件
checksum: # 传输文件的SHA1校验和。用于验证文件的副本是否成功。若没有提供,则使用src文件的本地计算校验和。
content: # 代替'src'使用,将文件的内容设置为指定的值。仅当'dest'是一个文件时工作。如果文件不存在,则创建文件。
decrypt: # 对源文件进行自动解密。
dest: # (必需)目的文件绝对路径。如果src是一个目录,那么它也必须是一个目录。如果目的是一个不存在的路径,并且以'/'结尾,或者'src'是一个目录,则dest被创建。如果src和dest是文件,则dest的父目录不会被创建,如果目录不存在,则任务会失败。
directory_mode: # 当执行递归复制时,设置目录的模式。如果没有设置,我们将使用系统默认值。该模式只设置在新创建的目录上,不会影响那些已经存在的目录。
follow: # 保留文件系统的链接
force: # 是否始终必须替换远程文件。如果是,当内容与源文件不同时,远程文件将被替换。否则只在目标不存在时传输文件。
group: # 设置文件/目录的所属组
local_follow: # 保留源代码树中的文件系统链接
mode: # 文件/目录的权限,可使用数字/符号模式(0644/"644"),也可以是特殊字符串'preserve'(与源文件相同权限)
owner: # 设置文件/目录的所属者
remote_src: # “src”是否需要转移或远程已经存在。如果no,它将在源机器上搜索'src'。如果yes,它将转到远程的'src'
selevel: # selinux的级别
serole: # SELinux文件上下文的角色部分
setype: # SELinux文件上下文的类型部分
seuser: # SELinux文件上下文的用户部分。
src: # 源文件路径。目录会递归复制。如果以“/”结尾,则只复制目录的内容。否则,则目录本身也将被复制。
unsafe_writes: # 影响使用原子操作来防止数据损坏或从目标文件读取不一致。
validate: # 拷贝前需要执行的验证命令
### 示例
$$ ansible all -m copy -a "src=test.sh dest=/root/ mode=0644"
$$ ansible all -m copy -a "src=/tmp/ dest=/tmp/ mode=0644 owner=zabbix"
### 与copy相反,从远程主机拉取文件值ansible端,目前不支持目录操作
### 格式参数
$$ ansible-doc -s fetch
- name: Fetch files from remote nodes
fetch:
dest: # (必需)保存文件的目录,上级目录为主机名
fail_on_missing: # 当设置为“yes”时,如果远程文件由于任何原因无法读取,任务将失败
flat: # 允许覆盖将主机名/路径/附加到/file到目标的默认行为。
src: # (必需)远程系统上要获取的文件。目前只支持文件操作
validate_checksum: # 在获取文件之后,验证源和目标校验和是否匹配。
### 示例
# 拉取文件
$$ ansible all -m fetch -a "src=/etc/hostname dest=./tmp"
# 查看 可以发现ansible以主机名创建了相应的目录,避免了目录冲突
$$ tree tmp
tmp
├── 192.168.236.162
│ └── etc
│ └── hostname
└── 192.168.236.164
└── etc
└── hostname
### 用来设置文件属性
### 格式参数
$$ ansible-doc -s file
- name: Manage files and file properties
file:
access_time: # 设置文件的访问时间
access_time_format: # 与'access_time'一起使用时,表示必须使用的时间格式。基于默认的Python格式
attributes: # 文件或者目录应该具有的特权属性
follow: # 保持文件系统链接
force: # 当源文件不存在(但稍后会出现)或者目标已经存在,并且是一个文件时创建软链接
group: # 文件或目录的所属组
mode: # 文件/目录的权限,可使用数字/符号模式(0644/"644")
modification_time: # 设置文件的修改时间
modification_time_format: # 当与' modification_time'一起使用时,表示必须使用的时间格式。基于默认的Python格式
owner: # 设置文件或目录的所属者
path: # (必需)文件的路径
recurse: # 递归地设置目录内容上的文件属性
selevel: # SELinux文件上下文的级别部分
serole: # SELinux文件上下文的角色部分
setype: # SELinux文件上下文的类型部分
seuser: # SELinux文件上下文的用户部分
src: # 要链接到的文件的路径。这只适用于' state=link'和' state=hard','touch'创建文件
state: # 'absent'删除,'directory'递归创建中间子目录,'hard'/'link'链接文件
unsafe_writes: # 使用原子操作来防止数据损坏或从目标文件读取不一致
### 示例
# 创建空文件
$$ ansible all -m file -a "state=touch path=/tmp/touch.txt"
# 删除文件
$$ ansible all -m file -a "state=absent path=/tmp/touch.txt"
# 创建目录
$$ ansible all -m file -a "state=directory path=/tmp/1/2/3 owner=zabbix group=zabbix"
### 打包压缩
### 格式参数
$$ ansible-doc -s archive
- name: Creates a compressed archive of one or more files or trees
archive:
attributes: # 执行完后的文件或者目录应该具有的属性(lsattr查看权限),默认是=
dest: # 压缩文件名
exclude_path: # 排除文件列表路径
force_archive: # 强制打包不压缩
format: # 要使用的压缩类型
group: # 所属组
mode: # 权限设置
owner: # 所属组
path: # (必需)需要压缩的文件或目录的绝对路径
remove: # 删除任何添加到存档后的源文件和树。
selevel: # SELinux文件上下文的级别部分
serole: # SELinux文件上下文的角色部分
setype: # SELinux文件上下文的类型部分
seuser: # SELinux文件上下文的用户部分
unsafe_writes: # 使用原子操作来防止数据损坏或从目标文件读取不一致
### 示例
$$ ansible all -m archive -a "path=""/root/ dest=/tmp/aaa.tar.gz"
### 和archive作用相反,解包解压缩
有两种使用方法:
1 将ansible端的压缩文件传到远程主机后解压缩至特定目录,设置copy=yes.
2 将远程主机上的某个压缩文件解压缩到指定路径下,设置copy=no
### 格式参数
ansible-doc -s unarchive
- name: Unpacks an archive after (optionally) copying it from the local machine.
unarchive:
attributes: # 执行完后的文件或者目录应该具有的属性(lsattr查看权限),默认是=
copy: # 执行模式,yes/no
creates: # 如果指定的绝对路径(文件或目录)已经存在,则不会运行此步骤。
decrypt: # 对文件自动解密
dest: # (必需)解压归档文件的远程绝对路径。
exclude: # 需要排除的文件列表
extra_opts: # 通过传入一个数组来指定其他选项
group: # 所属组
keep_newer: # 不要替换比存档中的文件更新的现有文件。
list_files: # 如果设置为True,则返回tarball中包含的文件列表。
mode: # 文件权限
owner: # 所属者
remote_src: # 'yes'表示归档文件已经在远程系统上,而不是在Ansible端。这个选项与“copy”是互斥的
selevel: # SELinux文件上下文的级别部分
serole: # SELinux文件上下文的角色部分
setype: # SELinux文件上下文的类型部分
seuser: # SELinux文件上下文的用户部分
src: # (必需)归档文件复制到远程的本地路径,当remote_src设置为yes,表示要解压缩的现有存档文件的路径。
unsafe_writes: # 使用原子操作来防止数据损坏或从目标文件读取不一致
validate_certs: # 只适用于使用https URL作为文件源的情况,使用证书
### 示例
# 创建一个空目录
$$ ansible all -m file -a "state=directory path=/root/tmp/test"
# 将之前压缩的文件进行解压缩
$$ ansible all -m unarchive -a "src=/tmp/aaa.tar.gz dest=/root/tmp/ copy=no"
# 在ansible端创建一个压缩文件
$$ tar -cvzf /tmp/test.tar.gz /root/*
# 解压缩至远程主机
$$ ansible all -m unarchive -a "src=/tmp/test.tar.gz dest=/root/tmp/ mode=0644 owner=zabbix"
### 管理主机名
### 格式参数
$$ ansible-doc -s hostname
- name: Manage hostname
hostname:
name: # (必需)主机名
use: # 使用哪个策略来更新主机名
### 示例
$$ ansible 192.168.236.162 -m hostname -a "name=agent01"
### 设置定时任务
### 格式参数
$$ ansible-doc -s cron
- name: Manage cron.d and crontab entries
cron:
backup: # 修改前备份crontab
cron_file: # 指定crontab的文件(通过该文件来设置crontab)
disabled: # disabled注释
env: # 环境变量
insertafter: # 与'state=present'和env一起使用。如果指定,则在声明指定环境变量后插入该环境变量
insertbefore: # 与'state=present'和env一起使用。如果指定,则在声明指定环境变量前插入该环境变量
job: # 任务
name: # (必需)条目名
reboot: # 重新执行
special_time: # 特殊时间规范
state: # 任务状态
user: # 任务的所属者
minute: # 分
hour: # 时
day: # 日
month: # 月
weekday: # 周
### 示例
# 设置定时任务
$$ansible 192.168.236.162 -m cron -a "name=test-job minute=*/5 job='/usr/bin/bash echo hello'"
# 查看定时任务
$$ ansible 192.168.236.162 -a "crontab -l"
# 取消定时任务(注释)
$$ ansible 192.168.236.162 -m cron -a "name=test-job job='/usr/bin/bash echo hello' disabled=yes"
# 取消定时任务(删除)
$$ ansible 192.168.236.162 -m cron -a "name=test-job state=absent"
### 管理rpm软件包
### 格式参数
$$ ansible-doc -s yum
- name: Manages packages with the `yum' package manager
yum:
allow_downgrade: # 是否允许降版本安装软件包
autoremove: # 自动卸载不必要软件
bugfix: # 如果设置为'yes',并且'state=latest',则只安装被标记为bug修复相关的更新。
conf_file: # 远程yum配置文件
disable_excludes: # 禁用yum配置文件中定义的排除
disable_gpg_check: # 是否关闭对正在安装包的签名进行GPG检查
disable_plugin: # 通过plugin名称禁用plugin
disablerepo: # 禁用存储库
download_dir: # 指定下载目录
download_only: # 只下载不安装
enable_plugin: # 通过plugin名称启用plugin
enablerepo: # 启用存储库
exclude: # 当state=present或latest时排除的包名
install_weak_deps: # 安装有弱依赖关系链接的所有包
installroot: # 指定一个替代的安装根,所有的包都将相对于它安装。
list: # 列出软件包名
lock_timeout: # 等待lock被释放的时间
name: # 软件包名
releasever: # 软件版本
security: # 只安装标记为安全相关的更新
skip_broken: # 跳过依赖关系损坏的包(devsolve)会导致的问题
state: # 对软件包的操作状态,安装还是删除
update_cache: # 检查缓存是否过期,只有state为'latest'时才有效果
update_only: # 只更新,只有state为'latest'时才有效果
use_backend: # 默认情况下,该模块将基于' ansible_pkg_mgr'事实选择后端。
validate_certs: # 只适用于使用https URL作为文件源的情况,使用证书
### 示例
#安装
$$ ansible all -m yum -a "name=tree"
# 列出tree的信息
$$ ansible all -m yum -a "list=tree"
# 卸载
$$ ansible all -m yum -a "name=tree state=absent"
### 管理服务
### 格式参数
$$ ansible-doc -s service
- name: Manage services
service:
arguments: # 其他参数
enabled: # 服务是否需要自启
name: # (必需)服务名
pattern: # 如果服务不响应状态命令,则命名一个要子字符串作为状态结果的替代。找到该字符串则假定服务已启动。
runlevel: # 此服务所属的运行级别
sleep: # 停止和启动命令之间休眠时间
state: # 服务状态
use: # 设置使用模块
### 示例
# 启动服务
$$ ansible all -m service -a "name=zabbix-agent.service state=started"
# 停止服务
$$ ansible all -m service -a "name=zabbix-agent.service state=stopped"
### 管理用户
### 格式参数
# ansible-doc -s user
- name: Manage user accounts
user:
append: # yes则将用户添加到groups中指定的组,否则将只被添加到groups中指定的组,并从所有其他组中删除它们
authorization: # 设置用户的授权
comment: # 设置用户帐户的描述
create_home: # 是否创建家目录,默认创建
expires: # 过期时间
force: # 当删除用户时,强制删除用户和相关目录
generate_ssh_key: # 是否为用户生成SSH密钥
group: # 设置用户的主组
groups: # 设置用户需要加入的组列表
home: # 设置家目录
local: # 强制在实现它的平台上使用“本地”命令替代
login_class: # 设置用户的登录方式
move_home: # 尝试将用户的旧主目录移动到指定的目录
name: # (必需)用户名
non_unique: # 当与-u选项一起使用时,此选项允许将用户ID更改为非惟一值。
password: # 密码
password_lock: # 锁定密码
profile: # 设置用户的配置文件
remove: # 当state=absent时,它试图删除与用户关联的目录
role: # 设置用户的角色
seuser: # 启用selinux的系统上设置seuser类型
shell: # 设置用户的shell
skeleton: # 设置主骨架目录,需要“create_home”选项
ssh_key_bits: # 指定SSH密钥中要创建的位数
ssh_key_comment: # 定义SSH密钥的注释
ssh_key_file: # SSH密钥文件
ssh_key_passphrase: # 设置SSH密钥的密码
ssh_key_type: # 指定要生成的SSH密钥的类型
state: # 用户的状态
system: # 设置为系统用户
uid: # 设置uid
update_password: # 总是更新密码
### 示例
# 创建用户
$$ ansible all -m user -a "name=test shell=/usr/bin/sh create_home=no"
# 删除用户
$$ ansible all -m user -a "name=test state=absent force=yes"
### 管理组
### 格式参数
$$ ansible-doc -s group
- name: Add or remove groups
group:
gid: # 设置组的gid
local: # 强制在实现它的平台上使用“本地”命令替代
name: # (必需)组名
non_unique: # 将组id设置为非唯一
state: # 组状态
system: # 设置为系统组
### 示例
# 创建组
$$ ansible all -m group -a "name=test state=present"
# 删除组
$$ ansible all -m group -a "name=test state=absent"
### 文件替换,修改文件内容,相当于sed
### 格式参数
ansible-doc -s lineinfile
- name: Manage lines in text files
lineinfile:
attributes: # 文件的特殊权限
backup: # 创建一个包含时间戳信息的备份文件
backrefs: # yes时,如果没有匹配,则文件保持不变。如果匹配了,把匹配内容替被换为line内容。
create: # 如果文件不存在,将创建该文件
firstmatch: # 用于匹配给定正则表达式的第一行
group: # 设置文件所属组
line: # 要插入/替换到文件中的行
mode: # 文件权限
others: # 其他参数列表
owner: # 所属者
path: # (必需)操作文件的路径名
regexp: # 正则表达式
selevel: # SELinux文件上下文的级别部分
serole: # SELinux文件上下文的角色部分
setype: # SELinux文件上下文的类型部分
seuser: # SELinux文件上下文的用户部分
state: # 文件状态
unsafe_writes: # 使用原子操作来防止数据损坏或从目标文件读取不一致
validate: # 复制之前需要执行的命令
### 示例
# 将/etc/selinux/config文件中的SELINUX=disabled替换成SELINUX=enforcing
$$ ansible all -m lineinfile -a "path=/etc/selinux/config regexp="SELINUX=disabled" line="SELINUX=enforcing""
### 文件替换,修改文件内容,相当于sed
### 格式参数
ansible-doc -s replace
- name: Replace all instances of a particular string in a file using a back-referenced regular expression
replace:
after: # 如果指定,则只替换/删除匹配后的内容
attributes: # 文件特殊权限
backup: # 创建一个包含时间戳信息的备份文件
before: # 如果指定,则只替换/删除匹配项之前的内容
encoding: # 用于读写文件的字符编码
group: # 所属组
mode: # 文件权限
others: # 其他参数列表
owner: # 所属者
path: # (必需) 操作文件的路径名
regexp: # (必需) 正则表达式
replace: # 要替换regexp匹配的字符串
selevel: # SELinux文件上下文的级别部分
serole: # SELinux文件上下文的角色部分
setype: # SELinux文件上下文的类型部分
seuser: # SELinux文件上下文的用户部分
unsafe_writes: # 使用原子操作来防止数据损坏或从目标文件读取不一致
validate: # 复制之前需要执行的命令
### 示例
# 将/etc/fstab文件中以UUID开头的行替换成#开头
$$ ansible all -m replace -a "backup=yes path=/etc/fstab regexp='^(UUID)' replace='#\1'"
### 用来手机主机的系统信息,facts信息直接以变量的形式使用,但主机过多会影响到性能,可以使用gather_facts:no来禁止收集facts信息
### 格式参数
$$ ansible-doc -s setup
- name: Gathers facts about remote hosts
setup:
fact_path: # facts信息文件的路径
filter: # 如果提供,则只返回与shell风格(fnmatch)通配符匹配的信息
gather_subset: # 如果提供,则将收集到的其他信息限制到给定的子集。
gather_timeout: # 设置默认超时时间
### 示例
$$ ansible 192.168.236.164 -m setup
$$ ansible 192.168.236.164 -m setup -a "filter=ansible_user*"
playbook 由一个或多个'plays'组成.它的内容是一个以'plays'为元素的列表
在play之中,一组机器被映射为定义好的角色.在ansible中,play的内容被称为 tasks,即任务。在基本层次的应用中,一个任务是一个对 ansible 模块的调用
playbook采用YAML语言编写
hosts 执行的远程主机列表(应用在哪些主机上)
tasks 任务集
两种格式:
(1) action: module arguments
(2) module: arguments 建议使用 模块: 参数
注意:shell和command模块后面跟命令,而非key=value
variables 内置变量或自定义变量在playbook中调用
templates 可替换模板文件中的变量并实现一些简单逻辑的文件
handlers和notify 由特定条件触发的操作,满足条件方才执行,否则不执行
tags标签 指定某条任务执行,用于选择运行playbook中的部分代码。
ansible具有幂等性,因此会自动跳过没有变化的部分,此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
### 运行playbook的方式
ansible-playbook <filename.yml> ... [options]
### 常见选项
--check -C 只检测可能会发生的改变,但不真正执行操作
(只检查语法,如果执行过程中出现问题,-C无法检测出来)
(执行playbook生成的文件不存在,后面的程序如果依赖这些文件,也会导致检测失败)
--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 web 限制主机
$$ vim create_user_group.yaml
# 编写playbook来创建用户和组
---
# 主机清单
- hosts: all
# 执行任务的用户
remote_user: root
# 不进行系统信息的收集
gather_facts: no
# 任务集
tasks:
- name: create user
user: name=yup shell=/usr/bin/bash
- name: create group
group: name=yup_group
### 检查playbook是否正确
$$ ansible-playbook create_user_group.yaml -C
### 执行
$$ ansible-playbook create_user_group.yaml
$$ vim install_nginx.yaml
# centos7安装nginx
---
- hosts: all
remote_user: root
gather_facts: no
tasks:
- name: install repo
shell: cmd="rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm"
- name: install nginx
yum: name=nginx state=present
- name: start nginx service
service: name=nginx state=started
Handlers(触发器)
是task列表,这些task与前述的task并没有本质上的不同,用于当关注的资源发生变化时,才会采取一定的操作。
Notify(通知)
此action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成最后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。
应用场景
当我们修改了某些程序的配置文件以后,有可能需要重启应用程序,以便能够使新的配置生效
示例
### 将nginx的端口修改为6666,然后使得配置生效
# 修改centos7上面的nginx配置文件,并重启生效
---
- hosts: all
remote_user: root
gather_facts: no
tasks:
- name: modify conf
replace: path=/etc/nginx/conf.d/default.conf regexp="(.*)listen(.*)80;" replace="\\1listen 6666;" backup=yes
notify: restart nginx
handlers:
- name: restart nginx
service: name=nginx state=restarted
tags: 添加标签
可以指定某一个任务添加一个标签,添加标签以后,想执行某个动作可以做出挑选来执行
多个动作可以使用同一个标签
示例
$$ vim test_tags.yaml
# 测试tags组件
---
- hosts: all
remote_user: root
gather_facts: no
tasks:
- name: test01
yum: name=httpd state=present
tags: install
- name: test02
yum: name=httpd state=absent
tags: absent
### 只运行absent的任务
$$ ansible-playbook --tags "absent" test_tags.yaml
### 只运行absent之外的任务
$$ ansible-playbook --skip-tags "absent" test_tags.yaml
# 变量名:由字母、数字和下划线组成,且只能以字母开头
# 变量定义:key=value
# 变量来源:
1> setup模块返回系统变量
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个数
2> 在/etc/ansible/hosts(主机清单)中定义变量
普通变量:主机组中主机单独定义,优先级高于公共变量(单个主机 )
公共(组)变量:针对主机组中所有主机定义统一变量(一组主机的同一类别)
3> 通过命令行指定变量,优先级最高
ansible-playbook –e varname=value
4> 在playbook中定义
vars:
- var1: value1
- var2: value2
5> 在独立的变量YAML文件中定义
6> 在role中定义
# 变量调用方式:
1> 通过{{ variable_name }} 调用变量,且变量名前后必须有空格,有时用“{{ variable_name }}”才生效
2> ansible-playbook –e 选项指定
ansible-playbook test.yml -e "hosts=www"
# 变量优先级
变量的默认加载顺序如下:
roles defaults目录下的变量
组变量:inventory 文件
组变量:inventory/group_vars/all
组变量:playbook/group_vars/all
组变量:inventory/group_vars/*
组变量:playbook/group_vars/*
主机变量:inventory 文件
主机变量:inventory/group_vars/*
主机变量:playbook/group_vars/*
facts变量
play变量:vars定义的
play变量:vars_prompt定义的
play变量:vars_files导入的
roles vars目录下的变量
block中task定义的变量
playbook中task定义的变量
include_vars导入的变量
set_facts/register注册的变量
使用roles/include_role/import_role语句时定义的变量
使用include语句(ansible旧版本)时定义的变量
命令行-e参数指定的额外变量(优先级最高)
### 不能禁用ansible收集facts信息的功能
$$ vim setup_var.yaml
# setup设置变量
---
- hosts: all
remote_user: root
tasks:
- name: test01
file: path=/tmp/{{ ansible_nodename }} state=touch
主机变量
可以在inventory中定义主机时为其添加主机变量以便于在playbook中使用
[websrvs]
192.168.236.162 port=80
[dbsrvs]
192.168.236.164 port=3360
组变量
组变量是指赋予给指定组内所有主机上的在playbook中可用的变量
[websrvs]
192.168.236.162
192.168.236.163
[websrvs:vars]
server_name=nginx
示例
### 编写主机清单文件
$$ vim /etc/ansible/hosts
[web-test]
192.168.236.162 port=6666
[db-test]
192.168.236.164 port=3306
[web-test:vars]
server_name=nginx
### 命令行使用变量
$$ ansible all -m file -a "path=/tmp/{{ port }}.txt state=touch"
$$ vim cmd_var.yml
- hosts: all
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }} state=present
### 命令行指定变量名
ansible-playbook –e pkname=httpd var.yml
$$ vim playbook_var.yml
- hosts: all
remote_user: root
vars:
- username: user1
- groupname: group1
tasks:
- name: create group
group: name={{ groupname }} state=present
- name: create user
user: name={{ username }} state=present
### 执行
ansible-playbook var.yml
ansible-playbook -e "username=user2 groupname=group2” var2.yml
$$ cat vars.yml
var1: httpd
var2: nginx
$$ cat var.yml
- hosts: all
remote_user: root
vars_files:
- vars.yml
tasks:
- name: create httpd log
file: name=/app/{{ var1 }}.log state=touch
- name: create nginx log
file: name=/app/{{ var2 }}.log state=touch
hostname zabbix_agent01 hostname模块 不支持"_",认为"_"是非法字符
hostnamectl set-hostnamezabbix_agent01 可以更改主机名
见后续role
一个文本文件,用来做为生成文件的模板,可以签到jinja语法
# 使用字面量,有下面形式
字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and,or,not
流表达式:for,if,when
jinja2文档
template功能:根据模块文件动态生成对应的配置文件
template文件必须存放于templates目录下,且命名为 .j2 结尾
yaml/yml 文件需和templates目录平级,目录结构如下:
./
├── temnginx.yml
└── templates
└── xxxxx.j2
示例1
# 利用template 同步nginx配置文件
# 准备templates/nginx.conf.j2文件 在该文件中使用变量设置nginx的工作进程数
$$ grep "ansible_processor_vcpus" nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }};
$$ vim temnginx.yml
- hosts: websrvs
remote_user: root
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
# 执行playbook
$$ ansible-playbook temnginx.yml
条件测试:如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,
通过when语句实现,在task中使用,jinja2的语法格式
when语句
在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法
# 示例
tasks:
- name: "shutdown RedHat flavored systems"
command: /sbin/shutdown -h now
when: ansible_os_family == "RedHat" 当系统属于红帽系列,执行command模块
when语句中还可以使用Jinja2的大多"filter",
例如要忽略此前某语句的错误并基于其结果(failed或者success)运行后面指定的语句,
# 示例
tasks:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result|failed
- command: /bin/something_else
when: result|success
- command: /bin/still/something_else
when: result|skipped
此外,when语句中还可以使用facts或playbook中定义的变量
迭代:当有需要重复性执行的任务时,可以使用迭代机制,
对迭代项的引用,固定变量名为"item"
要在task中使用with_items给定要迭代的元素列表
列表格式:
字符串
字典
# 示例 创建用户
- name: add several users
user: name={{ item }} state=present groups=wheel # {{ item }} 系统自定义变量
with_items: # 定义{{ item }} 的值和个数
- testuser1
- testuser2
上面语句的功能等同于下面的语句:
- name: add user testuser1
user: name=testuser1 state=present groups=wheel
- name: add user testuser2
user: name=testuser2 state=present groups=wheel
with_items中可以使用元素还可为hashes
# 示例
- name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
roles
ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook。
roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。
要使用roles只需要在playbook中使用include指令即可。
简单来讲,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,
并可以便捷地include它们的一种机制。
角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
复杂场景:建议使用roles,代码复用度高
变更指定主机或主机组
如命名不规范维护和传承成本大
某些功能需多个Playbook,通过includes即可实现
# 目录结构
每个角色,以特定的层级目录结构进行组织
playbook.yml 调用角色
roles/
project/ (角色名称)
tasks/ # 定义task,role的基本元素,至少应该包含一个名为main.yml的文件,其它的文件需要在此文件中通过include进行包含
files/ # 存放由copy或script模块等调用的文件
vars/ # 定义变量,至少应该包含一个名为main.yml的文件,其它的文件需要在此文件中通过include进行包含
templates/ # template模块查找所需要模板文件的目录
handlers/ # 此目录中应当包含一个main.yml文件,用于定义此角色用到的各handler,在handler中使用include包含的其它的handler文件也应该位于此目录中;
# 创建role的步骤
(1) 创建以roles命名的目录
(2) 在roles目录中分别创建以各角色名称命名的目录,如webservers等
(3) 在每个角色命名的目录中分别创建files、handlers、tasks、templates和vars目录,用不到的目录可以创建为空目录,也可以不创建
(4) 在playbook文件中,调用各角色