产品战略专家梁宁确认出席AICon北京站,分享AI时代下的商业逻辑与产品需求 了解详情
写点什么

TencentHub 技术架构与 DevOps 实践揭秘(上)

  • 2019-10-29
  • 本文字数:4222 字

    阅读完需:约 14 分钟

TencentHub技术架构与DevOps实践揭秘(上)

TencentHub 是一个集 Docker 镜像、二进制文件、helmcharts 于一体的仓库存储服务。那么这一架构技术是如何基于 Kubernetes 快速实现 workflow 引擎的呢?今天将为大家分享《TencentHub 技术架构与 DevOps 落地实践揭秘》,让我们开始吧!


大家好,这次主要是给大家分享 TencentHub 技术架构和 DevOps 相关的一些东西,这两点和大家日常开发结合会比较紧密,比较接地气一点。我今天会主要分享三部分,第一,简单聊一下 TencentHub 这个产品和 DevOps 的关系,我们如何去思考建设一个 TencentHub 镜像仓库+DevOps 引擎。第二部分讲讲 TencentHub 总体的一些东西和 Docker 镜像存储在腾讯云上是如何实现的,最后是我们的 workflow 引擎:为了支撑 DevOps 工作流去设计产品以及一些具体设计/实现细节。

TencentHub 与 DevOps?

什么是 DevOps?

我相信很多人对 DevOps 已经比较熟悉了,这个概念从 2009 年大火起来到现在已经过去了接近十年的时间。直击 DevOps 的核心理念,下面这句话是我最赞同的对 DevOps 的描述:以业务敏捷为中心,去构造适应快速发布软件的工具和文化。我们做 DevOps,要去推崇 DevOps,肯定不能忘掉我们的目标是快速交付软件产品。在达到这个目标的过程当中,非常重要的落地就是我们需要工具去支撑 DevOps,所以接下来分享 TencentHub 这样一个以 DevOps 引擎为指导的工具。


什么是 TencentHub?

TencentHub 是什么?TencentHub 核心有两部分,第一,它是一个多功能的存储仓库,包含了 Docker 镜像存储功能以及 helmcharts 这样的存储,还有一些构建产物的存储等等。第二,TencentHub 是一个 DevOps 引擎,通过我们自己设计的 workflow 引擎对工作流进行编排,去帮助大家建立自己的 DevOps 流程,比如说构建、测试、审核、部署等等任务。当然,在前置环节,我们也将去对接腾讯云提供的 TGit 代码托管服务,最终给开发者提供一套完整的云上 Devops 工具解决方案。


TencentHub 技术架构

TencentHub – 总体架构

我简单介绍一下 TencentHub 的总体架构,TencentHubd 的镜像仓库存储是基于 COS 实现,因为 COS 可靠性非常高,这非常方便地给我们的镜像存储带来高可靠保证。TencentHub 核心还有一个自研 workflow 引擎,可以使用 YAML 定义 DevOps 流程,让我们的 DevOps 本身达到 Programmable,这对 Devops 的管理是很重要的。在 TencentHub 的 Devops 引擎里面,我们使用容器去实现插件机制,用来封装用户自定义的 DevOps 任务,后面会详细介绍。使用 Kubernetes 作为执行引擎,运行 DevOps 任务,目前是使用 TKE 来实现的。在 Docker 存储仓库里,我们也会加入 Docker 镜像漏洞的安全扫描,后面会做一个的简单介绍。


镜像存储

Registry Token Authentication Specification

左边这个图分为两大部分。上面是 Registry,下面是 StorageEngine。Registry 主要包含了组织、团队、成员的管理,以及一些权限的控制,同时还包括仓库 Repository 的管理,负责 Docker 镜像、文件、helmchart 的存储。我们所有存储都是使用一个仓库来管理,镜像、文件等都会放在某一个仓库下面。在最上面,我们提供了 Webhook,可以帮助用户对接自己的系统,监听仓库或者 DevOps 流程发生的一些事情。在 Registry 里面还有 Component 组件,负责 DevOps 任务的存储。下面这部分 StorageEngine,是我们去解决统一的仓库存储层的问题,它是一个我们提供出来给全球的腾讯云的机房都能使用 TencentHub 服务的机制。



TencentHub 仓库中最重要的是 Docker 镜像的存储。除了公共的镜像存储之外,TencentHub 还支持私有的镜像存储。私有镜像存储需要通过登录才能获取或者上传 Docker 镜像。如何是想登录认证呢?这是 Docker 官方的 Registry 用户认证的规范,它并没有纳入到 OCI 规范里面,只是在官方有一个文档去说明流程是什么样的,Docker 客户端也是按这个流程去实现的,所以我们只需要在 TencentHub 后端按这个流程去实现自己的授权服务就可以了。

TencentHub pull 授权流程

