FinOps有望降低企业50%+的云成本! 了解详情
写点什么

HULK 容器镜像仓库简介

  • 2019-11-14
  • 本文字数:5795 字

    阅读完需:约 19 分钟

HULK容器镜像仓库简介

镜像仓库,顾名思义就是存储镜像的。Docker 仓库的概念跟 Git 类似,注册服务器可以理解为 GitHub 这样的托管服务。用户制作好镜像 push 到仓库,这样下次在另外一台机器上使用这个镜像时候,只需要从仓库上 pull 下来就可以了。本文主要介绍 HULK 使用的镜像仓库 Harbor。

什么是 Harbor

Habor 是由 VMWare 公司开源的容器镜像仓库,是一个用于存储和分发 Docker 镜像的企业级 Registry 服务器。


Harbor 主要是提供了一些企业级的管理功能,而镜像存储用的还是 docker registry,相当于 docker registry 的反向代理。

1 Harbor 架构


如上图所示,Harbor 由 6 个组件组成:


1.Proxy: nginx 反向代理。上图来自官网,已经滞后了。目前到 harbor 的所有请求都必须走 UI,包括上图中 Proxy–> Registry 这条。


2.Registry: 负责存储 Docker 图像和处理 Docker push/pull 命令。由于 Harbor 需要加强对映像的访问控制,因此注册中心将引导客户端到令牌服务,以便为每个 pull 或 push 请求获得一个有效的令牌。


3.Core services: Harbor 的核心功能,主要提供以下服务:


a.UI:提供了一个 web 管理页面,当然还包括了一个前端页面和后端 API。


b.Webhook:在 Registry 中配置,镜像复制,日志更新都是通过该功能实现。


c.Token service:令牌服务,如果从 Docker 客户机发送的请求中没有令牌,注册中心将把请求重定向到令牌服务。


d.Job services: 镜像复制。


e.Log collector: 日志收集。

2 HULK 使用的 Harbor 功能

用户管理

基于角色的访问控制:用户分为三种角色:项目管理员(MDRWS)、开发人员(RWS)和访客(RS),当然还有一个造物主 admin 系统管理员。


注:M:管理、D:删除、R:读取、W:写入、S:查询。

项目管理

项目管理是系统最主要的一个功能模块,项目是一组镜像仓库的逻辑集合,是权限管理和资源管理的单元划分。一个项目下面有多个镜像仓库,并且关联多个不同角色的成员,镜像复制也是基于项目的,通过添加复制规则,可以将项目下面的镜像从一个 harbor 迁移到另一个 harbor。

配置管理

配置管理主要是配置 harbor 的认证模式,企业内部使用,通常都是对接到公司 LDAP 上面,我们目前用的数据库认证;还可以设置 token 的有效时间。

镜像复制

HULK 多机房就是通过镜像复制功能实现的,可在不同的数据中心、不同的运行环境之间同步镜像。


目前 HULK 上,用户申请容器服务后,我们会为其创建个 Harbor 的 project(下图中的 xxl-api 即为 Harbor 中的项目名),


并为其分配两个用户名,一个 RWS、一个 RS,xxl-api 是只读用户,还有一个对用户隐藏的 xxl-api-p 开发人员用户。以达到用户只能操作自己私有仓库的目的。

3 Harbor 的高可用

  • 负载均衡


通过三个 harbor 完成高可用部署,前面通过负载均衡器(HULK 上的 LVS)对外提供服务。共享数据库与缓存。



  • 多机房


多机房可以应对单机房 s3 异常,机房孤岛等及特殊情况,同时可以减轻主机房负担。


目前我们有 bjyt(主)和 shyc2(从)两套 harbor,push 都到主,k8s 拉镜像可以选择拉主或者从。


每个机房的 harbor 组件完全独立,包括 s3 和数据库。目的就是为了即使出现孤岛也不会影响服务。

什么是镜像

镜像就是,联合文件系统(UnionFS),目前用的驱动是 overlay2。


