英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

Kubernetes 是在集群生产环境中运行 Docker 容器的绝佳工具。 然而,也有一些问题是 Kubernetes 无法解决的。 对于频繁的生产部署,我们需要完全自动化的蓝/绿部署以避免过程中的停机,这还需要处理外部 HTTP 请求并执行 SSL 卸载。 这需要与负载均衡器(例如 ha-proxy)集成。 另一个挑战是在云环境中运行时 Kubernetes 集群本身的半自动扩展,例如在夜间部分缩小集群。

虽然 Kubernetes 不具备这些开箱即用的功能,但它确实提供了一个可用于解决类似问题的 API。 用于自动蓝/绿部署和扩展 Kubernetes 集群的工具是作为 Cloud RTI 项目的一部分开发的,该项目是基于开源创建的。

本文是一个视频脚本,向您展示如何设置 Kubernetes 以及其他开源组件,以创建一个生产就绪环境,该环境接受来自 git 提交的代码,而无需在生产中停机。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第1部分

因此,一旦您可以从外部世界访问您的应用程序,您就可以开始完全设置自动化,也就是说,将其带到可以执行 git 提交并确保此 git 提交最终进入生产的阶段。 当然,在实施这些步骤、实施部署时,我们不希望遇到停机。 因此,Kubernetes 中的任何自动化都是从 API 开始的。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

Kubernetes 并不是一个可以立即高效使用的工具。 当然,你可以这样做,使用 kubectl 等,但 API 仍然是这个平台最有趣和有用的东西。 通过使用 API 作为一组函数,您几乎可以在 Kubernetes 中访问您想要执行的任何操作。 kubectl 本身也使用 REST API。

这是 REST,因此您可以使用任何语言或工具来使用此 API,但自定义库将使您的生活变得更加轻松。 我的团队编写了 2 个这样的库:一个用于 Java/OSGi,一个用于 Go。 第二个不经常使用,但无论如何你都可以使用这些有用的东西。 它们是一个部分许可的开源项目。 对于不同的语言有很多这样的库,因此您可以选择最适合您的库。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

因此,在开始自动化部署之前,您需要确保该过程不会出现任何停机时间。 例如,我们的团队在中午进行生产部署,此时人们最常使用应用程序,因此避免此过程中的延迟非常重要。 为了避免停机,使用了两种方法:蓝/绿部署或滚动更新。 在后一种情况下,如果您有 2 个正在运行的应用程序副本,它们将依次按顺序更新。 此方法效果很好,但如果在部署过程中同时运行不同版本的应用程序,则不适合。 在这种情况下,您可以在后端运行旧版本时更新用户界面,应用程序将停止工作。 因此,从编程的角度来看,在这样的条件下工作是相当困难的。

这就是我们更喜欢使用蓝/绿部署来自动化应用程序部署的原因之一。 使用此方法,您必须确保一次只有一个版本的应用程序处于活动状态。

蓝/绿部署机制如下所示。 我们通过 ha-proxy 接收应用程序的流量,该流量将其转发到同一版本应用程序的正在运行的副本。

当进行新的部署时,我们使用 Deployer,它会获得新组件并部署新版本。 部署应用程序的新版本意味着“引发”一组新的副本,之后这些新版本的副本将在单独的新 Pod 中启动。 然而,ha-proxy 对它们一无所知,也不会向它们路由任何工作负载。

因此,首先需要对新版本的健康检查进行性能检查,以确保副本已准备好为负载提供服务。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

所有部署组件都必须支持某种形式的运行状况检查。 这可以是非常简单的 HTTP 调用检查(当您收到状态 200 的代码时),也可以是更深入的检查(检查副本与数据库和其他服务的连接、动态环境连接的稳定性) ,以及一切是否正常启动和工作。 这个过程可能相当复杂。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

系统验证所有更新的副本都正常工作后,Deployer将更新配置并传递正确的confd,这将重新配置ha-proxy。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

只有在此之后,流量才会被定向到具有新版本副本的 Pod,并且旧 Pod 将会消失。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

这种机制不是 Kubernetes 的特性。 蓝/绿部署的概念已经存在了相当长的时间,并且它始终使用负载均衡器。 首先,您将所有流量引导到旧版本的应用程序,更新后,您将其完全转移到新版本。 这个原则不仅用在 Kubernetes 中。

