自动化运维工具(ansible入门教程)
参考资料
- 官网:https://docs.ansible.com/
- Ansible中文权威指南 http://www.ansible.com.cn/docs/intro_installation.html
- Ansible中文权威指南 https://ansible-tran.readthedocs.io/en/latest/docs/intro_inventory.html
- Ansible 超详细教程 https://blog.csdn.net/MagnumLuke/article/details/136380942
- 自动化运维工具(ansible入门教程) https://luanpeng.blog.csdn.net/article/details/86701167
- 超详细ansible-playbook剧本编写 https://blog.csdn.net/weixin_49343462/article/details/112852923
1.Ansible简介
Ansible 是一个 IT 自动化工具。它可以配置系统、部署软件并协调更高级的 IT 任务,例如持续部署或零停机时间滚动更新等。
Ansible 的主要目标是简单和易用,它还非常关注安全性和可靠性,具有最少的移动部件,其使用 OpenSSH 进行传输。
2.Ansible安装
方式1:通过yum安装,系统默认pyhton3时推荐
# EPEL-release(Extra Packages for Enterprise Linux Release)是一个为企业级Linux发行版(如CentOS、RHEL等)提供额外软件包的软件仓库。通过EPEL-release,用户可以访问到由社区维护的众多软件包,这些软件包经过严格的测试和验证,确保其质量和稳定性
yum install epel-release
yum install ansible # 默认安装使用centos7系统自带python2, 需要使用python3的,建议使用pyhton3安装ansible
配置文件
/etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性(一般无需修改)
/etc/ansible/hosts 主机清单(将被管理的主机放到此文件)
/etc/ansible/roles/ 存放角色的目录
程序
/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界面与用户交互的执行工具
方式2(推荐,很多ansible脚本运维需要python3环境):通过python3-pip安装ansible,需要先安装pyhton3
# 安装EPEL
yum install epel-release
# 安装pyhton3,推荐使用编辑指定安装路径安装python3,防止覆盖系统自带python2,centos7部分版本的yum依赖系统自带python2
推荐参考python3编译安装:https://wdsheng0i.github.io/dev-ops/2021/03/31/python.html
yum install python3-pip #直接在线安装python3、pip,如系统有python2可能会被覆盖
# 安装ansible
python3 -m pip install ansible==6.0 -i https://pypi.tuna.tsinghua.edu.cn/simple #指定ansible版本,指定pip源安装
# 安装最新版本 python3 -m pip install --user ansible
# 安装指定版本: python3 -m pip install --user ansible-core==2.12.3
# 升级 Ansible: python3 -m pip install --upgrade --user ansible
Ansible 版本 最低 Python 版本要求 兼容性说明
Ansible 2.9 Python 2.7 / 3.5+ 最后一个同时支持 Python 2 和 3 的版本。
Ansible 2.10+ Python 3.6+ 官方停止对 Python 2 的支持。
Ansible 5.0+ Python 3.8+ 社区版(原 ansible-base 分支)。
Ansible 6.0+ Python 3.9+ 推荐使用最新稳定版 Python。
Ansible 7.0+ Python 3.10+ 依赖现代 Python 特性。
# 生成默认配置文件
/usr/local/python3/bin/ansible-config init --disabled > ansible.cfg
# 修改配置项
host_key_checking=False
# 查看版本:ansible --version, 若没有系统命令,先查找ansible安装路径,然后创建系统命令软连接
find / -name "ansible" #找到安装路径/usr/local/python3/bin/ansible
/usr/local/python3/bin/ansible --version #可以查看ansible版本
ln -s /usr/local/python3/bin/ansible /usr/bin/ansible #创建命令软连接
ln -s /usr/local/python3/bin/ansible-playbook /usr/bin/ansible-playbook
ln -s /usr/local/python3/bin/ansible-inventory /usr/bin/ansible-inventory
即可使用系统命令 ansible --version查看版本
方式3:在运维主机上安装ansible及相关组件
# 切换到app用户
## CentOS
sudo yum install -y python3-pip sshpass
# cd /home/app 导入安装清单
cat >> requirements.txt << EOF
ansible==2.9.20
cryptography==2.8
jinja2==2.11.3
netaddr==0.7.19
pbr==5.4.4
jmespath==0.9.5
ruamel.yaml==0.16.10
MarkupSafe==1.1.1
EOF
pip3 install -r requirements.txt
## 如果安装时报权限问题执行
sudo pip3 install -r requirements.txt
sudo chmod -R 777 /usr/local/lib/python3.6
sudo chmod -R 777 /usr/lib/python3.6
## 查看版本:ansible --version
# 在.ansible.cfg中设置主机免key检查
cat >> /home/app/.ansible.cfg << EOF
[defaults]
host_key_checking = False
EOF
3.ansible模块及使用
Ansible 模块分为三种类型 : 核心模块(core module) , 附加模块(extra module) , 用户自定义模块(consume module)
- 核心模块 : 由 Ansible 的官方团队提供的
- 附加模块 : 由各个社区提供的 , 如 OPENSTACK , DOCKER 社区等
- 用户自定义模块 : 当核心模块和附加模块都无法满足需求时 , 用户可以自定义模块
3.1 使用示例(推荐使用SSH 公密)
1.编辑默认主机清单 vi /etc/ansible/hosts, 也可以自定义文件test_hosts,执行ansible命令时,使用-i test_hosts指定资源文件
# 1.不属于任何组的单独主机, 必须放在所有主机组的前面, 也就是必须位于文件最前方, 属于 all 组
blue.example.com
192.168.100.1
# 2.主机组 sretest 包含5个主机, 调用时可以通过组名匹配主机,连续主机可以用[start:end]表示
[sretest]
10.10.10.[1:5]
[sredev]
10.10.10.[6:7]
# 3. 组可以通过children包含添加子组,继承关系
[all_server]
[all_servers:children]
sredev
sretest
[sretest:vars]
ansible_ssh_port=22
ansible_ssh_user=app
ansible_ssh_pass=123321
ansible_sudo_pass=123321
2.执行ansible命令
基本语法:ansible PATTERN -i inventory -m moudle -a argument
PATTERN : 资源匹配,可以是IP列表, 也可以是组名, 用来在 -i 参数的资产中匹配一部分, all 代表匹配所有
-i : 指定Ansible的资产 , 即被管理主机 (也可以是文件名)
-m : 指定要运行的模板 , 比如这里的 ping模块 和 copy模块
-a : 指定模块的参数 , 如下示例中ping模块没有指定参数 , copy模块指定了 src 和 dest 参数
示例:
ansible all --list-hosts #仅列出“默认主机清单”中 所有主机host
ansible-inventory -i hosts --list #列出主机host及主机链接信息,-i指定清单文件
ansible sretest -i hosts --list-hosts #仅列出“默认主机清单”中 sretest组所有主机host,-i指定清单文件
ansible all -m ping #测试默认主机清单hosts中,所有主机是否通
ansible all -m ping --limit 10.10.10.1 #测试默认主机清单hosts中,只在一台机器上执行ping
ansible sretest -i hosts -m ping #测试指定清单hosts,sretest组下的主机是否ping的通
ansible all -i 10.10.10.2,10.10.10.3 -m ping # 默认使用ssh-key链接
ansible all -m ping -u bruce #测试默认主机清单hosts中,使用用户bruce执行ping
ansible all -m ping -u bruce --become-user app #测试默认主机清单hosts中,使用用户bruce执行ping,切用户
ansible all -m shell -a 'ip a' #所有默认主机清单,所有主机上执行shell命令
ansible all -i 10.10.10.2,10.10.10.3 -m copy -a "src=/tmp/a.conf dest=/tmp/a.conf"
3.2 command & shell模块介绍
两个模块都是在远程服务器上执行命令
- command 是 ad-hoc 的默认模块 , 在执行 ad-hoc 时 , 若不指定模块的名字则默认使用此模块,模块无法执行 SHELL 的内置命令和特性
- shell 模块可以执行 SHELL 的内置命令和特性 (比如管道符)
ansible all -i hosts -a "echo 'hello world'" #缺省command模块
ansible all -i hosts -m command -a "echo 'hello world'"
ansible all -i hosts -m shell -a "echo 'hello world'"
3.3 script 模块
将管理节点上的脚本传到被管理节点(远程服务器)上进行执行 , 理论上此模块的执行完全不需要被管理服务器上有Python
# 1.准备shell脚本
echo "touch /tmp/testfile" > /root/a.sh
# 2.分发并执行脚本
ansible webservers -i hosts -m script -a "/root/a.sh"
# 3.查看结果
ansible all -i hosts -m shell -a "ls -l /tmp"
3.4 copy 模块
copy 模块主要用于管理节点和被管理节点之间的文件拷贝 , 经常用到如下参数 :
- src 指定拷贝文件的源地址
- dest 指定考本文件的目标地址
- backup 拷贝文件前 , 若目标的原始文件发生变化 , 则对目标文件进行备份
- woner 指定新拷贝文件的所有者
- group 指定新拷贝文件的所有组
- mode 指定新拷贝文件的权限
# 复制本机/etc/hosts文件到被管理机的opt文件下
ansible all -i hosts -m copy -a "src=/etc/hosts dest=/opt"
# 复制本机/etc/hosts文件到被管理机的opt文件下 并根据情况备份文件(文件名+日期)
ansible all -i hosts -m copy -a "src=/root/hosts dest=/opt/hosts backup=yes"
# 复制本机/etc/hosts文件到被管理机的opt文件下 同时修改文件的用户及用户组)
ansible all -i hosts -m copy -a "src=/etc/hosts dest=/opt owner=nobody group=nobody"
# 复制本机/etc/hosts文件到被管理机的opt文件下 同时对文件的权限进行设置
ansible all -i hosts -m copy -a "src=/etc/hosts dest=/opt/hosts mode=0755"
3.5 yum_repsitory 模块
repo 必须是通过 Ansible 创建的才能进行管理
3.6 yum 模块
等同于 Linux 上的 yum 命令 , 对远程服务器上 RPM 包进行管理 , 常用参数如下
- name 要安装的软件包名 , 多个软件包以 ( , ) 隔开
- state 对当前指定的软件安装 , 移除操作 (present installed latest absent removed)
- present 确认已经安装 , 但不升级
- installed 确认已经安装
- latest 确保安装 , 且升级为最新
- absent 和 removed 确认已删除
# 安装一个软件包
ansible all -i hosts -m yum -a "name=nginx state=present"
ansible all -i hosts -m yum -a "name=nginx state=installed"
ansible all -i hosts -m yum -a "name=nginx state=latest"
# 检查是否安装
ansible all -i /etc/ansible/hosts -m shell -a "nginx -version"
# 移除一个软件包
ansible all -i /etc/ansible/hosts -m yum -a "name=nginx state=absent"
ansible all -i /etc/ansible/hosts -m yum -a "name=nginx state=removed"
# 安装一个软件包组
ansible all -i /etc/ansible/hosts -m yum -a "name='@Developmenttools' state=present"
3.7 systemd 模块
CentOS6 之前的版本使用 service 模块 , 使用 ansible-doc service 命令查看帮助信息
管理远程节点上的 systemd 服务 , 就是由 systemd 所管理的服务 , 常用参数如下
- daemon_reload 重新载入 systemd , 扫描新的或有变动的单元 , 值为yes
-
enabled 是否开机自启动 yes no - name 必选项 , 服务名称 , 比如 httpd , vsftpd 等
- state 对当前服务执行启动 , 停止 , 重新加载等操作 (started , stopped , restarted , reloaded)
# 重新加载 systemd
ansible all -i /etc/ansible/hosts -m systemd -a "daemon_reload=yes"
# 启动 nginx
ansible all -i /etc/ansible/hosts -m systemd -a "name=nginx state=started"
# 关闭 nginx
ansible all -i /etc/ansible/hosts -m systemd -a "name=nginx state=stopped"
3.8 group 模块
对被管理节点的组进行管理 , 常用参数如下
- name 组名称 , 必须的
-
system 是否为系统组 , yes no
ansible all -i /etc/ansible/hosts -m group -a "name=mysql"
3.9 user 模块
用于对被管理节点上的用户进行管理 , 常用参数如下 :
- name 必须的参数 , 指定用户名
- password 设置用户的密码 , 这里接受的是一个加密的值 , 因为会直接存到 shadow , 默认不设置密码
- update_password 加入设置的密码不同于原密码 , 则会更新密码 , 在1.3版本中被加入
- home 指定用户的家目录
- shell 设置用户的shell
- comment 用户的描述信息
- create_home 在创建用户时 , 是否创建其家目录 , 默认创建 , 加入不创建 , 设置为 no , 在2.5版本之前使用 createhome参数
- group 设置用户的主组
- groups 将用户加入到多个其他组中 , 多个用逗号隔开 , 默认会把用户从其他已经加入的组中删除
-
append 值为 yes no , 和 groups 配合使用 , 值为yes时 , 不会把用户从其他已经加入的组中删除 - system 值为 yes 时 , 会创建一个系统账户
- expires 设置用户的过期时间 , 值为时间戳 , 会转为天数后 , 放在 shadow 的第8个字段里
- generate_ssh_key 设置为yes时 , 会为用户生成密钥 , 这不会覆盖原来的密钥
- ssh_key_type 指定用户的密钥类型 , 默认rsa , 具体的类型取决于被管理节点
- state 删除或添加用户 , yes 为添加 , absent 为删除 , 默认值为 yes
- remove 当与 state=absent 一起使用时 , 删除一个用户及关联的目录 , 比如家目录 , 邮箱目录 , 可选的值为 yes/no
# 生成加密密码/
pass=$(echo “LML123456” | openssl passwd -l -stdin)
# 查看
echo $pass
# 创建账号,设置密码
ansible all -i /etc/ansible/hosts -m user -a "name=foo password=${pass}"
# 创建账号,设置密码,改密钥类型
ansible all -i /etc/ansible/hosts -m user -a "name=Dragon password=${pass} ssh_key_type=ecdsa"
# 创建账号,设置密码,有效期,加组
ansible all -i /etc/ansible/hosts -m user -a "name=Cai password=${pass} group=db_admin append=yes"
3.10 file 模块
file模块主要用于远程主机上的文件操作 , 常用参数
- group 定义文件/目录的属组
- mode 定义文件/目录的而权限
- owner 定义文件/目录属组
- path 必选项 , 操作文件/目录 的路径
- recurse 递归的设置文件的属性 , 只对目录有效
- src 要被链接(软/硬)的源文件的路径 , 值用于 state=link 的情况
- dest 被链接到的路径 , 只应用于 state=link 的情况
- state 对文件执行什么操作 ?
- directory 如果目录不存在则创建目录
- file 文件不存在则不不会被创建 , 存在则返回文件的信息 , 常用于检查文件是否存在
- link 创建软连接
- hard 创建硬链接
- touch 如果文件不存在 , 则会创建一个新的文件 , 如果文件或目录存在 , 则更新其最后修改时间
- absent 删除目录 , 文件或者取消链接
# 创建一个文件
ansible all -i /etc/ansible/hosts -m file -a "path=/tmp/foo.conf state=touch"
# 改变文件所有者及权限
ansible all -i /etc/ansible/hosts -m file -a "path=/tmp/foo.conf owner=nobody group=nobody mode=0644"
# 创建一个软连接
ansible all -i /etc/ansible/hosts -m file -a "src=/tmp/foo.conf dest=/tmp/link.conf state=link"
# 创建一个目录
ansible all -i /etc/ansible/hosts -m file -a "path=/tmp/test_dir state=directory"
# 取消一个链接
ansible all -i /etc/ansible/hosts -m file -a "path=/tmp/link.conf state=absent"
# 删除一个文件
ansible all -i /etc/ansible/hosts -m file -a "path=/tmp/foo.conf state=absent"
3.11 cron 模块
注意 : 使用 Ansible 创建的计划任务 , 是不能使用本地 crontab -e 去编辑 , 否则 Ansible 无法再次操作此计划任务
管理远程节点的 CRON 服务 , 等同于 Linux 中的计划任务 , 常用参数如下,
- name 指定一个 cron job 的名字 , 一定要指定 , 便于日后删除
- minute 指定分钟 , 可以设置成(0-59 , * , /2 等)格式 , 默认是 * , 也就是每分钟
- hour 指定小时 , 可以设置达成(0-23 , * , */2等)格式 , 默认是 * , 也就是每小时
- day 指定天 , 可以设置成(1-31 , * , */2 等)格式 , 默认是 * , 也就是每天
- month 指定月份 , 可以设置成(1-12 , * , */2 等)格式 , 默认是 * , 也就是每周
- weekday 指定星期 , 可以设置成(0-6 for Sunday-Saturday , * 等)格式 , 默认是* , 也就是每天
- job 要执行的内容 , 通常可以写个脚本 , 或者一段内容
- state 指定这个 job 的状态 , 可以是新增(present) , 或者是删除(absent) , 默认为(present)
# 创建一个 cron job 任务
[root@manager ~]# ansible all -i /etc/ansible/hosts -m cron -a "name=newJob minute='0' job='ls -alh > /dev/null'"
# 验证
[root@host1 ~]# crontab -l
#Ansible: newJob
0 * * * * ls -alh > /dev/null
# 删除一个 cron job 任务
[root@manager ~]# ansible all -i /etc/ansible/hosts -m cron -a "name=newJob state=absent"
3.12 debug 模块
debug 模块主要用于调试时使用 , 通常的作用是将一个变量的值打印出来 , 常用参数如下
- var 直接打印一个指定的变量值
- msg 打印一段可以格式化的字符串
# 直接打印一个变量 (-e 是传入变量)
ansible all -i /etc/ansible/hosts -m debug -a "var=role" -e "role=web"
# 打印带字符串的 变量
ansible all -i /etc/ansible/hosts -m debug -a "msg='role is '" -e "role=web"
3.13 template 模块
template 模块使用了 jinjia2 格式作文文件模板 , 可以进行文档内变量的替换 ,它的每次使用都会被 ansible 标记为 “changed” 状态 , 文件以 .j2 结尾 , 常用参数如下
- src 指定 Ansible 控制端的文件路径
- dest 指定 Ansible 被控制端的文件路径
- owner 指定文件的属主
- group 指定文件的属组
- mode 指定文件的权限
- backup 创建一个包含时间错信息的备份文件 , 这样如果以某种方式损坏了原始文件 , 就可以将其复原 , yes/no
# 1. 创建一个 hello_world.j2 文件
[root@manager ~]# cat hello_world.j2
Hello !
# 2. 执行命令 , 并且设置变量 var 的值为 world
[root@manager ~]# ansible all -i /etc/ansible/hosts -m template -a "src=hello_world.j2 dest=/tmp/hello_world.world" -e "var=world"
# 3. 在被控主机上验证
Hello world !
3.14 lineinfile 模块
在被管理节点上 , 使用正则匹配的方式对目标文件的一行内容修改删除等操作, 常用参数如下
- path 目标文件路径 , 必须的
-
state 可选值 present替换(默认 absent删除 - regexp 在文件的每一行中查找的正则表达式 , 对于 state=present , 进找到的最后一行将被替代
- line 要在文件中插入/替换的行 , 需要 state=present
- create 文件不存在时 , 是否要创建文件并添加内容 , yes/no
# 删除被控节点文件里的某一条内容
[root@manager ~]# ansible all -i /etc/ansible/hosts -m lineinfile -a "path=/etc/sudoers regexp='^%wheel' state=absent"
# 关闭远程主机的selinux
[root@manager ~]# ansible all -i /etc/ansible/hosts -m lineinfile -a "path=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=disabled' state=present"
3.15 replace 模块
在被管理节点上 , 使用正则匹配的方式对目标文件内容修改删除等操作,对一个文件中把所有匹配到的多行进行统一处理
3.16 blockinfile 模块
在被管理节点上 , 使用正则匹配的方式对目标文件内容修改删除等操作,对一个文件进行一次性 添加/更新/删除等多行内容操作
4.ansible-playbook
**Ad-Hoc 的问题 **: AD-HOC每次只能在被管理节点上执行简单的命令
日常工作中,往往面临的是一系列复杂的操作, 如可能需要安装软件,更新配置,重启服务等等一系列操作的组合,此时Ad-Hoc有些力不从心,需要使用PLAYBOOK解决这个批量多步过程性的操作问题
4.0 yml语法
ansible-playbook使用yaml文件编写;
基本语法:
- 大小写敏感
- 使用缩进表示层级关系 , 一般规范2个空格,缩进时使用 tab 键 , 还是空格 一定要达到统一 , 建议使用空格
- 相同层级的元素必须左侧对齐
- YAML 支持的数据结构有三种
字符串
# YAML 中的字符串可以不使用引号 , 即使里面存在空格的时候 , 当然使用单引号即双引号也没有错
this is a string
'this is a string'
"this is a string"
# YAML 中若一行写不下表达的内容 , 可以使用下面两种方法进行折行
long_line: |
Example 1
Example 2
Example 3
#或
long_line: >
Example 1
Example 2
Example 3
列表
# 相当于 C语言 中的数组
# 如何定义 : 以短横线开头 + 空格 + 具体的值
- red
- green
- blue
# 以上的值转为 python 的 List 会是这样的
# ['red', 'green', 'blue']
字典
# 若熟悉 python 的话, 可以认为他就是 Python 中的 Dict
# 如何定义 : key + 冒号 + 空格 + 值 , 即 key: value
name: Using Ansible
code: D1234
混合结构
class:
- name: stu1
num: 001
- name: stu2
num: 002
- name: stu3
num: 003
# 转换成 Python格式
# {'class': [{'name': '001', 'num': 1}, {'name': 'stu2', 'num': 2}, {'name': 'stu3', 'num': 3}]}
4.1 单文件定义简单playbook使用示例
task任务示例:
# 创建测试任务:vi test.yaml
---
- name: My first play
hosts: all
remote_user: root
tasks:
- name: ls file
command: ls /tmp
- name: Ping my hosts
ansible.builtin.ping:
- name: Print message
ansible.builtin.debug:
msg: Hello world
- name:copy_file
copy: src=/var/log/yum.log dest=/tmp || /bin/true #让ansible-playbook的某个模块报错也继续执行需要在模块后面加上 || /bin/true
# 执行 ansible-playbook -i hosts test.yaml
处理程序handlers与任务task完全相同(它可以做task可以做的任何事),但只有当另一个任务调用(通过notify)它时才会运行。您可以将其视为事件系统的一部分; 处理程序将通过其侦听的事件调用进行操作。
这对于运行任务后可能需要的“辅助”操作非常有用,例如在配置更改后安装或重新加载服务后启动新服务。
## 通过task安装Nginx,后调用handlers重启nginx服务
- hosts: local
connection: local
become: yes
become_user: root
tasks:
- name: Install Nginx
apt:
name: nginx
state: installed
update_cache: true
notify:
- Start Nginx
handlers:
- name: Start Nginx
service:
name: nginx
state: started
playbook定义
一个 Playbook 是由一个或多个 Play 构成,Play 中的每一个 key , 比如 key1 , key2 等 , 这些 key 在 PlayBook 中被定义为 Play 的属性
这些属性具有特殊意义 , 我们不能随意的自定义 Play 的属性 , 常用属性如下
- name 每个 play 的名字 , 用于任务执行后的回显 (一定要写)
- hosts 每个 play 涉及的被管理服务器 , 通 ad hoc 中的 pattern
- tasks 每个 play 中具体要完成的任务 , 以列表的形式表达
- become 如果需要提权 , 则加上 become 相关属性
- become_user 若提权的话 , 提权到哪个用户上
- remote_user 指定连接用户 , 若不指定 , 则默认使用当前执行 ansible Playbook 的用户
- …
playbook校验
ansible-playbook myplaybook.yml --syntax-check
playbook运行
ansible-playbook -i hosts test.yaml
playbook调试
# 单步跟从调试 PlayBook
ansible-playbook myplaybook.yml --step
# 测试运行 PlayBook, 会执行完整个 PlayBook , 但是所有 Task 中的行为都不会在远程服务器上执行 , 所有执行都是模拟行为
ansible-playbook myplaybook.yml -C
ansible-playbook ttt.yaml --syntax-check #检查yaml文件的语法是否正确
ansible-playbook ttt.yaml --list-task #检查tasks任务
ansible-playbook ttt.yaml --list-hosts #检查生效的主机
ansible-playbook ttt.yaml --start-at-task='abc' #指定从某个task开始运行
4.2 角色(Roles=任务+依赖的文件、变量、模板)
角色适合组织多个相关任务并封装完成这些任务所需的数据。例如,安装Nginx可能涉及添加软件包存储库,安装软件包和设置配置。
此外,真实的配置通常需要额外的数据,如变量,文件,动态模板等等。这些工具可以与Playbook一起使用,可以通过将相关任务和数据组织成一个角色(role, 相关的结构)
roles
rolename(例如nginx_install)
- files
- handlers
- meta
- templates
- tasks
- vars
role编排的playbook使用示例
可以使用ansible-galaxy命令来创建一个新角色。此工具可用于将角色保存到Ansible的公共注册表,但是我通常只是使用它来在本地创建role的基础目录结构。例如:
# 1.目录名称roles是一种惯例,在运行一个playbook时可以用来查找角色。该目录应该始终被命名roles,但并不强制
mkdir roles
# 2.在roles目录中运行 ansible-galaxy init nginx_install 命令将创建新角色所需的目录和文件。
cd roles
ansible-galaxy init nginx_install
# 3.运行角色(Running the Role),需要先定义一个playbook任务的nginx_install.yml, 然后引入roles中的任务
vi nginx-install.yml
- hosts: ''
gather_facts: true
become: yes
become_user: root
become_method: sudo
roles:
- 'nginx_install'
# 4.执行 ansible-playbook -i hosts nginx_install.yml
文件files
在files目录中,可以添加要复制到目标的服务器中的文件如conf、rpm等
处理程序handles
把曾经在nginx.yml 剧本中的定义的所有处理程序放入到handlers目录中。约定必须包含main.yml文件。 handlers/main.yml
handlers/main.yml中的处理程序定义好了,可以自由地从其他的yaml配置中引用它们。
元meta
meta目录中的main.yml文件包含Role元数据,包含的依赖关系。如果这个角色依赖于另一个角色,可以在这里定义。例如,nginx角色取决于安装SSL证书的ssl角色。约定必须包含main.yml文件。 meta/main.yml 内容, 如果我调用了”nginx”角色,它将尝试首先运行”ssl”角色。 否则可以省略此文件.
dependencies:
- { role: ssl }
模板templates
基于Python的Jinja2模板引擎(和django的模板引擎很类似),模板文件可以包含模板变量。这里的文件应该以.j2为类型后缀(eg.uwsgi.j2),提倡但是不强制,也可以取其他的名字。
类似于files,在templates目录中没有main.yml文件,只包含模板文件。
模板中使用的变量,在vars中定义
任务tasks
使用角色时运行的主文件是tasks/main.yml文件,将一切操作都是放在一系列的任务中。
# nginx安装任务示例
- name: Add Nginx Repository # 1.添加nginx / stable库
apt_repository:
repo: ppa:nginx/stable
state: present
- name: Install Nginx # 2.安装并启动Nginx
apt:
pkg: nginx
state: installed
update_cache: true
notify:
- Start Nginx
- name: Add H5BP Config # 3.添加H5BP配置文件
copy:
src: h5bp
dest: /etc/nginx
owner: root
group: root
- name: Disable Default Site Configuration # 4.从sites-enabled目录中删除文件的符号链接来禁用默认的Nginx配置
file:
dest: /etc/nginx/sites-enabled/default
state: absent
# `dest` in quotes as a variable is used!
- name: Add SFH Site Config # 5.将serversforhackers.com.conf.j2虚拟主机模板复制到Nginx配置中,渲染模板
register: sfhconfig
template:
src: serversforhackers.com.j2
dest: '/etc/nginx/sites-available/.conf'
owner: root
group: root
# `src`/`dest` in quotes as a variable is used!
- name: Enable SFH Site Config # 6.通过将其符号链接到sites-enabled目录来启用Nginx服务器配置
file:
src: '/etc/nginx/sites-available/.conf'
dest: '/etc/nginx/sites-enabled/.conf'
state: link
# `dest` in quotes as a variable is used!
- name: Create Web root # 7.创建Web根目录
file:
dest: '/var/www//public'
mode: 775
state: directory
owner: www-data
group: www-data
notify:
- Reload Nginx
# `dest` in quotes as a variable is used!
- name: Web Root Permissions # 8.更改项目根目录的权限(递归),该目录位于之前创建的Web根目录之上
file:
dest: '/var/www/'
mode: 775
state: directory
owner: www-data
group: www-data
recurse: yes
notify:
- Reload Nginx
变量Vars
vars目录包含一个main.yml文件(如handlers和meta目录一样),在main.yml中以key:value形式列出将要使用的所有变量
条件判断 when
迭代 with_items
4.3 事实Facts
运行剧本时的第一行总是“收集事实”。
在运行任何任务之前,Ansible将收集有关其配置的系统的信息。这些被称为事实,并且包括广泛的系统信息,如CPU核心数量,可用的ipv4和ipv6网络,挂载的磁盘,Linux发行版等等。
4.4 加密Vault
经常需要将敏感数据存储在我们的模板,文件或变量文件中; 需要用到Ansible Vault的解决方案。
Vault允许您加密任何Yaml文件,通常将其作用于变量文件
ansible-vault常用命令
ansible-vault create # 创建一个新文件并进行加密
ansible-vault edit # 编辑已经存在的加密文件
ansible-vault decrypt # 从加密文件创建明文文件
ansible-vault encrypt # 加密现有的纯文本文件
ansible-vault rekey # 在加密文件中设置新密码
5.ansible变量
根据变量的作用范围 , 大体的将变量分为以下三类, 但这只是一个比较除粗糙的划分 , 不能囊括 Ansible 中的所有变量
- 全局变量
- 剧本变量
- 资产变量
全局变量
全局变量 是 我们使用 ansible 或者使用 ansible-playbook 时 , 手动通过 -e 参数传递给 Ansible 的变量
# 传普通的 key-value 模式, 输出变量
[root@manager ~]# ansible all -i /etc/ansible/hosts -m debug -a "var=name" -e "name='testname2'"
10.10.10.1 | SUCCESS => {
"name": "testname2"
}
# 传普通的 key-value 模式, 拼字符串输出
[root@manager ~]# ansible all -i /etc/ansible/hosts -m debug -a "msg='name is '" -e "key='testname'"
10.10.10.1 | SUCCESS => {
"msg": "name is testname"
}
# 传文件,指定时必须加 @
[root@manager ~]# cat a.json
{"name": "zhansan", "age": "16"}
[root@manager ~]# ansible webservers -i /etc/ansible/hosts -m debug -a "msg='name is , age is '" -e @a.json
[WARNING]: Found variable using reserved name: name
10.10.10.1 | SUCCESS => {
"msg": "name is zhansan , age is 16"
}
[root@manager ~]# cat b.yaml
---
name: lisi
age: 33
...
[root@manager ~]# ansible webservers -i /etc/ansible/hosts -m debug -a "msg='name is , age is '" -e @b.yaml
[WARNING]: Found variable using reserved name: name
10.10.10.1 | SUCCESS => {
"msg": "name is lisi , age is 33"
}
剧本变量
在 Playbook 中使用的变量叫做剧本变量 , 他的定义由多种方式 , 我们使用两种 , play内定义和引用文件
1.定义变量
# 通过 PLAY 属性 vars 定义key:value
- name: test play vars
hosts: all
vars:
user: lisi
home: /home/lisi
# 通过 PLAY 属性 vars_file引用变量文件
- name: test play vars
hosts: all
vars_files:
- vars/users.yaml
# vi vars/users/yaml
user: lilei
home: /home/lilei
2.在 Playbook 中使用这些变量,使用 ““来使用变量
- name: Test Vars using in playbook
hosts: all
vars:
user: lisi
home: /home/lisi
tasks:
- name: create the users
user:
name: ""
home: ""
资产变量
资产变量是和资产紧密相关的一种变量 , 资产变量分为 主机变量 和 主机组变量 , 分别针对单个主机和一组主机;
主机组的变量可以被子组继承,使用