读一本书最好的时机是什么时候? 是你刚买的时候, 趁着新鲜劲, 先了解这本书, 继而马上阅读完这本书如果错过了最好的时机阅读一本书, 那什么时候是合适的时机, 是你需要这方面的资料或者知识的时候
最近我一直在研究 Ansible 自动化运维工具入手请参考 Ansible 上手指南主要是为了实现自己在远程主机进行相关操作的任务, 以此为切入点进行学习
在实现了自己的任务后, 我准备继续研究下 Ansible 的其他用法下面就是我的个人总结
体会:
文档内容很多, 不可能全部掌握, 使用 2/8 法则, 看看同事们口中的主要内容有哪些
实践型的内容, 还是需要自己写写代码, 运行, 看看效果当你跑通了你自己写的代码, 有可能你就学会了这个知识点
快速入手的方法是: 如果你急切需要解决问题, 那就问有经验的人如果你不是很急, 先尝试了解下内容, 不懂再问别人反复提出你的疑问
提问题不要觉得不好意思, 时间很珍贵的
下面的总结主要以例子为主:
第一稿: 抛弃所有参考资料, 凭借实践的经验总结
第二稿: 弥补不明白的地方
第三稿: 对着参考文献修正不对的地方, 发布
大纲:
ansible.cfg 配置文件
变量
判断
循环
常用模块
- debug
- copy
- file
- shell
- command
- stat
- unarchive
- ping
- template
- user
- group
- service
- get_url
- include
- role
目录结构
依赖
执行顺序
Ansible 是使用 Python 编写, 基于模块化的工作方式, 真正处理动作都是这些模块 Ansible 提供整体的框架
1 安装
pip install ansible
或者根据 Linux 的版本进行安装
apt-get install ansible
管理主机要求是 Linux, 节点主机需要带 Python 及相应的库
一般是管理主机和节点主机都是 Linux
2 基本使用
命令行方式运行:
命令行方式适合操作简单的动作
ansible all -m ping
playbook 运行:
playbook 适合复杂的处理动作
ansible-playbook example.yml
查看支持的模块:
ansible-doc -l
查看某模块用法及支持的参数:
ansible-doc -s ping
3 配置文件
安装完成之后, 默认目录下有两个文件:
- /etc/ansible/hosts
- /etc/ansible/ansible.cfg
hosts 文件定义节点主机的 IP 及以下配置信息
ansible.cfg 文件定义全局配置文件, 配置项很多, 一般默认就可以完成你的日常任务了
但是除默认的生成的 ansible.cfg 文件之外, 你可以在自己的项目中创建这样一个同名 ansible.cfg 文件
ansible 读取配置文件的顺序是:
ANSIBLE_CONFG 环境变量中定义
ansible.cfg 当前目录
*/ansible.cfg 当前用户 home/username/ansible.cfg
/etc/ansible/ansible.cfg 默认生成的文件路径
怎么理解这个读取配置文件的信息呢?
举个例子:
- # 当前项目结构
- ansible:
- ---playbooks
- ---example
- ---leanr-ansible/example.yml
- ---ansible.cfg
你在这个目录下执行: ansible 命令
那么首先查看环境变量有没有设置, 没有那就读取当前目录下的 ansible.cfg 配置信息;
如果当前目录没有设置, 那么就搜索 home 目录下有没有配置信息
否则读取默认生成的配置信息
4 常用模块
操作动作举例
这里为举例只明白这些模块的使用场景, 故意执行多步操作
拷贝管理节点
/home/ubuntu/zartclient
下的 zartcli 和 zartcli.ini 文件至节点主机
/home/ubuntu/zartclient
下
在上一步的基础之上, 拷贝
/home/ubuntu/zartclient/zartcli
至 /usr/bin/zartcli
在节点主机上使用刚才拷贝的文件, 执行下载命令:
zartcli -o=download -i=admin -m=bin -n=op-cli -v=v0.0.3 -p=/home/ubuntu/download
下载至
/home/ubuntu/download
目录
在节点主机上解压下载的文件至 /paasdata/data 目录下
在节点主机上拷贝解压之后的文件至 /etc/opcli 目录下
在节点主机上拷贝 op-cli 至 /usr/bin
在节点主机上 op-cli task list 执行命令
在节点主机上 op-cli node list 执行命令
快阅读时代, 估计没人想认真看这些动作画个流程图吧
把每一步动作认为是一个任务 task.
第一步: 先检查是否存在对应的文件, 是则拷贝
模块: stat, copy, debug, file
判断远端节点主机是否存在对应的文件夹
不存在则创建
拷贝本地文件至远程节点主机的对应的目录下
- - name: is /home/ubuntu/zartclient exists
- stat:
- path: /home/ubuntu/zartclient
- register: result
- - name: show result
- debug:
- msg: "{{result}}"
- - name: create dest path in remote
- file:
- path: "{{ dest-path }}"
- state: direstory
- with_items:
- - "/home/ubuntu/zartclient"
- when: not result.stat.exists
- - name: copy file to remote
- copy:
- src: "{{item.src}}"
- dest: "{{item.dest}}"
- with_items:
- - { src: "/home/ubuntu/zartclient/zartcli" dest: "/home/ubuntu/zartclient"}
- - { src: "/home/ubuntu/zartclient/zartcli.ini" dest: "/home/ubuntu/zartclient"}
- - name: copy zartcli into /usr/bin
- copy:
- src: "{{item.src}}"
- dest: "{{item.dest}}"
- with_items:
- - { src: "/home/ubuntu/zartclient/zartcli", dest: "/usr/bin"}
可以看出, 处理相应的动作, 有相应的模块, 模块带参数, 完成任务
{{ }} 里面表示变量
with_items: 是一个列表, 表示循环获取变量
register : 表示把执行的动作结果赋值给一个变量, 是一个 map, 可以根据键值, 获取内容
when: 表示判断, 根据结果的布尔值进行操作
第二步: 先查询是否存在文件, 存在则执行下载命令
第一步拷贝的文件是一个客户端, 主要是对文件的上传下载查询等
模块: shell command
- - name: is /home/ubuntu/download exists
- stat:
- path: "{{item}}"
- with_items:
- - "/home/ubunt/download"
- register: result
- - name: create /home/ubuntu/download
- file:
- path: "{{item}}"
- state: direstroy
- with_items:
- - "home/ubuntu/download"
- when: not result.stat.exists
- - name: query op-cli
- command: "{{tools}} -o={{operate}} -i={{tenants}} -m={{type}} -n={{name}} \
- -v={{version}}"
- vars:
- tools: zartcli
- operate: query
- tenants: admin
- type: bin
- name: op-cli
- version: v0.0.3
- register: result
- - name: download op-cli
- command: "{{tools}} -o={{operate}} -i={{tenants}} -m={{type}} -n={{name}} \
- -v={{version}} -p={{path}}"
- vars:
- tools: zartcli
- operate: query
- tenants: admin
- type: bin
- name: op-cli
- version: v0.0.3
- path: /home/ubuntu/download
item 是个关键字, 表示变量
item[0] 可以表示变量是一个列表, 这里表示列表的第一个值
item.src 可以表示变量是一个 map, 这里表示 map 的 src 的值
vars 表示模块中可以填充自定义的变量名称对应的值
第三步: 解压下载的文件
第二步下载的文件内是一个 tar 包, 需要将其解压至指定目录
模块: unarchive, file
- - name: create /paasdata/data
- file:
- path: "/paasdata/data"
- state: direstory
- - name: untar file
- unarchive:
- src: "{{src-path}}"
- dest: "{{dest-path}}"
- remote_src: yes
- vars:
- src-path: "/home/ubuntu/download/admin_op_cli_v0.0.3/op-cli.tar.gz"
- dest-path: "/paasdata/data"
yes 和 true 没区别
remote_src: yes 表示解压的文件在节点主机上操作
第四步: 拷贝文件
- - name: create /etc/opcli
- file:
- path: "/etc/opcli"
- state: directory
- - name: copy /paadata/data/conf||op-cli
- copy:
- src: "{{item.src}}"
- dest: "{{item.dest}}"
- with_items:
- - { src: "/paasdata/data/conf/common.yml" dest: "/etc/opcli/conf"}
- - { src: "/paasdata/data/op-cli" dest: "/usr/bin"}
第五步: 执行查询命令
- - name: op-cli task list || op-cli node list
- command: "{{item[0]}} {{item[1]}} list"
- with_nested:
- - [ "op-cli" ]
- - ["task", "node", "nodepool"]
with_nested: 嵌套循环
上文相当于:
op-cli task list, op-cli node list, op-cli nodepool list
上文借用一些循环, 把之前规划的 八 个动作改成了 五个动作, 即 五 个动作内的每一个又包含几个动作
新手容易把上面的所有的动作都处理在一个文件内: 但是其实存在更好的处理方法
- # main.yml
- ---
- - hosts: 10.62.60.21
- romote_user: root
- tasks:
- - name: one # 第一步
- - name: two # 第二步
- - name: three # 第三步
- - name: four # 第四步
- - name: five # 第五步
- - name: six # 第六步
- ...
- 5 include_tasks
假如你希望写的 task 能够进行复用, 就相当于编程领域里的抽象出函数一样 ansible 提供这样的机制即将上文一个很大的文件拆分成独立的文件使用 include_tasks 方法将文件导入
比如: 上文的五步动作分别单独写文件
- zartclient.yml
- download.yml
- untarfile.yml
- copyfile.yml
- executecommand.yml
playbook 入口: mail.yml
则 main.yml 如下:
- ---
- - hosts: 10.62.60.21
- root_usr: root
- tasks:
- - include_tasks: zartclient.yml
- - include_tasks: download.yml
- - include_tasks: untarfile.yml
- - include_tasks: copyfile.yml
- - include_tasks: executecommand.yml
即将各个处理动作独立出去随时复用
6roles
看上去 include_tasks 方式就是对 ansible-playbook 的一种比较好的组织方式了
ansible 提供了一种更好的组织方式: roles
Roles 基于一个已知的文件结构, 去自动的加载某些 vars_files,tasks 以及 handlers 基于 roles 对内容进行分组, 使得我们可以容易地与其他用户分享 roles 这样的组织方式使得复用更为简便每个相对独立的处理动作独立出来, 可以适用于更复杂的场景
一个 role 的文件大概包括这些:
tasks 文件: 主要编写某个独立模块的处理动作
handlers 文件:
vars 文件: 主要编写某个独立模块的变量
meta 文件: 主要编写依赖关系, 即一个独立模块引用另一个 role
defaults 文件: 默认的变量文件
templates 文件: 模板文件
files 文件
注意文件夹下可以有多个后缀名为 yml 的文件, 但一定要有 main.yml 文件
上文的处理动作, 使用 roles 重新组织如下:
目录:
- ansible
- playbook
- roles
- download-bin
- tasks
- vars
- op-cli
- meta
- tasks
- vars
这里以上文的处理动作: 下载文件独立成一个 download-bin role 为例, 讲述如何编写 role.
- tasks/deploy.yml
- - name: download bin by zartcli
- command: "{{zartcli_cli_path}}/zartcli -o=download -i={{tenant_id}} -m={{bin_type}} \
- -n={{bin_name}} -v={{bin_version}} -p={{download_path}}"
- tasks/main.yml
- ---
- - include_tasks: download.yml
- vars:
- zartcli_cli_path: "{{zartcli_clipath}}"
- tenant_id: "{{tenantid}}"
- bin_name: "{{binname}}"
- bin_version: "{{binversion}}"
- download_path: "{{downloadpath}}"
- bin_type: "{{bintype}}"
- vars/main.yml
- ---
- zartcli_clipath: "/home/cloud/zartclient"
- tenantid: "admin"
- binname: "op-cli"
- binversion: "v0.0.3"
- downloadpath: "/home/cloud/zartclidownload"
- bintype: "bin"
task/main.yml 是这个 role 的入口导入 download.yml, 下载所需要的变量全部置放在 var/main.yml 文件中
别的 role 需要复用这个模块:
- op-cli/meta/main.yml
- dependencies:
- - role: download-bin
这样 op-cli role 也有 download 动作
roles 适用于组织较为复杂的项目, 将各个模块独立处理, 又可以相互复用使用 include_tasks 存在模块的复用性变低变量需要重复定义等缺点
上文 op-cli role 复用 download-bin, 无需再次定义变量
再一个值得注意的是: 一般 playbook 的执行顺序和 task 的定义顺序一致
使用 roles 后, playbook 中 roles 先执行, 再按 tasks 的定义顺序执行
如果需要最先执行某个 task , 或者最后执行某个 task, 可以使用 pre_tasks 和 post_tasks
pre_tasks 最先执行
post-tasks 最后执行
再一个使用 roles 需要配置 ansible.cfg
roles_path = 目录
# 即 roles 所在的文件目录
7 参考文献
官方文档
这些原理性的东西, 用文字不是很好讲, 以后遇到文字难以表达出来, 我录个视频实际操作下这样读者可能更好理解
来源: https://juejin.im/post/5aa2b6b86fb9a028e25d2953