现在我将向您介绍一个新的部署组件——Deployer,它执行健康检查、重新配置代理等。 这是一个不适用于外界的概念,存在于 Kubernetes 内部。 我将向您展示如何使用开源工具创建您自己的部署程序概念。

因此,Deployer 做的第一件事就是使用 Kubernetes API 创建一个 RC 复制控制器。 该 API 创建 pod 和服务以供进一步部署,即为我们的应用程序创建一个全新的集群。 一旦 RC 确信副本已启动,它将对其功能执行运行状况检查。 为此,Deployer 使用 GET /health 命令。 它运行适当的扫描组件并检查支持集群操作的所有元素。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

在所有 pod 报告其运行状况后,Deployer 会创建一个新的配置元素 - etcd 分布式存储,该元素由 Kubernetes 内部使用,包括存储负载均衡器配置。 我们将数据写入 etcd,然后一个名为 confd 的小工具监视 etcd 是否有新数据。

如果它检测到初始配置有任何更改,它会生成一个新的设置文件并将其传输到 ha-proxy。 在这种情况下,ha-proxy 会在不丢失任何连接的情况下重新启动,并将负载分配给新服务,使新版本的应用程序能够正常工作。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

正如您所看到的,尽管组件丰富,但这里并不复杂。 你只需要多关注 API 和 etcd 即可。 我想向您介绍一下我们自己使用的开源部署器 - Amdatu Kubernetes Deployer。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

它是编排 Kubernetes 部署的工具,具有以下功能:

  • 蓝/绿部署;
  • 设置外部负载平衡器;
  • 部署描述符管理;
  • 管理实际部署;
  • 在部署期间检查健康检查的功能;
  • 将环境变量实施到 pod 中。

该部署程序构建在 Kubernetes API 之上,并提供用于管理句柄和部署的 REST API,以及用于在部署过程中流式传输日志的 Websocket API。

它将负载均衡器配置数据放入 etcd 中,因此您不必使用具有开箱即用支持的 ha-proxy,而是轻松使用您自己的负载均衡器配置文件。 Amdatu Deployer 是用 Go 编写的,就像 Kubernetes 本身一样,并由 Apache 许可。

在开始使用此版本的部署程序之前,我使用了以下部署描述符,它指定了我需要的参数。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

此代码的重要参数之一是启用“useHealthCheck”标志。 我们需要指定在部署过程中必须执行健全性检查。 当部署使用不需要验证的第三方容器时,可以禁用此设置。 该描述符还指示 ha-proxy 所需的副本数量和前端 URL。 最后是pod规范标志“podspec”,它调用Kubernetes获取端口配置、镜像等信息。 这是一个相当简单的 JSON 描述符。

开源 Amdatu 项目的另一个工具是 Deploymentctl。 它有一个用于配置部署的 UI,存储部署历史记录,并包含用于第三方用户和开发人员回调的 Webhook。 您可能不会使用 UI,因为 Amdatu Deployer 本身是 REST API,但此界面可以使您的部署更加轻松,而无需涉及任何 API。 Deploymentctl 是使用 Angular 2 在 OSGi/Vertx 中编写的。

我现在将使用预先录制的录音在屏幕上演示上述内容,这样您就不必等待。 我们将部署一个简单的 Go 应用程序。 如果您以前没有尝试过 Go,请不要担心,这是一个非常简单的应用程序,因此您应该能够弄清楚。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

在这里,我们创建一个仅响应 /health 的 HTTP 服务器,因此该应用程序仅测试运行状况检查,而不测试其他任何内容。 如果检查通过,则使用下面所示的 JSON 结构。 它包含部署者将部署的应用程序的版本、您在文件顶部看到的消息以及布尔数据类型 - 我们的应用程序是否正在运行。

我在最后一行做了一些作弊,因为我在文件顶部放置了一个固定的布尔值,这在将来将帮助我部署甚至是“不健康”的应用程序。 我们稍后会处理这个问题。

那么让我们开始吧。 首先,我们使用命令 ~ kubectl get pods 检查是否存在任何正在运行的 pod,并且根据前端 URL 没有响应,我们确保当前没有进行任何部署。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

接下来屏幕上你可以看到我提到的Deploymentctl界面,其中设置了部署参数:命名空间、应用名称、部署版本、副本数量、前端URL、容器名称、镜像、资源限制、健康检查端口号、等等。 资源限制非常重要,因为它们允许您使用尽可能多的硬件。 在这里您还可以查看部署日志。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

