Dragonfly Nydus——下一代容器格式的一种实现

OCIv2 implement

Posted by Zeusro on July 30, 2020
👈🏻 Select language

最近在学习造核弹,刚好碰到 Dragonfly 群里,来自蚂蚁金服的巴德大佬在直播分享另外一个子项目Nydus。

按照我的理解,Nydus是下一代容器格式的一种实现。其存在主要是为了解决旧的容器格式(container format)存在的问题。

那么问题来了,什么是 Nydus?什么是 container format? Nydus 具体解决了什么问题。这里先来一波名词扫盲。

名词扫盲

实际上,容器技术从1979年发展至今已经超过40年,docker 只能说是目前为止,其中一种比较著名而流行的实现。可以说,docker 解决了应用分发的难题,为日后 kubernetes 的流行奠定了基础。

但是,俗话说得好,勇士战胜恶龙之日,自身亦化作恶龙。不管是 Docker 公司后来各种神操作(把项目改名 Moby ,docker swarm 的弱鸡编排)也好,CoreOS 的崛起也罢,开源世界的战争,是一种技术标准的全球话语权争夺,这种争夺远比你想象的要残酷。

OCI

OCI全称 Open Container Initiative ,隶属于Linux基金会,是Docker, CoreOS联合其他容器厂商,于 2015-6-22 建立的一个开源组织。其目的主要是为了制定容器技术的通用技术标准。

OCI旗下主要有2个项目:

  1. runtime-spec
  2. image-spec

OCIv1

image

OCIv1 就是目前的容器格式。

OCIv2

OCIv2 就是为了解决 OCIv1 的历史技术债务。

Dragonfly Nydus

2020年4 月 10 日,由云原生计算基金会(CNCF)技术监督委员会投票决议,来自中国的开源项目 Dragonfly 正式晋升为 CNCF 孵化级别的托管项目,成为继 Harbor、TiKV 之后,第三个进入 CNCF 孵化阶段的中国项目。

image

Dragonfly 的架构主要是为了解决了大规模镜像下载、远距离传输、带宽成本控制、安全传输这四大难题。

image

Nydus 是OCIv2的一种实现,计划捐给 Dragonfly ,作为其旗下一个子项目运作。

当前容器格式的问题

image

在直播分享中,巴德大佬提到了OCIv1的几个问题:

  1. 分层效率很低
  2. 数据没有校验
  3. 可重建性问题

分层效率很低

image

分层效率低主要是指冗余性。如果把 docker image 比喻作汉堡包,镜像A是吉士汉堡包。

1
FROM centos

image

镜像B是双层吉士汉堡包。

1
2
FROM centos
RUN yum update -y
1
2
3
4
# 拉取吉士汉堡包
docker pull h1
# 拉取双层吉士汉堡包
docker pull h2

那么按照目前的设计,镜像之间是独立的,也就是说,拉取h1之后,虽然磁盘里面已经缓存了 centos 的底层镜像,但是拉取h2的时候,还是重新拉取整个镜像,并没有复用 centos 那个底层镜像。最终导致了磁盘的冗余和网络流量的浪费。

分层效率低还有另外一个体现。

1
2
3
4
5
FROM ubuntu:14.04
ADD compressed.tar /
# 这里的删除只是一个标记,实际镜像大小 = compressed.tar * 2 + ubuntu:14.04
RUN rm /compressed.tar
ADD compressed.tar /

像这个 docker image ,实际在运行的时候, container 里面的根目录大小比镜像小得多。

所以,镜像大小和容器大小有着本质的区别

数据没有校验(Verifiability)

这里稍加引述巴德大佬的话:

只读层被修改了,容器应用是不知道的。现在的OCI镜像格式下就有可能发生这种事情,镜像在构建和传输过程中是可校验的,但是镜像下载到本地后会被解压,解压后的文件的修改是无法探知的。

镜像需要下载,解压到本地文件系统,然后再交给容器去使用。这个流程中,解压到本地文件系统这一步是丢失可信的关键。

workspace 可重建性问题(repairability)

可重建性可以从某种程度上解决 docker build 慢的问题。