镜像的基础层是 rootfs:任何程序运行时都会有依赖,无论是开发语言层的依赖库,还是各种系统 lib、操作系统等,不同的系统上这些库可能是不一样的,或者有缺失的。为了让容器运行时一致,docker 将依赖的操作系统、各种 lib 依赖整合打包在一起(即镜像),然后容器启动时,作为它的根目录(根文件系统 rootfs),使得容器进程的各种依赖调用都在这个根目录里,这样就做到了环境的一致性。


Layer:Dockerfile 中的基础是 rootfs,而之后的每一个操作都是一层,如:RUN、ADD 等命令。所以为了镜像体积小写,可以把多个 RUN 命令整合成一行,这样多层就变成一层了。


镜像只有最上一层是读写的,其余都是只读的(目录的 whiteout 属性)。所谓 whiteout 属性 union 文件系统中,如果删除的文件在只读层,最上层看到文件已经删除,但是只读层文件依然存在,在最上层做改文件 whiteout 隐藏文件实现。rm mnt/haha.log 操作和 touch a/.wh.haha.log 效果相同。

1 容器的镜像挂载

docker 支持多种 graphDriver,包括 vfs、devicemapper、overlay、overlay2、aufs,docker-ce 镜像存储驱动目前用的是 overlay2。


docker 默认的存储目录是/var/lib/docker


[root@p22295v zhangzhifei]# ls -lrt /var/lib/docker/total 156drwx--x--x   3 root root  4096 Dec  6  2018 containerddrwx------   4 root root  4096 Dec  6  2018 pluginsdrwx------   3 root root  4096 Dec  6  2018 imagedrwx------   2 root root  4096 Dec  6  2018 trustdrwxr-x---   3 root root  4096 Dec  6  2018 networkdrwx------   2 root root  4096 Dec  6  2018 swarmdrwx------   2 root root  4096 Dec  6  2018 builderdrwx------  89 root root 12288 Jul 17 11:07 volumesdrwx------   2 root root  4096 Jul 17 14:30 runtimesdrwx------   2 root root  4096 Jul 23 12:51 tmpdrwx------ 758 root root 94208 Jul 29 19:12 overlay2drwx------  80 root root 12288 Jul 29 19:12 containers
复制代码


我们运行个容器演示下:


[root@p22295v zhangzhifei]# docker run -it -d  kraken-agent:dev 83555ad8c034682ad885fc9e320bfb1f8b75498b61a1a8684d738c411caa930b
复制代码


启动一个容器,在/var/lib/docker/overlay2 目录下生成一个容器视图层,目录包括 diff,link,lower,merged,work。


diff 记录每一层自己内容的数据,link 记录该层链接目录(实际是 l 目录下到层的链接),比如在容器中创建目录或在 diff 新增该目录。


根据存储数据及功能可以把这些层分为 3 部分:


1、只读层


2、init 层(夹在只读层和读写层之间,专门用来存放/etc/hosts、/etc/resolv.conf 等信息。需要这样一层的原因是,这些文件本来属于只读的系统镜像层的一部分,但是用户往往需要在启动容器时写入一些指定的值比如 hostname,所以就需要在可读写层对它们进行修改。可是,这些修改往往只对当前的容器有效,我们并不希望执行 docker commit 时,把这些信息连同可读写层一起提交掉。所以,Docker 做法是,在修改了这些文件之后,以一个单独的层挂载了出来。而用户执行 docker commit 只会提交可读写层,所以是不包含这些内容的。)


3、读写层(在没有写入文件之前,这个目录是空的。而一旦在容器里做了写操作,你修改产生的内容就会以增量的方式出现在这个层中)


查看容器挂载目录:


[root@p22295v zhangzhifei]# cat /var/lib/docker/image/overlay2/layerdb/mounts/83555ad8c034682ad885fc9e320bfb1f8b75498b61a1a8684d738c411caa930b/mount-id 3695f349587aaa2cdc82fcde1a380c7b567ef870a47e4c28b8b279e4edc9eb40[root@p22295v zhangzhifei]# #读写层[root@p22295v zhangzhifei]# ls /var/lib/docker/overlay2/3695f349587aaa2cdc82fcde1a380c7b567ef870a47e4c28b8b279e4edc9eb40/diff/[root@p22295v zhangzhifei]##只读层[root@p22295v zhangzhifei]# ls /var/lib/docker/overlay2/65e5cdd72f2995da4c73f2d9b90e8d974b9d2f18829a2479296aaec24e67d185/diff/bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var#只读层(Dockerfile时ADD的二进制程序)[root@p22295v zhangzhifei]# ls -lrt /var/lib/docker/overlay2/852fa5138c3da5070b59e6402348a5a281378b28ee08fede9c635e4101f91092/diff/usr/bin/total 28836-rwxr-xr-x 1 root root 29526888 Jul 10 16:23 kraken-origin
复制代码


最终,这些层都被联合挂载到/var/lib/docker/overlay2/3695f349587aaa2cdc82fcde1a380c7b567ef870a47e4c28b8b279e4edc9eb40/merged 目录下,表现为一个完整的文件系统和运行时环境供容器使用。


[root@p22295v zhangzhifei]# mount | grep 3695f349587aaa2cdc82fcde1a380c7b567ef870a47e4c28b8b279e4edc9eb40overlay on /var/lib/docker/overlay2/3695f349587aaa2cdc82fcde1a380c7b567ef870a47e4c28b8b279e4edc9eb40/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/Z7QMVXSKSNAKCUEJ6ZMU5YTFWG:/var/lib/docker/overlay2/l/2OYCXTK7M4QN3DT7IYJK6J7VYT:/var/lib/docker/overlay2/l/UZTDJDVUOBHU2VERRLXF5KMIQO:/var/lib/docker/overlay2/l/NAXXPRFMO4ATUIG6SFPU4LBUUV:/var/lib/docker/overlay2/l/AM4PHUFWOD4UHYIVO5Q6GVZ5L7:/var/lib/docker/overlay2/l/7XLJNT7Q3UQIKHDNV4QG4EX2C3:/var/lib/docker/overlay2/l/3RAVSDXXRS3BASAKZFPT2ESY2K:/var/lib/docker/overlay2/l/FFNAQF5ADFSTEBNZZ4O2R3CP4N:/var/lib/docker/overlay2/l/X6BOWOZKYRN3DZFY6QLLP7OFDP:/var/lib/docker/overlay2/l/P3EO3WHIM2XPDNPIFUP42EGMQI:/var/lib/docker/overlay2/l/EOSBLWDBASO7GKSDILC4XVGO45:/var/lib/docker/overlay2/l/7K7266OIDWAVXLAN6AA3SZXZQZ,upperdir=/var/lib/docker/overlay2/3695f349587aaa2cdc82fcde1a380c7b567ef870a47e4c28b8b279e4edc9eb40/diff,workdir=/var/lib/docker/overlay2/3695f349587aaa2cdc82fcde1a380c7b567ef870a47e4c28b8b279e4edc9eb40/work)[root@p22295v zhangzhifei]# ls  /var/lib/docker/overlay2/3695f349587aaa2cdc82fcde1a380c7b567ef870a47e4c28b8b279e4edc9eb40/mergedbin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
复制代码

镜像在镜像仓库中的存储

1 镜像存储的目录结构

以本地存储为例,默认在/data/registry/docker/registry/v2,镜像存储的任何一层都不会重复。


