写点什么

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:251131

评论

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

手把手教学电瓶车进电梯检测、多类别车辆追踪、异常行为检测产业级应用

百度大脑

【架构师训练营】模块八作业

樰巳-堕~Horry

架构实战营 「架构实战营」

重学架构之外包学生管理系统架构设计文档

陈华英

架构实战营

外包学生管理系统架构

浪飞

中国 PostgreSQL 分会加入龙蜥社区,携手共建基础软件开源新生态

OpenAnolis小助手

postgresql Linux 开源

全面解析湖仓一体与大数据演进历程|内含技术工具选型策略

云智慧AIOps社区

数据库 大数据 数据湖 Clickhouse 大数据运维

原生JavaScript灵魂拷问,你能答上多少(一)

战场小包

JavaScript 前端 2月月更

模块三作业

blazar

「架构实战营」

模块三作业

Leo

基于Qt设计的学生考勤系统

DS小龙哥

2月月更

web前端开发Nodejs的C++ 拓展开发_前端培训

@零度

node.js 前端开发

外包学生管理系统架构设计文档

石小天

「架构实战营」

外包学生管理系统架构设计文档

「架构实战营」

JUC 中 4 个常用的并发工具类

小谷哥

学生管理系统-详细架构设计文档

AragornYang

架构训练营 架构实战营

使用 Solidity、Web3 和 Vue.js 创建区块链游戏

devpoint

dapp NFT Solidity 2月月更

DDD实战(2):看看代码结构长啥样

深清秋

DDD 软件架构 生鲜电商系统

震坤行工业超市研发效能提升之路

阿里云云效

云计算 阿里云 DevOps 云原生 研发

外包学生管理系统架构设计文档

smile

Go学习笔记——复合数据类型

为自己带盐

Go 学习笔记 2月月更

学生管理系统 - 详细设计方案

tom

如何更好的使用TypeScript

Tone荣

前端 js ts js 转 ts

java培训:Netty的内存管理

@零度

Java Netty

等保2.0政策之物联网安全扩展要求包括哪四个?

行云管家

云计算 物联网 等保 等保2.0 扩展要求

模块三作业

Mr小公熊

「架构实战营」模块三作业 外包学生管理系统架构设计

hxb

「架构实战营」

G1 面向服务端(多CPU)应用的垃圾回收器

蜜糖的代码注释

Java 垃圾回收器 2月月更

云计算架构设计6大原则,你遵循了吗?

博文视点Broadview

掉入成功的深渊

Shinta

ESLint-源码分析

Tone荣

前端 eslint

微服务从代码到k8s部署应有尽有系列(三、鉴权)

万俊峰Kevin

微服务 web开发 鉴权 go-zero Go 语言

HULK容器镜像仓库简介_文化 & 方法_张志飞_InfoQ精选文章