以轻量级 kubernetes event导出组件 kube-eventer为例,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM golang:1.14 AS build-env
ADD . /src/github.com/AliyunContainerService/kube-eventer
ENV GOPATH /:/src/github.com/AliyunContainerService/kube-eventer/vendor
ENV GO111MODULE on
WORKDIR /src/github.com/AliyunContainerService/kube-eventer
RUN apt-get update -y && apt-get install gcc ca-certificates
RUN make


FROM alpine:3.10

COPY --from=build-env /src/github.com/AliyunContainerService/kube-eventer/kube-eventer /
COPY --from=build-env /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

ENV TZ "Asia/Shanghai"
RUN apk add --no-cache tzdata
COPY deploy/entrypoint.sh /

ENTRYPOINT ["/kube-eventer"]

我们在机器A上反复执行docker build,每次的构建都是原子的,也就是说,每一次都是从上到下重新跑一遍。但实际上我们知道,很多指令都是重复的,没有必要重复执行。

可重建性还有另外一层意思,从机器A拷贝到机器B之后,继续构建docker image。

我的吐槽

在我看来,目前的 OCIv1 借鉴了 git 的设计,但本质是一个很难吃的汉堡包。只有最上面一层可以吃(读写)。

云原生应用的交付周期,一般是

git Ops –> CI –> docker image –> waiting container/pod(docker pull,sandbox etc) –> running container/pod –> terminated container/pod

云原生应用的安全性由运行时环境和 docker container 组成,一个安全的 docker container ,应当尽量让它在各个环节里面,都没有可乘之机。

比如,从代码到CI的过程中,应当有静态代码分析 + 人工 code review 的机制,确保代码无安全性上的问题;从CI到 docker image 的构建过程中,应当让CI运行在一个可信的环境。这个可信的环境包括了可信的权威DNS,可控的安全防火墙,受限的网络连接以及安全扫描套件(杀毒软件)。

image

从这个层面上讲,Nydus 计算每一层哈希,不仅不是很专业,而且很慢。这一块内容交给更高效的安全引擎,Nydus 做个异步事件回调/消息发布订阅,也许更好。

综上所述,结合短桶原理,可以得出这样的结论:容器的安全性需要各方协调,云原生应用不存在绝对意义上的安全

最后,欢迎大家加入Dragonfly项目,项目钉群群主是《Docker源码分析》的作者孙宏亮。在国内《21天学会XX》垃圾技术书风行的大背景下,这本书是一股清流。

image

同时也欢迎大家参与OCIv2标准的共建

结论

PPT first,bug secondly.

我想暗中买一批孙宏亮大佬写的第一版《Docker源码分析》,之后再潜入阿里云,要到他的亲笔签名,最后再转卖出去🤣

image

参考链接

[1] docker、oci、runc以及kubernetes梳理 https://xuxinkun.github.io/2017/12/12/docker-oci-runc-and-kubernetes/

[2] About the Open Container Initiative https://opencontainers.org/about/overview/

[3] The Road to OCIv2 Images: What’s Wrong with Tar? https://www.cyphar.com/blog/post/20190121-ociv2-images-i-tar

[4] 重磅 | Dragonfly 晋升成为 CNCF 孵化项目 https://developer.aliyun.com/article/754452

[5] Dockerfile 操作建议 https://jiajially.gitbooks.io/dockerguide/content/chapter_fastlearn/dockerfile_tips.html

[6] 利用暴露在外的API,无法检测的Linux恶意软件将矛头指向Docker服务器 https://mp.weixin.qq.com/s?__biz=MzA5OTAyNzQ2OA==&mid=2649710368&idx=1&sn=afc957a5622a9bb658aa63574368400e&chksm=88936043bfe4e95563e6d8ca05c2bce662338072daa58f2ffd299ecbf26a7b57e33b5c871e4c&mpshare=1&scene=23&srcid=0803MLplml3bb8uyaXAyC2Rg&sharer_sharetime=1596696405119&sharer_shareid=9b8919de2238b20229856a42c8974cdc%23rd

