本文介绍了一种为云计算平台中常用的配置管理工具
Chef 所打造的集成开发测试环境解决方案,利用了轻量级虚拟化技术 Docker,将 Chef-Server、Chef-Workstation
和 Chef-Client 部署在同一个虚拟机当中,实现了系统资源最小化及开发效率最大化的尝试。通过本文您可以全面地了解到如何在一个资源有限的环境下面(比如开发人员的笔记本电脑)将
Chef 系统的各个模块按照清晰的逻辑结构部署并运转起来,从而快速高效地进行 Chef Cookbook
的开发与测试的解决方案与实施细节。
前言
Chef 是 DevOps 敏捷开发运维技术的重要工具之一,是一种直接面向开发和运维的集中配置管理工具。Chef
常用的工作模式是 Client-Server 模式,开发测试环境需要多个网络节点。如何高效利用硬件资源同时又能够敏捷轻便地搭建功能完备的开发测试环境是一个有意义的问题。Docker
是一个构建在 LXC(Linux Container)技术之上的,基于进程容器(Process Container)的轻量级
VM 解决方案。本文介绍了采用 VMware 虚拟机嵌套部署 Docker 容器的方式模拟多节点的网络环境,构建一套集成化的
Chef 开发测试环境,使 Chef 的开发测试更加高效敏捷。
轻量级虚拟化技术 Docker 的简介及在软件开发测试领域的使用场景描述
Docker 是 PaaS 提供商 dotCloud 开源的一个基于 LXC
的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,发布到任何流行的 Linux
机器上,实现一种轻量级的虚拟化方案。Docker 容器是完全使用沙箱机制,相互之间不会有任何接口,几乎没有性能开销,不依赖于任何语言、框架或包装系统,可以很容易地在机器和数据中心中运行。
Docker 的环境包括 image 和 container。image
是操作系统镜像,container 是运行镜像的容器,它们之间就像是面向对象程序设计中类和实例之间的关系。Docker
提供一个镜像服务器的功能,可以直接从网上下载各种事先配置好的镜像。把下载的基础镜像在容器中运行起来后,可以继续在里面安装部署应用及服务,就像是在一台独立的虚拟机中的操作一样,所有的应用安装及配置变化都可以保存或者打包生成一个新的定制化
image。
对于生产环境来说,Docker 是一个非常轻量级的容器,所以不必担心性能问题。尤其在某些硬件资源紧张却又需要多台独立主机进行分布式计算的使用场景中,引入
Docker 来实现虚拟机的嵌套部署一方面可以满足独立主机资源的模拟,另一方面又可大大降低硬件资源的需求。下文中将要介绍的配置管理工具
Chef 的集成化开发测试环境就是 Docker 的一个比较典型的应用场景。
配置管理工具 Chef 及其各个功能模块介绍
Chef 是目前比较流行的一种直接面向开发和运维的集中配置管理工具,由一种纯
Ruby 的领域专用语言(DSL)保存系统配置。Chef 由 Opscode 公司开发,并在 Apache
协议版本 2.0 下开源发布。
Chef 对要配置的对象提供了跨平台的抽象,使用 Chef 进行系统配置的系统管理员在大部分时间只需跟这些抽象的资源打交道,而不用关心具体实现,如只需关心要添加什么软件或用户,不需要关心这些用户或软件是怎么添加上去的。
Chef 一般常用的有两种管理模式,分别为:
1.Chef-Solo 模式,即 Chef 的 standalone 模式,没有专门的
Chef-server,Chef-Solo 作为一个后台服务一样运行在所管理的服务器上,通过 cookbook
来控制本机的配置管理。
2.Client-Server 模式,即所管理的服务器作为 chef-client,统一由
chef-server 进行管理,管理包括安装、配置等工作。Chef-client 与 Chef-server
之间用证书进行认证。开发人员可通过开发工作站 Chef-workstation 提供的工具集进行具体的配置实例的开发与管理。定制好的配置实例以菜谱"Cookbook"的形式通过
Chef-workstation 上传到 Chef-server 中,由 Chef-server 针对客户端生成资源列表,然后推送到客户端,在客户端上运行接收到的资源列表。此种模式功能功能最全,也最复杂,下文的开发测试环境搭建就是基于这种模式。
需求分析:构建一套完整的 Chef 开发测试环境所需的网络架构及系统资源
一个 Client-Server 模式下的 Chef 的开发测试环境,需要
chef-server、chef-workstation 以及 chef-client 等功能节点,在网络资源上彼此独立。如果用实体主机来支撑每一个功能节点模拟生产环境的话,则硬件开销会比较大,且资源分配相对冗余,性价比很低。
在单一物理机上用 VMware 虚拟机来支撑各功能节点,可以大大减少物理主机的数量,但考虑到虚拟机是对操作系统的完全模拟,所需占用的资源和物理主机差不多,多个虚拟机同时运行的时候对宿主实体机的性能是个考验。在多个
chef-client 集中部署的应用场景下,系统资源很快便会被耗尽。如图 1 所示是某个 Chef 开发人员的
8G 内存工作机,在同时开启了三台各分配了 1G 内存的 VMware 虚拟机运行 Chef 的 Server/Workstation/Client
之后,再开启 Eclipse 等开发工具,当调试运行时系统资源已濒临耗尽,此时开发效率大受影响。
图 1. 只使用 VMware 虚拟机构建
Chef 环境的资源使用情况
Docker 的容器级轻量化虚拟技术恰到好处地解决了这个难题,通过容器把
Chef 的各个功能节点彼此隔离的同时,又剔除了大量无谓的资源占用,相当于把一个原先需要多人联合操作的重型武器变成了一个轻盈灵动的随身单兵装备。
以本文接下来要展示的操作环境为例,硬件方面物理主机还是 8G 内存的笔记本电脑,从硬盘中预留
30G 存储空间给虚拟机。软件方面利用 VMware Workstation 或 VMware Server
创建一台虚拟机,分配 1G 内存,安装 64 位的 Ubuntu 12.04.3,虚拟网络以 VMware
的 NAT 模式与 Host 主机相连,以方便虚拟机连接外网进行软件包的获取与升级。
图 2. 本文环境中 VMware 虚拟机的配置
系统设计:利用 Docker 的轻量级虚拟机部署 Chef 的各个模块
首先在 VMware 中搭建 Ubuntu12.04.3 虚拟机,然后安装
Docker,限于篇幅 VMware 虚拟机和 Docker 的具体安装步骤就不详细介绍了,如需要请参见本系列其他相关文章。下面重点介绍一下为了搭建
Chef 的集成开发测试环境在 Docker 环境中所创建的 container 和相关配置。
在 Docker 中预先下载了两种操作系统的 image,分别是 Ubuntu 和 CentOS。由 Ubuntu
image 生成两个 Container,分别标记为 Container1 和 Container2,
由 CentOS image 生成一个 Container,标记为 Container3。Chef-Server
将被部署在 Ubuntu 虚机上,Chef-Workstation 将被部署在 Docker Container1
上,Container2 和 Container3 作为两种不同操作系统的 Chef-client。由于
Docker 是基于 LXC 的,而 LXC 又是基于 cgroup 等 Linux kernel 功能的,所以
Container 的 guest 系统只能是 Linux base 的,也就是说 Windows 下的
Chef-Client 无法用 Docker 的 Container 来模拟,只能再建一个 Windows
虚机,这也是目前使用 Docker 的一个局限,但比起全部节点都占用一个虚拟机的原方案,引入 Docker
还是至少释放出了 Chef-Workstation 这一个虚机资源,在使用 Linux base 的 Chef-Client
的场景下资源的节省则更加显著。下面是下载 image 并配置 Container 运行的过程,以 Ubuntu
镜像为例:
在 VMware 虚拟机上下载 Ubuntu image 并查看结果
# docker pull ubuntu # docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE ubuntu latest 736be02b6054 4 months ago 238.4 MB |
以交互式打开一个 Ubuntu Container,安装 SSH 服务器,以便后面可以让 Container
在后台运行,然后通过 SSH 客户端连入,这样在使用上就和普通虚机一样了。
# docker run –i –t ubuntu /bin/bash root@24808f660519:/# apt-get update #在 ubuntu container 的交互式环境中更新 apt 源 root@24808f660519:/# apt-get install openssh-server root@24808f660519:/# mkdir /var/run/sshd root@24808f660519:/# passwd #设置 ubuntu container 的 root 密码,以便 SSH 客户端登录 root@24808f660519:/# exit |
这时就可以通过后台进程方式长期运行此 Ubuntu Container 了,但针对我们这个 Chef
的使用场景还有一个步骤要做,就是设置 DNS 地址映射。在 Client-Server 模式的 Chef
系统中,要求 Chef-Server/Chef-Workstation/Chef-Client 彼此之间都能够通过
hostname 或域名来识别,而在 Docker Container 中/etc/hosts 是只读的不允许修改所以必须使用外部的
DNS 系统进行地址映射。在本文的使用场景中,安装 Docker 的 VMware 虚拟机被 Docker
分配了一个内部地址 172.17.42.1,Docker Container 会按启动顺序被依次分配 172.17.0.2,172.17.0.3……,为了解决地址映射问题,在安装
Docker 的 VMware Ubuntu 虚机上安装了 bind9 DNS server,对 Docker
内部地址做好映射。然后就可以通过以下命令正式启动 Docker Cotainer,并使其以后台进程方式长期运行:
#docker run -d -dns=192.168.87.137 -v /home/backup:/home/backup ubuntu /usr/sbin/sshd -D |
# -dns 参数指定了 DNS server 地址,这里是 VMware ubuntu 的地址。
# -v 参数指定了 Docker server 和 Docker container 之间的共享目录,也就是说在安装
Docker 的 VMware Ubuntu 虚机上的/home/backup 目录里的文件可以在 container
的/home/backup 目录直接访问。
# /usr/sbin/sshd 表示 container 开机启动 SSH server
# -D 表示 container 以后台方式运行
此时就可以通过 ssh 登录到 container 当中,像操作正常机器一样对 container 进行安装应用等各种操作了。然后根据系统需要依次开通其他几个
Container,这样我们这个应用场景的 IT 基础架构变准备完毕。通过图 3 的 VMware 截图可以看到,VMware
虚拟机启动了一台,然后在虚拟机内部运行了两个 docker 容器。
图 3.本文环境中的虚机与 docker 容器
在逻辑上,本文环境的整体架构可以如图 4 所示:
图 4.本文环境中的系统逻辑架构图
系统实施:Chef 各个模块在 Docker 中的安装与运行
在 Docker server 所在 VMware Ubuntu 虚拟机上安装
Chef-Server
安装过程可参考官方文档(http://docs.opscode.com/install_server.html),实际操作比较简单,具体如下:
从官网下载并安装 Chef-Server 的 deb 包,本文实例所采用的版本为 11.0.11:
# dpkg -i chef-server_11.0.11-1.ubuntu.12.04_amd64.deb |
进行安装后配置:
# chef-server-ctl reconfigure |
最后通过 chef 自带的集成测试集来验证安装:
如果返回报告中没有报错,则表示 Chef-Server 安装成功。
在 Docker Container1 上安装 Chef-Workstation
主要是安装 chef-client 的 deb 包,配置 Chef-Workstation 到 Chef-Server
的访问,并配置 knife 工具集。安装过程可参考官方文档(http://docs.opscode.com/chef/install_workstation.html),具体步骤如下:
从官网下载并安装 Chef-Client 的 deb 包,本文实例所采用的版本为 11.6.0:
root@24808f660519:/opt/chef-repo# dpkg -i chef_11.6.0-1.ubuntu .12.04_amd64.deb |
安装配置 chef-repo(chef-repo 是存放开发好的 cookbooks 的地方,knife
命令行工具会从 chef-repo 上传数据到 chef-server,以供所管理的目标主机也就是 Chef-Client
获取并执行。):
root@24808f660519:/opt/chef-repo # git clone git://github.com/ opscode/chef-repo.git |
在 chef-repo 目录下,创建.chef 目录,并且修改.gitignore 文件,添加 .chef
配置 knife 工具集:
root@24808f660519:/opt/chef-repo # knife configure --initial |
需要输入相关的信息,主要是 server 的 URL,client 的 key,client 注册 server
所需要的 validator 和 validator private key 等,需要从 server
端 copy 两个文件到 workstation 机器上:
root@24808f660519:/opt/chef-repo # scp root@<server ip>:/etc/chef- server/admin.pem /opt/chef-repo/.chef/ root@24808f660519:/opt/chef-repo # scp root@<server ip>:/etc/chef- server/ chef-validator.pem /opt/chef-repo/.chef/ |
用 knife 工具列出一下当前注册在 Chef-Server 上的 Chef-Client,如果能看到
chef-validator 就表示 workstation 配置成功。
root@24808f660519:/opt/chef-repo/.chef# knife client list chef-validator chef-webui |
Chef-Client 管理节点的自动化安装
就是在 Chef-Workstation 上利用 knifebootstrap 来实现的,安装过程可参考官方文档:
(http://docs.opscode.com/install_bootstrap.html)。在 workstation
上运行 knife bootstrap 命令,格式如下:
knife bootstrap <node ip> -x <username> -P <password> --sudo |
在本文环境实例中,我们想在 Docker Container2 上面安装 Chef-Client 管理节点,Docker
server 给 Container2 分配的 IP 是 172.17.0.3,我们在之前配置 Container
的时候设定的 root 密码是 passw0rd,则 bootstrap 命令执行如下:
root@24808f660519:/opt/chef-repo/.chef # knife bootstrap 172.17.0.3 –x root –P passw0rd |
执行过程中 Chef-Server 会自动推送 PAM 认证文件及命令集模板到 Chef-Client
管理节点上,然后 Chef-Client 自动批处理执行 client 包下载安装、在 server 上认证并注册等工作,bootstrap
执行结束后再运行 knife client list 可以看到 Chef-Client 管理节点的 FQDN
已出现在 client 列表中:
root@24808f660519:/opt/chef-repo/.chef# knife client list chef-validator chef-webui f8f99a0f4d52 #此即为 Docker Server 给 Docker Container2 分配的 hostname |
至此,这个由 VMware 虚拟机嵌套 Docker Container 实现的集成化的 Chef 开发测试环境就搭建完成了。
系统测试:在这套集成环境中进行一个完整的 Chef Cookbook
的开发测试过程
限于篇幅,本文就用一个官方提供的基本入门级 cookbook 实例来做一下测试,验证一下这套集成环境的运转流程。具体的
chef cookbook 开发技巧请参见本系列其他相关文章。
可以登录到 Chef 的官方社区 http://community.opscode.com/cookbooks,搜索是否已经存在有相关的
cookbook 提供使用。本文选取其中名为 user 的 cookbook 来做试验,其功能是在 Chef-Client
管理节点上创建指定用户。
下载 cookbook,在 Chef-Workstation 上操作:
# root@24808f660519:~# sudo knife cookbook site install user |
系统会自动去官网下载 user 的 cookbook 代码包,并在 Chef-Workstation
的 chef-reop 目录中自动解压缩好,最后可以看到如下提示表明安装成功:
Cookbook user version 0.3.0 successfully installed |
user cookbook 的目录结构为:
root@24808f660519:/opt/chef-repo/cookbooks/user# ls CHANGELOG.md README.md Rakefile attributes metadata.json metadata.rb providers recipes resources templates |
user 的 README.md 中对这个 cookbook 的使用有说明,需要建立一个名为 users
的 data bag,将用户的信息写成一个 JSOn 文件放在下面,再通过 override_attributes
在 role 的配置文件中指定需要配置的用户。
上传 cookbook 到 chef-server:
root@24808f660519:/opt/chef-repo# knife cookbook upload user Uploading user [0.3.0] Uploaded 1 cookbook. |
创建 role:
root@24808f660519:/opt/chef-repo# cd roles root@24808f660519:/opt/chef-repo/roles# vi testuser.rb name "testuser" run_list( "recipe[user]", "recipe[user::data_bag]" ) override_attributes( "users" => [ "testuser1" ] ) |
上传 role 到 chef-server:
root@24808f660519:/opt/chef-repo/roles# knife role from file testuser.rb Updated Role testuser! |
为 user 这个 cookbook 创建 data_bag:
root@24808f660519: /opt/chef-repo# cd data_bags root@24808f660519: /opt/chef-repo/data_bags# mkdir users; cd users root@24808f660519:/opt/chef-repo/data_bags/users# vi testuser1.json { "id" : "testuser1", "gid": "admin", "comment" : "testuser1", "home" : "/home/testuser1", "create_user_group":"true", "ssh_keygen": "false", "ssh_keys" : "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+upV++0vIM2PuD2XvH+zOUF6 JsfofPCvCdqZ/Wg0GaRvcuPpKs7Ua2APSsvtvEz9ohQvexS1DO4G1ZjIO20dsc82BHTFxd3DmZyQ8g/CLoIKIdkDI mSffQxBYM//8URvtk16HTmuYVY9poalbVhlErhg0xSbyx/DQfOChfc34T8481iWPZ0pnJLj7z5AUvYR8fcWGtbMhv eoyKuB4VocsQvKfgVUauS1jIGGac7kC8XGVc6fEVzzTycS7dTypzHDJp3I9wHWoiMF4SD5MRb0sEhlvaOtryHGVdc fFj4Mrdiu8NepL7yyCb9qGdB7QbT1+hNCnZukWP4Iz6yzATLzS" } |
上传 data_bag 到 Chef-Server
root@24808f660519:/opt/chef-repo/data_bags/users# knife data bag from file users testuser1.json Updated data_bag_item[users::testuser1] |
为节点增加 run_list,即将 testuser 这个角色赋给 Chef-Client
管理节点
root@24808f660519:/opt/chef-repo/roles# knife node run_list add f8f99a0f4d52 "role[testuser]" f8f99a0f4d52: run_list: role[testuser] |
至此,对 user 这个 cookbook 的配置及 server 端部署已完成,可以开始正式工作了。
在 Chef-Client 管理节点上执行 chef-client 拉取配置,执行结果如图所示:
图 5. 在 Chef-Client 管理节点上执行 chef-client
拉取配置的执行结果
我们可以看到 Chef-Client 管理节点已经成功拉取到了 testuser1 这个用户的信息,并自动的进行了一系列的配置,完成了这个新用户的自动化创建。
此时再来看一下主机的资源消耗情况,可以看到和之前没有引入 docker 时相比,主机内存和 CPU 的消耗情况都大幅好转,系统运转流畅。如图
6 所示:
图 6. 使用 VMware 虚拟机内嵌 docker 所构建的 Chef
环境的资源使用情况
结束语
通过以上实例,我们就成功地在这个集成化的 Chef 开发测试环境中,使用 Chef 的 user 这个
cookbook 完成一次服务器的自动化部署。
对于 Chef 开发人员来说,使用这套集成化环境可以减少对于硬件环境的依赖,使开发人员更多地集中于 Chef
recipe 的开发本身,也方便代码的导出与重构。对于 Chef 测试人员来说,由于这套环境是基于 VMware
的,可以利用 VMware 本身的一些特性方便地进行测试环境的回滚以及迭代,同时利用 Docker 可以敏捷地模拟出多节点的应用场景,配合
VMware 虚拟网络还可以与外部实体网络相通,使测试环境得到进一步的扩展。
|