如何减少运维团队的日常琐事?如何将服务平台化,赋予用户自我服务的能力?新东方云利用 Rancher 容器管理平台、Harbor 镜像仓库和 GitLab 构建企业应用商店。赋能运维团队和用户,尝试破解用户自服务的难题。
开场先讲个小故事:
运维团队一线支持小哥接到某团队的工单,要求部署一套 TiDB 做功能测试。小哥在云平台上申请机器,按照内部标准的部署文档安装配置,最终交付给该团队。小哥回复邮件后已经是下午 3 点多了,小哥的一天就这么过去了。平淡无奇的运维工作似乎就应该是这样的。
我相信这是大多数运维团队都会面临的问题,运维团队面临着很多不断重复,事务性的工作。组织规模变大以后,像这样有的没的项目都会来运维团队寻求支持。运维团队招了很多人,忙了一年下来,发现好像也没做成什么事情,功劳似乎都是别人的,成本都是自己的。为什么会这样?因为运维团队的大量时间和精力在服务其他团队的琐事中消耗掉了。
这也是我们信管部王威老师提出建设新东方云的初衷之一。我们设想是否能把手中的资源和我们的服务平台化?通过定制和开发,最终我们交付出去的不是针对具体项目的劳务,而是一个服务的平台。让大部分重复性的日常部署和维护工作由用户自己完成。我们将运维能力直接赋予其他团队和用户,让运维团队能将精力集中在提高 SLA 和技术提升上。
这也是我今天分享的主题,今天主要分享一下新东方利用容器技术在用户自服务方面的一些探索。
首先简单介绍一下新东方云和容器云服务:
新东方云采用自建数据中心+IDC+公有云的混合云架构,提供包括:云服务器、对象存储、分布式文件系统等 IaaS 层面的服务,提供消息队列、缓存服务等中间件层面服务,以及运维大数据方案和视频服务等等。
容器云服务是新东方云提供的最新服务,目前还在 beta 阶段。我们的容器云平台也是基于 Docker、Harbor 等主流技术作为后台,使用 Rancher 提供的 Cattle 作为编排引擎。
提到 Rancher 大家可能也听说过,简单介绍一下 Rancher。
Rancher 是一个轻量级的容器管理平台,CNI 兼容的网络服务、存储服务、主机管理、负载均衡等功能。Rancher 现在分为两个分支:
X:采用 Rancher 自己开发的 Cattle 编排引擎,已经有一套完整的平台和全球众多的粉丝。
X:目前已经进入 beta 阶段, 2.X 分支则完全将 Rancher 建立在 Kubernetes 之上,提供对公有云或自建的各种 Kubernetes 平台的纳管。
我们选择 Rancher 的主要是出于以下考虑:
项目 100%开源,可选的商业支持。
提供丰富的 API,可供用户自行定制。
学习成本低,直接沿用了 Docker 生态,好上手。
内置的应用商店框架(Rancher Catalog)。
Rancher Catalog 功能类似 Kubernetes 的 Helm,提供对应用的打包定制,并提供一整套用户 UI。用户只需要简单输入即可部署一套应用。这恰好也是我们比较看重的功能。我们尝试将日常常用的基础软件通过容器云平台打包,发布在企业应用商店中,这样团队内部在需要的时候只需要简单的通过界面设置一下就立刻获得这个服务。
说了这么多,应用商店是什么样的呢?下面就详细介绍一下应用商店的原理和实现。继续开场运维小哥的故事,同样的工作,他现在只需要打开应用商店:
填写一下表单:
大概等待 3 分钟左右, 一套完整的 TiDB 环境就出来了,期间小哥完全不用理会这边创建的过程,可以做其他事情去了。
创建好后根据暴露出来的端口和 IP,直接连接即可。
这就是应用商店创建应用的流程,从图片中大家也看到,我们还在不断的增加企业内部应用。
比如图片中的 SQL Server 2017 on Docker,定制这样一个应用的时间不会超过半天,复杂一些的应用两三天也能写完。
那么下面就简单说说应用商店的实现原理:
应用商店的组件
镜像仓库
我们选择的是业界广为使用的 Harbor 项目,我相信大家也很了解了。
简单介绍一下:Harbor 是 VMware 中国团队开源的一套基于 Docker Registry 构建的镜像仓库项目。这个项目集成了 CoreOS 的 Clair 脆弱性检查工具和 Notary 镜像签名工具,配以 LDAP 集成,UI 等企业应用必须的功能。可以说是目前企业镜像仓库的首选项目, 此项目为开源项目。用户可以下载下来自行定制。
我们对 Harbor 进行了简单的定制,我们的 Harbor 直接对接 Ceph 对象存储(通过 Swift 接口)。 这样后端存储在性能和可靠性上都有保障。同时前端也可以根据需要进行扩容,实际上 Harbor 中除了 MySQL 和 Pg 数据库外,其他服务都是无状态的,完全可以做到自动扩缩容,目前 Harbor 有基于 Kubernetes 和 Rancher(社区 Catalog 中)的实现,大家可以参考。
我们目前的实践是通过 docker-compose 方式离线安装的独立部署的,后期会考虑以独立的 environment 方式纳入 Rancher 的管理中,后面有进一步的实践成果后再和大家分享。这里就不展开说了,有兴趣的朋友可以看一下我的工作笔记:http://jiangjiang.space/2017/11/15/harbor-完全定制手册-制作一个更好用的registry/和http://jiangjiang.space/2017/11/03/harborregistry设置ceph对象存储/。
源码仓库
源码仓库是用来作为应用商店的载体,应用商店实际上是一个 Git 的项目。所有的编排文件以目录的形式存放在指定的路径下,这样 Rancher 就能读取为一个一个应用。
如图:
GitLab 中的目录结构:
Templates 下面是各个应用。
使用私有部署的 GitLab 或者直接使用 GitHub 也可以。
终于说到重点了,应用商店
之前提到过 Rancher 的 Catalog 和 Kubernetes 的 Helm 很相似,比如 Helm 各种 Charts,Values 和 Templates 等定义,帮助用户固化对应用的定制。Rancher 的 Catalog 也是这个设计思路,Helm 围绕 Kubernetes,Rancher 则是围绕 Cattle 而生。
下面以 Catalog 中的一个应用来解释一下。这是刚刚 TiDB 应用的目录结构:
0 目录和 1 目录是版本目录,Rancher 可以帮助维护应用的版本,可以帮你把老版本的应用实例升级到新版本,升级动作也是通过应用商店手工完成的。
进入 0 目录可以看到文件,这就是 Rancher 的服务定义文件了。
看到熟悉的 docker-compose.yml 和陌生的 rancher-compose.yml,这两个文件的关系要从 Cattle 说起。
Rancher 的 Cattle 编排引擎设计的很巧妙。 Cattle 直接用 docker-compose 定义服务和服务的关系,比如一个服务使用哪些镜像,暴露哪些端口,存储卷定义等等。我们知道 docker-compose 其实是一个单机容器编排工具,直接作为集群编排文件的话还缺少很多重要元素:
缺少对服务的 replica(副本)定义。
缺少容器之间的隶属关系(模拟 Kubernetes 的 Pod),通过 deponds_on 能控制 service 的先后启动,但是一个 service 中的多个容器之间的关系就没有了。
缺少对服务的编排控制,比如一个服务起来后调度到哪个主机上。
缺少对容器的生命周期控制,比如只在服务启动时某容器执行一次,重启服务也不再启动等。
docker-compose 缺少的定义则由 rancher-compose.yml 来补充。实际在执行时 Cattle 只是根据编排规则,将 docker-compose 文件中容器的定义部分直接丢给对应主机的 Docker 执行创建容器。利用 Docker 容器的 label 功能做标记,容器起来后 Cattle 从 label 中获取容器的现状,再与编排规则做对比看看是否满足要求, 比如:Scale,多了就干掉,少了就拉起。有了这两个文件的定义 Cattle 就可以在各个主机间调度和创建容器了,举几个调度的例子:
a:如果要调度一个容器到某个主机上,只需要在容器上打上如下标签:
Cattle 就会将容器的定义发送到有 cn.xdf.edge=true 标签的主机上,随后启动容器。
b:更复杂一点的调度实现,比如在每个主机上只启动某服务的一个容器(单例),或者说类似 Kubernetes daemonset,这个在 Rancher 里是怎么实现呢?
这个标签会把容器在每台主机上启动,并只启动一个。
如果我不想占用所有主机,只是按照 Scale 数目调度到目标主机,并且每个主机只跑一个实例:
这个意思是说:
启动时的主机上必须没有符合冒号后面表达式的容器,并且是一个软限制,去掉 soft 则是严格限制。
服务名字是这个服务的实例名和服务名。
也就是说只要这台机器启动了这个服务的一个实例就不要再调度另一个上去。
还有其他一些标签:
io.rancher.sidekicks:容器名,容器名
设置从属容器,比如做个side car容器,你希望第一个容器启动提供存储volume,然后启动第二个容器跑服务,接着第三个容器做日志的接收转发等等。
io.rancher.container.pull_image:always
启动服务时总是拉取容器镜像
详细的调度和标签说明请参考:http://rancher.com/docs/rancher/latest/en/cattle/labels/。
rancher-compose 除了定义调度外,还提供了 questions 功能。
questions 设置一些问题,用户在启动的时候输入,输入的结果保留到 answer.txt 中, 这个设计类似 helm 的 values_file,只不过 value 文件不是预先定义的,而是用户启动时输入后产生的。
根据上面的定义,Rancher UI 会为不同类型的 question 配置输入框,比如 enum 是一个下拉列表, int 是一个只能输入整数的输入框,Rancher 会做基本的输入检查。
上图的代码会被自动转化为下图中的 UI。
解释到这里可能大家就明白了,这就是应用商店的原理:
一套服务和容器的定义(docker-compose)
一套编排的设置(rancher-compose)
一套用户可以输入值的 UI
用户在 UI 中填入值
随后由编排引擎交给主机上的 Docker 执行。
应用商店使用情况:
目前应用商店主要是运维团队内部使用。下一步我们打算以 Rancher 作为管理后台,通过调用 Rancher 的 API,对接到新东方云平台上。与新东方云现有的申请和开通流程保持一致,简化用户的输入,最终形成一套用户能自服务的 PaaS 平台。
我最近会将 Rancher 1.X 的实践工作做一系列的总结,具体技术细节大家可以关注我的工作日志http://jiangjiang.space。
评论