在我们使用 Docker 进行 push/pull 的时候,本地的 Docker 客户端会调到 containerd,检查当前这个操作是否有授权。当我们没有带上一个 Token 的时候,后端的存储服务会返回 401,并且携带一个授权服务的地址,告诉客户端去这个地方拿授权码。客户端请求授权服务获取将要进行操作的授权 Token。


获取 Token 支持两种方式,一种是 OAuth2 密码模式,你可以通过登录之后,授权服务会给你下发一个 key,它和你的密码无关系,后续的通信都是使用 Key 获取 Token。


第二种方式是 Basic Authentication 方式,很多时候我们采用的都是这种方式。TencentHub 实现的也是后者。这种方式会在 Token 客户端留下帐号密码,并不是太安全,我们后面可能会去支持 OAuth2 的密码模式。


当客户端发起一个请求到授权服务的时候,授权服务就根据当前的请求去生成一个授权的列表,封装成 Token 返回客户端,这个 Token 的格式对客户端是透明的,可用使用任意自己的格式。我们这里继续保持了选择 JWT 的格式,是因为我们把 StorageEngine 和 Registry 做了一个状态的隔离,因为我们把需要的权限都放到了 Token 里面进行封装,不需要有一个中心化的带状态的权限校验服务去连接两者。最后当 Token 拿到之后,客户端重新再去请求 Registry,重新拉取它的 Docker 镜像,或者进行数据的上传/下载之类。


这里用一个时序图简单说一下它的流程。首先可以看到,Docker 服务端首先会去访问/v2/这样的路径,客户端会根据当前是否有携带 Token 来返回一个授权的地址,我们目前返回的是hub.tencentyun.com/token这个地址,客户端就会自动访问/token的URL,带上当前的账户以及申请的权限范围。客户端申请Token完成之后,就会进入Docker镜像拉取流程。


OCI Distribution Specification

Docker 镜像是分层组织形式,每个 Docker 镜像包含多个 Layer 和一个 Config 文件,每个 Layer 包含构建一个 Docker 镜像时文件系统里面出现的差异,Config 文件里面会包含当前这个 Docker 镜像能运行的一些环境要求,例如 OS,及一些配置入口命令,导出的一些端口之类。这些文件被一个 Manifest 文件引用起来,通过它可以找到这个 Docker 镜像的所有内容。Docker 是在 V2 版本设计了这样一套规范,目前它也已经提交到 OCI 组织,成为一个 Distribution Specification 标准。


这样的设计带来很多好处。


首先,它的安全性有比较大的提高。镜像中的所有文件都是 content addressable 的设计,让我们只需要拿到最后的 Manifest 去校验,就可以发现整个数据的传输过程中是否有篡改。这在现在比较流行的区块链中都采用类似的技术,是 merkle tree 的一种实现。


第二,它可以极大减少冗余。每个构造的 Docker 镜像都不会从空白文件开始,都是从各个发行版或者是比如 CentOS 的基础镜像开始,这些基础镜像存在非常多的基础镜像 Layer 都是相同的。它通过 content addressable storage 的组织结构,不仅在客户端减少存储空间,也可以在远端仓库中减少存储所需要的空间。


最后,它对缓存是非常友好的。因为整个 Docker 镜像里面不管哪一个 Layer 有改变,都会最终影响到 Manifest 的改变,所以 Docker 镜像并不是重新修改一个 Layer,而是重新生成的,我们去做缓存的时候就可以非常方便地在不同的环境下地部署我们的缓存,只需要使用 content digest 作为 Layer 的 key 来引用 Layer 文件即可,Layer 不会修改,只会生成新的或删除老的 Layer,缓存的管理就非常简单。


distribution RESTful API

这里再简单补充一下关于 distribution 规范的一些 API。前面两个不说,主要是第三个,每个 Docker 镜像的上传都会访问到/v2/仓库名/manifests/tags|digest 地址,在这个地址上,它支持去 GET、PUT、DELETE,去实现 Docker 镜像在远端仓库的拉取/上传/删除的功能。刚才所说的 Layer、Config 文件,包括 Menifests 文件,也可以通过 V2 这个路径下面的 name+blobs+digest 去获取。更详细的规范,可以看一下 OCI 组织已经成为标准的说明,下面有个 URL。


distribution 架构

TencentHub 镜像的存储核心还是利用了 Docker 官方的 distribution 来实现的,distribution 的实现在这个图里面描述得比较清楚,最上面有 API route 层分发 URL 的规则。第二层会有一个权限控制,我们在这里做了一些改造,增加了 TencentHub 的 hubtoken 的实现。我们为什么要去实现 hubtoken,而不是用官方现在自己的 GWT 格式?


是因为 TencentHub 可能还会面临着一些私有化部署的需求,或者说一些用户在公有云上面希望有自己独立的存储仓库。但是我们上面的 Registry 和 StorageEngine 两者之间并没有中心化的授权服务,所以我们就通过在 hubtoken 里面包含了一些不同租户的身份识别信息,在上下文进行传输,所以就单独改造了这里。


