<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>服务器安全维护工作室 &#187; linux系统代维</title>
	<atom:link href="https://www.fuwuqiok.com/topics/linux%e7%b3%bb%e7%bb%9f%e4%bb%a3%e7%bb%b4/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.fuwuqiok.com</link>
	<description></description>
	<lastBuildDate>Sun, 01 Mar 2020 07:28:40 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.2.26</generator>
	<item>
		<title>万能配置(网站_服务器_数据库_安全组及端口_系统配置及设置_ftp)</title>
		<link>https://www.fuwuqiok.com/%e4%b8%87%e8%83%bd%e9%85%8d%e7%bd%ae%e7%bd%91%e7%ab%99_%e6%9c%8d%e5%8a%a1%e5%99%a8_%e6%95%b0%e6%8d%ae%e5%ba%93_%e5%ae%89%e5%85%a8%e7%bb%84%e5%8f%8a%e7%ab%af%e5%8f%a3_%e7%b3%bb%e7%bb%9f%e9%85%8d/</link>
		<comments>https://www.fuwuqiok.com/%e4%b8%87%e8%83%bd%e9%85%8d%e7%bd%ae%e7%bd%91%e7%ab%99_%e6%9c%8d%e5%8a%a1%e5%99%a8_%e6%95%b0%e6%8d%ae%e5%ba%93_%e5%ae%89%e5%85%a8%e7%bb%84%e5%8f%8a%e7%ab%af%e5%8f%a3_%e7%b3%bb%e7%bb%9f%e9%85%8d/#comments</comments>
		<pubDate>Sun, 01 Mar 2020 07:25:16 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[linux服务器维护]]></category>
		<category><![CDATA[linux系统代维]]></category>
		<category><![CDATA[万能配置(网站_服务器_数据库_安全组及端口_系统配置及设置_ftp)]]></category>

		<guid isPermaLink="false">https://www.fuwuqiok.com/?p=4158</guid>
		<description><![CDATA[<p>万能配置(网站_服务器_数据库_安全组及端口_系统配置及设置_ftp) 服务范围：站点部署，网站部署，网站设置 [&#8230;]</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e4%b8%87%e8%83%bd%e9%85%8d%e7%bd%ae%e7%bd%91%e7%ab%99_%e6%9c%8d%e5%8a%a1%e5%99%a8_%e6%95%b0%e6%8d%ae%e5%ba%93_%e5%ae%89%e5%85%a8%e7%bb%84%e5%8f%8a%e7%ab%af%e5%8f%a3_%e7%b3%bb%e7%bb%9f%e9%85%8d/">万能配置(网站_服务器_数据库_安全组及端口_系统配置及设置_ftp)</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></description>
				<content:encoded><![CDATA[<h1 class="view-title"><span data-spm-anchor-id="5176.730006-52734001-52746001-cmfw007702.content.i0.7d187bf9B5uYpM">万能配置(网站_服务器_数据库_安全组及端口_系统配置及设置_ftp)</span></h1>
<p class="product-head-desccription" data-spm-anchor-id="5176.730006-52734001-52746001-cmfw007702.content.i1.7d187bf9B5uYpM">服务范围：站点部署，网站部署，网站设置，数据库设置 ，防火墙设置，系统配置，DEDECMS，帝国等开源模板导数据前配置，安全组设置，安全策略设置，服务器设置，80端口配置及设置，开启或关闭端口。</p>
<p class="product-head-desccription" data-spm-anchor-id="5176.730006-52734001-52746001-cmfw007702.content.i1.7d187bf9B5uYpM">
<table border="1" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td><strong><span data-spm-anchor-id="5176.730006-52734001-52746001-cmfw007702.content.i2.7d187bf9B5uYpM">服务</span>说明</strong></td>
<td><strong>价格</strong></td>
</tr>
<tr>
<td><strong>网站设置：</strong></p>
<p>1、开源网站设置，及其它网站设置。</td>
<td>100元/个</td>
</tr>
<tr>
<td><strong>网站/程序/服务器/应用部署：</strong></p>
<p>1、部署网站、程序、服务器、应用等。</p>
<p>2、配置网站、程序、服务器、应用等。</td>
<td>200元/个</td>
</tr>
<tr>
<td><strong>数据库设置</strong><strong>：</strong></p>
<p>1、数据库安全设置。</p>
<p>2、数据库应用设置等。</p>
<p>3、数据库性能调优。</td>
<td>200元/次</td>
</tr>
<tr>
<td><strong>防火墙设置</strong><strong>：</strong></p>
<p>1、第三方防火墙设置。</p>
<p>2、服务器防火墙设置，安全组设置，安全规则设置等。</td>
<td>200元/次</td>
</tr>
<tr>
<td><strong>系统设置</strong><strong>：</strong></p>
<p>1、系统安全设置，环境要求设置等。</p>
<p>2、80端口配置及其它端口配置等。</td>
<td>100元/次</td>
</tr>
<tr>
<td><strong>端口配置及设置</strong><strong>：</strong></p>
<p>1、如：80端口配置，或其它指定端口配置。</p>
<p>2、开启或关闭指定端口。</td>
<td>200元/次</td>
</tr>
<tr>
<td colspan="2"><strong>备注</strong><strong>：</strong></p>
<p>1、如果您无法确认或者需要更多服务，可以联系工作人员交流。</p>
<p>2、交付时间：1天内（通常2小时）</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<div class="box-icon">
<div class="element">
<div class="d-item">
<h2 data-spm-anchor-id="5176.730006-52734001-52746001-cmfw007702.content.i4.7d187bf9B5uYpM">产品价格</h2>
<table class="param-table price-table module-table" width="100%">
<thead>
<tr>
<td>版本名称</td>
<td>计费项</td>
<td>新购</td>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="1">网站设置</td>
<td>版本基础价格</td>
<td>100元</td>
</tr>
<tr>
<td rowspan="1">网站/程序/服务器部署</td>
<td>版本基础价格</td>
<td>200元</td>
</tr>
<tr>
<td rowspan="1">数据库设置</td>
<td>版本基础价格</td>
<td>200元</td>
</tr>
<tr>
<td rowspan="1">防火墙设置</td>
<td>版本基础价格</td>
<td>200元</td>
</tr>
<tr>
<td rowspan="1">系统配置</td>
<td>版本基础价格</td>
<td>100元</td>
</tr>
<tr>
<td rowspan="1" data-spm-anchor-id="5176.730006-52734001-52746001-cmfw007702.content.i5.7d187bf9B5uYpM">端口配置及设置</td>
<td>版本基础价格</td>
<td>200元</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="box-icon">
<div class="element">
<div class="r-comment-list">
<h2></h2>
</div>
</div>
</div>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e4%b8%87%e8%83%bd%e9%85%8d%e7%bd%ae%e7%bd%91%e7%ab%99_%e6%9c%8d%e5%8a%a1%e5%99%a8_%e6%95%b0%e6%8d%ae%e5%ba%93_%e5%ae%89%e5%85%a8%e7%bb%84%e5%8f%8a%e7%ab%af%e5%8f%a3_%e7%b3%bb%e7%bb%9f%e9%85%8d/">万能配置(网站_服务器_数据库_安全组及端口_系统配置及设置_ftp)</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.fuwuqiok.com/%e4%b8%87%e8%83%bd%e9%85%8d%e7%bd%ae%e7%bd%91%e7%ab%99_%e6%9c%8d%e5%8a%a1%e5%99%a8_%e6%95%b0%e6%8d%ae%e5%ba%93_%e5%ae%89%e5%85%a8%e7%bb%84%e5%8f%8a%e7%ab%af%e5%8f%a3_%e7%b3%bb%e7%bb%9f%e9%85%8d/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>兼职企业运维技术顾问</title>
		<link>https://www.fuwuqiok.com/%e5%85%bc%e8%81%8c%e4%bc%81%e4%b8%9a%e8%bf%90%e7%bb%b4%e6%8a%80%e6%9c%af%e9%a1%be%e9%97%ae/</link>
		<comments>https://www.fuwuqiok.com/%e5%85%bc%e8%81%8c%e4%bc%81%e4%b8%9a%e8%bf%90%e7%bb%b4%e6%8a%80%e6%9c%af%e9%a1%be%e9%97%ae/#comments</comments>
		<pubDate>Mon, 04 Mar 2019 13:50:04 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[aliyun服务器代维]]></category>
		<category><![CDATA[ECS云服务器运维代维服务]]></category>
		<category><![CDATA[linux代维]]></category>
		<category><![CDATA[linux系统代维]]></category>
		<category><![CDATA[服务器代维]]></category>
		<category><![CDATA[服务器代维合同]]></category>
		<category><![CDATA[服务器代维护]]></category>
		<category><![CDATA[服务器运维]]></category>
		<category><![CDATA[网站代维]]></category>
		<category><![CDATA[网站防挂马]]></category>
		<category><![CDATA[兼职企业运维技术顾问]]></category>

		<guid isPermaLink="false">https://www.fuwuqiok.com/?p=3914</guid>
		<description><![CDATA[<p>应用服务器运维技术顾问，为企业业务和应用提供技术咨询和指导、应急处理，为企业运营中的技术难题提供技术解决方案和 [&#8230;]</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e5%85%bc%e8%81%8c%e4%bc%81%e4%b8%9a%e8%bf%90%e7%bb%b4%e6%8a%80%e6%9c%af%e9%a1%be%e9%97%ae/">兼职企业运维技术顾问</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>应用服务器运维技术顾问，为企业业务和应用提供技术咨询和指导、应急处理，为企业运营中的技术难题提供技术解决方案和技术咨询，节约企业硬件和人力维护成本。</p>
<div class="box-icon" data-spm-anchor-id="5176.730006-52734001-52732002-cmfw015135.content.i2.239b5f96K55eo2">
<div class="element">
<div class="r-product-detail">
<div class="d-item rich-text">
<h2>产品亮点</h2>
<div>更灵活的运维服务，专家技术指导，病毒木马防范、处理，性能问题解决方案，云服务器方案指导。</div>
</div>
<div class="d-item rich-text">
<h2>产品说明</h2>
<div>
<p><strong>企业运维技术顾问：</strong></p>
<p><strong>在服务期内，我们为签约服务器提供技术顾问服务，包含安全防护，病毒木马查杀、安全解决方案，服务器应急处理，系统性能问题定位，应用服务故障定位服务。安全专家，运维架构师为您提供高效的技术服务！</strong></p>
<p><strong>资费标准：</strong></p>
<p><strong>每台ECS，如有多台请另外再购买，我们不提供程序代码修改。</strong></p>
<p><strong>一、安全防护</strong></p>
<p><strong>   提供全面安全防护设置，让服务器达到高级别安全。主要包含以下内容：</strong></p>
<p><strong>   1、系统补丁更新</strong></p>
<p><strong>   2、系统安全加固</strong></p>
<p><strong>   3、软件安全防护</strong></p>
<p><strong>   4、服务器安全策略</strong></p>
<p><strong> </strong></p>
<p><strong>二、应急处理</strong></p>
<p><strong>    1、网站无法访问；</strong></p>
<p><strong>    2、服务器木马，病毒处理；</strong></p>
<p><strong>三、数据备份，数据安全方案</strong></p>
<p><strong>      1、本地备份：对网站、MySQL、SQL Server进行本地自动备份,。</strong></p>
<p><strong>      2、云 备 份：将本地备份数据传输至百度网盘或者金山网盘。</strong></p>
<p><strong>      3、其它备份：根据客户实际情况，提供更高级的备份方案。</strong></p>
<p><strong> </strong></p>
<p><strong>四、系统优化</strong></p>
<p><strong>       依托我司丰富的经验和强大的技术，对系统进行全面优化；部分服务器性能可得到数倍提升。</strong></p>
<p><strong>五、每周安全检测</strong></p>
<p><strong>       每周二，我们将安排专门技术人员检测服务器的安全、性能及硬件等状况，并通过短信、邮件等方式告知用户。</strong></p>
<p><strong> 除此我们还为每台服务器安装“服务器巡查系统”；该系统自动检测服务器的10余项核心参数，发现异常立即报警，避免出现严重问题以及让问题更早解决。</strong></p>
<p><strong>       同时我们还为每台服务器提供7*24性能监控，您可以通过网页查看到服务器的CPU、内存、IO、带宽等资源参数，一目了然的掌握服务器情况。</strong></p>
<p><strong> </strong></p>
<p><strong>六、应急响应</strong></p>
<p><strong>       根据签约不同，我们正常的上班时间为9:00-22:00，其它时间可直接拨打我司电话。为客户提供最多可达7*24的应急响应服务，处理各种突发情况。</strong></p>
<p><strong>七、一站式扩展</strong></p>
<p><strong>       除了以上常规服务外，我们还可以提供多样化的扩展服务；如：攻击防护方案、网站加速、系统故障排查、负载均衡方案等等。</strong></p>
<p><strong>适用用户：</strong></p>
<p><strong>使用Linux CentOS、Debian、Ubuntu、Suse、Windows Server 2003/2008/2012</strong></p>
<p><strong>我们的优势：</strong></p>
<p><strong>和其他代维公司相比，我们最大的优势在于专业的技术团队，有各自专注于Linux多种发行版本、Windows各个版本操作系统运行环境的专业运维人员，我们的服务凝聚了所有技术人员在服务器运维领域多年的经验及技术，让我们处理问题时更便捷，效果也更加明显。</strong></p>
<p><strong>1、团队中最高十二年安全运维经验。</strong></p>
<p><strong>2、众多专业技术大神，处理问题更快捷。</strong></p>
<p><strong>3、系统工程师，系统架构师，专业运维团队，专业系统安全专家。</strong></p>
<p><strong>4、多种安全方案，云产品技术服务，为企业提供云端安全保障。</strong></p>
<p><strong>5、八千多家企业用户的选择。</strong></p>
</div>
</div>
<div class="d-item broderno"></div>
<div class="d-item rich-text">
<h2>售后支持范围</h2>
<div>服务时间：工作日9:00—12:00,13:00-18:00。</div>
<div></div>
<div>业务范围：服务器环境配置，故障排查（不含程序自身问题），数据库配置更改，数据库权限、账户，数据迁移，程序迁移，数据库故障排查等； 费用范围：详情参照本公司服务类商品定价，或咨询在线技术支持。</div>
</div>
</div>
</div>
</div>
<div class="box-icon">
<div class="element">
<div class="d-item">
<h2>产品价格</h2>
<table class="param-table price-table module-table" width="100%">
<thead>
<tr>
<td>版本名称</td>
<td>计费项</td>
<td>新购（按月购买）</td>
<td>新购（按年购买）</td>
<td>续费（按月购买）</td>
<td>续费（按年购买）</td>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="1">包月</td>
<td>版本基础价格</td>
<td>2000元/月</td>
<td>&#8212;</td>
<td>1200元/月</td>
<td>&#8212;</td>
</tr>
<tr>
<td rowspan="1">半年</td>
<td>版本基础价格</td>
<td>1200元/月</td>
<td>&#8212;</td>
<td>900元/月</td>
<td>&#8212;</td>
</tr>
<tr>
<td rowspan="1">包年维护</td>
<td>版本基础价格</td>
<td>12000元/年</td>
<td>&#8212;</td>
<td>10800元/年</td>
<td>&#8212;</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e5%85%bc%e8%81%8c%e4%bc%81%e4%b8%9a%e8%bf%90%e7%bb%b4%e6%8a%80%e6%9c%af%e9%a1%be%e9%97%ae/">兼职企业运维技术顾问</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.fuwuqiok.com/%e5%85%bc%e8%81%8c%e4%bc%81%e4%b8%9a%e8%bf%90%e7%bb%b4%e6%8a%80%e6%9c%af%e9%a1%be%e9%97%ae/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>建立 VPC 并基于参数动态创建子网的 CloudFormation 模板</title>
		<link>https://www.fuwuqiok.com/%e5%bb%ba%e7%ab%8b-vpc-%e5%b9%b6%e5%9f%ba%e4%ba%8e%e5%8f%82%e6%95%b0%e5%8a%a8%e6%80%81%e5%88%9b%e5%bb%ba%e5%ad%90%e7%bd%91%e7%9a%84-cloudformation-%e6%a8%a1%e6%9d%bf/</link>
		<comments>https://www.fuwuqiok.com/%e5%bb%ba%e7%ab%8b-vpc-%e5%b9%b6%e5%9f%ba%e4%ba%8e%e5%8f%82%e6%95%b0%e5%8a%a8%e6%80%81%e5%88%9b%e5%bb%ba%e5%ad%90%e7%bd%91%e7%9a%84-cloudformation-%e6%a8%a1%e6%9d%bf/#comments</comments>
		<pubDate>Wed, 21 Nov 2018 06:36:45 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[aliyun服务器代维]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[linux服务器代维]]></category>
		<category><![CDATA[linux服务器代维护]]></category>
		<category><![CDATA[linux服务器维护]]></category>
		<category><![CDATA[linux系统代维]]></category>
		<category><![CDATA[服务器代维合同]]></category>
		<category><![CDATA[服务器代维护]]></category>
		<category><![CDATA[服务器安全代维]]></category>
		<category><![CDATA[服务器安全设置]]></category>
		<category><![CDATA[服务器迁移]]></category>
		<category><![CDATA[服务器运维]]></category>
		<category><![CDATA[系统安全代维]]></category>
		<category><![CDATA[网站代维]]></category>
		<category><![CDATA[网站防挂马]]></category>
		<category><![CDATA[建立 VPC 并基于参数动态创建子网的 CloudFormation 模板]]></category>

		<guid isPermaLink="false">https://www.fuwuqiok.com/?p=3869</guid>
		<description><![CDATA[<p>创建 Subnet 在大型企业云迁移项目组，经常会遇到企业将线下数据中心的子网迁移到 AWS 云上。线下的子网 [&#8230;]</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e5%bb%ba%e7%ab%8b-vpc-%e5%b9%b6%e5%9f%ba%e4%ba%8e%e5%8f%82%e6%95%b0%e5%8a%a8%e6%80%81%e5%88%9b%e5%bb%ba%e5%ad%90%e7%bd%91%e7%9a%84-cloudformation-%e6%a8%a1%e6%9d%bf/">建立 VPC 并基于参数动态创建子网的 CloudFormation 模板</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></description>
				<content:encoded><![CDATA[<h2>创建 Subnet</h2>
<p>在大型企业云迁移项目组，经常会遇到企业将线下数据中心的子网迁移到 AWS 云上。线下的子网划分一般会根据子网的使用功能不同进行划分，例如防火墙子网、负载均衡器子网、配合部署高可用架构的心跳线子网、应用系统子网等。不同企业的子网划分规则、子网的掩码大小和路由规则均不相同，并且在迁移后的系统上线后，企业还会经常划分新的网段以部署新的应用系统，这就需要有一个通用的模板来协助网络管理人员简化工作流程，提高工作效率。在我所经历过的一个项目中，生产 VPC 的子网划分有47个之多，且子网掩码有/24, /25, /26. 27/, /28等不同，在添加新的子网时，需要仔细计算新的子网 CIDR 以及为新建子网配置路由表。</p>
<h2>动态创建子网的方案概述</h2>
<p>因为 CloudFormation 不支持程序逻辑，只支持静态资源的创建，所以在本方案中采用 AWS Lambda 来基于输入参数动态创建不同类型的子网。我们定义了3种不同类型的子网：公共子网 (Public Subnet)， 外部子网 (External Subnet)，内部子网 (Internal Subnet) Subnet。<br />
公共子网的路由表有如下路由信息：</p>
<table border="1">
<tbody>
<tr>
<td><strong>Destination</strong></td>
<td><strong>Target</strong></td>
</tr>
<tr>
<td>0.0.0.0/0</td>
<td>igw-xxxxx (Internet Gateway)</td>
</tr>
</tbody>
</table>
<p>部署在公共子网中的服务器可以直接与 Internet 进行通信（缺省分配 Internet IP 地址，并且有指向 Internet Gateway 的缺省路由）。<br />
外部子网的路由表有如下路由信息：</p>
<table border="1">
<tbody>
<tr>
<td width="293"><strong>Destination</strong></td>
<td width="192"><strong>Target</strong></td>
</tr>
<tr>
<td width="293">0.0.0.0/0</td>
<td width="192">nat-xxxxx (NAT gateway)</td>
</tr>
<tr>
<td width="293">pl-xxxxxx (com.amazonaws.cn-north-1.s3)</td>
<td width="192">vpce-xxxxxxx</td>
</tr>
<tr>
<td width="293">pl-xxxx (com.amazonaws.cn-north-1.dynamodb)</td>
<td width="192">vpce-xxxx</td>
</tr>
</tbody>
</table>
<p>部署在外部子网的服务器可以通过 NAT Gateway 与 Internet 进行通信，并且可以不通过互联网访问 S3 和 dynamodb。<br />
内部子网的路由表有如下路由信息：</p>
<table border="1">
<tbody>
<tr>
<td width="293"><strong>Destination</strong></td>
<td width="192"><strong>Target</strong></td>
</tr>
<tr>
<td width="293">pl-xxxxxx (com.amazonaws.cn-north-1.s3)</td>
<td width="192">vpce-xxxxxxx</td>
</tr>
<tr>
<td width="293">pl-xxxx (com.amazonaws.cn-north-1.dynamodb)</td>
<td width="192">vpce-xxxx</td>
</tr>
</tbody>
</table>
<p>部署在内部子网的服务器不能访问 Internet，但是能直接访问 S3 和 dynamodb。<br />
本方案使用2个 CloudFomation 模板， 第一个模板(CreateBaseVpc.json)创建共享资源，例如 VPC、Internet Gateway、公共子网 (Public Subnet) 路由表、在各个可用区内创建公共子网、NAT Gateway、 VPC Endpoint (S3 endpoint和DynamoDB endpoint)和创建外部子网路由表。在这个模板中还创建了3个 Lambda 功能函数：</p>
<ul>
<ul>
<li>
<h4>SharedInfra – 对应 python 程序 create_shared_infra.zip</h4>
</li>
</ul>
</ul>
<p>功能：根据输入的参数，在程序运行的AWS Region的每个AZ内创建公共子网，将在 CreateBaseVpc.json 模板中建立的公共子网路由表关联到每个公共子网。 在每个公共子网内创建 NAT Gateway 和VPC endpoint，创建内部子网路由表，创建外部子网路由表。删除已经创建完成的资源，包括：子网、路由表、vpc endpoint、NAT Gateway、Elastic IP。</p>
<ul>
<ul>
<li>
<h4>CreateExternalRoute – 对应 python 程序 create_external_route.zip</h4>
</li>
</ul>
</ul>
<p>功能：创建外部子网路由表中的路由。因为 NAT Gateway 的创建速度比较慢，创建路由时一定要等待 NAT Gateway 的状态变成 available 后才可以成功。如果将此功能与 SharedInfra 放在一起，在执行的时候容易发生 Lambda 运行超时错误。删除已经创建的路由信息。</p>
<ul>
<ul>
<li>
<h4>SubnetAutomation – 对应 python 程序 subnet_creation.zip</h4>
</li>
</ul>
</ul>
<p>功能：根据输入的参数，计算网路的子网掩码，创建公共子网、外部子网和内部子网，并将在公共子网路由表、内部子网路由表和外部子网路由表关联到相应的子网上。删除已经创建完成子网。在 CreateBaseVpc.json 模板运行时，通过创建用户定义资源 ExternalRouteCreation和SharedInfraCreation 分别触发 Lambda 功能 CreateExternalRoute 和 SharedInfra，从而完成共享资源的创建。并提供了 SubnetAutomation 的功能函数 ARN，供运行第二个模板时调用。</p>
<p>第二个模板 (SubnetAuto.json) 创建动态资源，例如根据输入参数的不同计算子网掩码、创建子网并分配路由表。</p>
<p>本方案中创建子网时的输入参数并不需要 CIDR，只需要指定子网要提供的可用 IP 地址的个数即可，程序在计算可用 IP 地址时已经排除了 AWS 子网子网中保留的5个 IP 地址。例如：如果要创建有50个 IP 的子网，则子网掩码是/26，共计有64-5=59个可用IP地址；如果要创建有16个 IP 的子网，则子网掩码是/27，共计有32-5=27个可用 IP 地址。</p>
<p>创建子网的参数输入规则如下：</p>
<ol>
<li>每个子网包含4个部分，之间使用“:”分隔 – 功能: IP 地址数量:可用区:子网类型</li>
<li>可用区根据Region的不同可选项为：1a,1b,1c,1d,1e等</li>
<li>子网类型的可选项为：p（公共子网），e（外部子网）或者 i（内部子网）</li>
<li>不同子网之间使用“,”分隔。</li>
</ol>
<h2>安装和运行</h2>
<ol>
<ol>
<li>在浏览器中输入：<a href="https://github.com/shaneliuyx/autosubnet_creation">https://github.com/shaneliuyx/autosubnet_creation</a>， 下载2个 json 文件和3个 zip 文件。将3个 zip 文件上传到一个 S3 存储桶中。</li>
<li>打开 AWS 控制台，并选择 CloudFormation，选择存储在本地的 json 文件 json，运行 CloudFormation 模板。</li>
<li>假设输入缺省的 PublicSubnetCapacity 和 VpcCidr 如下：</li>
</ol>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template1.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template1.png" alt="vpc-cloudformation-template1" width="878" height="399" /></a></p>
<ol>
<ol>
<li>选择 Next，直至 AWS 资源开始创建</li>
<li>最终运行结果如下：</li>
</ol>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template2.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template2.png" alt="vpc-cloudformation-template2" width="878" height="387" /></a></p>
<p>创建的 Subnet 如下：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template3.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template3.png" alt="vpc-cloudformation-template3" width="878" height="69" /></a></p>
<p>公共子网路由表：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template4.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template4.png" alt="vpc-cloudformation-template4" width="560" height="133" /></a></p>
<ol>
<ol>
<li>打开 AWS 控制台，并选择 CloudFormation，选择存储在本地的 json 文件 json，运行 CloudFormation 模板。</li>
<li>输入 SubnetParameters：web1:50:1a:p,web1:50:1b:p,app1:50:1a:e,app1:50:1b:e,db1:50:1a:i,db1:50:1b:i</li>
</ol>
</ol>
<p>这将创建6个子网，其中 Web、APP 和 DB 各2个子网，分布在2个 AZ 中:</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template5.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template5.png" alt="vpc-cloudformation-template5" width="878" height="346" /></a></p>
<ol>
<ol>
<li>运行结果如下:</li>
</ol>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template6.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template6.png" alt="vpc-cloudformation-template6" width="878" height="204" /></a></p>
<p>创建的子网：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template7.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template7.png" alt="vpc-cloudformation-template7" width="878" height="69" /></a><br />
<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template8.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template8.png" alt="vpc-cloudformation-template8" width="878" height="72" /></a><br />
<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template9.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template9.png" alt="vpc-cloudformation-template9" width="878" height="70" /></a></p>
<p>内部子网路由表：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template10.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template10.png" alt="vpc-cloudformation-template10" width="650" height="270" /></a></p>
<p>外部子网路由表：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template11.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template11.png" alt="vpc-cloudformation-template11" width="650" height="305" /></a></p>
<p>假设现在还要创建一个包含16个有效 IP 的公共子网用于部署网络设备，可以再运行一次SubnetAuto.json，输出参数：net1:16:1a:p,net1:16:1b:p<br />
则可以创建出如下子网：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template12.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template12.png" alt="vpc-cloudformation-template12" width="878" height="68" /></a></p>
<h2>与其他 CloudFormation 模板配合使用，进行 Landing Zone 部署</h2>
<p>Landing Zone 中文名称翻译成着陆区，是指 AWS 的基本环境，用户在其上部署安全和运维流程。Landing Zone 的内容包含：账户结构、账户安全基线、网络结构和AWS用户访问管理。下面简单的介绍一下 AWS Landing Zone 的最佳实践。</p>
<ul>
<ul>
<li>
<h4>账户结构</h4>
</li>
</ul>
</ul>
<p>AWS 建议账户的划分与企业的组织架构和运维部门的组织架构一致。例如按照如下结构划分账户：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template13.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template13.png" alt="vpc-cloudformation-template13" width="400" height="451" /></a></p>
<ul>
<ul>
<li>
<h4>账户安全基线</h4>
</li>
</ul>
</ul>
<p>AWS 建议在所有账户内打开 CloudTrail 和 AWS Config 功能。所有日志信息要复制到安全账户内的 S3 存储桶中。建立跨账户访问的 Auditor 角色。</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template14.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/vpc-cloudformation-template14.png" alt="vpc-cloudformation-template14" width="400" height="433" /></a></p>
<ul>
<ul>
<li>
<h4>网络结构</h4>
</li>
</ul>
</ul>
<p>AWS 建议删除缺省 VPC，建立客户自己定义的 VPC。建立共享 VPC（包含目录服务、邮件服务器等），应用 VPC 与共享 VP C建立 Peer 关系。通过 VPN 或者 Direct Connect 与线下的数据中心建立网络连接，或者采用 Transit VPC（参考 <a href="https://amazonaws-china.com/answers/networking/aws-global-transit-network/">https://aws.amazon.com/answers/networking/aws-global-transit-network/</a> ，<a href="https://amazonaws-china.com/blogs/aws/aws-solution-transit-vpc/">https://aws.amazon.com/blogs/aws/aws-solution-transit-vpc/</a> ）建立集中的网络控制机制。网络输入输出的安全控制（建立堡垒机，建立 Security Group、网络 ACL 或者第三方的防火墙工具）</p>
<ul>
<ul>
<li>
<h4>AWS 用户访问管理</h4>
</li>
</ul>
</ul>
<p>包括建议基于 SAML 的单点登录，建立跨账户角色访问机制等。</p>
<p>上述介绍的建立 VPC 和子网的方法可以看成建立 Landing Zone 的基础，在此之上，我们还可以使用 CloudFormation 建立堡垒机，打开 CloudTrail 和 AWS config，建立不同账户间的日志（log）复制机制，建立 Config Rule 进行合规性检查等等。 AWS 已经开发出多个 QuickStart CloudFormation 脚本协助用户完成上述工作，但是这些脚本在中国区（BJS）运行时需要做一些修改。下表列出了一些可用的资源，其中中国区部署模板是我针对中国区的特点修改过的，可以在BJS正常运行。</p>
<table border="1">
<tbody>
<tr>
<td></td>
<td></td>
<td><strong>原始代码</strong> <strong>参考</strong></td>
<td><strong>AWS </strong><strong>中国区部署模板</strong></td>
</tr>
<tr>
<td rowspan="5"><strong>账户安全基线</strong></td>
<td>配置 AWS config 和 CloudTrail</td>
<td rowspan="3"><a href="https://github.com/aws-quickstart/quickstart-compliance-pci">https://github.com/aws-quickstart/quickstart-compliance-pci</a></td>
<td><a href="https://s3.cn-north-1.amazonaws.com.cn/shane/quickstart-security/logging.template">https://s3.cn-north-1.amazonaws.com.cn/shane/quickstart-security/logging.template</a></td>
</tr>
<tr>
<td>配置 IAM 角色</td>
<td><a href="https://s3.cn-north-1.amazonaws.com.cn/shane/quickstart-security/iam.template">https://s3.cn-north-1.amazonaws.com.cn/shane/quickstart-security/iam.template</a></td>
</tr>
<tr>
<td>配置 Config rules</td>
<td><a href="https://s3.cn-north-1.amazonaws.com.cn/shane/quickstart-security/config-rules.template">https://s3.cn-north-1.amazonaws.com.cn/shane/quickstart-security/config-rules.template</a></td>
</tr>
<tr>
<td>将 CloudWatch Log 转储到S3存储桶</td>
<td><a href="https://github.com/alertlogic/cloudwatch-logs-s3-export#setup">https://github.com/alertlogic/cloudwatch-logs-s3-export#setup</a></td>
<td><a href="https://s3.cn-north-1.amazonaws.com.cn/shane/cwl-s3-export-new.template">https://s3.cn-north-1.amazonaws.com.cn/shane/cwl-s3-export-new.template</a></p>
<p>使用说明：<a href="https://s3.cn-north-1.amazonaws.com.cn/shane/User+Guide+-+Copy+VPC+Flow+Logs+to+S3+CloudFormation+Templates.docx">https://s3.cn-north-1.amazonaws.com.cn/shane/User+Guide+-+Copy+VPC+Flow+Logs+to+S3+CloudFormation+Templates.docx</a></td>
</tr>
<tr>
<td>将一个账户下的 S3 存储桶复制到另一个账户的 S3</td>
<td></td>
<td><a href="https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/1source.json">https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/1source.json</a><a href="https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/2target.json">https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/2target.json</a><a href="https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/3source.json">https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/3source.json</a></p>
<p>使用说明：<a href="https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/User+Guide+-+S3+to+S3+Replication+CloudFormation+Templates.docx">https://s3.cn-north-1.amazonaws.com.cn/shane/s3-to-s3/User+Guide+-+S3+to+S3+Replication+CloudFormation+Templates.docx</a></td>
</tr>
<tr>
<td rowspan="2"><strong>网络结构</strong></td>
<td>配置 Linux Bastion</td>
<td><a href="https://github.com/aws-quickstart/quickstart-linux-bastion">https://github.com/aws-quickstart/quickstart-linux-bastion</a></td>
<td><a href="https://s3.cn-north-1.amazonaws.com.cn/shane/linux-bastion.template">https://s3.cn-north-1.amazonaws.com.cn/shane/linux-bastion.template</a>不支持 CentOS</td>
</tr>
<tr>
<td>建立 VPC 和分配 Subnet</td>
<td><a href="https://github.com/aws-quickstart/quickstart-aws-vpc">https://github.com/aws-quickstart/quickstart-aws-vpc</a></td>
<td><a href="https://github.com/shaneliuyx/autosubnet_creation">https://github.com/shaneliuyx/autosubnet_creation</a></td>
</tr>
</tbody>
</table>
<h3></h3>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e5%bb%ba%e7%ab%8b-vpc-%e5%b9%b6%e5%9f%ba%e4%ba%8e%e5%8f%82%e6%95%b0%e5%8a%a8%e6%80%81%e5%88%9b%e5%bb%ba%e5%ad%90%e7%bd%91%e7%9a%84-cloudformation-%e6%a8%a1%e6%9d%bf/">建立 VPC 并基于参数动态创建子网的 CloudFormation 模板</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.fuwuqiok.com/%e5%bb%ba%e7%ab%8b-vpc-%e5%b9%b6%e5%9f%ba%e4%ba%8e%e5%8f%82%e6%95%b0%e5%8a%a8%e6%80%81%e5%88%9b%e5%bb%ba%e5%ad%90%e7%bd%91%e7%9a%84-cloudformation-%e6%a8%a1%e6%9d%bf/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用 AWS Lambda 支持的宏扩展 AWS CloudFormation</title>
		<link>https://www.fuwuqiok.com/%e4%bd%bf%e7%94%a8-aws-lambda-%e6%94%af%e6%8c%81%e7%9a%84%e5%ae%8f%e6%89%a9%e5%b1%95-aws-cloudformation/</link>
		<comments>https://www.fuwuqiok.com/%e4%bd%bf%e7%94%a8-aws-lambda-%e6%94%af%e6%8c%81%e7%9a%84%e5%ae%8f%e6%89%a9%e5%b1%95-aws-cloudformation/#comments</comments>
		<pubDate>Wed, 21 Nov 2018 06:34:24 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[aliyun服务器代维]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[linux代维]]></category>
		<category><![CDATA[linux服务器维护]]></category>
		<category><![CDATA[linux系统代维]]></category>
		<category><![CDATA[服务器安全代维]]></category>
		<category><![CDATA[服务器安全设置]]></category>
		<category><![CDATA[系统安全代维]]></category>
		<category><![CDATA[网站代维]]></category>
		<category><![CDATA[使用 AWS Lambda 支持的宏扩展 AWS CloudFormation]]></category>

		<guid isPermaLink="false">https://www.fuwuqiok.com/?p=3865</guid>
		<description><![CDATA[<p>今天，我非常高兴为大家介绍 AWS CloudFormation 的一个强大新功能，它叫做 Macros。Cl [&#8230;]</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e4%bd%bf%e7%94%a8-aws-lambda-%e6%94%af%e6%8c%81%e7%9a%84%e5%ae%8f%e6%89%a9%e5%b1%95-aws-cloudformation/">使用 AWS Lambda 支持的宏扩展 AWS CloudFormation</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>今天，我非常高兴为大家介绍 <a title="" href="https://amazonaws-china.com/cloudformation/">AWS CloudFormation</a> 的一个强大新功能，它叫做 <strong>Macros</strong>。CloudFormation Macros 允许开发人员调用 <a title="" href="https://amazonaws-china.com/lambda/">AWS Lambda</a> 支持的转换函数，从而扩展 CloudFormation 模板的原生句法。它采用与支持流行的<a title="无服务器应用程序模型 — SAM" href="https://github.com/awslabs/serverless-application-model">无服务器应用程序模型</a>功能所用的相同技术，但转换函数 (transform) 在您自己的账户中运行，使用您自己的 lambda 函数，并且是完全可自定义的。如果您还不熟悉 AWS，请记住 CloudFormation 是一个对基础设施即代码（YAML 或 JSON）的建模和定义绝对关键的工具。它也是所有 AWS 产品的核心组件之一，我们的许多服务都依赖它而存在。</p>
<p>宏的使用有两个主要步骤。首先，我们需要定义宏。当然，为此我们需要使用 CloudFormation 模板。然后，为了在我们的模板中使用宏，我们需要将它添加为整个模板的转换函数，或者直接调用它。在本博文中，宏和转换函数这两个术语基本可以互换。已经准备好了解其工作原理了？</p>
<h3>创建 CloudFormation 宏</h3>
<p>宏的创建有两个要素：一是定义，二是实现。如要创建宏的定义，我们需要一个类型为 <code>AWS::CloudFormation::Macro</code> 的 CloudFormation 资源，该资源定义了需要使用的 Lamda 函数以及应当调用的宏。</p>
<pre class=" language-yaml" data-language="YAML"><code class=" language-yaml">Type<span class="token punctuation">:</span> <span class="token string">"AWS::CloudFormation::Macro"</span>
<span class="token key atrule">Properties</span><span class="token punctuation">:</span>
  <span class="token key atrule">Description</span><span class="token punctuation">:</span> String
  <span class="token key atrule">FunctionName</span><span class="token punctuation">:</span> String
  <span class="token key atrule">LogGroupName</span><span class="token punctuation">:</span> String
  <span class="token key atrule">LogRoleARN</span><span class="token punctuation">:</span> String
  <span class="token key atrule">Name</span><span class="token punctuation">:</span> String</code></pre>
<p>宏的 <code>Name</code> 必须在整个区域是唯一的，并且通过 <code>FunctionName</code> 引用的 Lambda 函数必须与要创建的宏位于同一区域。您执行宏模板时，将会使该宏对其他模板也同样可用。宏的实现由 Lambda 函数完成。宏可以位于自己的模板中，也可与其他宏组合，但无法在注册宏的模板中使用该宏。Lambda 函数会收到与以下类似的 JSON 负载：</p>
<pre class=" language-json" data-language="Json"><code class=" language-json"><span class="token punctuation">{</span>
    <span class="token property">"region"</span><span class="token operator">:</span> <span class="token string">"us-east-1"</span><span class="token punctuation">,</span>
    <span class="token property">"accountId"</span><span class="token operator">:</span> <span class="token string">"$ACCOUNT_ID"</span><span class="token punctuation">,</span>
    <span class="token property">"fragment"</span><span class="token operator">:</span> <span class="token punctuation">{</span> ... <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"transformId"</span><span class="token operator">:</span> <span class="token string">"$TRANSFORM_ID"</span><span class="token punctuation">,</span>
    <span class="token property">"params"</span><span class="token operator">:</span> <span class="token punctuation">{</span> ... <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token property">"requestId"</span><span class="token operator">:</span> <span class="token string">"$REQUEST_ID"</span><span class="token punctuation">,</span>
    <span class="token property">"templateParameterValues"</span><span class="token operator">:</span> <span class="token punctuation">{</span> ... <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p>负载的 <code>fragment</code> 部分包含了整个模板或者模板的相关区段 — 具体取决于如何从调用宏的模板中调用转换函数。区段始终在 JSON 中，即使模板在 YAML 中亦是如此。</p>
<p>Lambda 函数预计将会返回一个简单的 JSON 应答：</p>
<pre class=" language-json" data-language="Json"><code class=" language-json"><span class="token punctuation">{</span>
    <span class="token property">"requestId"</span><span class="token operator">:</span> <span class="token string">"$REQUEST_ID"</span><span class="token punctuation">,</span>
    <span class="token property">"status"</span><span class="token operator">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
    <span class="token property">"fragment"</span><span class="token operator">:</span> <span class="token punctuation">{</span> ... <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<p><code>requestId</code> 需要输入负载中收到的相同，如果 <code>status</code> 包含除 success（不区分大小写）以外的任何值，则变更集的创建将会失败。然后，<code>fragment</code> 必须包含转换后模板的有效 CloudFormation JSON。即使您的函数未执行任何操作，仍然需要返回它的区段以包含到最终模板中。</p>
<h3>使用 CloudFormation 宏</h3>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/cfn_macro_use-1024x557.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/cfn_macro_use-1024x557.png" alt="cfn_macro_use-1024x557" width="1024" height="557" /></a><br />
如要使用宏，我们只需使用要求的参数调用<a><code>Fn::Transform</code></a>。如果您希望利用宏来对整个模板进行句法分析，则我们可以按照与 SAM: <code>Transform: [Echo]</code> 相同的方式，将其列入模板中的转换函数列表中。在我们执行模板时，通过调用每个宏的制定函数并返回最终模板，转换函数将会被收集到变更集中。</p>
<p>假设我们有一个名为 EchoFunction 的 虚拟 Lambda 函数，它只是记录通过它的数据并返回未加任何修改的区段。我们将宏定义为一种正常的 CloudFormation 资源，与以下类似：</p>
<pre class=" language-yaml" data-language="YAML"><code class=" language-yaml">EchoMacro<span class="token punctuation">:</span>
  <span class="token key atrule">Type</span><span class="token punctuation">:</span> <span class="token string">"AWS::CloudFormation::Macro"</span>
  <span class="token key atrule">Properties</span><span class="token punctuation">:</span>
    <span class="token key atrule">FunctionName</span><span class="token punctuation">:</span> arn<span class="token punctuation">:</span>aws<span class="token punctuation">:</span>lambda<span class="token punctuation">:</span>us<span class="token punctuation">-</span>east<span class="token punctuation">-</span>1<span class="token punctuation">:</span>1234567<span class="token punctuation">:</span>function<span class="token punctuation">:</span>EchoFunction
	<span class="token key atrule">Name</span><span class="token punctuation">:</span> EchoMacro</code></pre>
<p>Lambda 函数的代码可能简单如下：</p>
<pre class=" language-python" data-language="Python"><code class=" language-python"><span class="token keyword">def</span> <span class="token function">lambda_handler</span><span class="token punctuation">(</span>event<span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">:</span>
    <span class="token keyword">print</span><span class="token punctuation">(</span>event<span class="token punctuation">)</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token string">"requestId"</span><span class="token punctuation">:</span> event<span class="token punctuation">[</span><span class="token string">'requestId'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
        <span class="token string">"status"</span><span class="token punctuation">:</span> <span class="token string">"success"</span><span class="token punctuation">,</span>
        <span class="token string">"fragment"</span><span class="token punctuation">:</span> event<span class="token punctuation">[</span><span class="token string">"fragment"</span><span class="token punctuation">]</span>
    <span class="token punctuation">}</span></code></pre>
<p>然后在部署此函数并执行宏模板后，我们可以在任何其他模板的顶层的转换函数中调用宏，与以下类似：</p>
<pre class=" language-yaml" data-language="YAML"><code class=" language-yaml">AWSTemplateFormatVersion<span class="token punctuation">:</span> <span class="token datetime number">2010-09-09</span> 
 <span class="token key atrule">Transform</span><span class="token punctuation">:</span> <span class="token punctuation">[</span>EchoMacro<span class="token punctuation">,</span> AWS<span class="token punctuation">:</span><span class="token punctuation">:</span>Serverless<span class="token punctuation">-</span><span class="token datetime number">2016-10-31</span><span class="token punctuation">]</span>
 <span class="token key atrule">Resources</span><span class="token punctuation">:</span>
    <span class="token key atrule">FancyTable</span><span class="token punctuation">:</span>
      <span class="token key atrule">Type</span><span class="token punctuation">:</span> AWS<span class="token punctuation">:</span><span class="token punctuation">:</span>Serverless<span class="token punctuation">:</span><span class="token punctuation">:</span>SimpleTable</code></pre>
<p>CloudFormation 会首先调用我们定义的 Echo 宏，然后调用 AWS::Serverless 转换函数，从而创建模板的变更集。它将按照列表中的顺序执行转换函数中列举的宏。</p>
<p>此外，我们还可以使用内部函数 <code>Fn::Transform</code> 调用宏，该函数允许我们输入额外的参数。例如：</p>
<pre class=" language-yaml" data-language="YAML"><code class=" language-yaml">AWSTemplateFormatVersion<span class="token punctuation">:</span> <span class="token datetime number">2010-09-09</span>
<span class="token key atrule">Resources</span><span class="token punctuation">:</span>
  <span class="token key atrule">MyS3Bucket</span><span class="token punctuation">:</span>
    <span class="token key atrule">Type</span><span class="token punctuation">:</span> <span class="token string">'AWS::S3::Bucket'</span>
    <span class="token key atrule">Fn::Transform</span><span class="token punctuation">:</span>
      <span class="token key atrule">Name</span><span class="token punctuation">:</span> EchoMacro
      <span class="token key atrule">Parameters</span><span class="token punctuation">:</span>
        <span class="token key atrule">Key</span><span class="token punctuation">:</span> Value</code></pre>
<p>内联转换函数将拥有其所有同级节点和下级节点的访问权限。转换函数的处理顺序为由深到浅，这意味着最顶层的转换函数将会最后执行。我知道大多数人都会说：不对，你不能在宏中包含宏 — 但想法不错。</p>
<p>在您执行 CloudFormation 模板时，它将会直接要求您创建一个变更集，并且您可以在部署前预览输出结果。<br />
<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/cfn-1024x696.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/cfn-1024x696.png" alt="cfn-1024x696" width="1024" height="696" /></a></p>
<h3>示例宏</h3>
<p>我们正在推出多个<a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-macros.html">参考</a>宏，以帮助开发人员上手，同时我预计许多人也将发布更多的宏。以下四个宏是在此功能发布前，一个小的内部骇客马拉松的优胜作品：</p>
<table>
<tbody>
<tr>
<th>名称</th>
<th>描述</th>
<th>作者</th>
</tr>
<tr>
<td><a href="https://github.com/awslabs/aws-cloudformation-templates/tree/master/aws/services/CloudFormation/MacrosExamples/PyPlate/">PyPlate</a></td>
<td>允许您在模板中插入内敛 Python 函数</td>
<td>Jay McConnel — 合作伙伴解决方案架构师</td>
</tr>
<tr>
<td><a href="https://github.com/awslabs/aws-cloudformation-templates/tree/master/aws/services/CloudFormation/MacrosExamples/ShortHand/">ShortHand</a></td>
<td>定义通用 cloudformation 资源的简略句法</td>
<td><a href="https://www.linkedin.com/in/stilvoid">Steve Engledow — 解决方案构建师</a></td>
</tr>
<tr>
<td><a href="https://github.com/awslabs/aws-cloudformation-templates/tree/master/aws/services/CloudFormation/MacrosExamples/StackMetrics/">StackMetrics</a></td>
<td>为堆栈添加 Cloudwatch 指标</td>
<td>Steve Engledow 和 <a href="https://linkedin.com/in/jgregson">Jason Gregson — 全球解决方案架构师</a></td>
</tr>
<tr>
<td><a href="https://github.com/awslabs/aws-cloudformation-templates/tree/master/aws/services/CloudFormation/MacrosExamples/StringFunctions/">String Functions</a></td>
<td>为您的模板添加常用的串函数</td>
<td>Jay McConnel — 合作伙伴解决方案架构师</td>
</tr>
</tbody>
</table>
<p>以下是我认为有人可能会感兴趣实现的一些理念：</p>
<ul>
<li>自动注册 R53 域 + <a title="" href="https://amazonaws-china.com/certificate-manager/">AWS Certificate Manager (ACM)</a> 凭证预置</li>
<li>自动分配带自定义域的 S3 静态网站或 <a title="" href="https://amazonaws-china.com/cloudfront/">Amazon CloudFront</a></li>
<li>扩展 CloudFormation 映射以读取 DynamoDB 表</li>
<li>自动为 <a title="" href="https://amazonaws-china.com/vpc/">Amazon Virtual Private Cloud</a> 设置 IPv6</li>
<li>自动订阅 Webhook 以与 Slack、Twitter、Messenger 集成</li>
</ul>
<p>如果您有任何奇妙的想法，我非常期待您写出来！</p>
<h3>现已推出</h3>
<p>CloudFormation Macros 从今天开始已在所有支持 AWS Lambda 的 AWS 区域推出。使用 Macros 不会发生额外的 CloudFormation 费用，这意味着您只需承担正常的 AWS Lambda 函数费用。更多信息请参阅<a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-macros.html">文档</a>。</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e4%bd%bf%e7%94%a8-aws-lambda-%e6%94%af%e6%8c%81%e7%9a%84%e5%ae%8f%e6%89%a9%e5%b1%95-aws-cloudformation/">使用 AWS Lambda 支持的宏扩展 AWS CloudFormation</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.fuwuqiok.com/%e4%bd%bf%e7%94%a8-aws-lambda-%e6%94%af%e6%8c%81%e7%9a%84%e5%ae%8f%e6%89%a9%e5%b1%95-aws-cloudformation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>利用 AWS Config 监控和响应 Amazon Simple Storage Service (S3) 允许公开读写访问权限</title>
		<link>https://www.fuwuqiok.com/%e5%88%a9%e7%94%a8-aws-config-%e7%9b%91%e6%8e%a7%e5%92%8c%e5%93%8d%e5%ba%94-amazon-simple-storage-service-s3-%e5%85%81%e8%ae%b8%e5%85%ac%e5%bc%80%e8%af%bb%e5%86%99%e8%ae%bf%e9%97%ae%e6%9d%83/</link>
		<comments>https://www.fuwuqiok.com/%e5%88%a9%e7%94%a8-aws-config-%e7%9b%91%e6%8e%a7%e5%92%8c%e5%93%8d%e5%ba%94-amazon-simple-storage-service-s3-%e5%85%81%e8%ae%b8%e5%85%ac%e5%bc%80%e8%af%bb%e5%86%99%e8%ae%bf%e9%97%ae%e6%9d%83/#comments</comments>
		<pubDate>Wed, 21 Nov 2018 06:31:57 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[linux代维]]></category>
		<category><![CDATA[linux服务器代维]]></category>
		<category><![CDATA[linux服务器代维护]]></category>
		<category><![CDATA[linux服务器维护]]></category>
		<category><![CDATA[linux系统代维]]></category>
		<category><![CDATA[服务器代维]]></category>
		<category><![CDATA[服务器代维护]]></category>
		<category><![CDATA[服务器安全代维]]></category>
		<category><![CDATA[服务器维护]]></category>
		<category><![CDATA[服务器运维]]></category>
		<category><![CDATA[网站代维]]></category>
		<category><![CDATA[网站防挂马]]></category>
		<category><![CDATA[利用 AWS Config 监控和响应 Amazon Simple Storage Service (S3) 允许公开读写访问权限]]></category>

		<guid isPermaLink="false">https://www.fuwuqiok.com/?p=3845</guid>
		<description><![CDATA[<p>AWS Config 支持持续监控 AWS 资源，简化评估、审核以及记录资源配置和变化的过程。为此，AWS C [&#8230;]</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e5%88%a9%e7%94%a8-aws-config-%e7%9b%91%e6%8e%a7%e5%92%8c%e5%93%8d%e5%ba%94-amazon-simple-storage-service-s3-%e5%85%81%e8%ae%b8%e5%85%ac%e5%bc%80%e8%af%bb%e5%86%99%e8%ae%bf%e9%97%ae%e6%9d%83/">利用 AWS Config 监控和响应 Amazon Simple Storage Service (S3) 允许公开读写访问权限</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p><a title="AWS Config" href="https://amazonaws-china.com/config" target="_blank" rel="noopener noreferrer">AWS Config</a> 支持持续监控 AWS 资源，简化评估、审核以及记录资源配置和变化的过程。为此，AWS Config 使用一系列规则来定义 AWS 资源所需的配置状态。AWS Config 提供多种 <a title="AWS 托管规则" href="https://docs.aws.amazon.com/config/latest/developerguide/managed-rules-by-aws-config.html" target="_blank" rel="noopener noreferrer">AWS 托管规则</a>来解决各种安全问题，例如，检查您是否已将 Amazon Elastic Block Store (Amazon EBS) 卷加密，是否已正确标记资源，以及是否为根账户启用了 Multi-Factor Authentication (MFA)。您还可以使用 <a title="AWS Lambda" href="https://amazonaws-china.com/lambda/" target="_blank" rel="noopener noreferrer">AWS Lambda</a> 函数创建<a title="自定义规则" href="https://docs.aws.amazon.com/config/latest/developerguide/evaluate-config_develop-rules.html" target="_blank" rel="noopener noreferrer">自定义规则</a>，以编写整理您的合规性需求。</p>
<p>在本文中，我们将向您展示如何使用 AWS Config 监控 <a title="Amazon Simple Storage Service" href="https://amazonaws-china.com/s3/" target="_blank" rel="noopener noreferrer">Amazon Simple Storage Service</a> (S3) 存储桶 ACL 和策略，确定是否存在允许公开读写访问权限的违规行为。如果 AWS Config 发现违反策略的行为，我们会使其触发 <a title="Amazon CloudWatch Event" href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/WhatIsCloudWatchEvents.html" target="_blank" rel="noopener noreferrer">Amazon CloudWatch Event</a> 规则以触发 <a title="AWS Lambda" href="https://amazonaws-china.com/blogs/security/how-to-centralize-dns-management-in-a-multi-account-environment/" target="_blank" rel="noopener noreferrer">AWS Lambda</a> 函数，从而更正 S3 存储桶 ACL，或通过 <a title="Amazon Simple Notification Service" href="https://amazonaws-china.com/sns" target="_blank" rel="noopener noreferrer">Amazon Simple Notification Service</a> (Amazon SNS) 通知您存在违反策略且允许公开读写访问权限的行为。我们将通过五个主要步骤为您演示此过程。</p>
<ol>
<li><strong>启用 AWS Config</strong> 来监控 Amazon S3 存储桶 ACL 和策略，以发现违规行为。</li>
<li><strong>创建 IAM 角色和策略</strong>，为 Lambda 函数授予读取 S3 存储桶策略和通过 SNS 发送提醒的权限。</li>
<li><strong>创建和配置 CloudWatch Events 规则</strong>，在 AWS Config 检测到违反 S3 存储桶 ACL 或策略的行为时触发 Lambda 函数。</li>
<li><strong>创建 Lambda 函数</strong>，以使用 IAM 角色审核 S3 存储桶 ACL 和策略、更正 ACL，并通知您的团队策略违规行为。</li>
<li><strong>验证监控解决方案</strong>。</li>
</ol>
<blockquote><p><strong>注意：</strong>本文假设您的合规性策略要求您所监控的存储桶不允许公开读写访问权限。例如，如果您打算开放提供静态内容的存储桶，可以从本文着手，根据您的需要定制解决方案。</p></blockquote>
<p>在本文末尾，我们将提供一个可实施本文所述解决方案的 AWS CloudFormation 模板。您可以使用该模板在多个区域快速部署解决方案。</p>
<blockquote><p><strong>重要说明</strong>：如果使用部署的某些资源（包括使用所提供的 CloudFormation 模板部署的资源），则在使用这些资源期间会产生费用。在提供 AWS Config 规则的每个区域使用这些规则都会产生费用。</p></blockquote>
<h2>架构</h2>
<p>以下是我们将要实施的架构图：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-01-1.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-01-1.png" alt="AWS-config-01-1" width="1000" height="523" /></a></p>
<p>&nbsp;</p>
<h2>步骤 1：启用 AWS Config 和 Amazon S3 存储桶监控功能</h2>
<p>以下步骤将演示如何设置 AWS Config 来监控 Amazon S3 存储桶。</p>
<ol>
<li>登录 AWS 管理控制台，并打开<a title="未定义的" href="https://console.aws.amazon.com/config/" target="_blank" rel="noopener noreferrer">AWS Config 控制台</a>。</li>
<li>如果这是您第一次使用 AWS Config，请选择<strong>开始使用</strong>。如果您已经使用过 AWS Config，请选择<strong>设置</strong>。</li>
<li>在<strong>设置</strong>页面中的 <strong>Resource types to record</strong> (要记录的资源类型) 下，取消选中 <strong>All resources</strong> (所有资源) 复选框。在 <strong>Specific types</strong> (具体类型) 列表中，选择 <strong>S3</strong> 下的<strong>存储桶</strong>。<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-02.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-02.png" alt="AWS-config-02" width="1000" height="497" /></a>
<p>&nbsp;</li>
<li>选择用于存储配置历史记录和快照的 Amazon S3 存储桶。我们会创建一个新的 Amazon S3 存储桶。<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-03.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-03.png" alt="AWS-config-03" width="942" height="213" /></a>
<p>&nbsp;</p>
<ol type="a">
<li>如果您更希望使用账户中现有的 Amazon S3 存储桶，请选择 <strong>Choose a bucket from your account</strong> (从您的账户中选择存储桶) 单选按钮，然后使用下拉菜单选择现有的存储桶。<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-04.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-04.png" alt="AWS-config-04" width="800" height="286" /></a>
<p>&nbsp;</li>
</ol>
</li>
<li>在 <strong>Amazon SNS topic</strong> (Amazon SNS 主题) 下，选中 <strong>Stream configuration changes and notifications to an Amazon SNS topic</strong> (将配置更改和通知流式传输至 Amazon SNS 主题) 旁边的复选框，然后选择 <strong>Create a topic</strong> (创建主题) 旁边的单选按钮。
<ol type="a">
<li>您也可以选择之前创建和订阅的主题。<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-05.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-05.png" alt="AWS-config-05" width="800" height="217" /></a>
<p>&nbsp;</li>
<li>如果您创建了新的 SNS 主题，则需要订阅它才能收到通知。我们将在后面的步骤中演示此操作。</li>
</ol>
</li>
<li>除非您已经有要使用的角色，否则请在 <strong>AWS Config role</strong> (AWS Config 角色) 下选择 <strong>Create a role</strong> (创建角色)。我们使用系统自动推荐的角色名称。<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-06.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-06.png" alt="AWS-config-06" width="800" height="120" /></a>
<p>&nbsp;</li>
<li>选择<strong>下一步</strong>。</li>
<li>配置 Amazon S3 存储桶监控规则：
<ol type="a">
<li>在 <strong>AWS Config rules</strong> (AWS Config 规则) 页面上搜索 <strong>S3</strong>，选择 <strong>s3-bucket-publice-read-prohibited</strong> 和 <strong>s3-bucket-public-write-prohibited</strong> 规则，然后单击<strong>下一步</strong>。<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-07.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-07.png" alt="AWS-config-07" width="800" height="425" /></a>
<p>&nbsp;</li>
<li>在<strong>审核</strong>页面上，选择<strong>确认</strong>。AWS Config 此时会分析您的 Amazon S3 存储桶，捕获它们当前的配置，并根据我们选择的规则评估配置。</li>
</ol>
</li>
<li>如果您创建了新 Amazon SNS 主题，请打开 Amazon SNS 管理控制台并找到您创建的主题：<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-08.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-08.png" alt="AWS-config-08" width="800" height="135" /></a>
<p>&nbsp;</li>
<li>复制该主题的 ARN（以 arn: 开头的字符串），您需要在后面的步骤中使用它。</li>
<li>选择主题旁边的复选框，然后在<strong>操作</strong>菜单下选择<strong>订阅主题</strong>。</li>
<li>选择<strong>电子邮件</strong>作为协议，输入您的电子邮件地址，然后选择<strong>创建订阅</strong>。</li>
<li>几分钟后，您会收到一封电子邮件，要求您确认订阅与此主题有关的通知。选择对应链接以确认订阅。</li>
</ol>
<h2>步骤 2：为 Lambda 创建角色</h2>
<p>我们的 Lambda 需要相关权限，才能检查和修改 Amazon S3 存储桶 ACL 和策略，记录 CloudWatch 日志并发布到 Amazon SNS 主题。现在，我们将设置自定义 AWS Identity and Access Management (IAM) 策略和角色来支持这些操作，并将它们分配到我们将在下一节中创建的 Lambda 函数。</p>
<ol>
<li>在 AWS 管理控制台中，在<strong>服务</strong>下选择 <strong>IAM</strong> 以访问 IAM 控制台。</li>
<li>创建具有以下权限的策略，或者复制以下策略：
<div class="hide-language">
<pre class=" language-text"><code class=" language-text">
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "SNSPublish",
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Resource": "*"
        },
        {
            "Sid": "S3GetBucketACLandPolicy",
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketAcl",
                "s3:GetBucketPolicy"
            ],
            "Resource": "*"
        },
        {
            "Sid": "S3PutBucketACLAccess",
            "Effect": "Allow",
            "Action": "s3:PutBucketAcl",
            "Resource": "arn:aws:s3:::*"
        },
        {
            "Sid": "LambdaBasicExecutionAccess",
            "Effect"quot;: "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}

</code></pre>
</div>
</li>
<li>为 Lambda 函数创建角色：
<ol type="a">
<li>从要使用该角色的服务列表中选择 <strong>Lambda</strong>。</li>
<li>选择您之前创建的策略旁边的复选框，然后选择 <strong>Next: Review</strong> (下一步：审核)</li>
<li>指定角色名称，为其输入描述，然后选择<strong>创建角色</strong>。在该示例中，我们将角色命名为 LambdaS3PolicySecuringRole。</li>
</ol>
</li>
</ol>
<h2>步骤 3：创建和配置 CloudWatch 规则</h2>
<p>在这一节中，我们将创建一个 CloudWatch 规则，以便在 AWS Config 确定您的 Amazon S3 存储桶不合规时触发 Lambda 函数。</p>
<ol>
<li>在 AWS 管理控制台中，在<strong>服务</strong>下选择 <strong>CloudWatch</strong>。</li>
<li>在左侧的<strong>事件</strong>下，选择<strong>规则</strong>。</li>
<li>单击<strong>创建规则</strong>。</li>
<li>在 <strong>Step 1: Create rule</strong> (第 1 步：创建规则) 中的<strong>事件源</strong>下，选择下拉列表并选择<strong>生成自定义事件模式</strong>。</li>
<li>复制以下模式，并将其粘贴到文本框中：
<div class="hide-language">
<pre class=" language-text"><code class=" language-text">
{
  "source": [
    "aws.config"
  ],
  "detail": {
    "requestParameters": {
      "evaluations": {
        "complianceType": [
          "NON_COMPLIANT"
        ]
      }
    },
    "additionalEventData": {
      "managedRuleIdentifier": [
        "S3_BUCKET_PUBLIC_READ_PROHIBITED",
        "S3_BUCKET_PUBLIC_WRITE_PROHIBITED"
      ]
    }
  }
}

			</code></pre>
</div>
<p>该模式会在检查 Amazon S3 存储桶的公开访问权限时匹配 AWS Config 生成的事件。</li>
<li>我们将在稍后添加 Lambda 目标。现在，选择您之前创建的 Amazon SNS 主题，然后选择<strong>配置详细信息</strong>。<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-09-1.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-09-1.png" alt="AWS-config-09-1" width="1000" height="530" /></a>
<p>&nbsp;</li>
<li>输入规则的名称和描述。在该示例中，我们指定名称 AWSConfigFoundOpenBucket</li>
<li>单击<strong>创建规则</strong>。</li>
</ol>
<h2>步骤 4：创建 Lambda 函数</h2>
<p>在这一节中，我们将创建新的 Lambda 函数，用于检查 Amazon S3 存储桶的 ACL 和存储桶策略。如果发现存储桶 ACL 允许公开访问权限，该 Lambda 函数会将其覆盖，改为私密。如果找到了存储桶策略，Lambda 函数会创建 SNS 消息，将该策略添加到消息正文中，然后将其发布到我们创建的 Amazon SNS 主题。存储桶策略可能很复杂，而覆盖策略可能会导致访问权限意外丢失，因此该 Lambda 函数不会尝试对您的策略进行任何更改。</p>
<ol>
<li>获取之前创建的 Amazon SNS 主题的 ARN。</li>
<li>在 AWS 管理控制台中，在<strong>服务</strong>下选择 <strong>Lambda</strong> 进入 Lambda 控制台。</li>
<li>在控制面板中，选择<strong>创建函数</strong>。或者，如果您直接进入了<strong>函数</strong>页面，也可以选择右上角的<strong>创建函数</strong>按钮。</li>
<li>在<strong>创建函数</strong>页面上：
<ol type="a">
<li>选择<strong>从头开始创作</strong>。</li>
<li>为该函数提供一个名称。我们使用 AWSConfigOpenAccessResponder。</li>
<li>我们编写的 Lambda 函数与 Python 3.6 兼容，所以请在<strong>运行语言</strong>下拉列表中选择 <strong>Python 3.6</strong>。</li>
<li>在<strong>角色</strong>下选择<strong>选择现有角色</strong>。选择您在前一节中创建的角色，然后选择<strong>创建函数</strong>。<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-09.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-09.png" alt="AWS-config-09" width="1000" height="524" /></a>
<p>&nbsp;</li>
</ol>
</li>
<li>现在，我们根据之前创建的规则添加 CloudWatch 事件。
<ol type="a">
<li>在 <strong>Add triggers</strong> (添加触发器) 部分，选择 <strong>CloudWatch Events</strong>。CloudWatch Events 框应该会显示在 Lambda 函数左侧，还会显示一条内容为 <strong>Configuration required</strong> (需要配置) 的备注。<a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-11.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-11.png" alt="AWS-config-11" width="1000" height="361" /></a>
<p>&nbsp;</li>
<li>在<strong>规则</strong>下拉框中，选择您之前创建的规则，然后选择<strong>添加</strong>。</li>
</ol>
</li>
<li>向上滚动到 <strong>Designer</strong> (设计者) 部分，然后选择您的 Lambda 函数的名称。</li>
<li>删除默认代码，然后粘贴以下代码：
<div class="hide-language">
<pre class=" language-text"><code class=" language-text">
import boto3
from botocore.exceptions import ClientError
import json
import os

ACL_RD_WARNING = "The S3 bucket ACL allows public read access."
PLCY_RD_WARNING = "The S3 bucket policy allows public read access."
ACL_WRT_WARNING = "The S3 bucket ACL allows public write access."
PLCY_WRT_WARNING = "The S3 bucket policy allows public write access."
RD_COMBO_WARNING = ACL_RD_WARNING + PLCY_RD_WARNING
WRT_COMBO_WARNING = ACL_WRT_WARNING + PLCY_WRT_WARNING

def policyNotifier(bucketName, s3client):
    try:
        bucketPolicy = s3client.get_bucket_policy(Bucket = bucketName)
        # notify that the bucket policy may need to be reviewed due to security concerns
        sns = boto3.client('sns')
        subject = "Potential compliance violation in " + bucketName + " bucket policy"
        message = "Potential bucket policy compliance violation. Please review: " + json.dumps(bucketPolicy['Policy'])
        # send SNS message with warning and bucket policy
        response = sns.publish(
            TopicArn = os.environ['TOPIC_ARN'],
            Subject = subject,
            Message = message
        )
    except ClientError as e:
        # error caught due to no bucket policy
        print("No bucket policy found; no alert sent.")

def lambda_handler(event, context):
    # instantiate Amazon S3 client
    s3 = boto3.client('s3')
    resource = list(event['detail']['requestParameters']['evaluations'])[0]
    bucketName = resource['complianceResourceId']
    complianceFailure = event['detail']['requestParameters']['evaluations'][0]['annotation']
    if(complianceFailure == ACL_RD_WARNING or complianceFailure == ACL_WRT_WARNING):
        s3.put_bucket_acl(Bucket = bucketName, ACL = 'private')
    elif(complianceFailure == PLCY_RD_WARNING or complianceFailure == PLCY_WRT_WARNING):
        policyNotifier(bucketName, s3)
    elif(complianceFailure == RD_COMBO_WARNING or complianceFailure == WRT_COMBO_WARNING):
        s3.put_bucket_acl(Bucket = bucketName, ACL = 'private')
        policyNotifier(bucketName, s3)
    return 0  # done
			</code></pre>
</div>
</li>
<li>向下滚动到<strong>环境变量</strong>部分。该代码使用一个环境变量来存储 Amazon SNS 主题的 ARN。
<ol type="a">
<li>输入 TOPIC_ARN 作为密钥。</li>
<li>输入之前创建的 Amazon SNS 主题的 ARN 作为值。</li>
</ol>
</li>
<li>在 <strong>Execution role</strong> (执行角色) 下选择<strong>选择现有角色</strong>，然后从下拉菜单中选择之前创建的角色。</li>
<li>保留其他内容不变，然后在顶部选择<strong>保存</strong>。</li>
</ol>
<h2>步骤 5：验证效果</h2>
<p>到现在为止，我们已经有了一个 Lambda 函数、一个 Amazon SNS 主题、监控 Amazon S3 存储桶的 AWS Config，以及在发现存储桶不合规时触发 Lambda 函数的 CloudWatch 规则。我们来进行测试，确保它们能够正常工作。</p>
<p>我们有在受 AWS Config 监控的区域中创建的 Amazon S3 存储桶 myconfigtestbucket，还有关联的 Lambda 函数。ACL 或策略中未设置该存储桶的公开读写访问权限，所以它是合规的。</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-12.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-12.png" alt="AWS-config-12" width="1000" height="417" /></a></p>
<p>我们来更改存储桶的 ACL，以允许公开列出对象：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-13.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-13.png" alt="AWS-config-13" width="1000" height="545" /></a></p>
<p>保存后，该存储桶便可公开访问了。几分钟后，AWS Config 控制面板会发现一项不合规的资源：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-14.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-14.png" alt="AWS-config-14" width="1000" height="405" /></a></p>
<p>在 Amazon S3 控制台中，我们可以看到：在调用由之前创建的 CloudWatch 规则触发的 Lambda 函数后，存储桶中不再公开列出对象。</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-15.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-15.png" alt="AWS-config-15" width="1000" height="619" /></a></p>
<p>请注意，AWS Config 控制面板此时显示没有不合规的资源了：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-16.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-16.png" alt="AWS-config-16" width="1000" height="420" /></a></p>
<p>现在，我们来配置允许列表访问的存储桶策略，以尝试进行 Amazon S3 存储桶策略检查：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-17.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-17.png" alt="AWS-config-17" width="1000" height="421" /></a></p>
<p>对 myconfigtestbucket 存储桶设置该存储桶策略后，AWS Config 会在几分钟后检测到该存储桶不再合规。因为这是存储桶策略而不是 ACL，所以我们将一条通知发布到我们之前创建的 SNS 主题，以通知我们可能违反策略的行为：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-18.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/11/AWS-config-18.png" alt="AWS-config-18" width="1000" height="255" /></a></p>
<p>获知该策略允许公开列出存储桶后，我们现在可以修改或删除该策略，随后 AWS Config 会检测到资源符合策略。</p>
<h2>结论</h2>
<p>在本文中，我们演示了如何使用 AWS Config 监控 Amazon S3 存储桶是否使用公开的读写访问权限 ACL 和策略。另外，我们演示了如何使用 Amazon CloudWatch、Amazon SNS 和 Lambda 覆盖公开的存储桶 ACL，或者在存储桶使用可疑策略时提醒您。您可以使用 <a title="CloudFormation 模板" href="https://s3.amazonaws.com/awsiammedia/public/sample/AWSConfigToMonitorAndRespondToAmazonS3Buckets/config.template" target="_blank" rel="noopener noreferrer">CloudFormation 模板</a>在多个区域快速部署该解决方案。通过该方法，您将能够轻松找出并保护公开的 Amazon S3 存储桶 ACL 和策略。将该解决方案部署到多个区域后，可以使用 AWS Config 聚合器来聚合结果。阅读本文<a title="了解更多信息" href="https://amazonaws-china.com/blogs/aws/aws-config-update-aggregate-compliance-data-across-accounts-regions/" target="_blank" rel="noopener noreferrer">了解更多信息</a>。</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e5%88%a9%e7%94%a8-aws-config-%e7%9b%91%e6%8e%a7%e5%92%8c%e5%93%8d%e5%ba%94-amazon-simple-storage-service-s3-%e5%85%81%e8%ae%b8%e5%85%ac%e5%bc%80%e8%af%bb%e5%86%99%e8%ae%bf%e9%97%ae%e6%9d%83/">利用 AWS Config 监控和响应 Amazon Simple Storage Service (S3) 允许公开读写访问权限</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.fuwuqiok.com/%e5%88%a9%e7%94%a8-aws-config-%e7%9b%91%e6%8e%a7%e5%92%8c%e5%93%8d%e5%ba%94-amazon-simple-storage-service-s3-%e5%85%81%e8%ae%b8%e5%85%ac%e5%bc%80%e8%af%bb%e5%86%99%e8%ae%bf%e9%97%ae%e6%9d%83/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在Virtual Private Cloud中自建基于BIND的DNS服务器</title>
		<link>https://www.fuwuqiok.com/%e5%9c%a8virtual-private-cloud%e4%b8%ad%e8%87%aa%e5%bb%ba%e5%9f%ba%e4%ba%8ebind%e7%9a%84dns%e6%9c%8d%e5%8a%a1%e5%99%a8/</link>
		<comments>https://www.fuwuqiok.com/%e5%9c%a8virtual-private-cloud%e4%b8%ad%e8%87%aa%e5%bb%ba%e5%9f%ba%e4%ba%8ebind%e7%9a%84dns%e6%9c%8d%e5%8a%a1%e5%99%a8/#comments</comments>
		<pubDate>Fri, 27 Jul 2018 09:16:48 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[Amazon AWS]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[linux代维]]></category>
		<category><![CDATA[linux服务器代维]]></category>
		<category><![CDATA[linux服务器代维护]]></category>
		<category><![CDATA[linux服务器维护]]></category>
		<category><![CDATA[linux系统代维]]></category>
		<category><![CDATA[代维]]></category>
		<category><![CDATA[服务器代维]]></category>
		<category><![CDATA[在Virtual Private Cloud中自建基于BIND的DNS服务器]]></category>

		<guid isPermaLink="false">https://www.fuwuqiok.com/?p=3698</guid>
		<description><![CDATA[<p>Amazon Virtual Private Cloud (Amazon VPC) 是 AWS 提供的虚拟私有 [&#8230;]</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e5%9c%a8virtual-private-cloud%e4%b8%ad%e8%87%aa%e5%bb%ba%e5%9f%ba%e4%ba%8ebind%e7%9a%84dns%e6%9c%8d%e5%8a%a1%e5%99%a8/">在Virtual Private Cloud中自建基于BIND的DNS服务器</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>Amazon Virtual Private Cloud (Amazon VPC) 是 AWS 提供的虚拟私有网络服务，允许您在 AWS 云中预配置出一个采用逻辑隔离的部分，让您在自己定义的虚拟网络中启动 AWS 资源。您可以完全掌控您的虚拟联网环境，包括选择自有的 IP 地址范围、创建子网，以及配置路由表和网关。</p>
<p>除了提供IP资源及网络连接，Amazon VPC还提供DNS及DHCP等基础设施服务。当您将实例启动到默认 VPC 中时，我们为实例提供与其公有 IPv4 和私有 IPv4 地址对应的公有和私有 DNS 主机名。当您在非默认 VPC 中启动实例时，我们会为实例提供私有 DNS 主机名，并根据您为 VPC 和实例指定的设置来决定是否提供公有 DNS 主机名。</p>
<p>对于 us-east-1 区域，公有 (外部) DNS 主机名采用 ec2-&lt;public-ipv4-address&gt;.compute-1.amazonaws.com 形式，对于其他区域，则采用 ec2-&lt;public-ipv4-address&gt;.region.amazonaws.com 形式。例如，公有IP为54.222.212.110的EC2实例，其公有DNS名为ec2-54-222-212-110.cn-north-1.compute.amazonaws.com.cn。我们将公有 DNS 主机名解析为该实例在所在网络外的公有 IPv4 地址及其在所在网络内的私有 IPv4 地址。</p>
<p>私有 (内部) DNS 主机名解析为实例的私有 IPv4 地址，并对 us-east-1 区域采用 ip-&lt;private-ipv4-address&gt;.ec2.internal 形式，对其他区域采用 ip-&lt;private-ipv4-address&gt;.region.compute.internal 形式 (其中 private.ipv4.address 是反向查找 IP 地址)。例如，私有IP地址为10.206.2.239的EC2实例，其私有DNS名为ip-10-206-2-239.cn-north-1.compute.internal。您可以使用私有 DNS 主机名在同一网络中实现实例之间的通信，但我们无法解析实例所在网络之外的 DNS 主机名。要解析实例所在网络之外的主机名，可自建DNS服务器来为VPC及外部网络提供DNS服务。</p>
<p>常见的应用场景是在混合IT架构下，客户数据中心通过VPN或是Direct Connect专线连接到AWS上的VPC，在VPC中配置1台DNS服务器，在客户数据中心也配置1台DNS服务器，服务器的主从角色客户可自行定义。通过多台DNS服务器为不同位置的客户端提供DNS服务，即能保证服务的高可用，又能就近提供服务，减少DNS查询延迟。</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-1.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-1.png" alt="20170523-1" width="1748" height="678" /></a></p>
<p>接下来，我将基于上述架构图一步一步说明如何使用BIND搭建DNS服务器。本文不会涉及BIND的高级配置，如需了解BIND的高级配置，可参考<a href="https://www.isc.org/" target="_blank" rel="noopener noreferrer">BIND官方网站</a>。</p>
<h3>安装配置DNS主服务器</h3>
<p>首选需要准备一台EC2实例用于安装BIND软件，如何创建EC2实例可参考<a href="http://docs.amazonaws.cn/AWSEC2/latest/UserGuide/EC2_GetStarted.html" target="_blank" rel="noopener noreferrer">Amazon EC2入门指南</a>。本次示例选用Amazon Linux操作系统的AMI来创建实例，实例类型选用了通用型实例类型: m4.large。BIND对服务器硬件资源要求不高，在不启用DNSSEC的情况下(不在本文讨论范围)，普通配置的服务器即可承载DNS服务。m4.large配置有2颗vCPU和8G内存，运行DNS服务能够支持中等规模的DNS请求，当请求增加时，也可方便的调整实例类型到更大的配置。</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-2.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-2.png" alt="20170523-2" width="2314" height="594" /></a></p>
<p>创建EC2实例时需要指定安全组来开放服务端口，DNS服务通过UDP 53端口提供DNS查询相应，通过TCP 53端口提供区域传送。因此，安全组队VPC网段开放UDP 53端口，对客户数据中心的DNS服务器开放TCP 53端口，如下图所示：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-3.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-3.png" alt="20170523-3" width="1948" height="764" /></a></p>
<p>DNS服务器作为基础设施服务的重要性无须多言，Amazon EC2持续监控EC2实例的状态以及底层硬件的状态，分别称为实例状态检查和系统状态检查。我们可创建状态检查报告，当任一状态检查失败时，执行重启操作，并将警报发送至指定邮箱。</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-4.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-4.png" alt="20170523-4" width="1216" height="836" /></a></p>
<p>创建好警报之后，通过SSH登陆至EC2实例，并yum命令安装bind软件：</p>
<p><code>yum install bind-utils bind</code></p>
<p>安装好之后，我们接下来将创建一个示例的DNS域：aws.local，我们首先需要编辑/etc/named.conf文件，修改以下内容：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-5.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-5.png" alt="20170523-5" width="932" height="266" /></a></p>
<p>listen-on 缺省配置为127.0.0.1，DNS服务只会绑定到系统的环回接口，其他客户端无法访问，需要添加EC2实例的私有IP地址，才能提供外部访问</p>
<p>allow-query缺省配置为localhost，即只允许DNS服务器所在的EC2实例对自己进行DNS查询，添加VPC的网段可允许来自VPC内部的主机进行DNS查询。注：也可将此参数设置为0.0.0.0/0，因为前面安全组设置里只允许了VPC内的IP访问UDP 53端口。</p>
<p>此外，还需要增加对aws.local这个域的定义，在/etc/named.conf中增加以下内容，allow-transfer指定了只允许从DNS服务器进行区域传送，限定允许区域传送的范围颗可提高DNS服务的安全性：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-6.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-6.png" alt="20170523-6" width="556" height="160" /></a></p>
<p>上述配置说明aws.local域的具体解析配置在文件/var/named/aws.local.db 里，其内容如下，在这个示例配置中，定义了两条A记录，分别是dns.aws.local对应10.206.0.212和<a href="http://www.aws.local/">www.aws.local</a>对应10.206.0.213</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-7.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-7.png" alt="20170523-7" width="522" height="340" /></a></p>
<h3>配置Amazon VPC使用自建DNS服务器</h3>
<p>Amazon VPC通过DHCP服务为VPC中的EC2及其他连网组件动态分配IP地址，动态主机配置协议 (DHCP) 提供了将配置信息传递到 TCP/IP 网络中主机的标准。DHCP 消息中的options字段包含配置参数。这些参数包括域名、域名服务器以及“netbios-node-type”。接下来我们将创建一个新的DHCP选项集，并在选项集中将域名服务器指向刚才创建的DNS服务器。</p>
<p>在AWS控制台中选择VPC服务，并在左边的菜单中选择“DHCP选项集”，点击“创建DHCP选项集”按钮，输入以下信息，域名服务器可指定多个DNS服务器，按照顺序第一个为VPC内的DNS服务器，第二个为客户数据中心的DNS服务器：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-8.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-8.png" alt="20170523-8" width="1342" height="812" /></a></p>
<p>创建好DHCP选项集之后选择左边菜单中“您的VPC”选项，选中要修改的VPC，从“操作”下拉菜单中选择“编辑DHCP选项集”</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-9.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-9.png" alt="20170523-9" width="490" height="408" /></a></p>
<p>选择刚才创建的DHCP选项集并保存：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-10.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-10.png" alt="20170523-10" width="884" height="330" /></a></p>
<p>在您将新的 DHCP 选项集与 VPC 关联之后，任何现有实例以及您在 VPC 内启动的所有新增实例都将使用这些选项。 无需重新开始或重新启动实例。根据实例更新 DHCP 租赁权的频率，它们会在几个小时内自动拾取更改。如果您愿意，您也可以使用实例上的操作系统，直接更新租赁权。</p>
<h3>安装配置DNS从服务器</h3>
<p>在客户数据中心安装配置DNS服务器的步骤与在Aamazon EC2中安装配置DNS服务器的步骤相同，除了/etc/named.conf的配置稍有差别：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-11.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2018/07/20170523-11.png" alt="20170523-11" width="514" height="182" /></a></p>
<p>从服务器的type类型为slave，file参数对应的域配置文件会自动根据从主DNS服务器接收到的更新来进行创建和更新，masters指定aws.local域的主域名服务器，最后一个参数allow-transfer禁用了区域传送。</p>
<p>配置好从DNS服务器之后，可将客户数据中心内的连网设备设置为从DNS服务器，第二DNS服务器设置为AWS上的主DNS服务器。</p>
<h3>总结</h3>
<p>Amazon VPC提供DHCP服务和DNS服务，为VPC中的EC2实例提供IP地址分配和域名解析服务，为每个EC2实例创建特定格式的DNS域名。如果用户希望使用自定义域名，或者希望使用一套域名统一管理云上和云下的资源，可自行搭建DNS服务器来提供DNS解析服务，Amazon VPC能够支持客户。</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e5%9c%a8virtual-private-cloud%e4%b8%ad%e8%87%aa%e5%bb%ba%e5%9f%ba%e4%ba%8ebind%e7%9a%84dns%e6%9c%8d%e5%8a%a1%e5%99%a8/">在Virtual Private Cloud中自建基于BIND的DNS服务器</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.fuwuqiok.com/%e5%9c%a8virtual-private-cloud%e4%b8%ad%e8%87%aa%e5%bb%ba%e5%9f%ba%e4%ba%8ebind%e7%9a%84dns%e6%9c%8d%e5%8a%a1%e5%99%a8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>阿里云下配置keepalive，利用HAVIP实现HA</title>
		<link>https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91%e4%b8%8b%e9%85%8d%e7%bd%aekeepalive%ef%bc%8c%e5%88%a9%e7%94%a8havip%e5%ae%9e%e7%8e%b0ha-2/</link>
		<comments>https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91%e4%b8%8b%e9%85%8d%e7%bd%aekeepalive%ef%bc%8c%e5%88%a9%e7%94%a8havip%e5%ae%9e%e7%8e%b0ha-2/#comments</comments>
		<pubDate>Mon, 14 Mar 2016 14:34:22 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[aliyun服务器代维]]></category>
		<category><![CDATA[linux代维]]></category>
		<category><![CDATA[linux服务器代维]]></category>
		<category><![CDATA[linux系统代维]]></category>
		<category><![CDATA[代维]]></category>
		<category><![CDATA[服务器代维]]></category>
		<category><![CDATA[网站代维]]></category>
		<category><![CDATA[阿里云下配置keepalive，利用HAVIP实现HA]]></category>

		<guid isPermaLink="false">https://www.fuwuqiok.com/?p=3078</guid>
		<description><![CDATA[<p>包括阿里云在内的很多云环境，因为不支持浮动IP广受诟病。目前阿里云在VPC网络下发布了HAVIP，能够实现ar [&#8230;]</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91%e4%b8%8b%e9%85%8d%e7%bd%aekeepalive%ef%bc%8c%e5%88%a9%e7%94%a8havip%e5%ae%9e%e7%8e%b0ha-2/">阿里云下配置keepalive，利用HAVIP实现HA</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>包括阿里云在内的很多云环境，因为不支持浮动IP广受诟病。目前阿里云在VPC网络下发布了HAVIP，能够实现arp宣告IP。这样也就让自己搭建HA成为了可能，有幸拿到了内测权限体验了一下。(classical网络依然不支持)</p>
<p>测试环境：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/1.jpg"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/1.jpg" alt="1" width="893" height="267" /></a></p>
<div id="crayon-56e612a8cec97214385622" class="crayon-syntax crayon-theme-familiar crayon-font-droid-sans-mono crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap">
<div class="crayon-plain-wrap"></div>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-nums " data-settings="show">
<div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-56e612a8cec97214385622-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cec97214385622-2">2</div>
<div class="crayon-num" data-line="crayon-56e612a8cec97214385622-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cec97214385622-4">4</div>
<div class="crayon-num" data-line="crayon-56e612a8cec97214385622-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cec97214385622-6">6</div>
</div>
</td>
<td class="crayon-code">
<div class="crayon-pre">
<div id="crayon-56e612a8cec97214385622-1" class="crayon-line"><span class="crayon-i">VPC</span>：<span class="crayon-cn">192.168.1.0</span><span class="crayon-o">/</span><span class="crayon-cn">24</span></div>
<div id="crayon-56e612a8cec97214385622-2" class="crayon-line crayon-striped-line"><span class="crayon-v">ECS</span><span class="crayon-o">:</span></div>
<div id="crayon-56e612a8cec97214385622-3" class="crayon-line"><span class="crayon-i">nginx1</span>：<span class="crayon-cn">192.168.1.1</span></div>
<div id="crayon-56e612a8cec97214385622-4" class="crayon-line crayon-striped-line"><span class="crayon-v">nginx2</span><span class="crayon-o">:</span><span class="crayon-cn">192.168.1.2</span></div>
<div id="crayon-56e612a8cec97214385622-5" class="crayon-line"><span class="crayon-v">HAVIP</span><span class="crayon-o">:</span><span class="crayon-cn">192.168.1.3</span></div>
<div id="crayon-56e612a8cec97214385622-6" class="crayon-line crayon-striped-line">绑定到<span class="crayon-i">havip</span>的公网<span class="crayon-i">EIP</span>：<span class="crayon-cn">121.43.187.37</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>配置完毕后的拓扑如下：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/4.jpg"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/4.jpg" alt="4" width="641" height="405" /></a><br />
环境搭建完毕后，登陆主备ECS服务器，分别配置nginx+keepalived</p>
<div id="crayon-56e612a8ceca9851636518" class="crayon-syntax crayon-theme-familiar crayon-font-droid-sans-mono crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap">
<div class="crayon-plain-wrap"></div>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-nums " data-settings="show">
<div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-56e612a8ceca9851636518-1">1</div>
</div>
</td>
<td class="crayon-code">
<div class="crayon-pre">
<div id="crayon-56e612a8ceca9851636518-1" class="crayon-line"><span class="crayon-sy">[</span><span class="crayon-v">root</span><span class="crayon-sy">@</span><span class="crayon-v">Nginx1</span> <span class="crayon-o">~</span><span class="crayon-sy">]</span><span class="crayon-c"># yum install nginx keepalived -y</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>MASTER服务器（nginx1）配置文件/etc/keepalived/keepalived.conf内容以及解释如下：</p>
<div id="crayon-56e612a8cecae477615045" class="crayon-syntax crayon-theme-familiar crayon-font-droid-sans-mono crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap">
<div class="crayon-plain-wrap"></div>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-nums " data-settings="show">
<div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-2">2</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-4">4</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-6">6</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-7">7</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-8">8</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-9">9</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-10">10</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-11">11</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-12">12</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-13">13</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-14">14</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-15">15</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-16">16</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-17">17</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-18">18</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-19">19</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-20">20</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-21">21</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-22">22</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-23">23</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-24">24</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-25">25</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-26">26</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-27">27</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-28">28</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-29">29</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-30">30</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-31">31</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-32">32</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-33">33</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-34">34</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-35">35</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-36">36</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-37">37</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-38">38</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-39">39</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-40">40</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-41">41</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-42">42</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-43">43</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-44">44</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-45">45</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecae477615045-46">46</div>
<div class="crayon-num" data-line="crayon-56e612a8cecae477615045-47">47</div>
</div>
</td>
<td class="crayon-code">
<div class="crayon-pre">
<div id="crayon-56e612a8cecae477615045-1" class="crayon-line"><span class="crayon-o">!</span> <span class="crayon-e">Configuration</span> <span class="crayon-r">File</span> <span class="crayon-st">for</span> <span class="crayon-e">keepalived</span></div>
<div id="crayon-56e612a8cecae477615045-2" class="crayon-line crayon-striped-line"><span class="crayon-c">#配置global_defs，主要用于标示机器，以及故障时通知</span></div>
<div id="crayon-56e612a8cecae477615045-3" class="crayon-line"><span class="crayon-e">global_defs</span> <span class="crayon-sy">{</span><span class="crayon-h">  </span></div>
<div id="crayon-56e612a8cecae477615045-4" class="crayon-line crayon-striped-line"><span class="crayon-h">   </span><span class="crayon-e">router_id </span><span class="crayon-i">Nginx1</span></div>
<div id="crayon-56e612a8cecae477615045-5" class="crayon-line"><span class="crayon-sy">}</span></div>
<div id="crayon-56e612a8cecae477615045-6" class="crayon-line crayon-striped-line"><span class="crayon-c">#配置vrrp_script，主要用于健康检查，以及检查失败后执行的动作。</span></div>
<div id="crayon-56e612a8cecae477615045-7" class="crayon-line"><span class="crayon-e">vrrp_script</span> <span class="crayon-e">chk_nginx</span> <span class="crayon-sy">{</span></div>
<div id="crayon-56e612a8cecae477615045-8" class="crayon-line crayon-striped-line"><span class="crayon-c">#健康检查脚本，当脚本返回值不为0时认为失败</span></div>
<div id="crayon-56e612a8cecae477615045-9" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-i">script</span> <span class="crayon-s">&#8220;/etc/keepalived/ck_ng.sh&#8221;</span></div>
<div id="crayon-56e612a8cecae477615045-10" class="crayon-line crayon-striped-line"><span class="crayon-c">#检查频率，以下配置每2秒检查1次</span></div>
<div id="crayon-56e612a8cecae477615045-11" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-i">interval</span> <span class="crayon-cn">2</span></div>
<div id="crayon-56e612a8cecae477615045-12" class="crayon-line crayon-striped-line"><span class="crayon-c">#当检查失败后，将vrrp_instance的priority减小5</span></div>
<div id="crayon-56e612a8cecae477615045-13" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-v">weight</span> <span class="crayon-o">&#8211;</span><span class="crayon-cn">5</span></div>
<div id="crayon-56e612a8cecae477615045-14" class="crayon-line crayon-striped-line"><span class="crayon-c">#连续监测失败3次，才认为真的健康检查失败。并调整优先级</span></div>
<div id="crayon-56e612a8cecae477615045-15" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-i">fall</span> <span class="crayon-cn">3</span></div>
<div id="crayon-56e612a8cecae477615045-16" class="crayon-line crayon-striped-line"><span class="crayon-c">#连续监测2次成功，就认为成功。但不调整优先级</span></div>
<div id="crayon-56e612a8cecae477615045-17" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-i">rise</span> <span class="crayon-cn">2</span></div>
<div id="crayon-56e612a8cecae477615045-18" class="crayon-line crayon-striped-line"><span class="crayon-sy">}</span></div>
<div id="crayon-56e612a8cecae477615045-19" class="crayon-line"></div>
<div id="crayon-56e612a8cecae477615045-20" class="crayon-line crayon-striped-line"><span class="crayon-c">#定义对外提供服务的VIP vrrp_instance配置</span></div>
<div id="crayon-56e612a8cecae477615045-21" class="crayon-line"><span class="crayon-e">vrrp_instance</span> <span class="crayon-e">VI_1</span> <span class="crayon-sy">{</span></div>
<div id="crayon-56e612a8cecae477615045-22" class="crayon-line crayon-striped-line"><span class="crayon-c">#指定vrrp_instance的初始状态，是MASTER还是BackUP主要还是看优先级。</span></div>
<div id="crayon-56e612a8cecae477615045-23" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-e">state </span><span class="crayon-v">MASTER</span></div>
<div id="crayon-56e612a8cecae477615045-24" class="crayon-line crayon-striped-line"><span class="crayon-c">#指定vrrp_instance绑定的网卡，最终会通过指定的网卡宣告VIP</span></div>
<div id="crayon-56e612a8cecae477615045-25" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-t">interface</span> <span class="crayon-v">eth0</span></div>
<div id="crayon-56e612a8cecae477615045-26" class="crayon-line crayon-striped-line"><span class="crayon-c">#发送心跳包的源IP，可使用绑定的网卡IP，也可以使用本服务器上的其他IP</span></div>
<div id="crayon-56e612a8cecae477615045-27" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-v">mcast_src</span><span class="crayon-sy">_</span>ip <span class="crayon-cn">192.168.1.1</span></div>
<div id="crayon-56e612a8cecae477615045-28" class="crayon-line crayon-striped-line"><span class="crayon-c">#相当于VRID，用于在一个网内区分组播，需要组播域内内唯一。</span></div>
<div id="crayon-56e612a8cecae477615045-29" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-v">virtual_router</span><span class="crayon-sy">_</span>id <span class="crayon-cn">55</span></div>
<div id="crayon-56e612a8cecae477615045-30" class="crayon-line crayon-striped-line"><span class="crayon-c">#本机的优先级，VRID相同的机器中，优先级最高的会被选举为MASTER</span></div>
<div id="crayon-56e612a8cecae477615045-31" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-i">priority</span> <span class="crayon-cn">101</span></div>
<div id="crayon-56e612a8cecae477615045-32" class="crayon-line crayon-striped-line"><span class="crayon-c">#心跳间隔，下面配置，MASTER会每隔1秒发送一个报文高职组内其他机器，自己还活着。</span></div>
<div id="crayon-56e612a8cecae477615045-33" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-v">advert</span><span class="crayon-sy">_</span>int <span class="crayon-cn">1</span></div>
<div id="crayon-56e612a8cecae477615045-34" class="crayon-line crayon-striped-line"><span class="crayon-c">#定义主从的验证方式以及密码，一般使用PASS(最长8位，超过了只会识别前8位作为密码)</span></div>
<div id="crayon-56e612a8cecae477615045-35" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-e">authentication</span> <span class="crayon-sy">{</span></div>
<div id="crayon-56e612a8cecae477615045-36" class="crayon-line crayon-striped-line"><span class="crayon-h">        </span><span class="crayon-e">auth_type </span><span class="crayon-e">PASS</span></div>
<div id="crayon-56e612a8cecae477615045-37" class="crayon-line"><span class="crayon-e">        </span><span class="crayon-e">auth_pass </span><span class="crayon-i">aliyun</span></div>
<div id="crayon-56e612a8cecae477615045-38" class="crayon-line crayon-striped-line"><span class="crayon-h">    </span><span class="crayon-sy">}</span></div>
<div id="crayon-56e612a8cecae477615045-39" class="crayon-line"><span class="crayon-c">#VIP,在阿里云下就是刚才创建的HAVIP</span></div>
<div id="crayon-56e612a8cecae477615045-40" class="crayon-line crayon-striped-line"><span class="crayon-h">    </span><span class="crayon-e">virtual_ipaddress</span> <span class="crayon-sy">{</span></div>
<div id="crayon-56e612a8cecae477615045-41" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-cn">192.168.1.4</span></div>
<div id="crayon-56e612a8cecae477615045-42" class="crayon-line crayon-striped-line"><span class="crayon-h">        </span><span class="crayon-sy">}</span></div>
<div id="crayon-56e612a8cecae477615045-43" class="crayon-line"><span class="crayon-c">#本vrrp_instance所引用的脚本配置，名称就是vrrp_script 定义的容器名</span></div>
<div id="crayon-56e612a8cecae477615045-44" class="crayon-line crayon-striped-line"><span class="crayon-h">  </span><span class="crayon-e">track_script</span> <span class="crayon-sy">{</span></div>
<div id="crayon-56e612a8cecae477615045-45" class="crayon-line"><span class="crayon-h">       </span><span class="crayon-v">chk</span><span class="crayon-sy">_</span>nginx</div>
<div id="crayon-56e612a8cecae477615045-46" class="crayon-line crayon-striped-line"><span class="crayon-h">    </span><span class="crayon-sy">}</span></div>
<div id="crayon-56e612a8cecae477615045-47" class="crayon-line"><span class="crayon-sy">}</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>BACKUP服务器（nginx2）的配置需要修改：</p>
<div id="crayon-56e612a8cecb5455868472" class="crayon-syntax crayon-theme-familiar crayon-font-droid-sans-mono crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap">
<div class="crayon-plain-wrap"></div>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-nums " data-settings="show">
<div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-56e612a8cecb5455868472-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecb5455868472-2">2</div>
<div class="crayon-num" data-line="crayon-56e612a8cecb5455868472-3">3</div>
</div>
</td>
<td class="crayon-code">
<div class="crayon-pre">
<div id="crayon-56e612a8cecb5455868472-1" class="crayon-line"><span class="crayon-e">state </span><span class="crayon-i">MASTER</span>改为<span class="crayon-h">  </span><span class="crayon-e">state </span><span class="crayon-e">BACKUP</span></div>
<div id="crayon-56e612a8cecb5455868472-2" class="crayon-line crayon-striped-line"><span class="crayon-v">mcast_src</span><span class="crayon-sy">_</span>ip <span class="crayon-cn">192.168.1.1</span>改为<span class="crayon-i">backup</span>服务器实际的<span class="crayon-e">IP </span><span class="crayon-v">mcast_src</span><span class="crayon-sy">_</span>ip <span class="crayon-cn">192.168.1.2</span></div>
<div id="crayon-56e612a8cecb5455868472-3" class="crayon-line"><span class="crayon-i">priority</span> <span class="crayon-cn">101</span>改小一些，比如<span class="crayon-h">    </span><span class="crayon-i">priority</span> <span class="crayon-cn">100</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>其它保持一致即可</p>
<p>为了实现nginx服务异常的时候能够自动切换，需要自己写一个脚本，脚本没有硬性的要求，能够实现目标即可，这里 监控nginx进程数为例：</p>
<div id="crayon-56e612a8cecbb232281910" class="crayon-syntax crayon-theme-familiar crayon-font-droid-sans-mono crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap">
<div class="crayon-plain-wrap"></div>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-nums " data-settings="show">
<div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-56e612a8cecbb232281910-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecbb232281910-2">2</div>
<div class="crayon-num" data-line="crayon-56e612a8cecbb232281910-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecbb232281910-4">4</div>
<div class="crayon-num" data-line="crayon-56e612a8cecbb232281910-5">5</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecbb232281910-6">6</div>
<div class="crayon-num" data-line="crayon-56e612a8cecbb232281910-7">7</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecbb232281910-8">8</div>
<div class="crayon-num" data-line="crayon-56e612a8cecbb232281910-9">9</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecbb232281910-10">10</div>
<div class="crayon-num" data-line="crayon-56e612a8cecbb232281910-11">11</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecbb232281910-12">12</div>
<div class="crayon-num" data-line="crayon-56e612a8cecbb232281910-13">13</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecbb232281910-14">14</div>
<div class="crayon-num" data-line="crayon-56e612a8cecbb232281910-15">15</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecbb232281910-16">16</div>
<div class="crayon-num" data-line="crayon-56e612a8cecbb232281910-17">17</div>
</div>
</td>
<td class="crayon-code">
<div class="crayon-pre">
<div id="crayon-56e612a8cecbb232281910-1" class="crayon-line"><span class="crayon-r">vim</span> <span class="crayon-o">/</span><span class="crayon-v">etc</span><span class="crayon-o">/</span><span class="crayon-v">keepalived</span><span class="crayon-o">/</span><span class="crayon-v">ck_ng</span><span class="crayon-e">.sh</span></div>
<div id="crayon-56e612a8cecbb232281910-2" class="crayon-line crayon-striped-line"><span class="crayon-c">#!/bin/bash</span></div>
<div id="crayon-56e612a8cecbb232281910-3" class="crayon-line"><span class="crayon-c">#检查nginx进程是否存在</span></div>
<div id="crayon-56e612a8cecbb232281910-4" class="crayon-line crayon-striped-line"><span class="crayon-v">count</span><span class="crayon-o">=</span><span class="crayon-sy">$</span><span class="crayon-sy">(</span><span class="crayon-r">ps</span> <span class="crayon-o">&#8211;</span><span class="crayon-i">C</span> <span class="crayon-v">nginx</span> <span class="crayon-o">&#8212;</span><span class="crayon-v">no</span><span class="crayon-o">&#8211;</span><span class="crayon-v">heading</span><span class="crayon-o">|</span><span class="crayon-r">wc</span> <span class="crayon-o">&#8211;</span><span class="crayon-v">l</span><span class="crayon-sy">)</span></div>
<div id="crayon-56e612a8cecbb232281910-5" class="crayon-line"><span class="crayon-c">#进程数等于0的时候</span></div>
<div id="crayon-56e612a8cecbb232281910-6" class="crayon-line crayon-striped-line"><span class="crayon-st">if</span> <span class="crayon-sy">[</span> <span class="crayon-s">&#8220;${count}&#8221;</span> <span class="crayon-o">=</span> <span class="crayon-s">&#8220;0&#8221;</span> <span class="crayon-sy">]</span><span class="crayon-sy">;</span> <span class="crayon-st">then</span></div>
<div id="crayon-56e612a8cecbb232281910-7" class="crayon-line"><span class="crayon-c">#尝试启动一次nginx，停止2秒后再次检测</span></div>
<div id="crayon-56e612a8cecbb232281910-8" class="crayon-line crayon-striped-line"><span class="crayon-h">    </span><span class="crayon-e">service </span><span class="crayon-e">nginx </span><span class="crayon-e">start</span></div>
<div id="crayon-56e612a8cecbb232281910-9" class="crayon-line"><span class="crayon-e">    </span><span class="crayon-r">sleep</span> <span class="crayon-cn">2</span></div>
<div id="crayon-56e612a8cecbb232281910-10" class="crayon-line crayon-striped-line"><span class="crayon-h">   </span><span class="crayon-v">count</span><span class="crayon-o">=</span><span class="crayon-sy">$</span><span class="crayon-sy">(</span><span class="crayon-r">ps</span> <span class="crayon-o">&#8211;</span><span class="crayon-i">C</span> <span class="crayon-v">nginx</span> <span class="crayon-o">&#8212;</span><span class="crayon-v">no</span><span class="crayon-o">&#8211;</span><span class="crayon-v">heading</span><span class="crayon-o">|</span><span class="crayon-r">wc</span> <span class="crayon-o">&#8211;</span><span class="crayon-v">l</span><span class="crayon-sy">)</span></div>
<div id="crayon-56e612a8cecbb232281910-11" class="crayon-line"><span class="crayon-h">    </span><span class="crayon-st">if</span> <span class="crayon-sy">[</span> <span class="crayon-s">&#8220;${count}&#8221;</span> <span class="crayon-o">=</span> <span class="crayon-s">&#8220;0&#8221;</span> <span class="crayon-sy">]</span><span class="crayon-sy">;</span> <span class="crayon-st">then</span></div>
<div id="crayon-56e612a8cecbb232281910-12" class="crayon-line crayon-striped-line"><span class="crayon-c">#如果启动没成功，就杀掉keepalive触发主备切换</span></div>
<div id="crayon-56e612a8cecbb232281910-13" class="crayon-line"><span class="crayon-h">        </span><span class="crayon-o">/</span><span class="crayon-v">etc</span><span class="crayon-o">/</span><span class="crayon-v">init</span><span class="crayon-e">.d</span><span class="crayon-o">/</span><span class="crayon-e">keepalived </span><span class="crayon-e">stop</span></div>
<div id="crayon-56e612a8cecbb232281910-14" class="crayon-line crayon-striped-line"><span class="crayon-e">    </span><span class="crayon-st">fi</span></div>
<div id="crayon-56e612a8cecbb232281910-15" class="crayon-line"><span class="crayon-st">fi</span></div>
<div id="crayon-56e612a8cecbb232281910-16" class="crayon-line crayon-striped-line"><span class="crayon-c">#增加脚本的执行权限</span></div>
<div id="crayon-56e612a8cecbb232281910-17" class="crayon-line"><span class="crayon-r">chmod</span> <span class="crayon-o">+</span><span class="crayon-i">x</span> <span class="crayon-r">vim</span> <span class="crayon-o">/</span><span class="crayon-v">etc</span><span class="crayon-o">/</span><span class="crayon-v">keepalived</span><span class="crayon-o">/</span><span class="crayon-v">ck_ng</span><span class="crayon-e">.sh</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="crayon-56e612a8cecc0480674347" class="crayon-syntax crayon-theme-familiar crayon-font-droid-sans-mono crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap">
<div class="crayon-plain-wrap"></div>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-nums " data-settings="show">
<div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-56e612a8cecc0480674347-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecc0480674347-2">2</div>
<div class="crayon-num" data-line="crayon-56e612a8cecc0480674347-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecc0480674347-4">4</div>
</div>
</td>
<td class="crayon-code">
<div class="crayon-pre">
<div id="crayon-56e612a8cecc0480674347-1" class="crayon-line"><span class="crayon-c">#分别启动nginx1和nginx2的nginx&amp;keepalived服务：</span></div>
<div id="crayon-56e612a8cecc0480674347-2" class="crayon-line crayon-striped-line"><span class="crayon-sy">[</span><span class="crayon-v">root</span><span class="crayon-sy">@</span><span class="crayon-v">Nginx1</span> <span class="crayon-o">~</span><span class="crayon-sy">]</span><span class="crayon-c"># /etc/init.d/nginx start;/etc/init.d/keepalived start</span></div>
<div id="crayon-56e612a8cecc0480674347-3" class="crayon-line"><span class="crayon-e">Starting </span><span class="crayon-v">nginx</span><span class="crayon-o">:</span><span class="crayon-h">                                            </span><span class="crayon-sy">[</span><span class="crayon-h">  </span><span class="crayon-i">OK</span><span class="crayon-h">  </span><span class="crayon-sy">]</span></div>
<div id="crayon-56e612a8cecc0480674347-4" class="crayon-line crayon-striped-line"><span class="crayon-e">Starting </span><span class="crayon-v">keepalived</span><span class="crayon-o">:</span><span class="crayon-h">                                       </span><span class="crayon-sy">[</span><span class="crayon-h">  </span><span class="crayon-i">OK</span><span class="crayon-h">  </span><span class="crayon-sy">]</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div>
<div>测试：</div>
<div>NGINX1/192.168.1.1的priority 为101，NGINX2/192.168.1.2的priority为100，这时候访问HAVIP绑定的EIP：http://121.43.187.37/可以看到访问到了服务器NGINX1,如下：</div>
<div>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/5.jpg"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/5.jpg" alt="5" width="485" height="205" /></a></p>
<p>到HAVIP控制台查看，192.168.1.1的服务器为主服务器</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/111.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/111.png" alt="111" width="596" height="330" /></a></p>
<p>这时候我们KILL掉nginx1服务器的nginx服务</p>
</div>
</div>
<div>
<div>查看日志，发送了移除VIP的报文：</div>
<div>
<div id="crayon-56e612a8cecc6571294083" class="crayon-syntax crayon-theme-familiar crayon-font-droid-sans-mono crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap">
<div class="crayon-plain-wrap"></div>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-nums " data-settings="show">
<div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-56e612a8cecc6571294083-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8cecc6571294083-2">2</div>
<div class="crayon-num" data-line="crayon-56e612a8cecc6571294083-3">3</div>
</div>
</td>
<td class="crayon-code">
<div class="crayon-pre">
<div id="crayon-56e612a8cecc6571294083-1" class="crayon-line"><span class="crayon-i">Oct</span> <span class="crayon-cn">23</span> <span class="crayon-cn">17</span><span class="crayon-o">:</span><span class="crayon-cn">20</span><span class="crayon-o">:</span><span class="crayon-cn">01</span> <span class="crayon-e">iZ239aqzdi7Z </span><span class="crayon-v">Keepalived_vrrp</span><span class="crayon-sy">[</span><span class="crayon-cn">25019</span><span class="crayon-sy">]</span><span class="crayon-o">:</span> <span class="crayon-e">VRRP_Instance</span><span class="crayon-sy">(</span><span class="crayon-v">VI_1</span><span class="crayon-sy">)</span> <span class="crayon-i">sending</span> <span class="crayon-cn">0</span> <span class="crayon-e">priority</span></div>
<div id="crayon-56e612a8cecc6571294083-2" class="crayon-line crayon-striped-line"><span class="crayon-i">Oct</span> <span class="crayon-cn">23</span> <span class="crayon-cn">17</span><span class="crayon-o">:</span><span class="crayon-cn">20</span><span class="crayon-o">:</span><span class="crayon-cn">01</span> <span class="crayon-e">iZ239aqzdi7Z </span><span class="crayon-v">Keepalived_vrrp</span><span class="crayon-sy">[</span><span class="crayon-cn">25019</span><span class="crayon-sy">]</span><span class="crayon-o">:</span> <span class="crayon-e">VRRP_Instance</span><span class="crayon-sy">(</span><span class="crayon-v">VI_1</span><span class="crayon-sy">)</span> <span class="crayon-e">removing </span><span class="crayon-e">protocol </span><span class="crayon-v">VIPs</span><span class="crayon-sy">.</span></div>
<div id="crayon-56e612a8cecc6571294083-3" class="crayon-line"><span class="crayon-i">Oct</span> <span class="crayon-cn">23</span> <span class="crayon-cn">17</span><span class="crayon-o">:</span><span class="crayon-cn">20</span><span class="crayon-o">:</span><span class="crayon-cn">01</span> <span class="crayon-e">iZ239aqzdi7Z </span><span class="crayon-v">Keepalived_healthcheckers</span><span class="crayon-sy">[</span><span class="crayon-cn">25018</span><span class="crayon-sy">]</span><span class="crayon-o">:</span> <span class="crayon-e">Netlink </span><span class="crayon-e">reflector </span><span class="crayon-e">reports </span><span class="crayon-i">IP</span> <span class="crayon-cn">192.168.1.3</span> <span class="crayon-v">removed</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>这时候访问<a href="http://121.43.187.37/%EF%BC%8C%E5%8F%AF%E4%BB%A5%E7%9C%8B%E5%88%B0%E8%AE%BF%E9%97%AE%E8%87%AA%E5%8A%A8%E5%88%87%E6%8D%A2%E5%88%B0%E4%BA%86NGINX2">http://121.43.187.37/，可以看到访问自动切换到了NGINX2</a><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/6.jpg"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/6.jpg" alt="6" width="473" height="194" /></a></p>
</div>
<div>
<div>到HAVIP控制台查看，192.168.1.2的服务器为主服务器</div>
</div>
</div>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/2222.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/2222.png" alt="2222" width="603" height="354" /></a></p>
<div>
<div>重新启动nginx1的nginx和keepalive服务</div>
<div>查看日志可以看到keepalive重新发送了IP宣告的报文</div>
<div>
<div id="crayon-56e612a8ceccd574917624" class="crayon-syntax crayon-theme-familiar crayon-font-droid-sans-mono crayon-os-pc print-yes notranslate crayon-wrapped" data-settings=" minimize scroll-mouseover wrap">
<div class="crayon-plain-wrap"></div>
<div class="crayon-main">
<table class="crayon-table">
<tbody>
<tr class="crayon-row">
<td class="crayon-nums " data-settings="show">
<div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-56e612a8ceccd574917624-1">1</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8ceccd574917624-2">2</div>
<div class="crayon-num" data-line="crayon-56e612a8ceccd574917624-3">3</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-56e612a8ceccd574917624-4">4</div>
<div class="crayon-num" data-line="crayon-56e612a8ceccd574917624-5">5</div>
</div>
</td>
<td class="crayon-code">
<div class="crayon-pre">
<div id="crayon-56e612a8ceccd574917624-1" class="crayon-line"><span class="crayon-i">Oct</span> <span class="crayon-cn">23</span> <span class="crayon-cn">17</span><span class="crayon-o">:</span><span class="crayon-cn">22</span><span class="crayon-o">:</span><span class="crayon-cn">14</span> <span class="crayon-e">iZ239aqzdi7Z </span><span class="crayon-v">Keepalived_vrrp</span><span class="crayon-sy">[</span><span class="crayon-cn">25610</span><span class="crayon-sy">]</span><span class="crayon-o">:</span> <span class="crayon-e">VRRP_Instance</span><span class="crayon-sy">(</span><span class="crayon-v">VI_1</span><span class="crayon-sy">)</span> <span class="crayon-e">Entering </span><span class="crayon-e">MASTER </span><span class="crayon-e">STATE</span></div>
<div id="crayon-56e612a8ceccd574917624-2" class="crayon-line crayon-striped-line"><span class="crayon-i">Oct</span> <span class="crayon-cn">23</span> <span class="crayon-cn">17</span><span class="crayon-o">:</span><span class="crayon-cn">22</span><span class="crayon-o">:</span><span class="crayon-cn">14</span> <span class="crayon-e">iZ239aqzdi7Z </span><span class="crayon-v">Keepalived_vrrp</span><span class="crayon-sy">[</span><span class="crayon-cn">25610</span><span class="crayon-sy">]</span><span class="crayon-o">:</span> <span class="crayon-e">VRRP_Instance</span><span class="crayon-sy">(</span><span class="crayon-v">VI_1</span><span class="crayon-sy">)</span> <span class="crayon-e">setting </span><span class="crayon-e">protocol </span><span class="crayon-v">VIPs</span><span class="crayon-sy">.</span></div>
<div id="crayon-56e612a8ceccd574917624-3" class="crayon-line"><span class="crayon-i">Oct</span> <span class="crayon-cn">23</span> <span class="crayon-cn">17</span><span class="crayon-o">:</span><span class="crayon-cn">22</span><span class="crayon-o">:</span><span class="crayon-cn">14</span> <span class="crayon-e">iZ239aqzdi7Z </span><span class="crayon-v">Keepalived_vrrp</span><span class="crayon-sy">[</span><span class="crayon-cn">25610</span><span class="crayon-sy">]</span><span class="crayon-o">:</span> <span class="crayon-e">VRRP_Instance</span><span class="crayon-sy">(</span><span class="crayon-v">VI_1</span><span class="crayon-sy">)</span> <span class="crayon-e">Sending </span><span class="crayon-e">gratuitous </span><span class="crayon-e">ARPs </span><span class="crayon-e">on </span><span class="crayon-e">eth0 </span><span class="crayon-st">for</span> <span class="crayon-cn">192.168.1.3</span></div>
<div id="crayon-56e612a8ceccd574917624-4" class="crayon-line crayon-striped-line"><span class="crayon-i">Oct</span> <span class="crayon-cn">23</span> <span class="crayon-cn">17</span><span class="crayon-o">:</span><span class="crayon-cn">22</span><span class="crayon-o">:</span><span class="crayon-cn">14</span> <span class="crayon-e">iZ239aqzdi7Z </span><span class="crayon-v">Keepalived_healthcheckers</span><span class="crayon-sy">[</span><span class="crayon-cn">25609</span><span class="crayon-sy">]</span><span class="crayon-o">:</span> <span class="crayon-e">Netlink </span><span class="crayon-e">reflector </span><span class="crayon-e">reports </span><span class="crayon-i">IP</span> <span class="crayon-cn">192.168.1.3</span> <span class="crayon-e">added</span></div>
<div id="crayon-56e612a8ceccd574917624-5" class="crayon-line"><span class="crayon-i">Oct</span> <span class="crayon-cn">23</span> <span class="crayon-cn">17</span><span class="crayon-o">:</span><span class="crayon-cn">22</span><span class="crayon-o">:</span><span class="crayon-cn">19</span> <span class="crayon-e">iZ239aqzdi7Z </span><span class="crayon-v">Keepalived_vrrp</span><span class="crayon-sy">[</span><span class="crayon-cn">25610</span><span class="crayon-sy">]</span><span class="crayon-o">:</span> <span class="crayon-e">VRRP_Instance</span><span class="crayon-sy">(</span><span class="crayon-v">VI_1</span><span class="crayon-sy">)</span> <span class="crayon-e">Sending </span><span class="crayon-e">gratuitous </span><span class="crayon-e">ARPs </span><span class="crayon-e">on </span><span class="crayon-e">eth0 </span><span class="crayon-st">for</span> <span class="crayon-cn">192.168.1.3</span></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p>重新访问http://121.43.187.37/测试，重新访问到了服务器NGINX1，到HAVIP控制台查看，192.168.1.1的服务器重新夺回了控制权，成为了为主服务器</p></div>
<div><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/1111.png"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/1111.png" alt="1111" width="596" height="330" /></a></div>
<div>这样就实现了阿里云环境下的HA切换。</div>
<div>实际测试，阿里云的多个HAVIP可以绑定到同样的两台机器，可以配置多组vrrp_instance来实现双主。或者两台服务器同时为两个业务服务，避免资源浪费。同时能够做到主备</div>
</div>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91%e4%b8%8b%e9%85%8d%e7%bd%aekeepalive%ef%bc%8c%e5%88%a9%e7%94%a8havip%e5%ae%9e%e7%8e%b0ha-2/">阿里云下配置keepalive，利用HAVIP实现HA</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91%e4%b8%8b%e9%85%8d%e7%bd%aekeepalive%ef%bc%8c%e5%88%a9%e7%94%a8havip%e5%ae%9e%e7%8e%b0ha-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>阿里云SLB健康检查的日志特殊处理</title>
		<link>https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91slb%e5%81%a5%e5%ba%b7%e6%a3%80%e6%9f%a5%e7%9a%84%e6%97%a5%e5%bf%97%e7%89%b9%e6%ae%8a%e5%a4%84%e7%90%86/</link>
		<comments>https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91slb%e5%81%a5%e5%ba%b7%e6%a3%80%e6%9f%a5%e7%9a%84%e6%97%a5%e5%bf%97%e7%89%b9%e6%ae%8a%e5%a4%84%e7%90%86/#comments</comments>
		<pubDate>Mon, 14 Mar 2016 14:31:09 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[aliyun服务器代维]]></category>
		<category><![CDATA[linux代维]]></category>
		<category><![CDATA[linux服务器代维]]></category>
		<category><![CDATA[linux系统代维]]></category>
		<category><![CDATA[代维]]></category>
		<category><![CDATA[服务器代维]]></category>
		<category><![CDATA[网站代维]]></category>
		<category><![CDATA[阿里云SLB健康检查的日志特殊处理]]></category>

		<guid isPermaLink="false">https://www.fuwuqiok.com/?p=3076</guid>
		<description><![CDATA[<p>SLB健康检查的频率比较高，每秒都有好几个。日积月累就带来了大量web service的日志。一来浪费存储空间 [&#8230;]</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91slb%e5%81%a5%e5%ba%b7%e6%a3%80%e6%9f%a5%e7%9a%84%e6%97%a5%e5%bf%97%e7%89%b9%e6%ae%8a%e5%a4%84%e7%90%86/">阿里云SLB健康检查的日志特殊处理</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>SLB健康检查的频率比较高，每秒都有好几个。日积月累就带来了大量web service的日志。一来浪费存储空间，二来消耗磁盘性能。除了官方建议的降低健康检查频率外，或许有一些变通的思维</p>
<p><strong>1、如果对HTTP或者TCP转发协议不挑剔，换成TCP转发并不开启http健康检查就OK了。</strong></p>
<p>优势：方便，控制台操作下就好了。</p>
<p>劣势：只是这样也失去了应用层异常的发现能力。</p>
<p><strong>2、为健康检查单独建立一个没有开启日志的virtualhost，通过不同的端口或者hostname，让健康检查请求不会请求到业务host。</strong></p>
<p>优势：web service级别的异常依然能够被健康检查发现。</p>
<p>劣势：virtualhost级别的异常，SLB健康检查就无法发现了。</p>
<p><strong>3、利用nginx等web服务器的规则，为健康检查的文件名（URI）做单独的日志配置，以Nginx为例：</strong></p>
<p>如下配置，健康检查配置一个业务上无意义的check.html。针对这个文件做的请求，不记录日志。</p>
<div class="crayon-pre">
<div id="crayon-56e5649bd2574294403245-1" class="crayon-line"><span class="crayon-v">location</span> <span class="crayon-o">~</span> <span class="crayon-o">/</span><span class="crayon-v">check</span><span class="crayon-e">.html</span></div>
<div id="crayon-56e5649bd2574294403245-2" class="crayon-line crayon-striped-line"><span class="crayon-h">        </span><span class="crayon-sy">{</span></div>
<div id="crayon-56e5649bd2574294403245-3" class="crayon-line"><span class="crayon-h">              </span><span class="crayon-e">access_log </span><span class="crayon-v">off</span><span class="crayon-sy">;</span> <span class="crayon-c">#关闭日志</span></div>
<div id="crayon-56e5649bd2574294403245-4" class="crayon-line crayon-striped-line"><span class="crayon-h">             </span> <span class="crayon-c">#access_log  /var/log/nginx/access/health_check.log main;或者健康检查的日志配置到单独的文件</span></div>
<div id="crayon-56e5649bd2574294403245-5" class="crayon-line"><span class="crayon-h">        </span><span class="crayon-sy">}</span></div>
<div class="crayon-line">
<p>优势：健康检查日志可以随意配置，且不会损失健康检查的特性。</p>
</div>
</div>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91slb%e5%81%a5%e5%ba%b7%e6%a3%80%e6%9f%a5%e7%9a%84%e6%97%a5%e5%bf%97%e7%89%b9%e6%ae%8a%e5%a4%84%e7%90%86/">阿里云SLB健康检查的日志特殊处理</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91slb%e5%81%a5%e5%ba%b7%e6%a3%80%e6%9f%a5%e7%9a%84%e6%97%a5%e5%bf%97%e7%89%b9%e6%ae%8a%e5%a4%84%e7%90%86/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>阿里云VPC网络无EIP的主机上网</title>
		<link>https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91vpc%e7%bd%91%e7%bb%9c%e6%97%a0eip%e7%9a%84%e4%b8%bb%e6%9c%ba%e4%b8%8a%e7%bd%91/</link>
		<comments>https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91vpc%e7%bd%91%e7%bb%9c%e6%97%a0eip%e7%9a%84%e4%b8%bb%e6%9c%ba%e4%b8%8a%e7%bd%91/#comments</comments>
		<pubDate>Mon, 14 Mar 2016 14:28:04 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[linux代维]]></category>
		<category><![CDATA[linux服务器代维]]></category>
		<category><![CDATA[linux服务器代维护]]></category>
		<category><![CDATA[linux服务器维护]]></category>
		<category><![CDATA[linux系统代维]]></category>
		<category><![CDATA[代维]]></category>
		<category><![CDATA[服务器代维]]></category>
		<category><![CDATA[阿里云VPC网络无EIP的主机上网]]></category>

		<guid isPermaLink="false">https://www.fuwuqiok.com/?p=3072</guid>
		<description><![CDATA[<p>阿里云的VPC与其他基于OpenStack的IaaS不同，他的路由只是作为多网段的路由交换，不提供内到外的路由 [&#8230;]</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91vpc%e7%bd%91%e7%bb%9c%e6%97%a0eip%e7%9a%84%e4%b8%bb%e6%9c%ba%e4%b8%8a%e7%bd%91/">阿里云VPC网络无EIP的主机上网</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></description>
				<content:encoded><![CDATA[<p>阿里云的VPC与其他基于OpenStack的IaaS不同，他的路由只是作为多网段的路由交换，不提供内到外的路由，因此在VPC内的主机除非绑 定EIP，否则是无法连接公网的。通过工单询问客服，得到的结论是通过在路由器上添加一个路由，通过一个绑定EIP的主机做NAT上网，通过设置 iptables的方式来实现。</p>
<h1 id="VPC结构图">VPC结构图</h1>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/aliyun-vpc-snat.jpg"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/aliyun-vpc-snat.jpg" alt="aliyun-vpc-snat" width="523" height="472" /></a></p>
<h1 id="虚拟路由器配置">虚拟路由器配置</h1>
<h2 id="添加路由">添加路由</h2>
<p>为了让内网服务器借助EIP访问公网，所以设置所有目标地址0.0.0.0/0下一跳都转发到绑定了公网IP的ECS实例上。这里的下一跳ECS不支持搜索，需要提前记号名称：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/aliyun-vpc-snat-2.jpg"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/aliyun-vpc-snat-2.jpg" alt="aliyun-vpc-snat-2" width="264" height="234" /></a></p>
<h1 id="绑定EIP的主机配置">绑定EIP的主机配置</h1>
<h2 id="iptables添加SNAT规则">iptables添加SNAT规则</h2>
<figure class="highlight bash">
<table>
<tbody>
<tr>
<td class="code">
<pre><span class="line">iptables -t nat -I POSTROUTING <span class="operator">-s</span> <span class="number">192.168</span>.<span class="number">2.0</span>/<span class="number">24</span> -j SNAT --to-source <span class="number">192.168</span>.<span class="number">2.20</span></span></pre>
</td>
</tr>
</tbody>
</table>
</figure>
<blockquote><p><strong>注意：</strong> ubuntu 14.04 系统保存iptables设置需要安装iptables-persistent包，然后通过 <code>service iptables-persistent save</code> 的方式保存配置，安装完iptables-persistent后该服务随系统一起启动并会把保存的配置应用</p></blockquote>
<h2 id="开启IP转发">开启IP转发</h2>
<figure class="highlight bash">
<table>
<tbody>
<tr>
<td class="code">
<pre><span class="line"><span class="built_in">echo</span> <span class="string">"net.ipv4.ip_forward=1"</span> &gt;&gt;  /etc/sysctl.conf &amp;&amp; sysctl -p</span></pre>
</td>
</tr>
</tbody>
</table>
</figure>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91vpc%e7%bd%91%e7%bb%9c%e6%97%a0eip%e7%9a%84%e4%b8%bb%e6%9c%ba%e4%b8%8a%e7%bd%91/">阿里云VPC网络无EIP的主机上网</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.fuwuqiok.com/%e9%98%bf%e9%87%8c%e4%ba%91vpc%e7%bd%91%e7%bb%9c%e6%97%a0eip%e7%9a%84%e4%b8%bb%e6%9c%ba%e4%b8%8a%e7%bd%91/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用 Docker、GitHub Flow、CircleCI、AWS Elastic Beanstalk 與 Slack 來完成持續整合與持續交付的開發流程</title>
		<link>https://www.fuwuqiok.com/%e4%bd%bf%e7%94%a8-docker%e3%80%81github-flow%e3%80%81circleci%e3%80%81aws-elastic-beanstalk-%e8%88%87-slack-%e4%be%86%e5%ae%8c%e6%88%90%e6%8c%81%e7%ba%8c%e6%95%b4%e5%90%88%e8%88%87%e6%8c%81%e7%ba%8c/</link>
		<comments>https://www.fuwuqiok.com/%e4%bd%bf%e7%94%a8-docker%e3%80%81github-flow%e3%80%81circleci%e3%80%81aws-elastic-beanstalk-%e8%88%87-slack-%e4%be%86%e5%ae%8c%e6%88%90%e6%8c%81%e7%ba%8c%e6%95%b4%e5%90%88%e8%88%87%e6%8c%81%e7%ba%8c/#comments</comments>
		<pubDate>Tue, 01 Mar 2016 14:00:51 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[linux代维]]></category>
		<category><![CDATA[linux服务器代维护]]></category>
		<category><![CDATA[linux服务器维护]]></category>
		<category><![CDATA[linux系统代维]]></category>
		<category><![CDATA[代维]]></category>
		<category><![CDATA[服务器代维]]></category>
		<category><![CDATA[服务器运维]]></category>
		<category><![CDATA[AWS Elastic Beanstalk 與 Slack 來完成持續整合與持續交付的開發流程]]></category>
		<category><![CDATA[CircleCI]]></category>
		<category><![CDATA[GitHub Flow]]></category>
		<category><![CDATA[使用 Docker]]></category>

		<guid isPermaLink="false">https://www.fuwuqiok.com/?p=2972</guid>
		<description><![CDATA[<p>DevOps：持續整合＆持續交付（Docker、CircleCI、AWS） 這篇文章將一步一步介紹如何使用 D [&#8230;]</p>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e4%bd%bf%e7%94%a8-docker%e3%80%81github-flow%e3%80%81circleci%e3%80%81aws-elastic-beanstalk-%e8%88%87-slack-%e4%be%86%e5%ae%8c%e6%88%90%e6%8c%81%e7%ba%8c%e6%95%b4%e5%90%88%e8%88%87%e6%8c%81%e7%ba%8c/">使用 Docker、GitHub Flow、CircleCI、AWS Elastic Beanstalk 與 Slack 來完成持續整合與持續交付的開發流程</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></description>
				<content:encoded><![CDATA[<h1>DevOps：持續整合＆持續交付（Docker、CircleCI、AWS）</h1>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4b67777732504e5234526f2f5654704f4974746d6452492f41414141414141416b62772f78586c35317a477a6c36512f73313630302f636f7665722e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4b67777732504e5234526f2f5654704f4974746d6452492f41414141414141416b62772f78586c35317a477a6c36512f73313630302f636f7665722e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4b67777732504e5234526f2f5654704f4974746d6452492f41414141414141416b62772f78586c35317a477a6c36512f73313630302f636f7665722e706e6" width="800" height="375" /></a></p>
<p>這篇文章將一步一步介紹如何使用 Docker、GitHub Flow、CircleCI、AWS Elastic Beanstalk 與 Slack 來完成<strong>持續整合</strong>與<strong>持續交付</strong>的開發流程。</p>
<h2><a id="user-content-前言" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%89%8D%E8%A8%80"></a>前言</h2>
<h3><a id="user-content-什麼是持續整合持續交付" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E4%BB%80%E9%BA%BC%E6%98%AF%E6%8C%81%E7%BA%8C%E6%95%B4%E5%90%88%E6%8C%81%E7%BA%8C%E4%BA%A4%E4%BB%98"></a>什麼是持續整合＆持續交付？</h3>
<p>持續整合＆持續交付（Continuous Integration &amp; Continous Delivery），簡稱 CI &amp; CD，具體介紹可以參考「<a href="http://blog.eavatar.com/post/2013/10/continuous-integration-deployment-delivery/">山姆鍋對持續整合、持續部署、持續交付的定義</a>」這篇文章。</p>
<p>簡單來說就是盡量減少手動人力，將一些日常工作交給自動化工具。例如：環境建置、單元測試、日誌紀錄、產品部署。</p>
<h3><a id="user-content-我使用了哪些工具" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E6%88%91%E4%BD%BF%E7%94%A8%E4%BA%86%E5%93%AA%E4%BA%9B%E5%B7%A5%E5%85%B7"></a>我使用了哪些工具？</h3>
<ul>
<li><a href="http://git-scm.com/">Git</a> &#8211; 版本管理</li>
<li><a href="https://github.com/">GitHub</a> &#8211; 程式碼託管、審查</li>
<li><a href="https://circleci.com/">CircleCI</a> &#8211; 自動化建置、測試、部署</li>
<li><a href="https://www.docker.com/">Docker</a> &#8211; 可攜式、輕量級的執行環境</li>
<li><a href="https://aws.amazon.com/elasticbeanstalk/">AWS Elastic Beanstalk</a> &#8211; 雲端平台</li>
<li><a href="https://slack.com/">Slack</a> &#8211; 團隊溝通、日誌、通知</li>
</ul>
<h3><a id="user-content-看完這篇你可以學到什麼" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E7%9C%8B%E5%AE%8C%E9%80%99%E7%AF%87%E4%BD%A0%E5%8F%AF%E4%BB%A5%E5%AD%B8%E5%88%B0%E4%BB%80%E9%BA%BC"></a>看完這篇你可以學到什麼？</h3>
<ul>
<li>瞭解 GiHub 的工作流程（<a href="https://guides.github.com/introduction/flow/">GitHub Flow</a>），利用 <strong>Pull Request</strong> 以及<strong>分支</strong>來完成<strong>代碼審查</strong>（Code Review）與<strong>環境配置</strong>，例如：開發版（development）、測試版（testing/QA）、上線產品（staging/production）。</li>
<li>使用 Docker，統一開發者、測試人員、以及產品的執行環境。</li>
<li>使用 EB CLI 將應用程式部署到 AWS Elastic Beanstalk 平台上。</li>
<li>使用 CircleCI 將以上工作全部自動化。偵測 GitHub 分支上的程式碼，若有更新則觸發：建置 Docker 環境、單元測試、然後自動部署新版本到 AWS EB。</li>
<li>使用 Slack，讓團隊成員能夠即時接收 GitHub 與 CircleCI 每一項動作的通知。</li>
</ul>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d61794d50555969704159492f565470505754456c6a58492f41414141414141416b62382f767077352d77722d426a512f73313630302f73657175656e63652d6469616772616d2e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d61794d50555969704159492f565470505754456c6a58492f41414141414141416b62382f767077352d77722d426a512f73313630302f73657175656e63652d6469616772616d2e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d61794d50555969704159492f565470505754456c6a58492f41414141414141416b62382f767077352d77722d426a512f73313630302f73657175656e63652d6469616772616d2e706e6" width="577" height="500" /></a></p>
<h2><a id="user-content-內容大綱" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%85%A7%E5%AE%B9%E5%A4%A7%E7%B6%B1"></a>內容大綱</h2>
<ul>
<li><a href="https://github.com/zeus911/hello-ci-workflow#node.js">Node.js</a>
<ul>
<li>在本地端執行 Node.js</li>
<li>在本地端測試 Node.js</li>
</ul>
</li>
<li><a href="https://github.com/zeus911/hello-ci-workflow#github">GitHub</a></li>
<li><a href="https://github.com/zeus911/hello-ci-workflow#circleci">CircleCI</a>
<ul>
<li>在 CircleCI 測試 Node.js</li>
</ul>
</li>
<li><a href="https://github.com/zeus911/hello-ci-workflow#code-review-with-github-flow">Code Review with GitHub Flow</a></li>
<li><a href="https://github.com/zeus911/hello-ci-workflow#docker">Docker</a>
<ul>
<li>在 Docker 執行 Node.js</li>
<li>在 CircleCI 測試 Docker</li>
</ul>
</li>
<li><a href="https://github.com/zeus911/hello-ci-workflow#aws-elastic-beanstalk">AWS Elastic Beanstalk</a>
<ul>
<li>在本地端部署 AWS</li>
<li>在 CircleCI 部署 AWS</li>
</ul>
</li>
<li><a href="https://github.com/zeus911/hello-ci-workflow#slack">Slack</a></li>
</ul>
<h2><a id="user-content-nodejs" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#nodejs"></a>Node.js</h2>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d47567335784c4a783937632f56547051765544786244492f41414141414141416b63592f4d706c307775326e41366b2f73313630302f6e6f64652e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d47567335784c4a783937632f56547051765544786244492f41414141414141416b63592f4d706c307775326e41366b2f73313630302f6e6f64652e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d47567335784c4a783937632f56547051765544786244492f41414141414141416b63592f4d706c307775326e41366b2f73313630302f6e6f64652e706e6" width="296" height="80" /></a></p>
<blockquote><p>安裝：</p>
<ul>
<li><a href="https://nodejs.org/">node</a>: 0.10</li>
</ul>
</blockquote>
<p>這篇文章以 Node.js 的應用程式作為範例，其他語言（Ruby on Rails、Python、PHP）也同樣適用此工作流程。</p>
<h3><a id="user-content-建立新專案" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%BB%BA%E7%AB%8B%E6%96%B0%E5%B0%88%E6%A1%88"></a>建立新專案</h3>
<ol>
<li>建立一個專案資料夾（這裡以 <code>hello-ci-workflow</code> 為例）：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ mkdir hello-ci-workflow
$ <span class="pl-c1">cd</span> hello-ci-workflow</pre>
</div>
<h3><a id="user-content-在本地端執行-nodejs" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%9C%A8%E6%9C%AC%E5%9C%B0%E7%AB%AF%E5%9F%B7%E8%A1%8C-nodejs"></a>在本地端執行 Node.js</h3>
<ol>
<li>初始化 Node.js 的環境，填寫一些資料之後會在目錄下產生一個 <code>package.json</code> 的檔案：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ npm init</pre>
</div>
<ol>
<li>安裝 Node.js 的 web framework，以 <a href="http://expressjs.com/">Express</a> 為例：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ npm install express --save</pre>
</div>
<blockquote><p><code>--save</code>: 寫入 <code>package.json</code> 的 dependencies。</p></blockquote>
<ol>
<li>完成之後，<code>package.json</code> 大概會長這個樣子：</li>
</ol>
<div class="highlight highlight-source-json">
<pre>// package.json
{
  <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>hello-ci-workflow<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>main<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>index.js<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>dependencies<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>express<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>^4.12.3<span class="pl-pds">"</span></span>
  },
  <span class="pl-s"><span class="pl-pds">"</span>scripts<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>start<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>node index.js<span class="pl-pds">"</span></span>
  }
}</pre>
</div>
<ol>
<li>在 <code>index.js</code> 裡寫一段簡單的 Hello World! 的程式：</li>
</ol>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// index.js</span>
<span class="pl-k">var</span> express <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">'</span>express<span class="pl-pds">'</span></span>);
<span class="pl-k">var</span> app <span class="pl-k">=</span> <span class="pl-en">express</span>();

<span class="pl-smi">app</span>.<span class="pl-en">get</span>(<span class="pl-s"><span class="pl-pds">'</span>/<span class="pl-pds">'</span></span>, <span class="pl-k">function</span> (<span class="pl-smi">req</span>, <span class="pl-smi">res</span>) {
  <span class="pl-smi">res</span>.<span class="pl-c1">send</span>(<span class="pl-s"><span class="pl-pds">'</span>Hello World!<span class="pl-pds">'</span></span>);
});

<span class="pl-k">var</span> server <span class="pl-k">=</span> <span class="pl-smi">app</span>.<span class="pl-en">listen</span>(<span class="pl-c1">3000</span>, <span class="pl-k">function</span> () {

  <span class="pl-k">var</span> host <span class="pl-k">=</span> <span class="pl-smi">server</span>.<span class="pl-en">address</span>().<span class="pl-smi">address</span>;
  <span class="pl-k">var</span> port <span class="pl-k">=</span> <span class="pl-smi">server</span>.<span class="pl-en">address</span>().<span class="pl-c1">port</span>;

  <span class="pl-en">console</span>.<span class="pl-c1">log</span>(<span class="pl-s"><span class="pl-pds">'</span>Example app listening at http://%s:%s<span class="pl-pds">'</span></span>, host, port);

});</pre>
</div>
<ol>
<li>執行 <code>npm start</code> 或 <code>node index.js</code>：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ npm start</pre>
</div>
<ol>
<li>打開瀏覽器 <code>http://localhost:3000</code> 看結果：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d316f705f565f50574749492f56547055664f50796f67492f41414141414141416b65772f69576453534d2d453648592f73313630302f30312e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d316f705f565f50574749492f56547055664f50796f67492f41414141414141416b65772f69576453534d2d453648592f73313630302f30312e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d316f705f565f50574749492f56547055664f50796f67492f41414141414141416b65772f69576453534d2d453648592f73313630302f30312e706e6" width="250" height="70" /></a></p>
<h3><a id="user-content-在本地端測試-nodejs" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%9C%A8%E6%9C%AC%E5%9C%B0%E7%AB%AF%E6%B8%AC%E8%A9%A6-nodejs"></a>在本地端測試 Node.js</h3>
<ol>
<li>安裝 Node.js 的單元測試，以 <a href="http://mochajs.org/">Mocha</a> 為例：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ npm install mocha --save-dev</pre>
</div>
<blockquote><p><code>--save-dev</code>: 寫入 <code>package.json</code> 的 devDependencies，正式上線環境不會被安裝。</p></blockquote>
<div class="highlight highlight-source-json">
<pre>// package.json
{
  <span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>hello-ci-workflow<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>main<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>index.js<span class="pl-pds">"</span></span>,
  <span class="pl-s"><span class="pl-pds">"</span>dependencies<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>express<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>^4.12.3<span class="pl-pds">"</span></span>
  },
  <span class="pl-s"><span class="pl-pds">"</span>devDependencies<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>mocha<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>^2.2.4<span class="pl-pds">"</span></span>
  },
  <span class="pl-s"><span class="pl-pds">"</span>scripts<span class="pl-pds">"</span></span>: {
    <span class="pl-s"><span class="pl-pds">"</span>start<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>node index.js<span class="pl-pds">"</span></span>
  }
}</pre>
</div>
<ol>
<li>根目錄 <code>test</code> 資料夾，並新增一個測試腳本 <code>test.js</code>：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ mkdir <span class="pl-c1">test</span>
$ <span class="pl-c1">cd</span> <span class="pl-c1">test</span>
$ touch <span class="pl-c1">test</span>.js</pre>
</div>
<ol>
<li>加入一筆錯誤的測試 <code>assert.equal(1, [1,2,3].indexOf(0))</code>：</li>
</ol>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// test/test.js</span>
<span class="pl-k">var</span> assert <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>assert<span class="pl-pds">"</span></span>)
<span class="pl-en">describe</span>(<span class="pl-s"><span class="pl-pds">'</span>Array<span class="pl-pds">'</span></span>, <span class="pl-k">function</span>(){
  <span class="pl-en">describe</span>(<span class="pl-s"><span class="pl-pds">'</span>#indexOf()<span class="pl-pds">'</span></span>, <span class="pl-k">function</span>(){
    <span class="pl-en">it</span>(<span class="pl-s"><span class="pl-pds">'</span>should return -1 when the value is not present<span class="pl-pds">'</span></span>, <span class="pl-k">function</span>(){
      <span class="pl-smi">assert</span>.<span class="pl-en">equal</span>(<span class="pl-c1">1</span>, [<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>].<span class="pl-c1">indexOf</span>(<span class="pl-c1">0</span>));
    })
  })
})</pre>
</div>
<ol>
<li>執行 mocha 測試：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ ./node_modules/.bin/mocha


  Array
    <span class="pl-c">#indexOf()</span>
      1) should <span class="pl-k">return</span> -1 when the value is not present


  0 passing (9ms)
  1 failing</pre>
</div>
<p>結果顯示 <code>1 failing</code>，測試沒通過，因為 <code>[1,2,3].indexOf(0)</code> 回傳的值不等於 <code>-1</code>。</p>
<ol>
<li>將 <code>test.js</code> 的測試修正：</li>
</ol>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// test/test.js</span>
<span class="pl-smi">assert</span>.<span class="pl-en">equal</span>(<span class="pl-k">-</span><span class="pl-c1">1</span>, [<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>].<span class="pl-c1">indexOf</span>(<span class="pl-c1">0</span>));</pre>
</div>
<ol>
<li>再次執行 mocha 測試：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ ./node_modules/.bin/mocha


  Array
    <span class="pl-c">#indexOf()</span>
      ✓ should <span class="pl-k">return</span> -1 when the value is not present


  1 passing (6ms)</pre>
</div>
<p>結果顯示 <code>1 passing</code>，通過測試。</p>
<h2><a id="user-content-github" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#github"></a>GitHub</h2>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d736142616235336e3135772f56547051765149376636492f41414141414141416b63552f46703865346161467938452f73313630302f6769746875622e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d736142616235336e3135772f56547051765149376636492f41414141414141416b63552f46703865346161467938452f73313630302f6769746875622e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d736142616235336e3135772f56547051765149376636492f41414141414141416b63552f46703865346161467938452f73313630302f6769746875622e706e6" width="374" height="80" /></a></p>
<blockquote><p>安裝：</p>
<ul>
<li><a href="http://git-scm.com/">git</a>: 2.3</li>
</ul>
<p>帳號：</p>
<ul>
<li><a href="https://github.com/">GitHub</a></li>
</ul>
</blockquote>
<ol>
<li>初始化 git 環境：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git init <span class="pl-c1">.</span></pre>
</div>
<ol>
<li>輸入 <code>git status</code> 會顯示目前哪些檔案有過更動：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git status
On branch master

Initial commit

Untracked files:
  (use <span class="pl-s"><span class="pl-pds">"</span>git add &lt;file&gt;...<span class="pl-pds">"</span></span> to include <span class="pl-k">in</span> what will be committed)

  index.js
  node_modules/
  package.json
  test/</pre>
</div>
<ol>
<li>將 <code>node_modules</code> 加到 <code>.gitignore</code> 黑名單，因為這個資料夾是由 <code>npm install</code> 自動產生的，不需要放到 GitHub 上：</li>
</ol>
<div class="highlight highlight-source-yaml">
<pre><span class="pl-c"># .gitignore</span>

<span class="pl-c"># Dependency directory</span>
<span class="pl-c"># https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git</span>
node_modules</pre>
</div>
<ol>
<li>將更動 commit：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git add <span class="pl-c1">.</span>
$ git commit -m <span class="pl-s"><span class="pl-pds">"</span>first commit<span class="pl-pds">"</span></span></pre>
</div>
<ol>
<li>打開 GitHub，新增一個 repository：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d2d4a2d36343130534e74342f5654705566423150452d492f41414141414141416b65732f4e5a4476386d436e6661342f73313630302f30322e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d2d4a2d36343130534e74342f5654705566423150452d492f41414141414141416b65732f4e5a4476386d436e6661342f73313630302f30322e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d2d4a2d36343130534e74342f5654705566423150452d492f41414141414141416b65732f4e5a4476386d436e6661342f73313630302f30322e706e6" width="325" height="47" /></a></p>
<ol>
<li>輸入 repository 的名稱，以 <code>hello-ci-workflow</code> 為例：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4a7973694f3946663435492f56547055664166674532492f41414141414141416b65302f42465947614d5a394d55302f73313630302f30332e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4a7973694f3946663435492f56547055664166674532492f41414141414141416b65302f42465947614d5a394d55302f73313630302f30332e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4a7973694f3946663435492f56547055664166674532492f41414141414141416b65302f42465947614d5a394d55302f73313630302f30332e706e6" width="430" height="44" /></a></p>
<ol>
<li>使用 <code>git remote add</code> 將新創建的 GitHub repository 加入到 remote：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git remote add origin https://github.com/<span class="pl-k">&lt;</span>USER_NAME<span class="pl-k">&gt;</span>/hello-ci-workflow.git</pre>
</div>
<blockquote><p><code>&lt;USER_NAME&gt;</code> 改成自己的帳號。</p></blockquote>
<ol>
<li>使用 <code>git push</code> 將程式碼傳到 GitHub：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git push -u origin master</pre>
</div>
<p>成功之後前往 <code>https://github.com/&lt;USER_NAME&gt;/hello-ci-workflow</code> 就可以看到剛才上傳的檔案：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4c6642586942516b654e632f56547055666c6e683367492f41414141414141416b65342f634b316c703537725a79632f73313630302f30342e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4c6642586942516b654e632f56547055666c6e683367492f41414141414141416b65342f634b316c703537725a79632f73313630302f30342e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4c6642586942516b654e632f56547055666c6e683367492f41414141414141416b65342f634b316c703537725a79632f73313630302f30342e706e6" width="211" height="205" /></a></p>
<h2><a id="user-content-circleci" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#circleci"></a>CircleCI</h2>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d555466506b66356b5171302f56547051753441425969492f41414141414141416b634d2f4d6a6577393739315a7a672f73313630302f636972636c6563692e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d555466506b66356b5171302f56547051753441425969492f41414141414141416b634d2f4d6a6577393739315a7a672f73313630302f636972636c6563692e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d555466506b66356b5171302f56547051753441425969492f41414141414141416b634d2f4d6a6577393739315a7a672f73313630302f636972636c6563692e706e6" width="378" height="80" /></a></p>
<blockquote><p>帳號：</p>
<ul>
<li><a href="https://circleci.com/">CircleCI</a></li>
</ul>
</blockquote>
<h3><a id="user-content-加入-github-repository" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%8A%A0%E5%85%A5-github-repository"></a>加入 GitHub repository</h3>
<ol>
<li>點選左邊欄的 <code>Add Projects</code> 按鈕：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d37725766746e676c5f53632f56547055663743494b4c492f41414141414141416b66492f67326264753834777a65632f73313630302f30352e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d37725766746e676c5f53632f56547055663743494b4c492f41414141414141416b66492f67326264753834777a65632f73313630302f30352e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d37725766746e676c5f53632f56547055663743494b4c492f41414141414141416b66492f67326264753834777a65632f73313630302f30352e706e6" width="195" height="75" /></a></p>
<ol>
<li>選擇自己的 GitHub 帳號：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d34376b685743594648766b2f56547055663636374249492f41414141414141416b66412f3230614c6d7a484d6f67512f73313630302f30362e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d34376b685743594648766b2f56547055663636374249492f41414141414141416b66412f3230614c6d7a484d6f67512f73313630302f30362e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d34376b685743594648766b2f56547055663636374249492f41414141414141416b66412f3230614c6d7a484d6f67512f73313630302f30362e706e6" width="250" height="68" /></a></p>
<ol>
<li>搜尋要加入的 GitHub repository，然後點選 <code>Build project</code> 按鈕，以 <code>hello-ci-workflow</code> 為例：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d73444630306c78386361492f565470556e684e6c4739492f41414141414141416b686b2f50425669354952556676452f73313630302f30372e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d73444630306c78386361492f565470556e684e6c4739492f41414141414141416b686b2f50425669354952556676452f73313630302f30372e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d73444630306c78386361492f565470556e684e6c4739492f41414141414141416b686b2f50425669354952556676452f73313630302f30372e706e6" width="350" height="94" /></a></p>
<ol>
<li>完成之後 CircleCI 就會自動執行第一次的建構，不過因為還沒加入測試腳本，所以建構結果會顯示 no test：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d34364c78483678636f744d2f56547055677335734a56492f41414141414141416b664d2f396b3056394869476b35412f73313630302f30382e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d34364c78483678636f744d2f56547055677335734a56492f41414141414141416b664d2f396b3056394869476b35412f73313630302f30382e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d34364c78483678636f744d2f56547055677335734a56492f41414141414141416b664d2f396b3056394869476b35412f73313630302f30382e706e6" width="269" height="78" /></a></p>
<h3><a id="user-content-在-circleci-測試-nodejs" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%9C%A8-circleci-%E6%B8%AC%E8%A9%A6-nodejs"></a>在 CircleCI 測試 Node.js</h3>
<ol>
<li>在專案根目錄底下建立一個 <code>circle.yml</code>，並加入 mocha test：</li>
</ol>
<div class="highlight highlight-source-yaml">
<pre><span class="pl-c"># circle.yml</span>
<span class="pl-s"><span class="pl-ent">machine:</span></span>
  <span class="pl-s"><span class="pl-ent">node:</span></span>
    <span class="pl-c1"><span class="pl-ent">version:</span> 0.10</span>

<span class="pl-s"><span class="pl-ent">test:</span></span>
  <span class="pl-s"><span class="pl-ent">override:</span></span>
    <span class="pl-s">- <span class="pl-s">./node_modules/.bin/mocha</span></span></pre>
</div>
<ol>
<li>完成之後將檔案 push 上 GitHub：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git add circle.yml
$ git cimmit <span class="pl-s"><span class="pl-pds">"</span>add circle.yml<span class="pl-pds">"</span></span>
$ git push</pre>
</div>
<ol>
<li>Push 成功之後，CircleCI 會自動觸發建構和測試：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d47674d44483277596f5f672f56547055673877733434492f41414141414141416b66552f7a5431686f346c76546d382f73313630302f30392e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d47674d44483277596f5f672f56547055673877733434492f41414141414141416b66552f7a5431686f346c76546d382f73313630302f30392e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d47674d44483277596f5f672f56547055673877733434492f41414141414141416b66552f7a5431686f346c76546d382f73313630302f30392e706e6" width="500" height="300" /></a></p>
<ol>
<li>測試通過，建置成功：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d456c4d57747638537534492f565470556845325f4c4d492f41414141414141416b66592f51346b5a6c3544377172672f73313630302f31302e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d456c4d57747638537534492f565470556845325f4c4d492f41414141414141416b66592f51346b5a6c3544377172672f73313630302f31302e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d456c4d57747638537534492f565470556845325f4c4d492f41414141414141416b66592f51346b5a6c3544377172672f73313630302f31302e706e6" width="210" height="55" /></a></p>
<h2><a id="user-content-代碼審查code-reviewwith-github-flow" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E4%BB%A3%E7%A2%BC%E5%AF%A9%E6%9F%A5code-reviewwith-github-flow"></a>代碼審查（Code Review）with GitHub Flow</h2>
<p>目前開發中比較常用的 workflow 有 <a href="http://nvie.com/posts/a-successful-git-branching-model/">Git flow</a> 和 <a href="https://guides.github.com/introduction/flow/">GitHub flow</a> 兩種，可以參考以下幾篇文章：</p>
<p>Git flow：</p>
<ul>
<li><a href="https://ihower.tw/blog/archives/5140">Git flow 開發流程</a></li>
<li><a href="https://danielkummer.github.io/git-flow-cheatsheet/">git-flow cheatsheet</a></li>
<li><a href="http://nvie.com/posts/a-successful-git-branching-model/">A successful Git branching model</a></li>
</ul>
<p>GitHub flow：</p>
<ul>
<li><a href="https://guides.github.com/introduction/flow/">Understanding the GitHub Flow</a></li>
<li><a href="http://www.arthurtoday.com/2015/02/git-flow-vs-github-flow.html">Git Flow 和 Github Flow 的不同</a></li>
<li><a href="http://blog.krdai.info/post/17485259496/github-flow">在 GitHub 當中使用的 work flow</a></li>
</ul>
<p>這裡我們使用 GitHub flow，它的核心精神是：</p>
<ul>
<li>所有在 master 分支上的程式都一定要是通過測試，可以部署的產品版本。</li>
<li>要開發功能、修復 Bug、做任何事情，都要從 master 開一條新的分支。</li>
<li>隨時 commit 和 push 你的程式碼到 GitHub 上，與大家討論。</li>
<li>功能完成時，使用 pull request 讓大家作 code review。</li>
<li>確認沒問題之後才可以 merge 回 master，並且部屬新版本到線上。</li>
</ul>
<h3><a id="user-content-建立一條分支" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%BB%BA%E7%AB%8B%E4%B8%80%E6%A2%9D%E5%88%86%E6%94%AF"></a>建立一條分支</h3>
<ol>
<li>為了確保 master 這條主線上的程式碼都是穩定的，所以建議開發者依照不同的功能、建立不同的分支，這裡以 <code>test-github-flow</code> 為例，使用 <code>git branch</code> 新增分支、然後 <code>git checkout</code> 切換分支：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git branch test-github-flow
$ git checkout test-github-flow</pre>
</div>
<h3><a id="user-content-加入-commits" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%8A%A0%E5%85%A5-commits"></a>加入 commits</h3>
<ol>
<li>在 <code>test.js</code> 裡加入一行錯誤的測試 <code>assert.equal(3, [1,2,3].indexOf(5))</code>：</li>
</ol>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// test/test.js</span>
<span class="pl-c">// ...</span>
<span class="pl-smi">assert</span>.<span class="pl-en">equal</span>(<span class="pl-c1">3</span>, [<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>].<span class="pl-c1">indexOf</span>(<span class="pl-c1">5</span>));</pre>
</div>
<div class="highlight highlight-source-shell">
<pre>$ git add test/test.js
$ git commit -m <span class="pl-s"><span class="pl-pds">"</span>add a error test case<span class="pl-pds">"</span></span></pre>
</div>
<h3><a id="user-content-新增一個-pull-request" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E6%96%B0%E5%A2%9E%E4%B8%80%E5%80%8B-pull-request"></a>新增一個 Pull Request</h3>
<ol>
<li>Push 到 GitHub 的 test-github-flow 分支：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git push -u origin test-github-flow</pre>
</div>
<ol>
<li>打開 GitHub 之後，會出現 <code>test-github-flow</code> 分支的 push commits，點選旁邊的 <code>Compare &amp; pull request</code> 按鈕：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d3358664e484e4a485f76382f56547055694f727a456f492f41414141414141416b66302f6a385665765951437944672f73313630302f31332e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d3358664e484e4a485f76382f56547055694f727a456f492f41414141414141416b66302f6a385665765951437944672f73313630302f31332e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d3358664e484e4a485f76382f56547055694f727a456f492f41414141414141416b66302f6a385665765951437944672f73313630302f31332e706e6" width="800" height="120" /></a></p>
<ol>
<li>點選之後會進入 Open a pull request 的填寫頁面，選擇想要 merge 的分支、輸入描述之後，點選 <code>Create pull request</code> 按鈕：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d736645574f6e4f665747592f5654705569515a763571492f41414141414141416b66342f65387772416871544736512f73313630302f31342e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d736645574f6e4f665747592f5654705569515a763571492f41414141414141416b66342f65387772416871544736512f73313630302f31342e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d736645574f6e4f665747592f5654705569515a763571492f41414141414141416b66342f65387772416871544736512f73313630302f31342e706e6" width="775" height="540" /></a></p>
<h3><a id="user-content-檢視討論你的程式碼" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E6%AA%A2%E8%A6%96%E8%A8%8E%E8%AB%96%E4%BD%A0%E7%9A%84%E7%A8%8B%E5%BC%8F%E7%A2%BC"></a>檢視＆討論你的程式碼</h3>
<ol>
<li>新增一個 pull request 之後，其他人就會在 GitHub 上出現通知：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d4f393436777849474c696b2f5654705569393557376e492f41414141414141416b67452f454a354543344f677464732f73313630302f31352e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d4f393436777849474c696b2f5654705569393557376e492f41414141414141416b67452f454a354543344f677464732f73313630302f31352e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d4f393436777849474c696b2f5654705569393557376e492f41414141414141416b67452f454a354543344f677464732f73313630302f31352e706e6" width="170" height="35" /></a></p>
<ol>
<li>點進去之後可以看見相關的 commits 與留言，但是下面有一個紅紅大大的叉叉；因為每次 GitHub 只要有新的 push，就會觸發 CircleCI 的自動建置和測試，並且顯示結果在 GitHub 上：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d76337677694a59344759342f565470556a44714c6777492f41414141414141416b67492f57627850704769395069342f73313630302f31382e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d76337677694a59344759342f565470556a44714c6777492f41414141414141416b67492f57627850704769395069342f73313630302f31382e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d76337677694a59344759342f565470556a44714c6777492f41414141414141416b67492f57627850704769395069342f73313630302f31382e706e6" width="770" height="470" /></a></p>
<ol>
<li>點選叉叉，前往 CircleCI 查看錯誤原因：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d6172664e434532504e6a492f565470556a744b7a7042492f41414141414141416b67512f4a55396f6a63342d5630452f73313630302f31392e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d6172664e434532504e6a492f565470556a744b7a7042492f41414141414141416b67512f4a55396f6a63342d5630452f73313630302f31392e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d6172664e434532504e6a492f565470556a744b7a7042492f41414141414141416b67512f4a55396f6a63342d5630452f73313630302f31392e706e6" width="700" height="35" /></a></p>
<ol>
<li>就會發現剛剛 push 到 test-github-flow 的測試沒通過：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d432d71756474766c6a556b2f565470556872504b6d6c492f41414141414141416b666f2f664c52495566694b615a772f73313630302f31322e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d432d71756474766c6a556b2f565470556872504b6d6c492f41414141414141416b666f2f664c52495566694b615a772f73313630302f31322e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d432d71756474766c6a556b2f565470556872504b6d6c492f41414141414141416b666f2f664c52495566694b615a772f73313630302f31322e706e6" width="210" height="75" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d2d49783939655738646e412f56547055687253714a41492f41414141414141416b666b2f30617048456a33685a30632f73313630302f31312e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d2d49783939655738646e412f56547055687253714a41492f41414141414141416b666b2f30617048456a33685a30632f73313630302f31312e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d2d49783939655738646e412f56547055687253714a41492f41414141414141416b666b2f30617048456a33685a30632f73313630302f31312e706e6" width="580" height="535" /></a></p>
<p>回到 GitHub，因為測試沒通過，所以審查者不能讓這筆 pull request 被 merge 回 master。</p>
<ol>
<li>找到剛剛 commit 的那段程式碼，留言告知請開發者修正錯誤之後，再重新 commit push 上來：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4d466a385073454a2d68672f565470556a3644386c78492f41414141414141416b67592f347a644a76316a417945492f73313630302f32312e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4d466a385073454a2d68672f565470556a3644386c78492f41414141414141416b67592f347a644a76316a417945492f73313630302f32312e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4d466a385073454a2d68672f565470556a3644386c78492f41414141414141416b67592f347a644a76316a417945492f73313630302f32312e706e6" width="620" height="200" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d7253585f7a6d4c3542386b2f565470556b595f343662492f41414141414141416b67632f6632303541376a445043452f73313630302f32322e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d7253585f7a6d4c3542386b2f565470556b595f343662492f41414141414141416b67632f6632303541376a445043452f73313630302f32322e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d7253585f7a6d4c3542386b2f565470556b595f343662492f41414141414141416b67632f6632303541376a445043452f73313630302f32322e706e6" width="795" height="285" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d7a5154654271794e446d552f565470556b713566424b492f41414141414141416b676b2f36653653435453784474672f73313630302f32332e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d7a5154654271794e446d552f565470556b713566424b492f41414141414141416b676b2f36653653435453784474672f73313630302f32332e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d7a5154654271794e446d552f565470556b713566424b492f41414141414141416b676b2f36653653435453784474672f73313630302f32332e706e6" width="770" height="255" /></a></p>
<ol>
<li>修正 <code>test.js</code> 的測試腳本：</li>
</ol>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// test/test.js</span>
<span class="pl-c">// ...</span>
<span class="pl-smi">assert</span>.<span class="pl-en">equal</span>(<span class="pl-k">-</span><span class="pl-c1">1</span>, [<span class="pl-c1">1</span>,<span class="pl-c1">2</span>,<span class="pl-c1">3</span>].<span class="pl-c1">indexOf</span>(<span class="pl-c1">5</span>));</pre>
</div>
<ol>
<li>再次 commit &amp; push：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git add test/test.js
$ git commit -m <span class="pl-s"><span class="pl-pds">"</span>fix error test case<span class="pl-pds">"</span></span>
$ git push</pre>
</div>
<ol>
<li>回到 GitHub 的 pull request 頁面，可以看到最新一筆的 commit 成功通過 CircleCI 的測試了：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d773856576934434d51424d2f565470556c5164655878492f41414141414141416b67342f65794f736b3254314e68302f73313630302f32362e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d773856576934434d51424d2f565470556c5164655878492f41414141414141416b67342f65794f736b3254314e68302f73313630302f32362e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d773856576934434d51424d2f565470556c5164655878492f41414141414141416b67342f65794f736b3254314e68302f73313630302f32362e706e6" width="770" height="475" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d4b2d71506431356d7049772f565470556b324b6e7356492f41414141414141416b676f2f33744c6b74485a494778772f73313630302f32342e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d4b2d71506431356d7049772f565470556b324b6e7356492f41414141414141416b676f2f33744c6b74485a494778772f73313630302f32342e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d4b2d71506431356d7049772f565470556b324b6e7356492f41414141414141416b676f2f33744c6b74485a494778772f73313630302f32342e706e6" width="460" height="295" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d7874335859616c446d6a512f565470556c4a61797749492f41414141414141416b67302f6c306f44385969454b5a592f73313630302f32352e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d7874335859616c446d6a512f565470556c4a61797749492f41414141414141416b67302f6c306f44385969454b5a592f73313630302f32352e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d7874335859616c446d6a512f565470556c4a61797749492f41414141414141416b67302f6c306f44385969454b5a592f73313630302f32352e706e6" width="210" height="75" /></a></p>
<h3><a id="user-content-merge部署" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#merge%E9%83%A8%E7%BD%B2"></a>Merge＆部署</h3>
<ol>
<li>審查之後，確定沒有問題，就可以點選 <code>Merge pull request</code> 的按鈕，將 <code>test-github-flow</code> 的程式碼 merge 回主線 <code>master</code>：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d695a7353466776494b58772f565470556c796e715877492f41414141414141416b68412f4f73723949657778657a492f73313630302f32372e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d695a7353466776494b58772f565470556c796e715877492f41414141414141416b68412f4f73723949657778657a492f73313630302f32372e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d695a7353466776494b58772f565470556c796e715877492f41414141414141416b68412f4f73723949657778657a492f73313630302f32372e706e6" width="770" height="170" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d70326731666a5a66416c492f565470556d5070523652492f41414141414141416b68452f3063642d506b63544c30592f73313630302f32382e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d70326731666a5a66416c492f565470556d5070523652492f41414141414141416b68452f3063642d506b63544c30592f73313630302f32382e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d70326731666a5a66416c492f565470556d5070523652492f41414141414141416b68452f3063642d506b63544c30592f73313630302f32382e706e6" width="770" height="200" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d726a7a37474a7a665a6c412f565470556d6149617a68492f41414141414141416b684d2f744f655937536f325964732f73313630302f32392e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d726a7a37474a7a665a6c412f565470556d6149617a68492f41414141414141416b684d2f744f655937536f325964732f73313630302f32392e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d726a7a37474a7a665a6c412f565470556d6149617a68492f41414141414141416b684d2f744f655937536f325964732f73313630302f32392e706e6" width="175" height="70" /></a></p>
<h2><a id="user-content-docker" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#docker"></a>Docker</h2>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d7a426a6f4a4c4c6a7255302f56547051753752433841492f41414141414141416b63492f6b324e45733437595f4d492f73313630302f646f636b65722e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d7a426a6f4a4c4c6a7255302f56547051753752433841492f41414141414141416b63492f6b324e45733437595f4d492f73313630302f646f636b65722e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d7a426a6f4a4c4c6a7255302f56547051753752433841492f41414141414141416b63492f6b324e45733437595f4d492f73313630302f646f636b65722e706e6" width="335" height="80" /></a></p>
<blockquote><p>安裝：</p>
<ul>
<li><a href="https://github.com/boot2docker/boot2docker">boot2docker</a>: 1.5（Mac only）</li>
<li><a href="https://www.docker.com/">docker</a>: 1.5</li>
</ul>
</blockquote>
<p>什麼是 Docker？為什麼要用它？</p>
<p>因為 Docker 最近很火，所以網路上不缺關於介紹它的文章，原諒我這裡只稍微提一下：</p>
<p>以往開發人員面對開發環境不同的問題，常常出現「明明在我的電腦上可以跑」的囧境，所以為了解決這類問題，通常會使用虛擬機器（VM）搭配一些工具（<a href="https://www.vagrantup.com/">Vagrant</a>、<a href="https://www.chef.io/">Chef</a>）來協助統一開發人員、測試人員、上線產品的執行環境。</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d3564735356592d492d4e512f5654706263466c47564e492f41414141414141416b6b732f4546596f546a6774786d512f73313630302f766d2d76732d646f636b65722e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d3564735356592d492d4e512f5654706263466c47564e492f41414141414141416b6b732f4546596f546a6774786d512f73313630302f766d2d76732d646f636b65722e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d3564735356592d492d4e512f5654706263466c47564e492f41414141414141416b6b732f4546596f546a6774786d512f73313630302f766d2d76732d646f636b65722e706e6" width="500" height="257" /></a></p>
<p>Docker 也是類似的解決方案，不同於 VM 的是，Docker 運行起來更輕巧、可攜度更高。配置好一份設定之後，就可以讓大家馬上進入開發狀況，減少不必要的環境問題，提升效率。</p>
<h3><a id="user-content-在-docker-執行-nodejs" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%9C%A8-docker-%E5%9F%B7%E8%A1%8C-nodejs"></a>在 Docker 執行 Node.js</h3>
<ol>
<li>在專案根目錄底下建立一個 <code>Dockerfile</code>：</li>
</ol>
<div class="highlight highlight-source-yaml">
<pre><span class="pl-c"># Dockerfile</span>

<span class="pl-c"># 從 [Docker Hub](https://hub.docker.com/) 安裝 Node.js image。</span>
<span class="pl-ent">FROM node</span>:0.10

<span class="pl-c"># 設定 container 的預設目錄位置</span>
WORKDIR /hello<span class="pl-s">-<span class="pl-s">ci-workflow</span></span>

<span class="pl-c"># 將專案根目錄的檔案加入至 container</span>
<span class="pl-c"># 安裝 npm package</span>
ADD . /hello<span class="pl-s">-<span class="pl-s">ci-workflow</span></span>
RUN npm install

<span class="pl-c"># 開放 container 的 3000 port</span>
EXPOSE 3000
CMD npm start</pre>
</div>
<ol>
<li>使用 <code>docker build</code> 建構您的 image：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ docker build -t hello-ci-workflow <span class="pl-c1">.</span></pre>
</div>
<blockquote><p><code>-t hello-ci-workflow</code> 是 image 名稱。</p></blockquote>
<ol>
<li>使用 <code>docker run</code> 執行您的 image：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ docker run -p 3000:3000 -d hello-ci-workflow</pre>
</div>
<blockquote><p><code>-d</code> 在背景執行 node，可以使用 <code>docker logs</code> 看執行結果。</p></blockquote>
<ol>
<li>打開瀏覽器 <code>http://localhost:3000</code> 看結果：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d316f705f565f50574749492f56547055664f50796f67492f41414141414141416b65772f69576453534d2d453648592f73313630302f30312e706e671"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d316f705f565f50574749492f56547055664f50796f67492f41414141414141416b65772f69576453534d2d453648592f73313630302f30312e706e671" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d316f705f565f50574749492f56547055664f50796f67492f41414141414141416b65772f69576453534d2d453648592f73313630302f30312e706e67" width="250" height="70" /></a></p>
<blockquote><p>其實每一次都要 <code>build</code> 和 <code>run</code> 還蠻麻煩的，推薦可以試試 <a href="https://github.com/docker/compose">Docker Compose</a>，用起來有點像 <a href="https://www.vagrantup.com/">Vagrant</a>。</p></blockquote>
<h3><a id="user-content-在-circleci-測試-docker" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%9C%A8-circleci-%E6%B8%AC%E8%A9%A6-docker"></a>在 CircleCI 測試 Docker</h3>
<ol>
<li>修改 <code>circle.yml</code>：</li>
</ol>
<div class="highlight highlight-source-yaml">
<pre><span class="pl-c"># circle.yml</span>
<span class="pl-s"><span class="pl-ent">machine:</span></span>
  <span class="pl-c"># 環境改成 docker</span>
  <span class="pl-s"><span class="pl-ent">services:</span></span>
    <span class="pl-s">- <span class="pl-s">docker</span></span>

<span class="pl-s"><span class="pl-ent">dependencies:</span></span>
  <span class="pl-s"><span class="pl-ent">override:</span></span>
    <span class="pl-c"># 建構方式使用 docker build</span>
    <span class="pl-s">- <span class="pl-s">docker build -t hello-ci-workflow .</span></span>

<span class="pl-s"><span class="pl-ent">test:</span></span>
  <span class="pl-s"><span class="pl-ent">override:</span></span>
    <span class="pl-s">- <span class="pl-s">./node_modules/.bin/mocha</span></span>
    <span class="pl-c"># 使用 curl 測試 docker 是否有順利執行 node</span>
    <span class="pl-s">- <span class="pl-s">docker run -d -p 3000:3000 hello-ci-workflow; sleep 10</span></span>
    <span class="pl-s">- <span class="pl-s">curl --retry 10 --retry-delay 5 -v http://localhost:3000</span></span></pre>
</div>
<ol>
<li>Push 更新到 GitHub：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git add Dockerfile circle.yml
$ git commit -m <span class="pl-s"><span class="pl-pds">"</span>add Docker<span class="pl-pds">"</span></span>
$ git push</pre>
</div>
<ol>
<li>查看 CircleCI 建構＆測試結果：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d694264624c33546b4d624d2f565470556d6d4e4a6d31492f41414141414141416b68552f7473514d642d696b61776f2f73313630302f33302e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d694264624c33546b4d624d2f565470556d6d4e4a6d31492f41414141414141416b68552f7473514d642d696b61776f2f73313630302f33302e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d694264624c33546b4d624d2f565470556d6d4e4a6d31492f41414141414141416b68552f7473514d642d696b61776f2f73313630302f33302e706e6" width="498" height="806" /></a></p>
<h2><a id="user-content-aws-elastic-beanstalk" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#aws-elastic-beanstalk"></a>AWS Elastic Beanstalk</h2>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d784375514a6233395a32732f56547054317871345a5a492f41414141414141416b656b2f7452452d545f306d7950452f73313630302f6265616e7374616c6b2e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d784375514a6233395a32732f56547054317871345a5a492f41414141414141416b656b2f7452452d545f306d7950452f73313630302f6265616e7374616c6b2e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d784375514a6233395a32732f56547054317871345a5a492f41414141414141416b656b2f7452452d545f306d7950452f73313630302f6265616e7374616c6b2e706e6" width="300" height="80" /></a></p>
<blockquote><p>帳號：</p>
<ul>
<li><a href="https://aws.amazon.com/">Amazon Web Services</a></li>
</ul>
<p>安裝：</p>
<ul>
<li><a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli3-getting-set-up.html#eb_cli3-install-with-pip">AWS EB CLI</a>: 3.x</li>
</ul>
</blockquote>
<p>最後要將程式上線啦！現在 PaaS 雲端平台的選擇非常多（<a href="https://www.heroku.com/">Heroku</a>、<a href="https://cloud.google.com/appengine/">Google App Engine</a>、<a href="http://azure.microsoft.com/z">Azure</a>、<a href="https://www.openshift.com/">OpenShift</a>、<a href="https://www.linode.com/">Linode</a>），這裡我選擇 Amazon 推出的 Elastic Beanstalk 當作範例，以下是它的特色：</p>
<ul>
<li>支援的開發環境多（Java、.NET、PHP、Node.js、Python、Ruby、GO），重點是有支援 Docker！</li>
<li>只需要上傳程式碼，Elastic Beanstalk 即可幫你完成從容量配置、負載均衡（load balancing）、自動擴展（auto scaling）到應用程式的運行狀況監控的部署。</li>
</ul>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d455658386f4c4c753958772f565470634c776f385776492f41414141414141416b6b302f487a7555433277365562592f73313630302f6177732d65622e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d455658386f4c4c753958772f565470634c776f385776492f41414141414141416b6b302f487a7555433277365562592f73313630302f6177732d65622e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d455658386f4c4c753958772f565470634c776f385776492f41414141414141416b6b302f487a7555433277365562592f73313630302f6177732d65622e706e6" width="436" height="393" /></a></p>
<ol>
<li>初始化 EB 環境：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ eb init -p docker</pre>
</div>
<blockquote><p><code>-p</code> 可以指定 EB 的應用平台，例如 php 之類；這裡使用 docker。</p></blockquote>
<p>該命令將提示您配置各種設置。 按 Enter 鍵接受預設值。</p>
<blockquote><p>如果你已經存有一組 AWS EB 權限的憑證，該命令會自動使用它。 否則，它會提示您輸入 <code>Access key ID</code> 和 <code>Secret access key</code>，必須前往 AWS IAM 建立一組。</p></blockquote>
<ol>
<li>初始化成功之後，可以使用 <code>eb create</code> 快速建立各種不同的環境，例如：development, staging, production；這裡我們以 <code>env-development</code> 為例：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ eb create env-development</pre>
</div>
<p>等待 Elastic Beanstalk 完成環境的建立。 當它完成之後，您的應用已經備有負載均衡（load-balancing）與自動擴展（autoscaling）的功能了。</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d555743795f7342635776342f565470556d3276355946492f41414141414141416b68632f727362472d4d5f4958466f2f73313630302f33312e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d555743795f7342635776342f565470556d3276355946492f41414141414141416b68632f727362472d4d5f4958466f2f73313630302f33312e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d555743795f7342635776342f565470556d3276355946492f41414141414141416b68632f727362472d4d5f4958466f2f73313630302f33312e706e6" width="485" height="562" /></a></p>
<ol>
<li>使用 <code>eb open</code> 前往目前版本的執行結果：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ eb open env-development</pre>
</div>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d334631586d454e575230732f565470556e587a4e5835492f41414141414141416b68672f4b745671356a6e546c31512f73313630302f33322e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d334631586d454e575230732f565470556e587a4e5835492f41414141414141416b68672f4b745671356a6e546c31512f73313630302f33322e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d334631586d454e575230732f565470556e587a4e5835492f41414141414141416b68672f4b745671356a6e546c31512f73313630302f33322e706e6" width="475" height="70" /></a></p>
<h3><a id="user-content-在本地端部署-aws" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%9C%A8%E6%9C%AC%E5%9C%B0%E7%AB%AF%E9%83%A8%E7%BD%B2-aws"></a>在本地端部署 AWS</h3>
<ol>
<li>稍微修改 <code>index.js</code>：</li>
</ol>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// index.js</span>
<span class="pl-c">// ...</span>
<span class="pl-smi">app</span>.<span class="pl-en">get</span>(<span class="pl-s"><span class="pl-pds">'</span>/<span class="pl-pds">'</span></span>, <span class="pl-k">function</span> (<span class="pl-smi">req</span>, <span class="pl-smi">res</span>) {
  <span class="pl-smi">res</span>.<span class="pl-c1">send</span>(<span class="pl-s"><span class="pl-pds">'</span>Hello env-development!<span class="pl-pds">'</span></span>);
});
<span class="pl-c">// ...</span></pre>
</div>
<ol>
<li>執行 <code>eb deploy</code> 部署新版本到 AWS Elastic Beanstalk：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ eb deploy env-development</pre>
</div>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4f42364d644d6b6c7072672f5654705576712d597963492f41414141414141416b6b4d2f52426973343739336274632f73313630302f33342e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4f42364d644d6b6c7072672f5654705576712d597963492f41414141414141416b6b4d2f52426973343739336274632f73313630302f33342e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4f42364d644d6b6c7072672f5654705576712d597963492f41414141414141416b6b4d2f52426973343739336274632f73313630302f33342e706e6" width="341" height="190" /></a></p>
<ol>
<li>部署完成之後，執行 <code>eb open</code> 打開網頁：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ eb open env-development</pre>
</div>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d69636e30397167564961512f565470556e7a696a7364492f41414141414141416b68732f664b5541305048435a7a672f73313630302f33332e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d69636e30397167564961512f565470556e7a696a7364492f41414141414141416b68732f664b5541305048435a7a672f73313630302f33332e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d69636e30397167564961512f565470556e7a696a7364492f41414141414141416b68732f664b5541305048435a7a672f73313630302f33332e706e6" width="471" height="70" /></a></p>
<p><code>env-development</code> 上的應用程式更新完成。</p>
<h3><a id="user-content-在-circleci-部署-aws" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%9C%A8-circleci-%E9%83%A8%E7%BD%B2-aws"></a>在 CircleCI 部署 AWS</h3>
<ol>
<li><code>git checkout</code> 將分支切換回主線 master：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git checkout master</pre>
</div>
<ol>
<li><code>eb create</code> 新增一組新的環境，作為產品上線用，命名為 <code>env-production</code>：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ eb create env-production</pre>
</div>
<div class="highlight highlight-source-shell">
<pre>$ eb open env-production</pre>
</div>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d636e4f4e667977414d54512f565470556f664a36656a492f41414141414141416b68772f6d304173684841356e524d2f73313630302f33352e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d636e4f4e667977414d54512f565470556f664a36656a492f41414141414141416b68772f6d304173684841356e524d2f73313630302f33352e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d636e4f4e667977414d54512f565470556f664a36656a492f41414141414141416b68772f6d304173684841356e524d2f73313630302f33352e706e6" width="471" height="70" /></a></p>
<p>這樣就成功啟動第二組機器了，目前我們有 <code>env-development</code> 和 <code>env-production</code> 兩組環境。</p>
<h3><a id="user-content-前往-aws-iam-新增一組帳號給-circleci-使用" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%89%8D%E5%BE%80-aws-iam-%E6%96%B0%E5%A2%9E%E4%B8%80%E7%B5%84%E5%B8%B3%E8%99%9F%E7%B5%A6-circleci-%E4%BD%BF%E7%94%A8"></a>前往 <a href="https://console.aws.amazon.com/iam/home">AWS IAM</a> 新增一組帳號給 CircleCI 使用：</h3>
<ol>
<li><code>Dashboard</code> &gt; <code>Users</code></li>
<li><code>Create New Users</code></li>
<li>Enter User Names: <strong>CircleCI</strong> &gt; <code>Create</code></li>
<li><code>Download Credentials</code></li>
<li><code>Dashboard</code> &gt; <code>Users</code> &gt; <code>CircleCI</code></li>
<li><code>Attach Pollcy</code></li>
<li><code>AWSElasticBeanstalkFullAccess</code> &gt; <code>Attach Pollcy</code></li>
</ol>
<p>前往 CircleCI，設定您的 AWS 權限：</p>
<ol>
<li><code>Project Settings</code></li>
<li><code>Permissions</code> &gt; <code>AWS Permissions</code></li>
<li>打開剛才下載的 <code>credentials.csv</code>，輸入 <code>Access Key ID</code> &amp; <code>Secret Access Key</code></li>
<li><code>Save AWS keys</code></li>
<li>在 <code>.elasticbeanstalk</code> 目錄底下，建立 <code>config.global.yml</code>：</li>
</ol>
<div class="highlight highlight-source-yaml">
<pre><span class="pl-c"># .elasticbeanstalk/config.global.yml</span>
<span class="pl-s"><span class="pl-ent">global:</span></span>
  <span class="pl-s"><span class="pl-ent">application_name:</span> <span class="pl-s">hello-ci-workflow</span></span>
  <span class="pl-s"><span class="pl-ent">default_region:</span> <span class="pl-s">us-west-2 </span></span><span class="pl-c"># EB 所在的 region，預設是 us-west-2</span></pre>
</div>
<ol>
<li>修改 <code>circle.yml</code>：</li>
</ol>
<div class="highlight highlight-source-yaml">
<pre><span class="pl-c"># circle.yml</span>
<span class="pl-s"><span class="pl-ent">machine:</span></span>
  <span class="pl-c"># 安裝 eb 需要 python</span>
  <span class="pl-s"><span class="pl-ent">python:</span></span>
    <span class="pl-c1"><span class="pl-ent">version:</span> 2.7</span>
  <span class="pl-s"><span class="pl-ent">services:</span></span>
    <span class="pl-s">- <span class="pl-s">docker</span></span>

<span class="pl-s"><span class="pl-ent">dependencies:</span></span>
  <span class="pl-s"><span class="pl-ent">pre:</span></span>
    <span class="pl-c"># 安裝 eb</span>
    <span class="pl-s">- <span class="pl-s">sudo pip install awsebcli</span></span>
  <span class="pl-s"><span class="pl-ent">override:</span></span>
    <span class="pl-s">- <span class="pl-s">docker build -t hello-ci-workflow .</span></span>

<span class="pl-s"><span class="pl-ent">test:</span></span>
  <span class="pl-s"><span class="pl-ent">override:</span></span>
    <span class="pl-s">- <span class="pl-s">npm test</span></span>
    <span class="pl-s">- <span class="pl-s">docker run -d -p 3000:3000 hello-ci-workflow; sleep 10</span></span>
    <span class="pl-s">- <span class="pl-s">curl --retry 10 --retry-delay 5 -v http://localhost:3000</span></span>

<span class="pl-c"># 新增一筆部署腳本</span>
<span class="pl-s"><span class="pl-ent">deployment:</span></span>
  <span class="pl-s"><span class="pl-ent">production:</span></span>
    <span class="pl-s"><span class="pl-ent">branch:</span> <span class="pl-s">master</span></span>
    <span class="pl-s"><span class="pl-ent">commands:</span></span>
      <span class="pl-s">- <span class="pl-s">eb deploy env-production</span></span></pre>
</div>
<p>這樣就能在 GitHub 的 master 支線有更新時，觸發 CircleCI 的自動建置、測試、然後部署。</p>
<ol>
<li>接下來馬上來試試看流程，修改 <code>index.js</code>：</li>
</ol>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// index.js</span>
<span class="pl-c">// ...</span>
<span class="pl-smi">app</span>.<span class="pl-en">get</span>(<span class="pl-s"><span class="pl-pds">'</span>/<span class="pl-pds">'</span></span>, <span class="pl-k">function</span> (<span class="pl-smi">req</span>, <span class="pl-smi">res</span>) {
  <span class="pl-smi">res</span>.<span class="pl-c1">send</span>(<span class="pl-s"><span class="pl-pds">'</span>Hello env-production!<span class="pl-pds">'</span></span>);
});
<span class="pl-c">// ...</span></pre>
</div>
<ol>
<li>Commit &amp; Push：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git add <span class="pl-c1">.</span>
$ git cimmit <span class="pl-s"><span class="pl-pds">"</span>test deploy production<span class="pl-pds">"</span></span>
$ git push</pre>
</div>
<ol>
<li>前往 CircleCI 看結果：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d333156596e4b726e5a5f672f565470556f6879575442492f41414141414141416b68342f70696f43374162314765732f73313630302f33362e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d333156596e4b726e5a5f672f565470556f6879575442492f41414141414141416b68342f70696f43374162314765732f73313630302f33362e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d333156596e4b726e5a5f672f565470556f6879575442492f41414141414141416b68342f70696f43374162314765732f73313630302f33362e706e6" width="615" height="390" /></a></p>
<ol>
<li>部署成功，<code>eb open</code> 打開瀏覽器來看看結果：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ eb open env-production</pre>
</div>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d456f705179646e757872552f565470556f2d72597873492f41414141414141416b68382f584137736b506b744151412f73313630302f33372e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d456f705179646e757872552f565470556f2d72597873492f41414141414141416b68382f584137736b506b744151412f73313630302f33372e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d456f705179646e757872552f565470556f2d72597873492f41414141414141416b68382f584137736b506b744151412f73313630302f33372e706e6" width="471" height="70" /></a></p>
<h2><a id="user-content-slack" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#slack"></a>Slack</h2>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d61367938543547665330492f5654705176365370615f492f41414141414141416b63672f567242693661527a366a632f73313630302f736c61636b2e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d61367938543547665330492f5654705176365370615f492f41414141414141416b63672f567242693661527a366a632f73313630302f736c61636b2e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d61367938543547665330492f5654705176365370615f492f41414141414141416b63672f567242693661527a366a632f73313630302f736c61636b2e706e6" width="200" height="80" /></a></p>
<blockquote><p>帳號：</p>
<ul>
<li><a href="https://slack.com/">Slack</a></li>
</ul>
</blockquote>
<p>到這邊其實已經差不多結束了，最後來講講 Slack 吧。</p>
<p>Slack 是一款給團隊使用的即時溝通工具，類似的產品還有 <a href="https://gitter.im/">Gitter</a> 與 <a href="https://www.hipchat.com/">HipChat</a>。</p>
<p>至於跟 Skype、Lync 這些軟體有什麼不一樣的地方呢？</p>
<p>它們整合了許多開發工具（GitHub、CircleCI）的服務，例如 GitHub 有新的 push、pull request、issue；CircleCI 的單元測試沒有通過之類的通知，會即時出現在你的團隊的 Slack 上面，既然我們已經將大部分的工作自動化，勢必需要讓相關人員知道這些工具發生了哪些事情，所以使用 Slack 是必要的。</p>
<ol>
<li>登入 Slack 頁面</li>
<li>點選 <code>Configure Integrations</code> &gt; <code>CircleCI</code></li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d64555f5549556e757231412f56547055705245614c4c492f41414141414141416b69492f67613447547853786b36512f73313630302f33382e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d64555f5549556e757231412f56547055705245614c4c492f41414141414141416b69492f67613447547853786b36512f73313630302f33382e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d64555f5549556e757231412f56547055705245614c4c492f41414141414141416b69492f67613447547853786b36512f73313630302f33382e706e6" width="300" height="365" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d3148714b4a69353056514d2f565470557056335f504d492f41414141414141416b694d2f665a706d35567a48396f4d2f73313630302f33392e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d3148714b4a69353056514d2f565470557056335f504d492f41414141414141416b694d2f665a706d35567a48396f4d2f73313630302f33392e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d3148714b4a69353056514d2f565470557056335f504d492f41414141414141416b694d2f665a706d35567a48396f4d2f73313630302f33392e706e6" width="550" height="75" /></a></p>
<ol>
<li>選擇要接收 CircleCI 通知的 channel</li>
<li>點選 <code>Add CircleCI Integration</code> 按鈕</li>
<li>複製畫面上的 <code>webhook URL</code></li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d764f74756f31593048346b2f5654705571466e7a5177492f41414141414141416b69552f7478366739686f4a6778732f73313630302f34302e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d764f74756f31593048346b2f5654705571466e7a5177492f41414141414141416b69552f7478366739686f4a6778732f73313630302f34302e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d764f74756f31593048346b2f5654705571466e7a5177492f41414141414141416b69552f7478366739686f4a6778732f73313630302f34302e706e6" width="602" height="196" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d63567852614c2d76434f672f5654705572666e4a3354492f41414141414141416b69772f5a796f324762307a79306f2f73313630302f34342e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d63567852614c2d76434f672f5654705572666e4a3354492f41414141414141416b69772f5a796f324762307a79306f2f73313630302f34342e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d63567852614c2d76434f672f5654705572666e4a3354492f41414141414141416b69772f5a796f324762307a79306f2f73313630302f34342e706e6" width="654" height="78" /></a></p>
<ol>
<li>返回 CircleCI</li>
<li>點選 <code>Project settings</code> &gt; <code>Chat Notifications</code></li>
<li>貼上將複製的 <code>Webhook URL</code> &gt; <code>Save</code></li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d4d34304773505f696b39512f56547055714f41516c67492f41414141414141416b69592f31556f54417573534279342f73313630302f34312e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d4d34304773505f696b39512f56547055714f41516c67492f41414141414141416b69592f31556f54417573534279342f73313630302f34312e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d4d34304773505f696b39512f56547055714f41516c67492f41414141414141416b69592f31556f54417573534279342f73313630302f34312e706e6" width="207" height="49" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d70416e74524e30694252632f565470557171504a6479492f41414141414141416b69732f496e517278586c4a436d302f73313630302f34322e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d70416e74524e30694252632f565470557171504a6479492f41414141414141416b69732f496e517278586c4a436d302f73313630302f34322e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d70416e74524e30694252632f565470557171504a6479492f41414141414141416b69732f496e517278586c4a436d302f73313630302f34322e706e6" width="220" height="65" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d76337161332d786b3341512f565470557139364f6952492f41414141414141416b696b2f635139436759396c3058772f73313630302f34332e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d76337161332d786b3341512f565470557139364f6952492f41414141414141416b696b2f635139436759396c3058772f73313630302f34332e706e67" alt="687474703a2f2f322e62702e626c6f6773706f742e636f6d2f2d76337161332d786b3341512f565470557139364f6952492f41414141414141416b696b2f635139436759396c3058772f73313630302f34332e706e6" width="300" height="445" /></a></p>
<ol>
<li>類似的步驟，將 GitHub 的通知加入 Slack：</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d5a426d55686a595535586f2f565470557277546e3758492f41414141414141416b6a452f6b617837544264465668412f73313630302f34352e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d5a426d55686a595535586f2f565470557277546e3758492f41414141414141416b6a452f6b617837544264465668412f73313630302f34352e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d5a426d55686a595535586f2f565470557277546e3758492f41414141414141416b6a452f6b617837544264465668412f73313630302f34352e706e6" width="551" height="71" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d6f79475a51765442484c382f56547055723879697935492f41414141414141416b69382f6d595f525561547266706b2f73313630302f34362e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d6f79475a51765442484c382f56547055723879697935492f41414141414141416b69382f6d595f525561547266706b2f73313630302f34362e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d6f79475a51765442484c382f56547055723879697935492f41414141414141416b69382f6d595f525561547266706b2f73313630302f34362e706e6" width="290" height="160" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d706a6d686a6347656268512f5654705573556f547877492f41414141414141416b6a492f30516f6671664e6b5566342f73313630302f34372e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d706a6d686a6347656268512f5654705573556f547877492f41414141414141416b6a492f30516f6671664e6b5566342f73313630302f34372e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d706a6d686a6347656268512f5654705573556f547877492f41414141414141416b6a492f30516f6671664e6b5566342f73313630302f34372e706e6" width="751" height="77" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d315451324558564556764d2f56547055733254327576492f41414141414141416b6a512f526e3561567359665553412f73313630302f34382e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d315451324558564556764d2f56547055733254327576492f41414141414141416b6a512f526e3561567359665553412f73313630302f34382e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d315451324558564556764d2f56547055733254327576492f41414141414141416b6a512f526e3561567359665553412f73313630302f34382e706e6" width="230" height="155" /></a></p>
<ol>
<li>測試 Slack 通知，是否能夠順利運作，新增一條 <code>test-slack</code> 分支：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git branch test-slack
$ git checkout test-slack</pre>
</div>
<ol>
<li>修改 <code>index.js</code>：</li>
</ol>
<div class="highlight highlight-source-js">
<pre><span class="pl-c">// index.js</span>
<span class="pl-c">// ...</span>
<span class="pl-smi">app</span>.<span class="pl-en">get</span>(<span class="pl-s"><span class="pl-pds">'</span>/<span class="pl-pds">'</span></span>, <span class="pl-k">function</span> (<span class="pl-smi">req</span>, <span class="pl-smi">res</span>) {
  <span class="pl-smi">res</span>.<span class="pl-c1">send</span>(<span class="pl-s"><span class="pl-pds">'</span>Hello Slack!<span class="pl-pds">'</span></span>);
});
<span class="pl-c">// ...</span></pre>
</div>
<ol>
<li>Commit &amp; Push：</li>
</ol>
<div class="highlight highlight-source-shell">
<pre>$ git add index.js
$ git commit -m <span class="pl-s"><span class="pl-pds">"</span>index.js: update to test slack<span class="pl-pds">"</span></span>
$ git push -u origin test-slack</pre>
</div>
<ol>
<li>CircleCI 通過測試，開啟一個 Pull Request</li>
<li>將 <code>test-slack</code> merge 回 <code>master</code>，觸發 CircleCI 自動部署</li>
</ol>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d795a376f566f6854426f452f56547055745a6936506e492f41414141414141416b6a672f47345f4464567465444b672f73313630302f35302e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d795a376f566f6854426f452f56547055745a6936506e492f41414141414141416b6a672f47345f4464567465444b672f73313630302f35302e706e67" alt="687474703a2f2f342e62702e626c6f6773706f742e636f6d2f2d795a376f566f6854426f452f56547055745a6936506e492f41414141414141416b6a672f47345f4464567465444b672f73313630302f35302e706e6" width="515" height="475" /></a></p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d43376b5051362d5a376b6f2f56547055743855494d46492f41414141414141416b6a6f2f4a66724a4232554c45486f2f73313630302f35312e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d43376b5051362d5a376b6f2f56547055743855494d46492f41414141414141416b6a6f2f4a66724a4232554c45486f2f73313630302f35312e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d43376b5051362d5a376b6f2f56547055743855494d46492f41414141414141416b6a6f2f4a66724a4232554c45486f2f73313630302f35312e706e6" width="615" height="45" /></a></p>
<p>That’s it! On your next build, you’ll start seeing CircleCI build notifications in your Slack chatroom.</p>
<p>結束！可以看見 Slack channel 會顯示每一個步驟的通知過程：</p>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4e71796a57466f317245452f56547055744578583343492f41414141414141416b6a592f47537943665037777735732f73313630302f34392e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4e71796a57466f317245452f56547055744578583343492f41414141414141416b6a592f47537943665037777735732f73313630302f34392e706e67" alt="687474703a2f2f332e62702e626c6f6773706f742e636f6d2f2d4e71796a57466f317245452f56547055744578583343492f41414141414141416b6a592f47537943665037777735732f73313630302f34392e706e6" width="450" height="580" /></a></p>
<p><code>eb open</code> 打開瀏覽器查看結果，成功自動部署新版本：</p>
<div class="highlight highlight-source-shell">
<pre>$ eb open env-production</pre>
</div>
<p><a href="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d654a7367563843654430342f565470557544466c7237492f41414141414141416b6a732f666131785759656b7849732f73313630302f35322e706e67"><img class="attachment-medium" src="https://www.fuwuqiok.com/wp-content/uploads/2016/03/687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d654a7367563843654430342f565470557544466c7237492f41414141414141416b6a732f666131785759656b7849732f73313630302f35322e706e67" alt="687474703a2f2f312e62702e626c6f6773706f742e636f6d2f2d654a7367563843654430342f565470557544466c7237492f41414141414141416b6a732f666131785759656b7849732f73313630302f35322e706e6" width="471" height="65" /></a></p>
<h2><a id="user-content-結語" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E7%B5%90%E8%AA%9E"></a>結語</h2>
<blockquote><p>「書山有路勤為徑，學海無涯苦作舟。」——韓愈</p></blockquote>
<p>DevOps 的開發流程與工具每天都在不斷推陳出新，請站在巨人的肩膀上、保持一顆「活到老、學到老」的心。</p>
<p>我將這個範例的程式碼放在 <a href="https://github.com/amowu/hello-ci-workflow">GitHub</a> 上，有興趣的人可以參考看看。</p>
<p>文章若有需要改進的地方，還請不吝指教，感激不盡。</p>
<h2><a id="user-content-參考" class="anchor" href="https://github.com/zeus911/hello-ci-workflow#%E5%8F%83%E8%80%83"></a>參考</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/DevOps">DevOps &#8211; Wikipedia</a> [<a href="https://zh.wikipedia.org/zh/DevOps">中文</a>]</li>
<li><a href="https://en.wikipedia.org/wiki/Continuous_integration">Continuous integration（持續整合）- Wikipedia</a> [<a href="https://zh.wikipedia.org/wiki/%E6%8C%81%E7%BA%8C%E6%95%B4%E5%90%88">中文</a>]</li>
<li><a href="https://en.wikipedia.org/wiki/Continuous_delivery">Continuous delivery（持續交付）- Wikipedia</a></li>
<li><a href="http://blog.eavatar.com/post/2013/10/continuous-integration-deployment-delivery/">山姆鍋對持續整合、持續部署、持續交付的定義</a></li>
<li><a href="http://rettamkrad.blogspot.tw/2014/11/integrate-circleci-with-github.html">Integrate CircleCI with GitHub</a></li>
<li><a href="https://guides.github.com/introduction/flow/">Understanding the GitHub Flow · GitHub Guides</a></li>
<li><a href="https://docs.docker.com/examples/nodejs_web_app">Dockerizing a Node.js Web App</a></li>
<li><a href="https://circleci.com/integrations/docker">Integration with Docker Containers &#8211; CircleCI</a></li>
<li><a href="https://circleci.com/docs/docker">Continuous Integration and Delivery with Docker</a></li>
<li><a href="http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/eb-cli3-getting-started.html">Getting Started with EB CLI 3.x</a></li>
<li><a href="http://blog.circleci.com/slack-integration/">Slack Integration | The Circle Blog</a></li>
<li><a href="https://realpython.com/blog/python/docker-in-action-fitter-happier-more-productive/">Docker in Action &#8211; Fitter, Happier, More Productive</a> [<a href="http://segmentfault.com/a/1190000002598713">中文</a>]</li>
<li><a href="http://qiita.com/sawanoboly/items/28e98827bc044abdc32f">CircleCIからAWS Elastic Beanstalkにpush</a></li>
<li><a href="http://waytothepiratecove.blogspot.tw/2015/03/delivery-pipeline-and-zero-downtime.html">Delivery pipeline and zero downtime release</a></li>
<li><a href="http://sauceio.com/index.php/2014/12/ci-cd-with-docker-beanstalk-circleci-slack-gantree/">Re-Blog: CI &amp; CD With Docker, Beanstalk, CircleCI, Slack, &amp; Gantree</a></li>
<li><a href="http://mherman.org/blog/2015/03/06/node-with-docker-continuous-integration-and-delivery">Node With Docker &#8211; Continuous Integration and Delivery</a></li>
<li><a href="http://www.infoq.com/cn/articles/docker-integrated-test-and-deployment">深入浅出Docker（四）：Docker的集成测试部署之道</a></li>
</ul>
<p><a rel="nofollow" href="https://www.fuwuqiok.com/%e4%bd%bf%e7%94%a8-docker%e3%80%81github-flow%e3%80%81circleci%e3%80%81aws-elastic-beanstalk-%e8%88%87-slack-%e4%be%86%e5%ae%8c%e6%88%90%e6%8c%81%e7%ba%8c%e6%95%b4%e5%90%88%e8%88%87%e6%8c%81%e7%ba%8c/">使用 Docker、GitHub Flow、CircleCI、AWS Elastic Beanstalk 與 Slack 來完成持續整合與持續交付的開發流程</a>，首发于<a rel="nofollow" href="https://www.fuwuqiok.com">服务器安全维护工作室</a>。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.fuwuqiok.com/%e4%bd%bf%e7%94%a8-docker%e3%80%81github-flow%e3%80%81circleci%e3%80%81aws-elastic-beanstalk-%e8%88%87-slack-%e4%be%86%e5%ae%8c%e6%88%90%e6%8c%81%e7%ba%8c%e6%95%b4%e5%90%88%e8%88%87%e6%8c%81%e7%ba%8c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