Recently I’ve been learning how to build nuclear bombs, and I happened to come across a live stream in the Dragonfly group where Ba De, a big shot from Ant Financial, was sharing another sub-project called Nydus.

Based on my understanding, Nydus is an implementation of the next-generation container format. It exists mainly to solve problems with the old container format.

So the question is: What is Nydus? What is a container format? What specific problems does Nydus solve? Let’s start with some terminology.

Terminology

In fact, container technology has been developing for over 40 years since 1979. Docker can only be said to be one of the more famous and popular implementations so far. It can be said that Docker solved the problem of application distribution and laid the foundation for the future popularity of Kubernetes.

However, as the saying goes, when the warrior defeats the dragon, he himself becomes the dragon. Whether it’s Docker Inc.’s later various operations (renaming the project to Moby, Docker Swarm’s weak orchestration) or CoreOS’s rise, the war in the open source world is a global battle for discourse power over technical standards, and this battle is far more brutal than you imagine.

OCI

OCI stands for Open Container Initiative, which belongs to the Linux Foundation. It is an open source organization established on 2015-6-22 by Docker, CoreOS, and other container vendors, with the main purpose of establishing common technical standards for container technology.

OCI has two main projects:

  1. runtime-spec
  2. image-spec

OCIv1

image

OCIv1 is the current container format.

OCIv2

OCIv2 is designed to solve the historical technical debt of OCIv1.

Dragonfly Nydus

On April 10, 2020, through a vote by the CNCF Technical Oversight Committee, the open source project Dragonfly from China officially became a CNCF incubating project, becoming the third Chinese project to enter the CNCF incubation stage after Harbor and TiKV.

image

Dragonfly’s architecture is mainly designed to solve four major problems: large-scale image downloads, long-distance transmission, bandwidth cost control, and secure transmission.

image

Nydus is an implementation of OCIv2, planned to be donated to Dragonfly and operated as a sub-project under it.

Problems with Current Container Format

image

In the live stream, Ba De mentioned several problems with OCIv1:

  1. Very low layer efficiency
  2. No data verification
  3. Repairability issues

Very Low Layer Efficiency

image

Low layer efficiency mainly refers to redundancy. If we compare a docker image to a hamburger, image A is a cheeseburger.

1
FROM centos

image

Image B is a double cheeseburger.

1
2
FROM centos
RUN yum update -y
1
2
3
4
# Pull the cheeseburger
docker pull h1
# Pull the double cheeseburger
docker pull h2

According to the current design, images are independent of each other. That is, after pulling h1, although the underlying centos image is already cached on disk, when pulling h2, it still pulls the entire image again without reusing the underlying centos image. This ultimately leads to disk redundancy and wasted network traffic.

Low layer efficiency has another manifestation.

1
2
3
4
5
FROM ubuntu:14.04
ADD compressed.tar /
# The deletion here is just a marker, actual image size = compressed.tar * 2 + ubuntu:14.04
RUN rm /compressed.tar
ADD compressed.tar /

For this docker image, when actually running, the root directory size in the container is much smaller than the image.

So, image size and container size are fundamentally different.

No Data Verification (Verifiability)

Here’s a quote from Ba De:

If a read-only layer is modified, the container application doesn’t know. This can happen with the current OCI image format. Images are verifiable during construction and transmission, but after the image is downloaded locally, it will be decompressed, and modifications to the decompressed files cannot be detected.

Images need to be downloaded, decompressed to the local file system, and then handed over to the container for use. In this process, the step of decompressing to the local file system is where trust is lost.

Workspace Repairability Issues

Repairability can solve the problem of slow docker build to some extent.

Taking the lightweight Kubernetes event export component kube-eventer as an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM golang:1.14 AS build-env
ADD . /src/github.com/AliyunContainerService/kube-eventer
ENV GOPATH /:/src/github.com/AliyunContainerService/kube-eventer/vendor
ENV GO111MODULE on
WORKDIR /src/github.com/AliyunContainerService/kube-eventer
RUN apt-get update -y && apt-get install gcc ca-certificates
RUN make


FROM alpine:3.10