├── blobs│   └── sha256│       │   └── dfa94d685d1c2179324f02bf2a119f6d8ee0d380cef5506566012f7c4936a04a│       │       └── data│       ├── e6│       │   └── e6ae4ac760c8457aca9be07de8ca66b3a358a19b950389a0d158ae885178f6cf│       │       └── data│       ├── e7│       │   └── e71de1ca8f2b18993c258e2bf50edea8c23ea4a78a821bcfef181de50b3c32f4│       │       └── data└── repositories    ├── registry-share-private    │   ├── push-mount    │   │   ├── _layers    │   │   │   └── sha256    │   │   │       ├── 1b1ad4542c99b8881265610cf5dc09e37d38445529a7584edb2a607fd783216f    │   │   │       │   └── link    │   │   ├── _manifests    │   │   │   ├── revisions    │   │   │   │   └── sha256    │   │   │   │       └── 9e4cf4691735c02e59dd49ee561a3f5e56bccf78d57eaa94581e29f69a5162bd    │   │   │   │           └── link    │   │   │   └── tags    │   │   │       └── v1    │   │   │           ├── current    │   │   │           │   └── link    │   │   │           └── index    │   │   │               └── sha256    │   │   │                   └── 9e4cf4691735c02e59dd49ee561a3f5e56bccf78d57eaa94581e29f69a5162bd    │   │   │                       └── link    │   │   └── _uploads    │   ├── push-new    │   │   ├── _layers    │   │   │   └── sha256    │   │   │       ├── 1b1ad4542c99b8881265610cf5dc09e37d38445529a7584edb2a607fd783216f    │   │   │       │   └── link    │   │   ├── _manifests    │   │   │   ├── revisions    │   │   │   │   └── sha256    │   │   │   │       └── 9e4cf4691735c02e59dd49ee561a3f5e56bccf78d57eaa94581e29f69a5162bd    │   │   │   │           └── link    │   │   │   └── tags    │   │   │       └── v1    │   │   │           ├── current    │   │   │           │   └── link    │   │   │           └── index    │   │   │               └── sha256    │   │   │                   └── 9e4cf4691735c02e59dd49ee561a3f5e56bccf78d57eaa94581e29f69a5162bd    │   │   │                       └── link
复制代码


1、blobs


目录是存放每层数据(gzip)以及一个镜像的 manifests 信息(json)的具体文件


2、repositories


存储镜像的组织信息,类似于元数据


  • 仓库名


registry-share-private/push-mount 就是一个仓库名,registry-share-private 相当于 project 的概念,push-mount 容器名


  • _layers


目录类似于 blobs 目录,但是它不存储真是数据仅仅以 link 文件保存每个 layer 的 sha256 编码。保存该 repository 长传过得所有 layer 的 sha256 编码信息


  • _manifests


该 repository 的上传的所有版本(tag)的 manifest 信息。其目录下有 revisions 目录和 tags 目录


  • tags


每个 tag 一组记录(v1), 每个 tag 下面有 current 目录和 index 目录, current 目录下的 link 文件保存了该 tag 目前的 manifest 文件的 sha256 编码,而 index 目录则列出了该 tag 历史上传的所有版本的 sha256 编码信息


  • _revisions


目录里存放了该 repository 历史上上传版本的所有 sha256 编码信息


  • _uploads


是一个临时目录,一旦镜像上传完成,该目录下的文件就被删除

2 上传镜像流程

  • 认证

  • 到认证服务获取 token

  • 查询仓库中是否有欲上传的层

  • 开始上传 blob


大块用 patch 分块传,小块用 put。分块上传后也要以一个 put 请求表示完成上传。


  • 上传 mainfest


当所有的 blob 上传完成后需上传文件清单。


注意:


如果上传镜像的某一层在仓库中已经存在,并且有读的权限。docker 会先获取 token,之后携带这个 toke 进行 mount,减少重复层的上传,加快 push 速度


mount 信息处理其实就是在生产对应 layer 的信息放在_layers 目录下。


对于已经存在的层,但是没有权限的,客户端需要重新上传,但是最终存储还是一份。但是文件系统做 move 时,先判断目的路径是否存在,存在则不进行覆盖。


对于已经存在的镜像 HEAD 请求时世界返回 200,表示不需要上传。


