服务器系统是各式各样应用程序的基础,现代的应用程序应该是经过版本控制,测试和自动化等DevOps流程迭代生产出来的。 因此,寻找可以解决我们自动化需求的配置管理工具是非常关键的一步。自动化配置管理也能够抽象为一种新的云服务类型AaaS(Automation as a Service)。
配置管理工具并不是什么新鲜事物,它们已经存在了一段时间,但是它们的复杂性总是使应用它们成为一个困难的过程。 你会发现当你要完成一个简单或稍微复杂一点的任务时,用Puppet,Chef并不比自己写一段Shell脚本更简单和快捷。云星数据的RightCloud CMP(
www.rightcloud.com.cn)混合云管理平台工程团队在架构和实现AaaS服务过程中,遵循了如下的选择标准:
- 稳定运行
- 安全可靠
- 版本控制集成
- 无需额外环境依赖
- 开箱即用、插件扩展
通过前期的验证对比,自动化工具栈中大量优秀的解决方案都是基于代理架构进行设计开发的重量级产品或框架,Puppet功能强大但过于复杂,Chef的架构并不完全符合我们的使用场景,两者原生架构都是基于代理Agent。直到Ansible的出现,Ansible是用Python语言开发的自动化配置管理框架。
Ansible的技术优势:
Ansible的应用场景:
通常你会与其他配置管理工具(如Puppet,Chef,SaltStack等)来对比。Ansible不仅限于配置管理。 它也可以用于许多不同的方式:
Ansible架构解析:
Inventories: 主机节点列表,其中包含 IP地址,服务器别名、服务器逻辑分组。用于指定自动化任务的管理目标。
- API: 命令行工具CLI和Python API编程接口
- Modules: 模块代码在被管理的远程服务器行执行。模块能够控制系统资源, 例如服务、软件包, 以及文件或则执行系统命令,有超过450个以上的Ansible模块提供格式各样的IT环境管理日常任务的支持。
- Notification 模块集中的 email 模块实现邮件的发送功能;
- Database 模块集中的mssql_db 模块提供远程主机上MYSQL数据库实例的创建、删除、导入数据的功能;
- Cloud 模块集ec2模块实现在AWS不同Region下云主机的创建,终止、启动、停止的功能;
- Plugins: 允许执行任务时插入扩展,这些扩展通过一小python代码实现。Ansible默认带了一些很有用的Plugin插件,能够轻松开发自己的定制化Plugin。
- Cache plugins 用于保存收集到的管理目标的相关'facts'数据,避免每次执行耗时的'facts'收集任务重复执行;
- Callback plugins 允许你挂在回调函数,响应Ansible的相关事件,多用于显示执行结果和日志收集;
- Playbook:采用YAML语法格式描述模块任务的组合、变量注册/引用、逻辑判别的纯文本文件。通过它不能能够简单申明配置信息,更能够将任何可以手工顺序执行的任务集中编排到一块完成更为复杂的IT运维场景需求。
企业级Ansible自动化服务需求:
- 可视化Inventory管理;
- 实时监控Ansible Playbook的各项Task的执行状况;
- 内置的定时任务调度机制;
- 按项目组织维护Ansible Playbook,便于扩展重用;
- 与Git,SVN等版本控制管理工具的集成,参与DevOps相关流程阶段;
- 基于用户角色的访问控制、Playbook执行审计;
- 中心服务器水平伸缩,支持大量被管理节点;
- Dashboard,全面展示自动化任务配置状况、执行计划、执行状态的汇总情况;
让我们看看Ansible如何使用独特的无代理架构,实现应用服务的部署以及更为复杂的IT流程编排。
场景示例:
作为一个开发者,运维管理员越来越多的发现通过云基础设施(IaaS)申请的服务器主机需要安装Docker容器引擎来以容器化的方式跑应用、中间件环境以及数据库。
那么通过Ansible是如何使这件日常任务变得非常容易的呢?接下来我们一步一步分解自动化流程的步骤和整个Docker引擎安装过程中用到的关键Ansible模块。
1. 创建工作目录
通过下面两条Shell命令,创建工作目录,并切换到该目录下
2. 准备inventory
这一步就是告诉Ansible Master需要在那些目标主机上执行任务。编辑如下格式的纯文本文件,例如可以命名为hosts
注意:其中[docker]这个格式代表分组(Group),在后面的Playbook中通过引用来关联角色(Role)。这样我们就能轻松定义那个角色的任务项在那个分组的目标主机上执行的关联关系了。
3.配置全局变量
这一步的目的是定义,ansible playbook运行时可以访问的全局变量,变量定义格式为典型的key: value格式,变量之间可以通过{{key}}的方式引用。该全局变量有固定的目录结构,和默认的文件命名。
执行下面的命令在工作目录下创建目录和编辑配置文件。
我们选择了通过二进制文件的模式来安装docker,所以我们在全局变量文件all中做了如下变量定义:
# 目标主机上存放二进制文件执行的目录
BIN_DIR: /root/local/bin
# ansible master主机上存放下载的第三方软件包,预生成的CA证书,配置文件等目录
DATA_DIR: /opt/data
### docker配置
DOCKER_URL: "https://get.docker.com/builds/Linux/x86_64/docker-17.04.0-ce.tgz"
DOCKER_DIR: "{{DATA_DIR}}/docker"
注意:DATA_DIR: /opt/data 这个变量定义,根据其描述这个是在Ansible Master主机上的目录,并不是目标服务器上的目录。为什么要这样设置呢?好处又是什么呢?原因是避免每次需要对目标服务器主机安装Docker引擎时都通过DOCKER_URL这个变量定义的地址去网上下载docker的二进制软件包。一方面:这样可以极大的加快整个自动化任务的执行速度(下载任务通常占到全部任务执行时间的90%以上),另一方面:对于私有化部署,网络策略不允许对外访问的服务器主机也能够实现安装,因为Ansible Master与服务器节点内部网络是联通的。
4.配置Ansible Role的目录结构
通过Role的方式来结构化Ansible Playbook的执行,需要对应的目录结构。首先需要创建一个名叫roles的顶级目录,然后创建一个名叫docker的目录,这个目录名称就代表角色名。
通过Role的方式来结构化Ansible Playbook的执行,需要对应的目录结构。首先需要创建一个名叫roles的顶级目录,然后创建一个名叫docker的目录,这个目录名称就代表角色名
之后在角色目录下分别建立2个目录:tasks、templates。tasks目录下面存放yml格式的playbook文件,templates目录下存放jinja2格式的安装docker引擎需要的配置文件模板。
5. 编写安装Docker引擎的Playbook
想想如果不是用偷懒的方法试用linux的包管理其程序yum,apt的方式来安装Docker,二进制文件方式如何安装呢?本质上通过yum,apt方式来安装docker也是通过二进制文件、文本配置文件的方式来完成的。
下面就来看看ansible的playbook通过内置核心模块实现安装任务的自动化。
---
- name: 创建{{BIN_DIR}}目录
file:
dest={{BIN_DIR}}
state=directory mode=0740
- name: 关闭firewalld服务
systemd:
name=firewalld
state=stopped
enabled=no
- name: 修改iptables FORWARD chain的默认策略设置
iptables:
chain=FORWARD
policy=ACCEPT
- name: 保存iptables规则配置
command: iptables-save
- name: 复制docker二进制执行文件
copy:
src={{DOCKER_DIR}}/{{item}}
dest={{BIN_DIR}}/{{item}}
mode=0540
with_items:
- docker
- dockerd
- docker-init
- docker-proxy
- docker-runc
- docker-containerd
- docker-containerd-ctr
- docker-containerd-shim
- name: 复制docker completion文件
copy:
src={{DOCKER_DIR}}/completion/bash/{{item}}
dest=/etc/bash_completion.d/{{item}}
mode=0440
with_items:
- docker
- name: 创建/etc/docker目录
file:
dest=/etc/docker
state=directory
- name: 创建docker-daemon.json.j2文件
template:
src=docker-daemon.json.j2
dest=/etc/docker/daemon.json
- name: 创建docker.service文件
template:
src=docker.service.j2
dest=/etc/systemd/system/docker.service
- name: 重新加载systemd
command: systemctl daemon-reload
- name: 启动docker
service:
name=docker
state=restarted
enabled=yes
注意:playbook中的几个值得特别说明下的模块任务:
- name: 复制docker二进制执行文件 这个task使用了copy模块,从ansible master主机的src属性指定的目录复制文件到目标主机dest属性指定的目录下,同时通过mode属性来指定目标主机下这些复制过去文件的权限。这些文件你通过DOCKER_URL: "https://get.docker.com/builds/Linux/x86_64/docker-17.04.0-ce.tgz"下载到ansible master上解压缩后就全部有了。
- name: 创建docker-daemon.json.j2文件 这个task使用了template模块,该模块会将docker-daemon.json.j2这个jnjia2的模板文件通过变量替换后复制到目标服务器主机由dest属性指定的路径下
- name: 创建docker.service文件 这个task使用了template模块,该模块会将docker.service.j2这个jnjia2的模板文件通过变量替换后复制到目标服务器主机由dest属性指定的路径下。该文件为Systemd格式的服务定义文件。
6. 准备主入口Playbook
上面第5步,我们完成了Ansbile Role的开发编写,该Role定义了安装Docker需要自动化执行的模块任务。在运行之前还需要写一个入口Playbook,这个yaml文件放在项目的根目录下,内容非常简单,就是关联Inventory里面定义的Group和Role。
#vi install.yml
---
- hosts: docker_nodes
gather_facts: False
remote_user: root
become: yes
become_method: sudo
roles:
- docker
7.运行自动安装Docker
通过一条简单的Ansible CLI命令就可以启动整个自动化安装流程,在Ansible Master主机上进入项目工作目录ansible_docker
注意:有2点是成功执行的前提:1. 目标服务器主机与Ansible Master主机之间需要用root帐号做ssh免密码; 2. 在Ansible Master主机上需要提前下载docker-17.04.0-ce.tgz,解压存放到/opt/data/docker目录下(由{{DATA_DIR}}, {{DOCKER_DIR}}两个全局白变量定义)
到这里你能够用Ansible提供的自动化能力实现Docker的全自动安装,Ansible提供了非常丰富的核心内置模块、云连接器模块以及大量第三方自定义模块来帮助实现各种各样的自动化任务。云星数据的RightCloud CMP(
www.rightcloud.com.cn)作为业界领先的混合云管理平台,以Ansible为核心对其提供的AaaS自动化管理服务进行了全面的优化。