Agent是一种常见的IaaS软件管理设备的方式;例如,ZStack使用Python agents去管理KVM主机。由于海量的设备,安装和升级agents成为巨大的挑战,因此大多数IaaS软件把这个问题留给客户或分发商,从而致使解决方案变得脆弱,由于缺少IaaS软件自己的支持。ZStack从一开始就在考虑这个问题,前后尝试了Puppet、Salt和Ansible,最后实现与Ansible无缝并对用户透明的集成。全部的ZStack agents经过Ansible自动部署、配置、升级;用户可能根本没有注意到他们的存在。java
动机python
IaaS软件一般是一个包含不少小程序的组合软件。理想状况下,IaaS软件能够被写成一个中央管理软件,能够经过设备的SDK和设备对话;但在现实中,设备要么没有提供SDK,要么提供的SDK不完整,迫使IaaS软件必须部署一个叫agent的小程序去控制它们。虽然ZStack把全部服务打包在一个单一的进程中(详见“进程内的Microservices架构”),部分agent依旧须要部署到不一样的设备上以控制它们。部署agent的过程当中,不只须要安装agent和相关依赖的软件,还须要配置目标设备,这并不简单,并且一般须要用户作大量的手动工做。当IaaS软件管理着大量的设备的时候,这个问题变得很是显著,甚至会限制数据中心规模。web
问题shell
部署、升级agent以及配置目标设备的问题都属于配置管理问题,Puppet、Chef、Salt和Ansible这类软件就是旨在解决这类问题。许多开发人员已经开始使用这些工具软件将IaaS软件包装成一个易于部署的方式;例如,为了安装OpenStack,你可能会试图找到一些puppet模块而不是依据它提供的文档手动完成每一步操做。这些第三方包装能在必定程度上缓解问题,但它们同时又是脆弱的,包装的软件发生任何变化都会破坏它们。另外一方面,当用户想要配置软件包的某一部分的时候,他们可能不得不深刻那些第三方包装去作一个即需的改变。最后,第三方包装没法处理封装的软件升级的情况,迫使用户从新面对他们试图隐藏的使人气馁的细节。小程序
经过与配置管理软件Ansible无缝且透明的集成,ZStack解决了这个问题。使用的方式是对用户隐藏细节并承担了管理agent的责任,最终展现给用户一个能够简单下载和运行(或升级)的软件,彻底知足在数据中心自动化完成一切的目标,并帮助管理员克服安装、配置和升级云的恐惧。安全
和Ansible集成服务器
ZStack有一个典型的服务端-代理(server-agent)架构,服务器端包含全部驱动业务逻辑的编排服务,代理端执行来自于编排服务的命令,经过使用运行在不一样的设备上的小的Python agents(如KVM agents、虚拟路由agents)。架构
服务和agents:ZStack对服务和agents有明确的定义。服务负责在云中完成一部分业务,例如存储服务。服务一般在ZStack管理节点运行的进程中,有本身的API和配置,与其余服务协同完成云上的业务。agent是一个被服务命令的小附属程序,能够经过使用它来操做没有提供像样SDK的外部设备;例如,SFTP备份存储agent在一台使用SFTP协议的Linux机器上建立了一个的备份存储。服务和代理的设计原则是把全部复杂的业务逻辑放在服务中,使代理尽量简单。咱们但愿这个解释能够给你一个在ZStack中咱们把什么称之为服务和代理的概念,由于其余IaaS软件可能有不一样的想法,咱们看到一些IaaS软件已经在agent代码中处理业务逻辑了。app
全部的ZStackagents包含三个文件:一个Python包(xxx.tar.gz)和init.d服务文件,和一个AnsibleYAML的配置,在$web_container_root/webapps/zstack/WEB-INF/classes/ansible文件夹下它们本身目录中,因此一个服务能够经过javaclasspath找到它的agent。Ansible YAML配置将全部的东西放在一块儿;它讲述了如何安装agent,agent的依赖,以及如何配置目标设备。引用KVM为例,其Ansible YAML配置中的一部分看起来像这样:框架
- name: install kvm related packages on RedHat based OS
when: ansible_os_family == 'RedHat'
yum: name=""
with_items:
- qemu-kvm
- bridge-utils
- wget
- qemu-img
- libvirt-python
- libvirt
- nfs-utils
- vconfig
- libvirt-client
- net-tools
- name: install kvm related packages on Debian based OS
when: ansible_os_family == 'Debian'
apt: pkg=""
with_items:
- qemu-kvm
- bridge-utils
- wget
- qemu-utils
- python-libvirt
- libvirt-bin
- vlan
- nfs-common
- name: disable firewalld in RHEL7 and CentOS7
when: ansible_os_family == 'RedHat' and ansible_distribution_version >= '7'
service: name=firewalld state=stopped enabled=no
- name: copy iptables initial rules in RedHat
copy: src="/iptables" dest=/etc/sysconfig/iptables
when: ansible_os_family == "RedHat" and is_init == 'true'
- name: restart iptables
service: name=iptables state=restarted enabled=yes
when: chroot_env == 'false' and ansible_os_family == 'RedHat' and is_init == 'true'
- name: remove libvirt default bridge
shell: "(ifconfig virbr0 &> /dev/null && virsh net-destroy default > /dev/null && virsh net-undefine default > /dev/null) || true"
像上面展现的这样,这个YAML配置会关心对一个KVM主机的全部设置。你不须要担忧ZStack会要求你手动安装不少依赖软件,而且不会收到任何因为缺少依赖或者错误配置引发的奇怪的错误。让一切运行在你的Linux机器上是ZStack的责任,无论你的Linux操做系统是Ubuntu仍是CentOS,即便你只部署了一个最小的安装,ZStack也知道如何让它们准备就绪。
在java代码中的服务能够在某个恰当的时机,使用AnsibleRunner
去调用Ansible去部署或升级agents。KVM的AnsibleRunner
看起来像:
AnsibleRunnerrunner=newAnsibleRunner();
runner.installChecker(checker);
runner.setAgentPort(KVMGlobalProperty.AGENT_PORT);
runner.setTargetIp(getSelf().getManagementIp());
runner.setPlayBookName(KVMConstant.ANSIBLE_PLAYBOOK_NAME);
runner.setUsername(getSelf().getUsername());
runner.setPassword(getSelf().getPassword());
if(info.isNewAdded()){
runner.putArgument("init","true");
runner.setFullDeploy(true);
}
runner.putArgument("pkg_kvmagent",agentPackageName);
runner.putArgument("hostname",String.format("%s.zstack.org",self.getManagementIp().replaceAll("\\.","-")));
runner.run(newCompletion(trigger){
@Override
publicvoidsuccess(){
trigger.next();
}
@Override
publicvoidfail(ErrorCodeerrorCode){
trigger.fail(errorCode);
}
});
AnsibleRunner
很是智能。它将跟踪每个agent文件的MD5校验值,并在远程设备测试agent的端口链接性,保证Ansible只在须要的时候被调用。一般状况下,部署或升级的过程是对用户透明的,在服务定义的触发点被触发;例如,一个KVM agent将在添加一个新的KVM主机的时候自动被部署。然而,服务也提供叫作Reconnect API的API,让用户用命令式的方式触发agent部署;例如,用户能够调用APIReconnectHostMsg让一个KVM agent从新部署,从新部署的缘由多是为Linux操做系统修复一个关键的安全漏洞,在他们对KVM YAML配置作出了相应的改变以后。将来,ZStack将提供一个框架,容许用户执行他们定制的YAML配置而不用修改ZStack的默认配置。
在软件升级过程当中,用户在安装完一个新的ZStack版本并重启全部管理节点后,AnsibleRunner
将检测到agents的MD5校验和发生了变化,并自动在外部设备升级agents。这个过程是对用户透明的且精心设计的;例如,主机服务若是它发现共有10,000台主机,将每次升级1000台KVM主机,以免管理节点的资源被耗尽;固然,咱们也为用户提供了全局配置去优化这个行为(例如每次升级100台主机)。
总结
在这篇文章中,咱们演示了ZStack与Ansible的无缝、透明的集成。经过这种方式,agent安装、配置和升级的过程是全自动的,让繁杂的细节远离用户,留给ZStack自身来处理。