如果现在重复命令 ~ kubectl get pods,您可以看到系统“冻结”了 20 秒,在此期间 ha-proxy 被重新配置。 之后,pod 启动,我们的副本可以在部署日志中看到。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

我从视频中删除了 20 秒的等待,现在您可以在屏幕上看到该应用程序的第一个版本已经部署。 所有这一切都是仅使用 UI 完成的。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

现在让我们尝试第二个版本。 为此,我将应用程序的消息从“Hello, Kubernetes!”更改为“Hello, Kubernetes!” 在“Hello, Deployer!”中,系统创建此映像并将其放置在 Docker 注册表中,之后我们只需在 Deploymentctl 窗口中再次单击“Deploy”按钮即可。 在这种情况下,部署日志将以与部署应用程序的第一个版本时相同的方式自动启动。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

命令 ~ kubectl get pods 显示当前有 2 个版本的应用程序正在运行,但前端显示我们仍在运行版本 1。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

负载均衡器等待运行状况检查完成,然后再将流量重定向到新版本。 20 秒后,我们切换到curl,看到我们现在已经部署了应用程序的版本2,并且第一个版本已被删除。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

这是“健康”应用程序的部署。 让我们看看,如果对于新版本的应用程序,我将 Healthy 参数从 true 更改为 false,也就是说,我尝试部署一个未通过健康检查的不健康应用程序,会发生什么情况。 如果应用程序在开发阶段出现一些配置错误,并以这种形式投入生产,则可能会发生这种情况。

如您所见,部署执行了上述所有步骤,并且 ~kubectl get pods 显示两个 pod 都在运行。 但与之前的部署不同的是,日志显示的是超时状态。 即由于健康检查失败,导致新版本的应用无法部署。 结果,您看到系统已恢复使用旧版本的应用程序,而新版本只是被卸载。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

这样做的好处是,即使您有大量同时请求进入应用程序,他们甚至不会注意到实施部署过程时的停机时间。 如果您使用 Gattle 框架测试此应用程序,该框架会向其发送尽可能多的请求,那么这些请求都不会被丢弃。 这意味着我们的用户甚至不会实时注意到版本更新。 如果失败,将继续使用旧版本;如果成功,用户将切换到新版本。

只有一件事可能会失败 - 如果健康检查成功,但应用程序一施加工作负载就失败,即只有在部署完成后才会发生崩溃。 在这种情况下,您将必须手动回滚到旧版本。 因此,我们研究了如何将 Kubernetes 与为其设计的开源工具结合使用。 如果您将这些工具构建到构建/部署管道中,部署过程将会变得更加容易。 同时,要开始部署,您可以使用用户界面或使用提交到 master 等方式完全自动化此过程。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

我们的构建服务器将创建一个 Docker 映像,将其推送到 Docker Hub 或您使用的任何注册表中。 Docker Hub支持webhook,因此我们可以按照如上所示的方式通过Deployer触发远程部署。 通过这种方式,您可以完全自动化地将应用程序部署到潜在的生产中。

让我们继续下一个主题 - 扩展 Kubernetes 集群。 请注意,kubectl 命令是一个缩放命令。 有了更多帮助,我们可以轻松增加现有集群中的副本数量。 然而,在实践中,我们通常希望增加节点数量而不是 Pod 数量。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

同时,在工作时间你可能需要增加,而在晚上,为了降低亚马逊服务的成本,你可能需要减少正在运行的应用程序实例的数量。 这并不意味着仅扩展 Pod 数量就足够了,因为即使其中一个节点闲置,您仍然需要向 Amazon 付费。 也就是说,除了扩展 Pod 之外,您还需要扩展所使用的机器数量。

这可能具有挑战性,因为无论我们使用 Amazon 还是其他云服务,Kubernetes 对正在使用的机器数量一无所知。 它缺少一个允许您在节点级别扩展系统的工具。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

所以我们必须同时照顾节点和 Pod。 我们可以使用AWS API和Scaling组机器轻松扩展新节点的启动,以配置Kubernetes工作节点的数量。 您还可以使用 cloud-init 或类似的脚本来注册 Kubernetes 集群中的节点。