COPY --from=build-env /src/github.com/AliyunContainerService/kube-eventer/kube-eventer /
COPY --from=build-env /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

ENV TZ "Asia/Shanghai"
RUN apk add --no-cache tzdata
COPY deploy/entrypoint.sh /

ENTRYPOINT ["/kube-eventer"]

When we repeatedly execute docker build on machine A, each build is atomic, meaning each time it runs from top to bottom again. But actually we know that many instructions are repeated and don’t need to be executed repeatedly.

Repairability also means another thing: after copying from machine A to machine B, continue building the docker image.

My Thoughts

In my opinion, the current OCIv1 borrows from git’s design, but is essentially a hamburger that’s hard to eat. Only the top layer can be eaten (read-write).

The delivery cycle of cloud-native applications is generally:

git Ops –> CI –> docker image –> waiting container/pod (docker pull, sandbox etc) –> running container/pod –> terminated container/pod

The security of cloud-native applications consists of the runtime environment and docker container. A secure docker container should try to leave no opportunities for exploitation at every stage.

For example, in the process from code to CI, there should be static code analysis + manual code review mechanisms to ensure there are no security issues in the code; in the process from CI to docker image construction, CI should run in a trusted environment. This trusted environment includes trusted authoritative DNS, controllable security firewalls, restricted network connections, and security scanning suites (antivirus software).

image

From this perspective, Nydus calculating the hash of each layer is not only not very professional, but also slow. This content should be handed over to a more efficient security engine, and Nydus should do asynchronous event callbacks/message pub-sub, which might be better.

In summary, combined with the short barrel principle, we can draw this conclusion: Container security requires coordination from all parties, and cloud-native applications are not absolutely secure.

Finally, welcome everyone to join the Dragonfly project. The project DingTalk group owner is Sun Hongliang, author of “Docker Source Code Analysis”. In the context of domestic “Learn XX in 21 Days” garbage technical books being popular, this book is a breath of fresh air.

image

Also welcome everyone to participate in co-building the OCIv2 standard.

Conclusion

PPT first, bug secondly.

I want to secretly buy a batch of the first edition of “Docker Source Code Analysis” written by Sun Hongliang, then infiltrate Alibaba Cloud to get his autograph, and finally resell it 🤣

image

References

[1] docker、oci、runc以及kubernetes梳理 https://xuxinkun.github.io/2017/12/12/docker-oci-runc-and-kubernetes/

[2] About the Open Container Initiative https://opencontainers.org/about/overview/

[3] The Road to OCIv2 Images: What’s Wrong with Tar? https://www.cyphar.com/blog/post/20190121-ociv2-images-i-tar

[4] 重磅 | Dragonfly 晋升成为 CNCF 孵化项目 https://developer.aliyun.com/article/754452

[5] Dockerfile 操作建议 https://jiajially.gitbooks.io/dockerguide/content/chapter_fastlearn/dockerfile_tips.html

[6] 利用暴露在外的API,无法检测的Linux恶意软件将矛头指向Docker服务器 https://mp.weixin.qq.com/s?__biz=MzA5OTAyNzQ2OA==&mid=2649710368&idx=1&sn=afc957a5622a9bb658aa63574368400e&chksm=88936043bfe4e95563e6d8ca05c2bce662338072daa58f2ffd299ecbf26a7b57e33b5c871e4c&mpshare=1&scene=23&srcid=0803MLplml3bb8uyaXAyC2Rg&sharer_sharetime=1596696405119&sharer_shareid=9b8919de2238b20229856a42c8974cdc%23rd

Недавно я изучал, как создавать ядерные бомбы, и случайно наткнулся на прямую трансляцию в группе Dragonfly, где Ба Дэ, большой специалист из Ant Financial, делился другим подпроектом Nydus.

По моему пониманию, Nydus — это реализация формата контейнеров следующего поколения. Он существует главным образом для решения проблем старого формата контейнеров (container format).

Итак, вопрос: Что такое Nydus? Что такое container format? Какие конкретные проблемы решает Nydus? Начнём с терминологии.

Терминология

