最近在重构一款命令行工具,使用 golang 从新开发,但须要继续维持原有的命令,同时增长新命令。node
在重构的过程当中,须要对现命令行工具和原命令行工具的命令输出结果进行比对,确保彻底一致(项目要求),命令行工具须要在部署完成系统以后进行使用,每一个系统完成时的部署组件又稍微有点差别。因此其实须要在多套服务主机上进行测试。python
须要作这些动做:golang
按理说,我不断把须要的配置和二进制文件拷贝到主机上进行测试也能完成。web
但在使用的过程当中存在下面几个问题:正则表达式
看上去手动的方法,有点费劲。shell
目前我从事的工做就是 PaaS
部署相关的,部署层面的脚本的运行、组件的安装、服务的启动等都是使用 Ansible 来操做。具体的脚本编写由其余同事,我只知道这个东西是干吗的。没实质性的学习。因而想借这个机会主动学习下 Ansible.编程
学习之处,差点犯了老问题,即:从头开始看官方文档,而不注重当前须要解决的问题。api
由于其实整个 Ansible 的内容体系不少。不注重当前须要解决的问题,会致使你抓不住重点。数组
意识到后专一在当前须要解决的问题上:安全
看了上面的事件背景,你大概知道这个 Ansible 究竟是个什么东西。
Ansible 是一个配置管理和应用部署工具,即在管理主机上操做一些命令就能在节点主机上进行相应的动做。由 Python 编写,由模块化组成,即执行动做的实体,在 ansible 上都是靠着相应的模块执行动做,好比拷贝 copy 模块、执行 command 模块、shell 模块、文件 file 模块等。
Ansible 的目标有以下:
管理主机从 hosts 里读取主机清单,经过 playbook 按顺序同时对管理的主机进行相应的操做。
如图:
管理主机主要是对主机的定义和配置、编写 playbook(即节点主机的执行动做)。
运行:
1. 命令行
ansible all -m ping
复制代码
2. playbook
ansible-playbook example.yml
复制代码
编辑文件:/etc/ansible/hosts
即:定义主机名称,变量等
主机的变量包括什么: 主机的执行用户、链接端口、密码等
相似于 ini 格式的文件
[test-new-cli]
10.62.60.72
[test-old-cli]
10.62.62.88
复制代码
上面的例子:将两个主机的分为两组:test-new-cli
和 test-old-cli
主机的变量有这么些:
ansible_ssh_host 将要链接的远程主机名.与你想要设定的主机的别名不一样的话,可经过此变量设置.
ansible_ssh_port ssh端口号.若是不是默认的端口号,经过此变量设置.
ansible_ssh_user 默认的 ssh 用户名
ansible_ssh_pass ssh 密码(这种方式并不安全,咱们强烈建议使用 --ask-pass 或 SSH 密钥)
ansible_sudo_pass sudo 密码(这种方式并不安全,咱们强烈建议使用 --ask-sudo-pass)
ansible_sudo_exe (new in version 1.8) sudo 命令路径(适用于1.8及以上版本)
ansible_connection 与主机的链接类型.好比:local, ssh 或者 paramiko.
ansible_ssh_private_key_file ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的状况.
ansible_shell_type 目标系统的shell类型.默认状况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'.
ansible_python_interpreter 目标主机的 python 路径.
看不懂怎么用:
举个例子,你想链接主机 192.168.100.100
, 切换到 root 用户下执行相应的操做。
若是你直接ssh username@192.168.100.100
会要求你输入用户名和密码。
假如我编辑主机清单使得本身不须要输入用户名密码,怎么操做?
[test-new-cli]
example ansible_ssh_host=192.168.100.100 ansible_ssh_user=username ansible_ssh_pass=root
复制代码
即配置好192.168.100.100
的主机别名为example
, 主机的用户名和密码为:username/root
包含三种类型:
这个很好理解:若是你熟悉Python, 这三种类型就至关于:map, list, 变量
若是你熟悉golang, 这三种类型就至关于: map, 数组, 变量
示例:
---
- name: "execute command nodepool node list {{item.name}}"
shell: "{{item.cli}} nodepool node list {{item.id}}"
register: result
- name: show result
debug:
msg: "{{result.stdout_lines}}"
with_items:
- { name: "new-cli", cli: "new-cli", id: "1" }
- { name: "old-cli", cli: "old-cli", id: "1" }
复制代码
ansible 命令行式,适合执行单条命令。
# 操做 192.168.100.100 主机,看管理主机是否和192.168.100.100的主机连通
ansible example -m ping
# 操做 192.168.100.100 主机,拷贝管理主机下的/root/opcli/conf 文件至节点主机/etc/opcli/conf 下
ansible test-new-cli -m copy -a="src=/root/opcli/conf dest=/etc/opcli/conf"
复制代码
能够看出适合执行单条命令
假如你的节点主机分组不少了,Ad-hoc 如何选择特定特征的节点主机分组呢?
使用类正则表达式。
好比触发全部节点主机进行动做:
ansible all -m ping
ansible * -m ping
二者等价,都是选择全部的节点主机
复制代码
示例:
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
复制代码
webservers
webservers:dbservers
复制代码
webservers:!phoenix
# 隶属 webservers 组但同时不在 phoenix组
复制代码
webservers:&staging
# 同时隶属于 webservers 和 staging 组
复制代码
webservers[0]
webservers[0-25]
复制代码
有什么需求,看官方文档吧。
编写 yaml 文件,适合执行多步操做的复杂操做。能够当作是Ad-doc 命令的集合。甚至能够当作是一门编程语言。
执行:ansible-playbook example.yml
按照 example.yml 文件里的任务集合按步执行任务。
命令示例,仅举几例,有带参数、有没带参数的。
咱们最终的目标是:在节点主机上执行这些命令进行比对二者结果。
目录:
demo-for-ansible:
--- nodepool:
nodepool-list.yml
nodepool-node-list.yml
--- node:
node-list.yml
node-show.yml
--- task/task-list.yml
--- main.yml
复制代码
新版本:
命令 | 说明 |
---|---|
command-cli nodepool list | 查询资源池 |
command-cli nodepool node list | 查询资源池节点 |
command-cli node list | 查询节点 |
command-cli node show | 查询某个节点 |
command-cli task list | 查询部署任务 |
...
旧版本:
命令 | 说明 |
---|---|
old-cli nodepool list | 查询资源池 |
old-cli nodepool node list | 查询资源池节点 |
old-cli node list | 查询节点 |
old-cli node show | 查询某个节点 |
old-cli task list | 查询部署任务 |
...
/etc/ansible/hosts
[test_client]
192.168.100.100 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh
192.168.100.101 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh
192.168.100.102 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh
复制代码
定义主机链接类型、用户名、密码
主要动做:
/etc/client/conf
和 /et/client/commands
/etc/client/conf
文件至节点主机: /etc/client/conf
/root/gosrc/src/client/command-cli
至节点主机 /etc/client/commands
/etc/client/commands/command-cli
至节点主机 /usr/bin/command-cli
main.yml
---
- hosts: test_client
remote_user: root
become: yes
become_user: root
tasks:
# 在节点主机上建立目录:/etc/client/conf
- name: create /etc/client/conf /etc/client/commands
file:
path: "/etc/client/{{item}}"
owner: root
group: root
mode: 0755
state: directory
with_items:
- "conf"
- "commands"
# 软链接到 /usr/bin/command-cli
- name: link /etc/client/commands
file: src="/ect/client/commands" dest="/usr/bin/command-cli" state=link
# 拷贝管理主机配置文件/etc/client/conf和二进制文件至 /etc/client/conf, /etc/client/commands
- name: copy /etc/client/conf
copy: src="{{ itme.src }}" dest="{{ item.dest }}" owner=root group=root mode=0644
with_items:
- { src: "/etc/client/conf", dest: "/etc/client/conf" }
- { src: "/root/gosrc/src/client/command-cli", dest: "/etc/client/commands"}
# nodePool list
- include_tasks: "/nodepool/nodepool-list.yml"
with_items:
- { client: "new client", name: "command-cli"}
- { client: "old client", name: "old-cli"}
# nodePool node list <id>
- include_tasks: "/nodepool/nodepool-node-list.yml"
with_items:
- { id: "1", client: "new client", name: "command-cli"}
- { id: "1", client: "old client", name: "old-cli"}
# node list
- include_tasks: "node/node-list.yml"
with_items:
- { client: "new client", name: "command-cli"}
- { client: "old client", name: "old-cli"}
# node show <id>
- include_tasks: "node/node-show.yml"
with_items:
- { client: "new client", name: "command-cli", id: 1}
- { client: "old client", name: "old-cli", id: 1}
# task list
- include_tasks: "task/task-list.yml"
with_items:
- { client: "new client", name: "command-cli"}
- { client: "old client", name: "old-cli"}
复制代码
task-list.yml
---
- name: "execute command task list by {{ item.client}}"
shell: "{{item.name}} task list"
register: result
- name: show result
debug:
msg: "{{result.stdout_lines}}"
复制代码
两种方法
ansible-playbook main.yml --syntax-check
复制代码
先安装 pip install ansible-lint
ansible-lint main.yml
复制代码
ansible-playbook main.yml
复制代码
整个的编写流程大概是这样。核心是编写 yml 文件,调用 ansible 支持的各类模块完成任务。
关注你当前须要解决的问题,切入学习,事半功倍。