在权限控制下面会有 API 协议的函数处理,一些主要的业务逻辑,都在这里实现。最终到下面 storage 的实现,它提供了一套存储的插件机制,有一个标准的存储接口,规定了文件上传、文件移动等等接口,只要去实现就可以了。我们这里也会实现 GOS,是对 COS 的简单封装,后面会做一个 GOS 简单介绍。



现在腾讯云容器服务的仓库是 CCR,还没有提到 TencentHub 上面来。CCR 有两个问题,第一是不同地域的镜像是不通的,比如说我们在广州上传一个镜像,想在硅谷拉取是拉取不到的,这是我们直接依赖了 COS 提供的分发能力,没有去对它做封装,COS 是无法跨区域访问的,所以会存在这个问题,这会带来用户体验上的不一致,基于仓库的触发器、Docker 镜像构建功能,都会受到这个问题的影响,所有基于仓库的服务都需要单独又去部署一份,维护上也带来了很大影响。所以我们就做了下面这一层。


我们在设计 global object storage 的时候,发现 distribution 协议的设计没有事务的需求,第二是我们拉取多个镜像,它对延时不太敏感,但是对吞吐量很敏感。因此,实现这个存储,我们只对 COS 做了很简单的封装,提供中心化的服务,它类似于一个 p2p 的 tracker,会去记录它所有的文件分布在哪个区域的哪个 COS 里面。比如说我们从广州上传了一个镜像,他需要在硅谷去拉取,我们通过这个 global object storage 服务,会发现它在本地是没有的。这个时候通过腾讯云内部的专线,直接去广州把它拉取过来。在拉的过程当中,它会同步写到本地的 COS 和客户端去,这样客户端也不用做很长的等待。当下一次硅谷再访问该镜像的时候,它就不会再跨区域去访问这个数据,给我们减少了很多成本,最终也给用户带来很好的体验。


2019-10-29 19:132070

评论

发布
暂无评论
发现更多内容

架构杂谈——也谈互联网系统架构演进

老农小江

Java 架构

【Flutter 专题】69 图解基本 Stepper 步进器

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 8月日更

LeetCode题解:783. 二叉搜索树节点最小距离,递归,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

Vue进阶(二十八):浅析 Vue 中 computed 与 method 区别

No Silver Bullet

Vue 8月日更 computed

手撸二叉树之二叉树的最近公共祖先

HelloWorld杰少

数据结构与算法 8月日更

优秀的求职者,是如何巧妙应对面试提问呢?

xcbeyond

面试 求职 8月日更

Discourse 用户的邮件无法投递的时候如何处理

HoneyMoose

oeasy教您玩转vim - 15 - # 行内查找

o

4种基于像素分割的文本检测算法

华为云开发者联盟

目标检测算法 文本检测 像素分割 文本检测算法 文本

TCP-三次握手和四次挥手简单理解

一个大红包

8月日更

IntelliJ IDEA 如何在 Java 中进行快速注释

HoneyMoose

旗舰机怎么做隐私安全?荣耀Magic3有个答案

脑极体

在线HTTP/HTTPS协议GET,POST,RESTful接口测试

入门小站

Linux

另一个失败的小项目

箭上有毒

8月日更

「免费开源」基于Vue和Quasar的前端SPA项目crudapi后台管理系统实战之EXCEL数据导出(十三)

crudapi

Vue crud crudapi qusar 数据导出

有状态算子和应用(七)

Databri_AI

flink 算子 状态

如何评价《Java 并发编程艺术》这本书?

苹果看辽宁体育

书籍推荐 java 并发

【Vue2.x 源码学习】第三十四篇 - 组件部分-Vue组件与初始化流程简介

Brave

源码 vue2 8月日更

毕业总结

方堃

Linux之ss命令

入门小站

Linux

Redis入门到超神 - 03 redis.conf配置文件详解

陈皮的JavaLib

redis 运维 8月日更

iOS开发:苹果开发者账号第一次新建APP ID以及创建App的步骤

三掌柜

8月日更 8月

三分钟看完单例模式的八个例子

4ye

Java 后端 设计模式 单例模式 8月日更

从0开始的TypeScriptの六:webpack5热更新打包TS

空城机

JavaScript typescript 大前端 8月日更

大厂offer?拿来吧你!网易有道笔试编程题特辑

有道技术团队

招聘 笔试 #技术干货# 网易有道

Golang中的Remove和RemoveAll的对比分析

liuzhen007

8月日更

毕业设计:设计电商秒杀系统

9527

#架构实战营

netty系列之:文本聊天室

程序那些事

Java Netty nio 程序那些事

Spring @Transactional 注解事务

Rubble

springboot 8月日更

算法分析

一个大红包

8月日更

跟我读论文丨ACL2021 NER 模块化交互网络用于命名实体识别

华为云开发者联盟

自然语言处理 机器学习 ACL2021 NER 模块化交互网络 实体识别

TencentHub技术架构与DevOps实践揭秘(上)_DevOps & 平台工程_彭磊_InfoQ精选文章