通过前两篇文章《持续集成与持续部署宝典Part 1:将构建环境容器化》和《持续集成与持续部署宝典Part 2:创建持续集成流水线》,我们使用Docker创建了一个集中管理的构建环境,它可以应用到任意数量的机器上。接着,我们将环境设置到了Jenkins CI上,自动化处理了源代码的持续构建、打包和测试。在本章中,我们将进一步对流水线进行研究(如下所示),了解如何将项目持续部署到一个长时间运行的测试环境中。除了自动验收测试外,它还将允许人工测试代码。有了这样的环境,你就可以在产品投入生产之前让你的客户或者QA(质量管理员)看到最新的变化。此外,它还是一个构建和部署到生产环境的好方法,我们将这一章中进行介绍。
创建应用程序环境
在我们构建并且测试了应用程序后,可以将它部署到一个长期运行的、潜在面向外部的环境中。这种环境要允许客户或者QA在产品投入生产前查看和测试最新的更改,它也是生产过程中一个重要步骤。有了它,我们能够发现在自动化集成测试中会隐藏起来、只有在真实环境才能发现的bug。我们通常把这样的环境称为QA或集成环境,当然你也可以自己命名。我们将通过以下步骤来创建集成环境:
1. 在Rancher中创建一个集成环境
2. 定义Docker Compose以及Rancher Compose模板
3. 用Rancher创建应用程序堆栈
4. 用Rancher和AWS Route53管理DNS记录
5. 添加对HTTPS的支持
在Rancher中创建一个集成环境
在Rancher UI中,在左上角选择Manage Environments 以及 Add Environment,会出现下面屏幕显示的内容,添加Name(Integration),给每个环境添加一定的描述。你还需要选择有权访问环境的用户和组织清单。
在环境设置好后,在屏幕左上角的下拉菜单中选择Integration(集成)环境。现在我们可以为集成环境创建应用程序堆栈了。在这之前,我们先了解一下Rancher部署的API密钥。从顶部菜单中选择API > Key,接着Add Account API Key。会出现一个弹出式屏幕,在这里你可以创建一个命名的API密钥对。在后续步骤中我们需要使用到Rancher Compose创建测试环境。我们将创建名为JenkinsKey的密钥对,由Jenkins实例运行Rancher Compose。记得要留下密钥(access key)和密码(secret key)以备后用,之后不会再显示这些值了。请注意,API密钥匙是针对于特定环境的,因此需要为每个环境创建一个新密钥。
定义Compose模板
在上篇文章中,我们创建了一个Docker Compose模板定义我们的项目所需的容器类型。Compose模板(docker-compose.yml)如下图所示。现在我们将使用与之前相同的Docker Compose模板,不过增加了auth-lb服务。这会在我们的go-auth服务前添加一个负载均衡器,并将所有运行该服务的容器的流量分开。在服务前添加一个负载均衡器对于确保可用性和扩展性来说至关重要,因为即使一个(或多个)服务容器死亡,它依然能够提供流量。另外,它还能将负载扩展到多个容器上,这些容器可能在多个主机上运行。我在本文中使用的Rancher旧版本不支持3版本的compose文件,因此我们必须要设置版本为2,删除错误的环境变量,修正go-auth的版本。
我们在多主机环境中使用的是Rancher Compose启动环境,这样更贴近生产环境,允许我们测试和各种服务的集成,例如Rancher和Docker Hub等等。和我们之前不同,我们以前基于Docker Compose的环境是明确设计成独立于外部服务,在CI服务器本身上启动的,无需将镜像推送到dockerhub。
现在我们使用Rancher Compose启动一个多主机测试环境来代替Docker Compose,我们还需要定义一个rancher compose模板。创建一个叫做rancher-compose.yml的文件,添加以下内容。在这个文件中,我们定义了两个需要用到auth-service的容器、一个运行数据库的容器以及另一个运行负载均衡器的容器。
接下来我们将向auth-service中添加一个健康检查(health check),确保我们可以检测到容器何时启动以及能够响应请求。为此,我们使用go-auth服务的/health URI。rancher-compose.yml的auth-service部分现在应该是这样的:
我们现在给每2秒(2000毫秒)运行的服务容器的9000端口定义一个健康检查。该检查会向/health URL发出http请求,连续3次检查失败会将容器标记为不健康,而2次成功则标记为健康。
同样,我们需要将lb_config部分添加到负载均衡器rancher-compose.yml文件中,让它知道针对哪个服务(GoAuth),需要公开哪些端口,以及如何验证负载均衡器之后实例的健康情况。rancher-compose.yml文件的auth-lb部分应该如下所示:
用Rancher CLI创建一个应用程序堆栈
现在我们定义好了模板,就可以使用Rancher Compose来启动我们的环境了。接下来,只需要检出go-message项目并从Rancher UI中下载Rancher CLI即可。关于如何在开发机器上设置rancher-compose,可以参考这里的说明:
https://rancher.com/docs/rancher/v1.5/en/cattle/rancher-compose/。运行 ./rancher config为接下来的命令指定rancher url、access key、secret key和默认环境。
在Rancher CLI设置好后,你可以使用下面的创建命令来设置你的集成环境。这里的命令是假设docker-compose.yml和rancher-compose.yml文件是在当前目录下的。
在UI中,你现在应该能够看到你的项目的堆栈和服务了。注意,create命令在创建堆栈的同时还会启动所有的服务。
要确保一切正常,找到运行“authlb”服务的主机的公共IP,使用下面的命令创建一个用户。你应该会得到200 OK的回复,而重复上述请求会返回409错误,提示与数据库现有用户出现冲突。到这为止,我们就为应用程序提供了一个基本的集成环境,这也是一个长期运行的环境。
管理DNS记录
现在这个环境是需要长期运行并且对外开放的,我们将会使用DNS条目以及HTTPS。这样我们能够安全地在企业防火钱之外分发应用程序,并允许更多的临时用户依赖持久的DNS而不是可能会改变的IPs。你可以使用你所选择的DNS提供者。而我们在这里将演示如何在Amazon Route53中设置DNS条目。进入到AWS Console > Route53 > Hosted Zones,选择Create Hosted Zone。在hosted zone(托管区域)中,你需要指定你选择的域名(比如gomessenger.com)。当你在AWS Console中时,你还可以为Rancher创建用户进行Route53的更新。转到AWS Console > IAMS > Users,选择Create New Users。记住用户的Access Key和Secret Key,之后我们还会使用到。在用户创建后,你需要将AmazonRoute53FullAccess策略添加到用户中,这样它就可以对route53进行更新。
现在我们已经有了Hosted Zone以及IAMs用户设置,我们可以将Route53集成添加到我们的 Rancher Server(rancher服务器)。有关如何操作的详细说明可以在这里找到:https://rancher.com/introducing-rancher-service-discovery-integration-with-amazon-route53/。简而言之,你需要在rancher服务器上浏览Catalog > Library并选择Route 53 DNS。系统会要求你指定之前设置的Hosted Zone,以及具有Route53访问权限的Rancher IAMs用户的AWS Access和Secret Keys。输入信息并且单击创建后,你应该能看到在你的环境中有一个包含route53服务的新堆栈。
该服务会监听Rancher事件,捕获任何任何负载均衡器实例的启动和终止。有了这些信息,它将自动为所有运行负载均衡器容器的主机创建DNS条目。DNS条目的格式是[Loadbalancer].[stack].[env].[domain],比如:
goauth.integration.testing.gomessenger.com.
随着越来越多的容器在各个Rancher计算节点上启动与关闭,Route53服务将保持DNS记录的一致性。这对我们的集成测试环境来说至关重要,我们稍后就会看到它的重要性。我们需要重新启动环境容器来,以便将更新作为持续部署的一部分。通过使用Route53 DNS集成,我们不必再为给我们的客户和测试人员获取最新主机名而担心了。
启用HTTPS
在为我们的环境创建DNS记录后,让它支持HTTPS协议会是一个不错的选择。首先,我们需要拿到我们域名的SSL证书。你可以从很多可信任的证书颁发机构中选择一个购买域名的SSL证书。如果你没有证书,可以生成自签名(self-signed)证书来完成设置,在一段时间后把它更换成可信任的证书。自签名证书的含义是:任何用户都会在浏览器中看到“此连接不可信”的警告,但通信仍然是加密的。那么要生成自签名证书,首先需要生成ssl密钥,它可以由openssl的genrsa命令实现。然后你可以用这个密钥文件,使用req命令生成证书。下面列出了这一步骤。你也可以将证书的sha256指纹打印并储存下来,这样就手动地保证了在发出HTTPS请求时向你显示相同的证书。在缺少可信证书的情况下,手动匹配指纹是避免中间人×××的唯一方法。
现在你已经拥有了证书和私钥文件,下面需要讲这些文件上传到Rancher中。我们可以在Rancher UI的Infrastructure选项卡,单击Certificates部分的Add Certificate按钮上传证书。你还需要给你的证书起一个有意义的名称,填写描述。接着分别在Private Key和Certificate字段复制粘贴integration.gomessenger.com.key和integration.gomessenger.com.crt的内容(或者选择Read from File从文件读取)。在完成了表单后,点击保存,等待片刻证书便生效了。
证书激活之后,我们可以将HTTPS端点添加到我们的环境中。想要做到这一点,我们必须修改rancher-compose文件,让它包含SSL端口配置。我们将第二个端口(9001)添加到ports部分,让我们的环境可以在负载均衡器之外访问,并且使用io.rancher.loadbalancer.ssl.ports标签指定'9001'是具有SSL终止的公共负载均衡器端口。
此外,因为我们在负载均衡器处终止了SSL,我们可以使用原9000端口上的常规HTTP将请求发送到我们的实际服务容器中。我们使用了io.rancher.loadbalancer.target.auth-service标签来指定从9001到9000的映射。
我们还需要更新rancher-compose文件指定SSL证书,该证书是我们在负载均衡器服务中针对SSL终止要使用的。将我们之前上传的证书名称添加到default_cert上。有了这些更改,你还需要删除并重新创建堆栈,这是因为目前还没有办法将这些属性添加到已有的堆栈上。
现在可以使用curl命令确保一切正常了。当你使用https协议说明符和9001端口尝试相同的命令时,应该会看到一个failure,说你使用了一个不受信任的证书。你可以使用--insecure开关关闭可信证书检查,并且在没有证书的情况下使用https。
总结
在本文中,我们开始了持续部署流水线的创建,并且完成了第一部分的重要工作——创建应用程序环境,内容包含在Rancher中创建一个集成环境、定义Compose模板、用Rancher CLI创建一个应用程序堆栈、管理DNS记录、启用HTTPS。
下篇文章将是本系列文章的最后一篇,完成创建持续部署流水线的最后工作,敬请期待!