通过前两篇文章《持续集成与持续部署宝典Part 1:将构建环境容器化》和《持续集成与持续部署宝典Part 2:创建持续集成流水线》,我们使用 Docker 创建了一个集中管理的构建环境,它可以应用到任意数量的机器上。接着,我们将环境设置到了 Jenkins CI 上,自动化处理了源代码的持续构建、打包和测试。在本章中,我们将进一步对流水线进行研究(如下所示),了解如何将项目持续部署到一个长时间运行的测试环境中。除了自动验收测试外,它还将允许人工测试代码。有了这样的环境,你就可以在产品投入生产之前让你的客户或者 QA(质量管理员)看到最新的变化。此外,它还是一个构建和部署到生产环境的好方法,我们将这一章中进行介绍。
创建应用程序环境
在我们构建并且测试了应用程序后,可以将它部署到一个长期运行的、潜在面向外部的环境中。这种环境要允许客户或者 QA 在产品投入生产前查看和测试最新的更改,它也是生产过程中一个重要步骤。有了它,我们能够发现在自动化集成测试中会隐藏起来、只有在真实环境才能发现的 bug。我们通常把这样的环境称为 QA 或集成环境,当然你也可以自己命名。我们将通过以下步骤来创建集成环境:
在 Rancher 中创建一个集成环境
定义 Docker Compose 以及 Rancher Compose 模板
用 Rancher 创建应用程序堆栈
用 Rancher 和 AWS Route53 管理 DNS 记录
添加对 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。
评论