新机器在 Scaling 组中启动,将自身初始化为节点,在主服务器注册表中注册并开始工作。 之后,您可以增加在生成的节点上使用的副本数量。 缩小规模需要付出更多努力,因为您需要确保这样的步骤不会导致在关闭“不必要的”机器后破坏已经运行的应用程序。 为了防止这种情况发生,需要将节点设置为“不可调度”状态。 这意味着默认调度程序在调度 DaemonSet Pod 时将忽略这些节点。 调度程序不会从这些服务器中删除任何内容,但也不会在那里启动新的容器。 下一步是驱逐 Drain 节点,即将正在运行的 Pod 从该节点转移到另一台机器或其他有足够容量的节点。 一旦确保这些节点上不再有任何容器,您就可以将它们从 Kubernetes 中删除。 此后,它们对于 Kubernetes 来说将不再存在。 接下来,您需要使用 AWS API 禁用不必要的节点或机器。
您可以使用 Amdatu Scalerd,这是另一个类似于 AWS API 的开源扩展工具。 它提供了一个 CLI 来添加或删除集群中的节点。 它有趣的功能是能够使用以下 json 文件配置调度程序。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

显示的代码在夜间将集群容量减少一半。 它配置 Amazon 集群的可用副本数量和所需容量。 使用这个调度程序将在晚上自动减少节点数量并在早上增加节点数量,从而节省使用亚马逊等云服务节点的成本。 此功能未内置于 Kubernetes 中,但使用 Scalerd 将允许您根据需要扩展该平台。

我想指出的是,很多人告诉我,“这一切都很好,但是我的数据库呢,通常是静态的?” 如何在像 Kubernetes 这样的动态环境中运行这样的东西? 在我看来,你不应该这样做,你不应该尝试在 Kubernetes 中运行数据仓库。 这在技术上是可行的,并且互联网上有关于此主题的教程,但它会使您的生活严重复杂化。

是的,Kubernetes 中有持久存储的概念,您可以尝试运行 Mongo 或 MySQL 等数据存储,但这是一项相当耗费人力的任务。 这是因为数据仓库不完全支持与动态环境的交互。 大多数数据库需要大量配置,包括手动配置集群,不喜欢自动缩放和其他类似的东西。
因此,您不应该因为尝试在 Kubernetes 中运行数据仓库而使您的生活变得复杂。 使用熟悉的服务以传统方式组织他们的工作,并简单地向 Kubernetes 提供使用它们的能力。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

最后,我想向大家介绍一下我的团队正在开发的基于 Kubernetes 的 Cloud RTI 平台。 它提供集中日志记录、应用程序和集群监控以及许多其他有用的功能,这些功能将派上用场。 它使用Grafana等各种开源工具来显示监控。

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

英国DEVOXX。 生产中的 Kubernetes:蓝/绿部署、自动扩展和部署自动化。 第2部分

有人问为什么要在 Kubernetes 中使用 ha-proxy 负载均衡器。 好问题,因为目前有 2 个级别的负载平衡。 Kubernetes 服务仍然驻留在虚拟 IP 地址上。 您不能将它们用于外部主机上的端口,因为如果 Amazon 使其云主机过载,地址就会发生变化。 这就是为什么我们将 ha-proxy 放在服务前面 - 为流量创建一个更加静态的结构,以便与 Kubernetes 无缝通信。

另一个好问题是在进行蓝/绿部署时如何处理数据库架构更改? 事实是,无论使用 Kubernetes,更改数据库架构都是一项艰巨的任务。 您需要确保新旧模式兼容,然后您可以更新数据库,然后更新应用程序本身。 您可以热插拔数据库,然后更新应用程序。 我知道有人用新模式启动了一个全新的数据库集群,如果您有像 Mongo 这样的无模式数据库,这是一个选择,但无论如何这都不是一件容易的事。 如果您没有其他问题,感谢您的关注!

一些广告🙂

感谢您与我们在一起。 你喜欢我们的文章吗? 想看更多有趣的内容? 通过下订单或推荐给朋友来支持我们, 面向开发人员的云 VPS,4.99 美元起, 我们为您发明的入门级服务器的独特模拟: VPS (KVM) E5-2697 v3(6 核)10​​4GB DDR480 1GB SSD 19Gbps XNUMX 美元或如何共享服务器的全部真相? (适用于 RAID1 和 RAID10,最多 24 个内核和最多 40GB DDR4)。

Dell R730xd 在阿姆斯特丹的 Equinix Tier IV 数据中心便宜 2 倍? 只有这里 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 电视低至 199 美元 在荷兰! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - 99 美元起! 阅读 如何建设基础设施公司同级使用价值730欧元的Dell R5xd E2650-4 v9000服务器一分钱?

来源: habr.com

添加评论