【编者的话】本教程介绍和解释了如何使用 Docker 容器和 Kubernetes 构建一个配备 OpenContrail SDN 的企业 OpenStack 私有云,包括它的生命周期管理和运维。
共分为五部分。第一部分解释了持续的开发运维工作流程;第二部分描述了在构建流程中构建和集成容器的步骤;第三部分详细描述了容器编排工具 Kubernetes 的架构,包括各种插件以及 OpenStack 服务的分解;第四部分介绍了集中编排所需的“单一信任源”理论;第五部分是汇总,演示了如何部署和升级配备 OpenContrail 的 OpenStack 。
为了便于阅读,我们把五部分内容分为两篇博文,第一篇涵盖了创建持续的开发运维工作流和容器构建。
咋看之下,你可能会问:为什么我要在已有部署工具之上增添更多的工具?这就需要解释为什么任何人在生产环境中运行 OpenStack 时都应该考虑使用 Docker 和/或 Kubernetes 工具。我司已经部署和运维了大量面向生产环境基于 OpenStack 的企业私有云,这项业务还在持续增长。每一个 OpenStack 私有云的部署都不尽相同(存储、网络和模块),根据客户的需求,需要的服务组合也不一样。不过,所有的部署有一个共同之处:部署阶段和初始目标。这些已经是显而易见的了,所有客户的部署过程都遵循一个单独的云成熟模型。OpenStack 部署的演化分为下列三个阶段。
这一阶段的特点是混乱、没有精心组织、不一致。任何人开始使用 OpenStack 时都属于这一阶段,有些人最终也还是这样。每一家公司或者每一个个人,在考虑使用 OpenStack 作为私有云解决方案时,都有一个共同的初始目标:部署 OpenStack 。
人们通常从 openstack.org 开始,再使用 Puppet, Chef, Ansible, TripleO, Helion, Fuel 等部署工具。任何人,如果没有运维经验,想要找出启动和运行 OpenStack 的正确方式,这几乎是不可能的。虽然所有的部署工具都号称能快速简便地设置整个环境,所有用户最后都需要如下图所示的生产环境逻辑拓扑。这张图显示的是一个典型的面向生产服务的单区域、高可用 OpenStack 的部署架构。显然,这张图非常复杂。
接着你会发现现有的部署工具无法涵盖整个生产环境(多个网卡绑定聚合、存储设置、服务分离等)。这时候云团队会问自己:我们真的需要花一天功夫设置好环境,再花 5 分钟部署到一台机器上吗?我们真的需要一个能点击的图形界面来部署吗?这些是能决定将来生产环境正确选择的关键点吗?启动一个 OpenStack 系统相对容易而部署工具只会被运行一次?你无法两次运行部署工具? 如何解决 OpenStack 系统生命周期的各种问题,如打补丁、升级和配置修改等?思考这些问题,我们会再次得出结论:任何人,只要他不具备“次日运维”经验,就没法选择正确的解决方案。
译者注:次日运维(Day 2 Operations)实际上就是指运维。第一天引导、配置和运行基础设施及应用,第二天管理和维护正在运行的基础设施及应用。
第二个阶段是运维(或者叫次日运维)。一个典型的例子是: OpenStack 已经运行起来了,然后你收到安全团队的一封邮件,信里说“为了防止安全威胁,请升级或者重新配置 RabbitMQ ”。你该如何充满信息地做到这一点?部署工具不能再用了。现在你要出里的是日常运维,复杂性远超部署工作。
由此,我们定义了日常运维工作(如打补丁、升级、业务持续性、灾难恢复、自动监控、文档、备份和恢复)的下列评判标准。一般人以为部署工具能够管理运维,实情并非如此。
前文已经提及,部署工具是一次性的。因此,你必须启用这样的构建和运维工具:杂乱的脚本(重启服务或修改配置)、手动维护、局限知识(只有特定的人才知道如何管理生产服务)。
理想的运维工作流包含下列术语,如可重复模式、单一信任源(基础设施即代码)、最佳实践、由不可修改特性获得的敏捷性(rigid-to-agile)、声明式(期望状态)和个性化云体验。
我们可不想自己开发这样的工作流,最后我们找到了最佳工具 OpenStack-Salt 。从 2016 年 5 月开始, OpenStack-Salt 成为 OpenStack 的正式项目,它采用面向服务的方法,几乎涵盖了上述理想工作流的所有方面。它提供了经过证明的生产环境可用的架构,像编码那样管理 OpenStack 服务。
不过,即使用上了 OpenStack-Salt ,基础设施仍然如下图所示那么复杂。单看云控制平面部分,就包含了运行在至少 3 台物理机(安装了 KVM 虚拟机管理器)上的 23 个虚拟机。为了提供灵活性和面向服务的架构,我们必须升级、打补丁和维护 23 个操作系统。
根据前述思路,我们会问:“把基础设施作为一种微服务怎么样?”这就把运维变成了开发运维(DevOps),实际上就是把 OpenStack 当作一个应用集合。
我们定义的评判标准是:必须具备组合、模块化、可重复、不可更改等特性和将应用与基础设施分开,必须把单一整体的虚拟机分解成容器和微服务。
我们还决定不再造轮子(创建一个新项目),而是复用 OpenStack-Salt 项目的已有知识。
以上描述了最近两三年我们部署 OpenStack 的演化过程。接下来,看看如何构建容器和微服务,而不是像以前那样的单体部署。下面的内容解释了开发运维工作流。
几年前,配置管理流行起来,相关的工具包括 Fabric, Puppet, Chef 以及稍后出现的 SaltStack 或者 Ansible ,这改变了企业部署基础设施和应用的方法。这些工具终结了使用 bash 脚本部署的时代,带来了可重复、幂等、可复用的部署模式和持续的知识。企业对配置管理的投入巨大, OpenStack 社区提供了几乎所有配置管理工具部署 OpenStack 的方法。
最近,微服务时代( Docker 容器加速了这一进程)初见端倪。正如我们在开发运维工作流中描述的那样,容器应该把服务封装起来,这有助于运维和把基础设施当作微服务应用对待。不幸的是, Docker 完全不用配置管理工具,也不理会知识的持续性。有些专家甚至预测 Docker 会终结配置管理时代。但是仔细想想,在 Docker 容器的定义文件 Dockerfile 中,又使用 bash 脚本作为容器的入口点(entry point)。既然我们已经在单一信任源(基础设施即代码)投入这么多,为什么还要推倒重来?我们在开始 OpenStack 容器化工作之前就有这个疑问了。因此,我们的第一个需求是更有效地构建 Docker 容器,而不是一切都用 bash 脚本实现。我们了解了 OpenStack Kolla 、 CoreOS 和其他实现 OpenStack 容器化的项目。
Kolla 使用 Ansible 构建容器,用 Jinja 实现带参数的 Dockerfile 。这种概念非常有趣,也有光明的将来。然而,就 OpenStack 的持续知识和生产运维而言,这是一种全新的方式。 Kolla 试图普遍适用于 Docker 容器构建。然而,它缺乏编排或者在生产环境中运行 OpenStack 的推荐工作流,此时包含的不仅仅是一台主机,还需要解决跨主机联网。一个月前, Kolla-Kubernetes 项目启动了,它仍然处于早期阶段,还不能在企业环境中运行。要实现一种更适合运维的方法,需要做的工作台多了。根本而言,我们想尽可能复用我们在 OpenStack-Salt 上的积累,不用创建一个新项目或者维护两种解决方案。
我们定义了使用容器运行 OpenStack 服务的两个评判标准:
用配置管理工具构建 Docker 容器和标准的操作系统;
复用已有解决方案——不要另起炉灶,没必要仅仅为了构建容器就用另外一个工具重新实现我们的已有知识,这就得维护两种解决方案了。
我们创建一个简单的代码仓库 Docker-Salt ,它使用已经用于生产环境部署的 salt 脚本来构建容器。这实现了知识复用,例如,当某人修补了标准 OpenStack 部署的配置,同时会自动构建对应的 Docker 容器的新版本。这样,用一个工具实现了 OpenStack 的虚拟机式部署和微服务式部署。无需使用两种或三种工具,我们就能混合部署和运行虚拟机 和 Docker 容器环境,提供单一的环境运维入口。
下图显示的是 Docker 镜像的构建流程,由 Jenkins CI 实现完全自动化的构建。
每一次部署,对应特定的重新分类元数据模型。这个模型是单一信任源,包括各种配置,如 Neutron 插件、 Cinder 后端、 Nova CPU 分配比例等。这是一个由 YAML 文件构成的 Git 代码仓库。
用到 OpenStack-Salt 脚本的任务包括安装软件包、配置和启动一个服务、设置用户和许可以及其他很多常见任务。
Docker Salt 提供了构建、测试和上载 Docker 镜像的脚本,包括基础镜像、所有 OpenStack 支持和核心服务的 Dockerfile 定义。
构建进程下载元数据代码库和所有的 salt 脚本,然后构建带特定标记的基于 salt 的镜像。标记可以是 OpenStack 的发行版本或者内部版本。OpenStack 配置的每一处修改,都需要重新构建这个基础镜像。基础镜像是构建其他镜像的基础,所有的镜像上载到一个私有 Docker 镜像中心。
Docker salt 代码仓库还包含了用于本地测试和开发的 Docker Compose 文件。 OpenStack 可以在本地运行,无需用到 Kubernetes 或任何其他编排工具。Docker compose 属于持续集成过程中功能测试的一部分。
下面这个代码评论描述了需要对 salt-formula-glance 做的修改。基本思路是在容器构建期间,要防止启动 Glance 服务和 sync_db 操作;然后需要添加 entrypoint.sh ,这不是一个用特定取值替换环境变量的巨长脚本文件,而是调用 salt highstate ,完成配置文件的重新配置和运行 sync_db 。
你可能会注意到 Salt 没有从容器内卸载。我们需要了解带有 salt 和不带 salt 两种容器的区别。带有 salt 的 glance 容器比不带 salt 的 glance 容器增大约 20MB ,原因是 salt 和 glance 都是用 python 编写的,共用了很多库。
第二篇博文将提供有关容器编排和实时升级的更多信息。
原文链接: Making OpenStack production ready with Kubernetes and OpenStack-Salt - Part 1 (翻译:柳泉波)