“认知课堂(Cognitive Class)”是 IBM 面向全球技术人员提供的高质量课程学习平台,课程主题包括人工智能(AI)、机器学习、数据科学、大数据、分析和数据库等,前身为 IBM Big Data University。自发布以来,“认知课堂”跨过了一项又一项里程碑,如今已拥有超过 100 万名学习者。
这篇文章中将分享 IBM“认知课堂”在技术方面的里程碑和演变,特别是平台是如何从一个静态基础架构转变到现在使用 Docker、运行着数十个 Open edX 实例的动态+可扩展部署的。
OPEN EDX 101
Open edX 是 edx.org 提供的开源代码。它由几个存储库组成,edx-platform 是其主要存储库。如果想要部署 Open edX 实例,官方的方法是使用配置好的 repo,通过 Ansible playbooks 自动安装。这种方式需要访问正在运行 Ansible playbook 的服务器。在这些完成之后,你将获得一个全新的 Open edX 部署。
IBM 也是这样运营 cognitiveclass.ai(我们的对外网站)的,从 2015 年开始 IBM 将“认知课堂”从 Moodle 部署转移到了 Open edX 上。Open edX 提供了很好的服务,使得我们每天可以为数百名并发学习者提供超过 70 门课程。
但我们仍然面临着一些挑战:
Open edX 主要针对的是 Amazon 的 AWS 服务,但我们要在 IBM Cloud 上运行我们的基础架构。
需要创建虚拟机来部署新实例。
Open edX 从存储在服务器中的 JSON 文件中读取配置信息,每个实例必须保持这些文件同步。
虽然我们能够在大型的单一部署中克服这些问题,但对于我们的新目标对象,Cognitive Class Private Portals 来说它们会变得很难管理。
商业用途的“认知课堂”
在向其他公司介绍时,我们经常会听到同样的问题:“我怎么样才能让我的员工明白并使用这些内容呢?”,这也是我们为“认知课堂”创立“专属门户(Private Portals)”的动机所在。
“专属门户”是一个专门为客户创建的专用部署 ,用户可以独享专属于他的“认知课堂“,可以创建自定义学习路径、自行定制课程、追踪学习进度、设置访问限制、创立竞赛等等。“专属门户”服务是 IBM 为团队、部门、小型企业、大型企业、学术机构和培训提供商等推出的。从技术角度来看,这就要求我们能够快速按需推出新的部署。我们回到前文提到的几点挑战,随着部署数量的增长,第二点和第三点尤其具有挑战性。
为每个部署创建和配置新的虚拟机是一个缓慢而且昂贵的过程。如果某个 Portals 超出了它的资源,我们不得不需要找到一种方法来扩展它,并且在多个虚拟机中管理它的配置。
使用 Docker
与此同时,我们在 Virtual Labs(供课程用户进行实践操作的环境)的基础设施中遇到了类似的需求,数百个虚拟机的使用让管理非常混乱。于是 IBM 的 Virtual Labs 团队开始研究并且实现基于 Docker 的解决方案。
对我们来说,Docker 的主要好处有两个:
提高服务器的使用密度;
隔离服务进程以及文件。
这些好处是密切相关的:因为每个容器管理自己 runtime 和文件,我们能够在同一个服务器上轻松运行不同的软件,而不会相互干扰。与虚拟机相比,我们这样做的开销要低很多,因为 Docker 在它们之间提供了轻量级的隔离。
通过提高使用密度,我们能够在少量大型服务器中运行数千个容器,这些服务器可以提前进行配置,而不需要去管理数千个较小的实例。
对于 IBM 的“认知课堂-专属门户“网站来说,这意味着我们可以在几分钟内准备好使用新部署。底层的基础设施已经就位,所以我们只需要启动一些容器即可。
使用 Rancher 管理容器
Docker 本身就是一项出色的技术,但面对高度可扩展的分布式生产环境,我们仍需要借助其他工具或平台来管理容器的生命周期。在“认知课堂”平台中,我们决定使用 Rancher,它能够让我们将基础设施抽象出来,只需专注于应用程序本身。
简而言之,Rancher 将容器组织成服务,接着服务被分组到 stack 中。把 stack 部署到环境中,而环境由主机控制,主机是最终启动容器的底层服务器。Rancher 负责在所有主机上创建专用网络,以便他们可以相互安全地进行通信。
让一切运行起来
我们的网站采用微服务架构,都在 Rancher 中以 stack 的形式组合在一起。Open edX 是主要组成部分,它可以分为较小的服务。除了 Open edX 之外,我们还有其他几个组件可以为我们的产品提供额外的功能。下图是我们的 Rancher 界面示例:
这里有非常多的内容,所以我们来快速解释一下这些内容:
Open edX
lms:这是学生访问课程内容的地方
cms:用于创作课程
forum:处理课程讨论
nginx:提供静态资源
rabbitmq:消息队列系统
附加组件
glados:管理员用户界面,用于控制和自定义 Protal
companion-cube:用于开放 Open edX 额外功能的 API
compete:运行数据黑客马拉松的服务
learner-support:内置的学习者支持系统
lp-certs:为完成多门课程的学生颁发证书
支持服务
cms-workers 和 lms-workers:执行 lms 和 cms 的后台任务
glados-worker:执行 glados 的后台任务
letsencrypt:使用 Let 的加密自动管理 SSL 证书
load-balancer:根据请求主机名控制路由到服务的流量
mailer:代理 SMTP 请求到外部服务器或者以其他方式发送电子邮件
ops:用于运行特定任务的容器组
rancher-cron:按照类似 cron 的计划启动容器
数据存储
elasticsearch
memcached
mongo
mysql
redis
其中 ops 服务的行为和其他服务的行为有所不同,因此我们深入研究一下:
这里我们可以看到在 ops 中有几个容器,通常情况下它们是不运行的。某些容器(如 edxapp-migrations)会在部署 Portal 时运行,但除非在特殊情况下(例如数据库架构更改),否则不会再次启动。而其他容器,如 backup,由 rancher-cron 定期启动,一旦完成就停止。
在这两种情况下,我们都可以通过单击启动按钮来触发手动启动。这样我们能够轻松地按需运行重要的操作任务,而不需要使用 SSH 进入特定服务器,确定要运行的脚本来执行。
操作文件
Docker 的一个关键特性是每个容器的文件系统都是隔离开的。这意味着,如果没有适当注意,在容器死亡的时候您可能会丢失重要的文件。处理这种情况的方法,是 使用 Docker 的卷将本地文件系统路径挂载进容器。
此外,当您有多个主机时,最好有一个共享数据层,以避免在容器和服务器之间创建隐式调度依赖关系。换句话说,您希望容器能够访问相同的文件,而无论它们运行在哪个主机上。
在我们的基础架构中,我们使用 IBM Cloud NFS 驱动器,它安装在所有主机的相同路径下。NFS 负责存储 Portal 生成的任何持久化数据,从数据库文件到已编译的静态资源,比如镜像、CSS 和 JavaScript 文件。
每个 Portal 在 NFS 驱动器中都有自己的目录,容器会挂载该特定 Portal 的目录。因此,一个 Portal 无法访问另一个 Portal 的文件。
其中一个最重要的文件是 ansible_overrides.yml 。正如我们在文章开头所提到的,Open edX 是由进程启动时所读取到的 JSON 文件配置的。Ansible playbook 在执行时生成这些 JSON 文件。
为了把 Portal 管理员对 glados 所做的更改应用到 Open edX 的 lms 和 cms,我们将 ansible_overrides.yml 挂载到容器中。当某些内容发生变化时,glados 可以将新值写入此文件,lms 和 cms 可以读取它们。
接着我们重新启动 lms 和 cms 容器,通过这些容器来运行 Ansible playbook,在启动时重新生成 JSON 文件。ansible_overrides.yml 作为变量文件传递给 Ansible,这样在那里声明的任何值都可以覆盖 Open edX 的默认值。
有了这个共享数据层,我们不必再担心容器会被重新分配到另一个主机上了,我们确信 Docker 能够找到正确的路径,并将所需要的卷挂载进容器中。
结论
通过在 IBM 认知课堂平台的发展过程中,依靠学到的经验教训以及使用最新的技术,我们能够构建出快速、可靠和可扩展的解决方案,为认知课堂的学生和客户提供更好的学习体验。这篇文章中介绍了很多内容,希望能让您有所收获。Happy learning!
评论