На самом деле, технология контейнеров развивается уже более 40 лет с 1979 года. Docker можно назвать лишь одной из более известных и популярных реализаций на данный момент. Можно сказать, что Docker решил проблему распространения приложений и заложил основу для будущей популярности Kubernetes.

Однако, как гласит поговорка, когда воин побеждает дракона, он сам становится драконом. Будь то последующие операции Docker Inc. (переименование проекта в Moby, слабая оркестрация docker swarm) или подъём CoreOS, война в мире open source — это глобальная борьба за право голоса в технических стандартах, и эта борьба гораздо более жестока, чем вы думаете.

OCI

OCI — это Open Container Initiative, принадлежащая Linux Foundation. Это открытая организация, основанная Docker, CoreOS и другими производителями контейнеров 22 июня 2015 года, с основной целью установления общих технических стандартов для технологии контейнеров.

У OCI есть два основных проекта:

  1. runtime-spec
  2. image-spec

OCIv1

image

OCIv1 — это текущий формат контейнеров.

OCIv2

OCIv2 создан для решения исторического технического долга OCIv1.

Dragonfly Nydus

10 апреля 2020 года, по решению голосования Технического надзорного комитета CNCF, открытый проект Dragonfly из Китая официально стал проектом уровня инкубации CNCF, став третьим китайским проектом, вошедшим в стадию инкубации CNCF после Harbor и TiKV.

image

Архитектура Dragonfly в основном предназначена для решения четырёх основных проблем: загрузка образов в больших масштабах, передача на большие расстояния, контроль стоимости пропускной способности и безопасная передача.

image

Nydus — это реализация OCIv2, планируется передать в дар Dragonfly и работать как подпроект под ним.

Проблемы текущего формата контейнеров

image

В прямой трансляции Ба Дэ упомянул несколько проблем OCIv1:

  1. Очень низкая эффективность слоёв
  2. Нет проверки данных
  3. Проблемы ремонтопригодности

Очень низкая эффективность слоёв

image

Низкая эффективность слоёв в основном относится к избыточности. Если сравнить docker image с гамбургером, образ A — это чизбургер.

1
FROM centos

image

Образ B — это двойной чизбургер.

1
2
FROM centos
RUN yum update -y
1
2
3
4
# Загрузить чизбургер
docker pull h1
# Загрузить двойной чизбургер
docker pull h2

Согласно текущему дизайну, образы независимы друг от друга. То есть после загрузки h1, хотя базовый образ centos уже закэширован на диске, при загрузке h2 всё равно загружается весь образ заново без повторного использования базового образа centos. Это в конечном итоге приводит к избыточности диска и растрате сетевого трафика.

Низкая эффективность слоёв имеет ещё одно проявление.

1
2
3
4
5
FROM ubuntu:14.04
ADD compressed.tar /
# Удаление здесь — это просто маркер, фактический размер образа = compressed.tar * 2 + ubuntu:14.04
RUN rm /compressed.tar
ADD compressed.tar /

Для этого docker image, при фактическом запуске, размер корневого каталога в контейнере намного меньше образа.

Итак, размер образа и размер контейнера принципиально различны.

Нет проверки данных (Verifiability)

Вот цитата Ба Дэ:

Если слой только для чтения изменён, контейнерное приложение не знает об этом. Это может произойти с текущим форматом образа OCI. Образы проверяемы во время построения и передачи, но после загрузки образа локально он будет распакован, и изменения в распакованных файлах не могут быть обнаружены.

Образы нужно загрузить, распаковать в локальную файловую систему, а затем передать контейнеру для использования. В этом процессе шаг распаковки в локальную файловую систему — это место, где теряется доверие.

Проблемы ремонтопригодности workspace

Ремонтопригодность может в некоторой степени решить проблему медленного docker build.

Возьмём в качестве примера лёгкий компонент экспорта событий Kubernetes kube-eventer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM golang:1.14 AS build-env
ADD . /src/github.com/AliyunContainerService/kube-eventer
ENV GOPATH /:/src/github.com/AliyunContainerService/kube-eventer/vendor
ENV GO111MODULE on
WORKDIR /src/github.com/AliyunContainerService/kube-eventer
RUN apt-get update -y && apt-get install gcc ca-certificates
RUN make


