https://blog.csdn.net/O4dC8OjO7ZL6/article/details/79765539 css
点击上方“中兴开发人员社区”,关注咱们html
天天读一篇一线开发人员原创好文node
前言python
近期在重构一款命令行工具。使用 golang 又一次开发。但需要继续维持原有的命令,同一时候添加新命令。golang
在重构的过程当中,需要对现命令行工具和原命令行工具的命令输出结果进行比对,确保全然一致(项目要求)。命令行工具需要在部署完毕系统以后进行使用,每个系统完毕时的部署组件又略微有点差别。web
因此事实上需要在多套服务主机上进行測试。shell
需要作这些动做:编程
拷贝一些配置文件到主机上:用户配置、IP和port文件api
安装命令行工具,确保使其在服务主机上可以使用数组
运行一堆測试命令
按理说,我不断把需要的配置和二进制文件复制到主机上进行測试也能完毕。
但在使用的过程当中存在如下几个问题:
測试发现,结果不正确时需要及时改动代码。再次拷贝二进制文件到主机上
主机环境需要屡次推倒,又一次部署,验证版本号更新问题
需要手动一个一个命令的运行
測试有几套主机
看上去手动的方法。有点费劲。
眼下我从事的工做就是 PaaS
部署相关的,部署层面的脚本的运行、组件的安装、服务的启动等都是使用 Ansible 来操做。详细的脚本编写由其它同事,我仅仅知道这个东西是干吗的。没实质性的学习。因而想借这个机会主动学习下 Ansible.
学习之处,差点犯了老问题,即:从头開始看官方文档,而不注重当前需要解决的问题。
因为事实上整个 Ansible 的内容体系很是多。
不注重当前需要解决的问题,会致使你抓不住重点。
意识到后专一在当前需要解决的问题上:
拷贝配置文件和安装脚本到多个主机上
在多个主机上測试命令行工具
看了上面的事件背景。你大概知道这个 Ansible 到底是个什么东西。
Ansible 是一个配置管理和应用部署工具。即在管理主机上操做一些命令就能在节点主机上进行对应的动做。由 Python 编写。由模块化组成,即运行动做的实体。在 ansible 上都是靠着对应的模块运行动做,比方拷贝 copy 模块、运行 command 模块、shell 模块、文件 file 模块等。
Ansible 的目标有例如如下:
本身主动化部署应用
本身主动化管理配置
本身主动化的持续交付
本身主动化的(AWS)云服务管理。
管理主机从 hosts 里读取主机清单,经过 playbook 按顺序同一时候对管理的主机进行对应的操做。
如图:
管理主机主要是对主机的定义和配置、编写 playbook(即节点主机的运行动做)。
运行:
1. 命令行
ansible all -m ping
2. playbook
ansible-playbook example.yml
编辑文件:/etc/ansible/hosts
即:定义主机名称,变量等
主机的变量包括什么: 主机的运行用户、链接port、password等
类似于 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
sshport号.假设不是默认的port号,经过此变量设置.
ansible_ssh_user
默认的 ssh username
ansible_ssh_pass
ssh password(这样的方式并不安全,咱们强烈建议使用 —ask-pass 或 SSH 密钥)
ansible_sudo_pass
sudo password(这样的方式并不安全,咱们强烈建议使用 —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
会要求你输入username和password。
假如我编辑主机清单使得本身不需要输入usernamepassword,怎么操做?
[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和password为:username/root
包括三种类型:
键值对:key: value
数组
纯量:整型、字符串、布尔型
这个很是好理解:假设你熟悉Python, 这三种类型就至关于:map, list, 变量
假设你熟悉golang, 这三种类型就至关于: map, 数组。 变量
演示样例:
--- - name: "execute command nodepool node list by { {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"
m: 模块
a: 接參数
可以看出适合运行单条命令
假如你的节点主机分组很是多了。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 文件中的任务集合按步运行任务。
命令演示样例,仅举几例。有带參数、有没带參数的。
咱们终于的目标是:在节点主机上运行这些命令进行比对二者结果。
新版本号:
命令 | 说明 |
---|---|
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 | 查询部署任务 |
…
文件夹结构:
demo-for-ansible: ---nodepool/nodepool-list.yml ---nodepool/nodepool-node-list.yml ---node/node-list.yml ---node/node-show.yml ---task/task-list.yml ---main.yml
/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
定义主机链接类型、username、password
主要动做:
在节点主机上建立两个文件夹: /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
运行上表中查询命令:nodepool, node, task
main.yml
--- - hosts: test_client remote_user: root become: yes become_user: root become_method: sudo 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" # 拷贝管理主机配置文件/etc/client/conf和二进制文件至 /etc/client/conf, /etc/client/commands - name: copy /etc/client/conf copy: src="{ { item.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"} # 软链接到 /usr/bin/command-cli - name: link /etc/client/commands file: src="/etc/client/commands/command-cli" dest="/usr/bin/command-cli" state=link # 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 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 支持的各类模块完毕任务。
熟悉 playbook
熟悉 ansible 模块
熟悉 ansible api
关注你当前需要解决的问题,切入学习,事半功倍。