读一本书最好的时机是何时?是你刚买的时候,趁着新鲜劲,先了解这本书,继而立刻阅读完这本书。若是错过了最好的时机阅读一本书,那何时是合适的时机,是你须要这方面的资料或者知识的时候。html
最近我一直在研究 Ansible 自动化运维工具。入手请参考 Ansible 上手指南。主要是为了实现本身在远程主机进行相关操做的任务,以此为切入点进行学习。node
在实现了本身的任务后,我准备继续研究下 Ansible 的其余用法。下面就是个人我的总结。shell
体会:编程
下面的总结主要以例子为主:ubuntu
大纲:bash
Ansible 是使用Python 编写,基于模块化的工做方式,真正处理动做都是这些模块。Ansible 提供总体的框架。框架
pip install ansible
复制代码
或者根据Linux 的版本进行安装运维
apt-get install ansible
复制代码
管理主机要求是Linux, 节点主机须要带 Python 及相应的库。模块化
通常是管理主机和节点主机都是Linux。函数
命令行方式运行:
命令行方式适合操做简单的动做。
ansible all -m ping
复制代码
playbook 运行:
playbook 适合复杂的处理动做。
ansible-playbook example.yml
复制代码
查看支持的模块:
ansible-doc -l
复制代码
查看某模块用法及支持的参数:
ansible-doc -s ping
复制代码
安装完成以后,默认目录下有两个文件:
/etc/ansible/hosts
/etc/ansible/ansible.cfg
复制代码
hosts 文件定义节点主机的IP 及如下配置信息。
ansible.cfg 文件定义全局配置文件,配置项不少, 通常默认就能够完成你的平常任务了。
可是除默认的生成的 ansible.cfg 文件以外,你能够在本身的项目中建立这样一个同名ansible.cfg 文件。
ansible 读取配置文件的顺序是:
怎么理解这个读取配置文件的信息呢?
举个例子:
# 当前项目结构
ansible:
---playbooks
---example
---leanr-ansible/example.yml
---ansible.cfg
复制代码
你在这个目录下执行:ansible 命令
操做动做举例
这里为举例只明白这些模块的使用场景,故意执行多步操做。
/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
目录下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"}
复制代码
能够看出,处理相应的动做,有相应的模块,模块带参数,完成任务。
{{ }}
里面表示变量第二步:先查询是否存在文件,存在则执行下载命令
第一步拷贝的文件是一个客户端,主要是对文件的上传、下载、查询等。
模块: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
复制代码
第三步:解压下载的文件
第二步下载的文件内是一个 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"
复制代码
第四步:拷贝文件
- 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"]
复制代码
上文至关于: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 # 第六步
...
复制代码
假如你但愿写的task 可以进行复用,就至关于编程领域里的抽象出函数同样。ansible 提供这样的机制。即将上文一个很大的文件拆分红独立的文件。使用 include_tasks 方法将文件导入。
好比:上文的五步动做分别单独写文件
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
复制代码
即将各个处理动做独立出去。随时复用。
看上去 include_tasks 方式就是对ansible-playbook 的一种比较好的组织方式了。
ansible 提供了一种更好的组织方式:roles
Roles 基于一个已知的文件结构,去自动的加载某些 vars_files,tasks 以及 handlers。基于 roles 对内容进行分组,使得咱们能够容易地与其余用户分享 roles。 这样的组织方式使得复用更为简便。每一个相对独立的处理动做独立出来,能够适用于更复杂的场景。
一个role 的文件大概包括这些:
注意文件夹下能够有多个后缀名为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 所在的文件目录
复制代码
这些原理性的东西,用文字不是很好讲,之后遇到文字难以表达出来,我录个视频实际操做下。这样读者可能更好理解。