本文转载自公众号 360 云计算(ID:hulktalk)。


原文链接:


https://mp.weixin.qq.com/s/GkISsJ6bBQ5_Kn6UdjoEeg


2019-11-14 18:251383

评论

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

软件测试 | 测试开发 | 测试平台开发-前端开发之Vue.js 框架的使用(二)

测吧(北京)科技有限公司

测试

软件测试 | 测试开发 | 被测系统架构与数据流分析

测吧(北京)科技有限公司

测试

关于事务注解中的常用参数详解

codeshero

Java 后端 事务 注解 9月月更

软件测试 | 测试开发 | BAT 大厂最流行的性能压测、监控、剖析技术体系解析

测吧(北京)科技有限公司

测试

k8s Tidb 实践-运维篇

TiDB 社区干货传送门

数据库前沿趋势

TiDB Lightning导入超大型txt文件实践

TiDB 社区干货传送门

迁移 管理与运维

软件测试 | 测试开发 | 被测项目需求你理解到位了么?

测吧(北京)科技有限公司

测试

实现Promise的原型方法--前端面试能力提升

helloworld1024fd

JavaScript

【“玩物立志”-scratch少儿编程】亲手实现小猫走迷宫小游戏:其实挺简单

清风莫追

游戏 scratch 10月月更

隐私计算大规模落地场景的解决之道:分布式计算架构

Jessica@数牍

隐私计算 分布式技术 分布式计算框架

DAPP系统开发Web3合约技术

薇電13242772558

dapp web3

软件测试 | 测试开发 | Docker 镜像构建可以分享的快乐

测吧(北京)科技有限公司

测试

TiFlash 源码阅读(九)TiFlash 中常用算子的设计与实现

TiDB 社区干货传送门

从React源码角度看useCallback,useMemo,useContext

goClient1992

React

百草味上线“本味甄果”系列罐装坚果 打造高品质坚果新标准

E科讯

C语言太细了

清风莫追

c 10月月更

Java | interface 和 implements关键字【接口,看这篇就够了】

Fire_Shield

Java 接口 9月月更

链上自动化何以成就更好的 Web3 | 对话 OAK Network

One Block Community

区块链 自动化 专访 波卡生态

软件测试 | 测试开发 | 30 分钟轻松搞定正则表达式基础

测吧(北京)科技有限公司

测试

软件测试 | 测试开发 | 测试平台开发-前端开发之Vue.js 框架(一)

测吧(北京)科技有限公司

测试

面试官:能用JavaScript手写一个bind函数吗

helloworld1024fd

JavaScript

国庆福利:6大云原生落地指南、100余页实用转型干货 免费下载!

York

容器 DevOps 微服务 云原生 应用现代化

软件测试 | 测试开发 | BAT大厂都在用的Docker。学会这三招,面试、工作轻松hold住

测吧(北京)科技有限公司

测试

软件测试 | 测试开发 | 黑盒测试方法论—等价类

测吧(北京)科技有限公司

测试

k8s Tidb实践-部署篇

TiDB 社区干货传送门

数据库前沿趋势

NFT 离商业化还有多远?

One Block Community

区块链 程序员 NFT 商业化

软件测试 | 测试开发 | 黑盒测试方法论—场景法

测吧(北京)科技有限公司

测试

数据中台中事实表设计概述

穿过生命散发芬芳

数据中台 9月月更

软件测试 | 测试开发 | Dubbo-admin+Zookeeper 的环境搭建实操与 Could-not-extract-archive 报错踩坑

测吧(北京)科技有限公司

测试

运维成本降低 50%,丽迅物流是如何应对大规模容器镜像管理挑战的

阿里巴巴云原生

阿里云 容器 云原生 镜像

弯曲矫正技术概述

合合技术团队

人工智能 深度学习 图片处理

  • 需要帮助,请添加网站小助手,进入 InfoQ 技术交流群
HULK容器镜像仓库简介_文化 & 方法_张志飞_InfoQ精选文章