FROM alpine:3.10

COPY --from=build-env /src/github.com/AliyunContainerService/kube-eventer/kube-eventer /
COPY --from=build-env /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

ENV TZ "Asia/Shanghai"
RUN apk add --no-cache tzdata
COPY deploy/entrypoint.sh /

ENTRYPOINT ["/kube-eventer"]

Когда мы многократно выполняем docker build на машине A, каждая сборка атомарна, то есть каждый раз она запускается заново сверху вниз. Но на самом деле мы знаем, что многие инструкции повторяются и не нужно выполнять их повторно.

Ремонтопригодность также означает другое: после копирования с машины A на машину B продолжить построение docker image.

Мои мысли

На мой взгляд, текущий OCIv1 заимствует дизайн git, но по сути это гамбургер, который трудно есть. Только верхний слой можно есть (чтение-запись).

Цикл доставки облачных приложений обычно такой:

git Ops –> CI –> docker image –> waiting container/pod(docker pull, sandbox etc) –> running container/pod –> terminated container/pod

Безопасность облачных приложений состоит из среды выполнения и docker container. Безопасный docker container должен стараться не оставлять возможностей для эксплуатации на каждом этапе.

Например, в процессе от кода к CI должны быть механизмы статического анализа кода + ручного code review, чтобы убедиться, что в коде нет проблем безопасности; в процессе от CI к построению docker image, CI должен работать в доверенной среде. Эта доверенная среда включает доверенный авторитетный DNS, управляемый брандмауэр безопасности, ограниченные сетевые подключения и наборы сканирования безопасности (антивирусное программное обеспечение).

image

С этой точки зрения, вычисление Nydus хеша каждого слоя не только не очень профессионально, но и медленно. Эту часть следует передать более эффективному механизму безопасности, а Nydus должен делать асинхронные обратные вызовы событий/публикацию-подписку сообщений, что может быть лучше.

В заключение, в сочетании с принципом короткой бочки, можно сделать такой вывод: Безопасность контейнеров требует координации всех сторон, облачные приложения не являются абсолютно безопасными.

Наконец, приветствуем всех присоединиться к проекту Dragonfly. Владелец группы проекта DingTalk — Сун Хунлян, автор «Анализа исходного кода Docker». На фоне популярности мусорных технических книг «Изучи XX за 21 день» в стране, эта книга — глоток свежего воздуха.

image

Также приветствуем всех принять участие в совместном построении стандарта OCIv2.

Заключение

PPT first, bug secondly.

Я хочу тайно купить партию первого издания «Анализа исходного кода Docker», написанного Сун Хунлян, затем проникнуть в Alibaba Cloud, получить его автограф, и в конце концов перепродать 🤣

image

Ссылки

[1] docker、oci、runcおよびkubernetesの整理 https://xuxinkun.github.io/2017/12/12/docker-oci-runc-and-kubernetes/

[2] About the Open Container Initiative https://opencontainers.org/about/overview/

[3] The Road to OCIv2 Images: What’s Wrong with Tar? https://www.cyphar.com/blog/post/20190121-ociv2-images-i-tar

[4] Важно | Dragonfly становится проектом инкубации CNCF https://developer.aliyun.com/article/754452

[5] Рекомендации по работе с Dockerfile https://jiajially.gitbooks.io/dockerguide/content/chapter_fastlearn/dockerfile_tips.html

[6] Используя открытые API, необнаруживаемое Linux-вредоносное ПО нацеливается на серверы Docker https://mp.weixin.qq.com/s?__biz=MzA5OTAyNzQ2OA==&mid=2649710368&idx=1&sn=afc957a5622a9bb658aa63574368400e&chksm=88936043bfe4e95563e6d8ca05c2bce662338072daa58f2ffd299ecbf26a7b57e33b5c871e4c&mpshare=1&scene=23&srcid=0803MLplml3bb8uyaXAyC2Rg&sharer_sharetime=1596696405119&sharer_shareid=9b8919de2238b20229856a42c8974cdc%23rd