避免您发展过程中的难题
简介: 目前为止,您已经将应用程序迁移到了云环境中,可以根据需求自动地启用或者停用一些资源。在本文中,迁移 Linux 应用程序到 Amazon 云中系列文章的第 4 篇,您将会了解如何控制这个不断变化的环境,使得它能够支持您的应用程序和业务。
查看本系列更多内容
<!-- <p class="ibm-no-print"> <div id="dw-tag-this" class="ibm-no-print"></div> <div id="interestShow" class="ibm-no-print"></div> </p> -->
发布日期: 2010 年 11 月 29 日
级别: 中级
原创语言: 英文
访问情况 5706 次浏览
建议: 0 (添加评论) <!-- Rating_Area_Begin --><!-- Ensure that div id is based on input id and ends with -widget -->
您在本系列的 将您的 Linux 应用程序迁移到 Amazon 云,第 1 部分:初始迁移 中将 SmallPayroll.ca 应用程序迁移到 Amazon 云中,在 将您的应用移植到 Amazon 云,第 2 部分:提高应用的可靠性 中使其变得更强壮。这个应用程序可以根据负载自行添加和删除,正如您在 将您的 Linux 应用程序迁移到 Amazon 云,第 3 部分:实现可扩展性 中看到的。现在基本上在任何给定的时间,处于激活状态的服务器数量和 IP 地址都不能被预测,这使得和它们连接成为一个挑战。因此,云环境是不同于传统数据中心的。
云环境的动态特性加大了应用程序部署的难度。部署不同,您的服务器清单也将不同,这样您要怎么升级应用程序?您要如何监视服务器故障?
这不是您通常的数据中心
在一个“通常”的数据中心,您可以随意命名您的电脑,给它们适合的 IP 地址 — 如果您想的话 — 您可以去查看服务器是不是还在原地。您可能使用电子表格追踪服务器,也许使用软件,或者只是在脑中、文本文件中记忆信息。您是否有进行配置管理,保证您的配置是一致的?
云环境和传统的数据中心是很不同的,因为您放弃了对许多功能的控制。您无法预测 IP 地址,甚至无法肯定两个服务器在同一个子网上。如果您进行资源的自动扩展,当加载新节点的时候,就可能会失去所有手动配置的硬件。您的脚本,依赖知道您有 20 个 Web 服务器和可预测的名称,在云环境中也无法运行。
幸运的是,有一些规则能够解决这些问题,甚至改善您在物理数据中心的运行时间!
IP 寻址和命名
人们喜欢花费大量时间担心如何命名他们的服务器,怎样能得到明智的寻址方案。Amazon Elastic Compute Cloud(Amazon EC2)实例是用任意的 IP 地址和基于这个地址的命名。您当然可以重命名服务器,但是这需要了解剩余环境。例如,要调用一个服务器 webprd42, 您就需要知道您最后加载的服务器是 webprd41。
依赖名称或者 IP 地址并不是好的解决方案,构建您的软件,这样名称就不再重要。
配置管理
在物理环境中,您通常可以避免对服务器的手动配置改变。当服务器自动加载时,手动改变并不适用。在每次更改后,您可以重新构建 Amazon Machine Imageual(AMI),但是这么做并不解决如何升级其他已经在运行中的服务器的问题。幸运的是,有丰富的软件包,例如 Puppet 和 Cfengine,能够为您自动完成这些变更(详见 参考资料)。
部署应用程序变更是配置管理中值得我们关注的另一方面。良好的配置管理工具能够完成这项工作,但是使用它们重新完成部署应用程序中特定的步骤,或者管理迁移和配置回滚是很困难的。Rails 社区研发了其他工具,例如 Capistrano,用于完成应用程序部署的任务(详见 参考资料)。
将配置管理视作两个不同的问题是很有帮助的。第一个问题是如何管理服务器 — 从软件包安装到各种守护进程的配置。第二个问题是如何用控制的方式部署新版本的软件。
系统监控
了解您的服务器在做什么很重要。CPU,磁盘资源,内存和网络都是您监控所需的重要组件。在您的系统上运行的守护进程,包括应用程序自身,可能都有其他指标要监视。例如,监视应用程序的响应时间和连接到 Web 服务器的数量,应用程序服务器可以在问题发生前向您预警。
许多工具都可用于监控服务器和绘制结果。挑战是如何在新服务器上线时监控,以及如何在它们下线时取消监控。
应用到云架构时的模式
当您查看如何管理一个动态环境,如 Amazon EC2 时,有三种常见模式:
- 客户端调查。服务器查询一个中央服务器的资源。使用这种模式,您无需知道服务器的所有地址,但是服务器按其自身的计划运行,所以您无法控制客户端调查的时机。
- 服务器推动。这个模式首先查询云环境提供商的应用程序编程接口(API),查找当前服务器的清单,然后中央服务器会联系各个服务器完成这项工作。这个模式会较为缓慢,并且需要管理工具明白环境的动态特性,但是它的好处就是允许您同步更新。
- 客户端注册。当各个服务器上线时,它就注册到一个中央服务器上。在服务器终止之前,它就登记到中央服务器。这个方法更复杂,但是允许您在云环境中使用不感知云的工具。
回页首
用于配置管理的客户端调查
这个模式很容易实现:客户端简单地调查一个众所周知的服务器,看预定的计划上是否有指示。如果服务器上没有任何任务需要客户端完成,它就告之客户端。缺点就是指示只有在客户端调查的情况下才会被发现;如果更改很紧急,它就必须等到下一次调查。
调查的一个良好使用方法就是服务器的配置管理。Reductive Labs 的 Puppet 包是很流行的配置管理工具。一个名为 Puppetmaster 的进程在中央服务器上运行。客户端运行 Puppet 守护进程,该进程会调查 Puppetmaster 的应用程序配置显示。这些配置显示指定某特定组件的所需终端状态,例如 “保证 NTP 守护进程已安装,并且正在运行”。Puppet 读取这些表示,改正所有错误。
您的发布可能由 Puppet 完成,或者您可以快速地使用 gem install puppet facter
进行安装。然而,Puppet 会实现一个更复杂的安全系统。客户端必须有一个签名密钥才能和 Puppetmaster 对话。您可以告诉 Puppetmaster 自动地签名所连接客户端密钥,但是这么做会导致任何人都能下载您的配置文件。替换解决方案就是忽略 Puppetmaster,自行发布您的显示,然后本地运行 Puppet 工具。
客户端运行 Puppet 显示的步骤如下所述:
- 从服务器下载显示的已更新副本和任何相关文件。
- 运行 Puppet 进行显示。
第 1 步中,选择的工具是 rsync
,它只能下载有更改的文件。第 2 步中,puppet
命令(puttet 安装的部分)执行显示。请注意,这个方法有两个提示:
- 服务器必须接受客户端 Secure Shell(SSH)的公共密钥。这个密钥可以在 AMI 上发布。
- 您在显示中指定的任何配置文件必须使用显示复制。内置的 Puppet 文件服务器也需要证书,这样您就不能使用这个文件传输方法。
示例显示保证客户端已经改正了网络时间协议配置。这涉及需要保证软件已安装,配置文件已修改,以及守护进程正在运行。清单 1 中显示了最高级的显示。
清单 1. 最高级的显示
import "classes/*"node default {include ntpclient } |
清单 1 首先输入在类目录中所有的文件;每个文件都包含着独立组件的信息。所有的节点都包含着 ntpclient
类,这些类在清单 2 中定义。
清单 2. ntpclient 类
class ntpclient {package {ntp:ensure => installed}service {ntpd:ensure => true,enable => true,subscribe => [ Package [ntp], File["ntp.conf"] ],}file {"ntp.conf":mode => 644,owner => root,group => root,path => "/etc/ntp.conf",source => "/var/puppetstage/files/etc/ntp.conf",before => Service["ntpd"]} } |
详细说明 Puppet 语言不在文本的探讨范畴,但是在更高的水平上,清单 2 定义了名为 ntpclient
的类,它由名为 ntp
的包,名为 ntpd
的服务,和 /etc 中名为 ntp.conf. 的文件组成。如果 ntp
包未安装,Puppet 就使用适当的工具,例如 yum
或者 apt-get
来进行安装。如果服务不在运行中,在启动脚本中,它就会被修复。如果 ntp.conf 文件不同于 /var/puppetstage/files/etc 中的副本,文件就会被更新。如果配置发生改变,before
和 subscribe
就保证守护进程重启。
服务器在 /var/puppetdist 中保存显示和文件,客户端将目录树复制到 /var/puppetstage。目录树的显示如清单 3 所示。
清单 3. /var/puppetdist 下的内容
/var/puppetdist/ |-- files | `-- etc | `-- ntp.conf `-- manifests|-- classes| `-- ntp.conf`-- site.pp |
最后,清单 4 同步文件,并在客户端上运行显示。
清单 4. 同步和运行显示的客户端代码
#!/bin/bash /usr/bin/rsync -avz puppetserver:/var/puppetdist/ /var/puppetstage/ --delete /usr/bin/puppet /var/puppetstage/manifests/site.pp |
当从 cron
定期地运行时,这些代码就会收集显示中的任何变更,然后将它们应用到云服务器。如果服务器的配置出现变更,Puppet 就会采取行动将服务器返回到其遵从性。
回页首
推动应用程序升级
在服务器上的配置升级很少需要在服务器间同步。如果一个数据包需要升级,半小时的窗口就足够了。然而,在应用程序升级中,您希望快速完成变更,并且控制时机。完成这项任务的流行工具就是 Capistrano。编写一个使用 Capistrano 特定区域语言的脚本,然后运行各种任务。清单 5 显示了最小的 Capistrano 脚本,将应用程序推动到一系列已知的服务器。
清单 5. 简单的 Capistrano 脚本
set :application, "payroll" set :repository, "https://svn.smallpayroll.ca/svn/app/trunk/" set :user, 'payroll' set :home, '/home/payroll' set :deploy_to, "#{home}" set :rails_env, "production"role :db, "174.129.174.213", :primary => true role :web, "174.129.174.213", "184.73.3.169" |
清单 5 中的大部分内容设置了变量,这些变量改变了 Capistrano 的默认动作,使用 SSH 访问所有的服务器,使用源代码管理工具检查应用程序副本。最后两行定义了使用的服务器 — 特别是,数据库和 Web 服务器。Capistrano 知道这些角色(这些角色可以根据您的目的进行扩展)。
清单 5 中的问题是,服务器必须被预定义。然而,Capistrano 可以在运行时使用 Amazon Web Services(AWS)APIs 定义服务器清单。首先运行:
gem install amazon-ec2 |
安装实现 API 的库。然后,如清单 6 所示,修正您的 Capistrano 脚本(deploy.rb)。
清单 6. 修正 Capistrano,在运行时动态地加载服务器清单
# Put this at the beginning of your deploy.rb require 'AWS'# Change your role :web definition to this role(:web) { my_instances }# This goes at the bottom of the recipe def my_instances@ec2 = AWS::EC2::Base.new( :access_key_id => ENV['AWS_ACCESS_KEY_ID'],:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'])servers = @ec2.describe_instances.reservationSet.item.collect do |itemgroup|itemgroup.instancesSet.item.collect {|item| item.ipAddress}endservers.flatten end |
清单 6 将 Web 角色从一个静态的定义改变为由 my_instances
功能返回的服务器动态清单。该功能使用 Amazon EC2 API DescribeInstances
调用返回服务器清单。API 以集合实例的格式返回数据,这些实例是在同样的保留标识符下加载在一起的。外部的 collect
循环遍历这些保留组,而内部的 collect
循环遍历每个限制组中的服务器。这个结果是一组数组,它紧贴服务器 IP 地址的一维数组,并且传回给调用者。
很幸运,Capistrano 提供了在服务器动态清单上操作的方法。如果它没有提供这种方法,那么您就需要采取其他的方法了。
回页首
注册管理服务器
对那些不轻易允许您使用服务器动态清单的应用程序,可以通过让云服务器注册到其他应用程序来解决这个问题。这个过程大体上采取两种形式之一:
- 云服务器连接到其他服务器,运行一个直接升级管理应用程序的脚本。
- 云服务器在通常的位置放置一个带有元数据的文件,例如 Amazon Simple Storage Service(Amazon S3),在这个位置其他脚本会重建它们的配置文件。
直接升级
Cacti 是一种流行的性能管理工具,能够通过 Simple Network Management Protocol(SNMP)或者脚本获取各种标准,并且将这些图片联合到仪表盘或者元图中(见 参考资料)。Cacti 的限制是您必须在 Cacti Web 接口或者通过命令行脚本匹配置管理服务器。在这个例子中,云服务器连接回到 Cacti 服务器,并且自行配置。
Cacti 基于模板系统,这使得对图表进行大量更改更容易。所有的命令行工具都在模板标识符上操作,所以您必须首先确定使用哪个标识符。清单 7 中显示了如何查找主模板,它为您预填充了一些数据。
清单 7. 主模板清单
$ php -q /var/lib/cacti/cli/add_device.php --list-host-templates Valid Host Templates: (id, name) 0 None 1 Generic SNMP-enabled Host 3 ucd/net SNMP Host 4 Karlnet Wireless Bridge 5 Cisco Router 6 Netware 4/5 Server 7 Windows 2000/XP Host 8 Local Linux Machine |
第 3 号模板用于主机运行 Net-SNMP
守护进程,它对大多数 Linux® 发行版可用。使用这个特定的守护进程而非更良好的版本允许您更容易地监视部分 Linux 特有的计数器。
知道了您正在使用主模板 3,可用图表的清单如清单 8 所示。
清单 8. 图表模板清单
$ php -q /var/lib/cacti/cli/add_graphs.php --list-graph-templates --host-template-id=3 Known Graph Templates:(id, name) 4 ucd/net - CPU Usage 11 ucd/net - Load Average 13 ucd/net - Memory Usage |
清单 8 中的三个图表是您从默认的 Cacti 分布中得到的。您可以添加更多,可以停止 --host-template-id
选项来查看它们,或者从 Internet 上的资源导入图表。
清单 9 显示了如何添加一个新的设备,然后是一个 CPU 图表。
清单 9. 添加一个带图表的新设备
$ php -q /var/lib/cacti/cli/add_device.php --description="EC2-1.2.3.4" \--ip=1.2.3.4 --template=3 Adding EC2-1.2.3.4 (1.2.3.4) as "ucd/net SNMP Host" using SNMP v1 with community "public" Success - new device-id: (5) php -q /var/lib/cacti/cli/add_graphs.php --host-id=5 --graph-type=cg \--graph-template-id=4 Graph Added - graph-id: (6) - data-source-ids: (11, 12, 13) |
清单 9 首先添加了一个 IP 地址为 1.2.3.4 的主机。返回的设备 ID 是 5
,然后它用于为 CPU 使用添加一个图表(cg
图表类型和模板 4)。结果就是图表的 ID 和正在被监视的各种数据资源的 ID。
要编写清单 9 中的过程非常简单。清单 10 显示了这样一个脚本。
清单 10. add_to_cacti.sh
#!/bin/bashIP=$1# Add a new device and parse the output to only return the id DEVICEID=`php -q /var/lib/cacti/cli/add_device.php --description="EC2-$IP" \--ip=$IP --template=3 | grep device-id | sed 's/[^0-9]//g'` # CPU graph php -q /var/lib/cacti/cli/add_graphs.php --host-id=$DEVICEID --graph-type=cg \--graph-template-id=4 |
脚本的第一个参数被保存为一个名为 $IP
的变量。add_device.php 脚本就在此 IP 地址运行,其结果只被那些包含使用 grep
命令 ID 的行所过滤。这个输出被送入只允许数字的 sed
脚本。这个值被保存在名为 $DEVICEID
的变量中。
存储了设备 ID 之后,添加一个图表就和调用 add_graphs.php 脚本一样简单。请注意,CPU 图表是最简单的情况,其他的图表类型需要更多参数。
add_to_cacti.sh 脚本在 Cacti 服务器上之后,所需的就是让云服务器运行它。清单 11 中显示了如何调用脚本。
清单 11. 从云服务器调用 cacti 脚本
#!/bin/bashMYIP=`/usr/bin/curl -s http://169.254.169.254/2007-01-19/meta-data/public-ipv4` ssh cacti@cacti.example.com "/usr/local/bin/add_to_cacti.sh $MYIP" |
清单 11 首先调用了 Amazon EC2 元数据服务器返回公共的 IP 地址,然后在 Cacti 服务器上远程运行命令。
回页首
结束语
本系列说明了应用程序从独立服务器到 AWS 云中的迁移。应用程序不断地改进,以利用 Amazon EC2 所提供的功能,从加载新服务器到加载均衡器。最后的这篇文章关注管理动态云环境,为您提供了使用的一些模式。
考虑到使用云资源的低成本门槛,您应该了解并尝试执行一个实际的迁移。即使您决定不在使用云的产品中运行应用程序,您还是会了解到很多在云中可进行的活动,可能还会改善您的系统管理技能。
<!-- CMA ID: 592023 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-document-html-6.0.xsl -->参考资料
学习
- LPI exam 301 prep,Topic 306:Capacity planning(developerWorks,2008 年 4 月)详细解释了如何监控系统和测量结果。
- Scott Patten 所写的 The S3 Cookbook 是来自 Leanpub 的 PDF,解释了如何使用有 Ruby 的 Amazon S3。这本书解决了大约 60 个问题,并且解释了如何使用代码解决各个问题。
- 浏览 developerWorks 的云计算专区,获取在云中开发和部署应用程序所需要的资源,了解最新云开发技术。
- 在 developerWorks Linux 专区 寻找为 Linux 开发人员(包括 Linux 新手入门)准备的更多参考资料,查阅我们 最受欢迎的文章和教程。
- 在 developerWorks 上查阅所有 Linux 技巧 和 Linux 教程。
- 随时关注 developerWorks 技术活动和网络广播。
- 观看 developerWorks 演示中心,包括面向初学者的产品安装和设置演示,以及为经验丰富的开发人员提供的高级功能。
获得产品和技术
- 现在您已经了解了几个 Amazon S3 的 AMI,您可能希望调整一些旧的 AMI。Amazon S3 File Manager 是一个基于 Web 的文件管理器,它与许多独立应用程序或浏览器插件有相似的特性。如果删除一个 AMI,请别忘记将它
ec2-deregister
。 - Capistrano 是一个流行的部署包,它的工作方式与 Rake 相似。
- Cfengine 是 UNIX® 最流行的配置管理工具。它很轻便,能够在大量机器上操作。
- Cacti 是一个围绕 RRDTool 构建的网络绘图工具。您几乎可以绘制任何想得到的东西。如果它在您的数据中心,很可能已经有人编写了插件来绘制它。
- Puppet 是一个用 Ruby 编写的配置管理工具,用于克服在 Cfengine 中的某些限制。如果您正在寻找开始的好方法,James Turnbull 所写的 Pulling Strings with Puppet(Apress,2008 年)是很受读者喜爱的一本书。
- 以最适合您的方式 IBM 产品评估试用版软件:下载产品试用版,在线试用产品,在云环境中使用产品,或者在 IBM SOA Sandbox for People 花几个钟头,学习如何高效地实现 Service Oriented Architecture。
讨论
- 欢迎加入 My developerWorks 中文社区。
- 加入 My developerWorks 社区。查看开发人员推动的博客、论坛、组和 wikis,并与其他 developerWorks 用户交流。
关于作者