首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

终于可以像使用 Docker 一样丝滑地使用 Containerd 了!

有追求的工程师一般都是有技术洁癖的,云原生的世界更是如此,Kubernetes?虽然制定了容器运行时接口(CRI)标准,但早期能用的容器运行时只有?Docker,而?Docker?又不适配这个标准,于是给?Docker?开了后门,花了大量的精力去适配它。后来有了更多的容器运行时可以选择后,Kubernetes 就不得不重新考量要不要继续适配 Docker 了,因为每次更新 Kubelet 都要考虑与 Docker 的适配问题。

标准这个东西就是这样,我定好标准,你兼容了就一起玩,不兼容就拜拜,它就像两个人在一起的底线,你可以重,你可以丑,你也可以不完善,但是你不兼容标准就真的不能一起玩了,于是 Kubernetes 就把 Docker 踢出了群聊。

最终 Kubernetes 选择了?Containerd,时至今日?Containerd?已经变成一个工业级的容器运行时了,它足够简单、健壮,可移植性也很强。

现有 CLI 的不足

虽然 Docker 能干的事情,现在?Containerd?都能干,但?Containerd?还有一个非常明显的缺陷:CLI 不够友好。它无法像 Docker 和 Podman 一样通过一条简单的命令启动一个容器,它的两个 CLI 工具?ctr[1]?和?crictl[2]?都无法实现这么一件非常简单的需求,而这个需求是大多数人都需要的,我总不能为了在本地测试容器而专门部署一个 Kubernetes 集群吧?

ctr 的设计对人类不太友好,例如缺少以下这些和 Docker 类似的功能:

  • docker run -p <PORT>
  • docker run --restart=always
  • 通过凭证文件?~/.docker/config.json?来拉取镜像
  • docker logs

除此之外还有一个 CLI 工具叫?crictl,和?ctr?一样不太友好。

为了解决这个痛点,Containerd 官方推出了一个新的 CLI 叫?nerdctl[3]。nerdctl 的使用体验和 docker 一样顺滑,例如:

代码语言:javascript
复制
???→?nerdctl?run?-d?-p?8080:80?--name=nginx?--restart=always?nginx

nerdctl 只是 docker 的复制品?

nerdctl?的目标并不是单纯地复制 docker 的功能,它还实现了很多 docker 不具备的功能,例如延迟拉取镜像(lazy-pulling[4])、镜像加密(imgcrypt[5])等。

延迟拉取镜像功能可以参考这篇文章:Containerd 使用 Stargz Snapshotter 延迟拉取镜像[6]

虽然这些功能预计最终也会在 Docker 中实现,但可能需要几个月甚至几年的时间[7],因为 Docker 目前的设计只使用一小部分?Containerd?子系统。将来 Docker 有可能重构代码以使用完整的?Containerd,但目前还没看到什么实质性进展。所以?Containerd?社区决定创建一个新的 CLI 来更友好地使用?Containerd

nerdctl 试用

你可以从?nerdctl 的 release[8]?中下载最新的可执行文件,每一个版本都有两种可用的发行版:

  • nerdctl-<VERSION>-linux-amd64.tar.gz?: 只包含 nerdctl。
  • nerdctl-full-<VERSION>-linux-amd64.tar.gz?: 包含了 nerdctl 和相关依赖组件(containerd, runc, CNI, …)。

如果你已经安装了 Containerd,只需要选择前一个发行版,否则就选择完整版。

安装好 nerdctl 后,就可以使用 nerdctl 来运行容器了:

代码语言:javascript
复制
???→?nerdctl?run?-d?-p?80:80?--name=nginx?--restart=always?nginx:alpine

docker.io/library/nginx:alpine:???????????????????????????????????????????????????resolved???????|++++++++++++++++++++++++++++++++++++++|
index-sha256:d33e9e24389d7d8b90fe2bcc2dd1bc09b4d235e916ba9d5d9a71cf52e340edb6:????done???????????|++++++++++++++++++++++++++++++++++++++|
manifest-sha256:c1f4e1974241c3f9ddb2866b2bf8e7afbceaa42dae82aabda5e946d03f054ed2:?done???????????|++++++++++++++++++++++++++++++++++++++|
config-sha256:bfad9487e175364fd6315426feeee34bf5e6f516d2fe6a4e9b592315e330828e:???done???????????|++++++++++++++++++++++++++++++++++++++|
layer-sha256:29d3f97df6fd99736a0676f9e57e53dfa412cf60b26d95008df9da8197f1f366:????done???????????|++++++++++++++++++++++++++++++++++++++|
layer-sha256:9aae54b2144e5b2b00c610f8805128f4f86822e1e52d3714c463744a431f0f4a:????done???????????|++++++++++++++++++++++++++++++++++++++|
layer-sha256:a5f0adaddd5456b7c5a3753ab541b5fad750f0a6499a15f63571b964eb3e2616:????done???????????|++++++++++++++++++++++++++++++++++++++|
layer-sha256:5df810e1c460527fe400cdd2cab62228f5fb3da0f2dce86a6a6c354972f19b6e:????done???????????|++++++++++++++++++++++++++++++++++++++|
layer-sha256:345aee38d3533398e0eb7118e4323a8970f7615136f2170dfb2b0278bbd9099d:????done???????????|++++++++++++++++++++++++++++++++++++++|
layer-sha256:e6a4c36d7c0e358e5fc02ccdac645b18b85dcfec09d4fb5f8cbdc187ce9467a0:????done???????????|++++++++++++++++++++++++++++++++++++++|
elapsed:?5.7?s????????????????????????????????????????????????????????????????????total:??9.4?Mi?(1.6?MiB/s)
27b55e0b18b10c4c8f34e3ba709614e7b1760a75db061d2ce5183e8b1101ce09

查看创建的容器:

代码语言:javascript
复制
???→?nerdctl?ps

CONTAINER?ID????IMAGE?????????????????????????????COMMAND???????????????????CREATED??????????STATUS????PORTS?????????????????NAMES
3b5faa266a43????docker.io/library/nginx:alpine????"/docker-entrypoint.…"????3?minutes?ago????Up????????0.0.0.0:80->80/tcp????nginx

和 Docker 一样,Containerd 也有一个子命令?network

代码语言:javascript
复制
???→?nerdctl?network?ls

NETWORK?ID????NAME???????????????FILE
0?????????????bridge
??????????????k8s-pod-network????/etc/cni/net.d/10-calico.conflist
??????????????host
??????????????none

来看下默认的 bridge 配置:

代码语言:javascript
复制
???→?nerdctl?network?inspect?bridge
[
????{
????????"CNI":?{
????????????"cniVersion":?"0.4.0",
????????????"name":?"bridge",
????????????"nerdctlID":?0,
????????????"plugins":?[
????????????????{
????????????????????"type":?"bridge",
????????????????????"bridge":?"nerdctl0",
????????????????????"isGateway":?true,
????????????????????"ipMasq":?true,
????????????????????"hairpinMode":?true,
????????????????????"ipam":?{
????????????????????????"type":?"host-local",
????????????????????????"routes":?[
????????????????????????????{
????????????????????????????????"dst":?"0.0.0.0/0"
????????????????????????????}
????????????????????????],
????????????????????????"ranges":?[
????????????????????????????[
????????????????????????????????{
????????????????????????????????????"subnet":?"10.4.0.0/24",
????????????????????????????????????"gateway":?"10.4.0.1"
????????????????????????????????}
????????????????????????????]
????????????????????????]
????????????????????}
????????????????},
????????????????{
????????????????????"type":?"portmap",
????????????????????"capabilities":?{
????????????????????????"portMappings":?true
????????????????????}
????????????????},
????????????????{
????????????????????"type":?"firewall"
????????????????},
????????????????{
????????????????????"type":?"tuning"
????????????????}
????????????]
????????},
????????"NerdctlID":?0
????}
]

可以看到?network?子命令背后还是 CNI 在运作,与 docker network 子命令原理不同。

构建镜像

nerdctl?也可以和?buildkit?结合使用来构建容器镜像,需要先下载 buildkit 的可执行文件:

代码语言:javascript
复制
???→?wget?https://github.com/moby/buildkit/releases/download/v0.8.2/buildkit-v0.8.2.darwin-amd64.tar.gz

将其解压到?$PATH?中:

代码语言:javascript
复制
???→?tar?-C?/usr/local/?-zxvf?buildkit-v0.8.2.linux-amd64.tar.gz

编写 systemd unit 文件:

代码语言:javascript
复制
#?/etc/systemd/system/buildkit.service
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit

[Service]
ExecStart=/usr/local/bin/buildkitd?--oci-worker=false?--containerd-worker=true

[Install]
WantedBy=multi-user.target

启用 buildkit.service 并设置开机自动运行:

代码语言:javascript
复制
???→?systemctl?enable?--now?buildkit.service

下面以?KubeSphere[9]?项目为例,展示如何使用?nerdctl?来构建镜像。

首先克隆 KubeSphere 官方仓库:

代码语言:javascript
复制
???→?git?clone?--depth=1?https://github.com.cnpmjs.org/kubesphere/kubesphere.git

进入仓库目录,编译二进制文件:

代码语言:javascript
复制
???→?cd?kubesphere
???→?make?ks-apiserver

将二进制文件拷贝到?Dockerfile?目录:

代码语言:javascript
复制
???→?cp?bin/cmd/ks-apiserver?build/ks-apiserver

进入?Dockerfile?目录,修改 Dockerfile:

代码语言:javascript
复制
#?Copyright?2020?The?KubeSphere?Authors.?All?rights?reserved.
#?Use?of?this?source?code?is?governed?by?an?Apache?license
#?that?can?be?found?in?the?LICENSE?file.
FROM?alpine:3.11

ARG?HELM_VERSION=v3.5.2

RUN?apk?add?--no-cache?ca-certificates
#?install?helm
RUN?wget?https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz?&&?\
????tar?xvf?helm-${HELM_VERSION}-linux-amd64.tar.gz?&&?\
????rm?helm-${HELM_VERSION}-linux-amd64.tar.gz?&&?\
????mv?linux-amd64/helm?/usr/bin/?&&?\
????rm?-rf?linux-amd64
#?To?speed?up?building?process,?we?copy?binary?directly?from?make
#?result?instead?of?building?it?again,?so?make?sure?you?run?the
#?following?command?first?before?building?docker?image
#???make?ks-apiserver
#
COPY??ks-apiserver?/usr/local/bin/

EXPOSE?9090
CMD?["sh"]

构建镜像:

代码语言:javascript
复制
???→?cd?build/ks-apiserver

???→?nerdctl?build?-t?ks-apiserver?.
[+]?Building?22.6s?(9/9)?FINISHED
?=>?[internal]?load?build?definition?from?Dockerfile????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????0.0s
?=>?=>?transferring?dockerfile:?812B????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????0.0s
?=>?[internal]?load?.dockerignore???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????0.0s
?=>?=>?transferring?context:?2B?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????0.0s
?=>?[internal]?load?metadata?for?docker.io/library/alpine:3.11??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1.0s
?=>?[1/4]?FROM?docker.io/library/alpine:3.11@sha256:bf5fa774f08a9ed2cb301e522b769d43d48124315a4ec50eae3228d03b9dc558????????????????????????????????????????????????????????????????7.9s
?=>?=>?resolve?docker.io/library/alpine:3.11@sha256:bf5fa774f08a9ed2cb301e522b769d43d48124315a4ec50eae3228d03b9dc558????????????????????????????????????????????????????????????????0.0s
?=>?=>?sha256:9b794450f7b6db7c944ba1f4161edb68cb535052fe7db8ac06e613516c4a658d?2.10MB?/?2.82MB?????????????????????????????????????????????????????????????????????????????????????21.4s
?=>?=>?extracting?sha256:9b794450f7b6db7c944ba1f4161edb68cb535052fe7db8ac06e613516c4a658d???????????????????????????????????????????????????????????????????????????????????????????0.1s
?=>?[internal]?load?build?context???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1.0s
?=>?=>?transferring?context:?115.87MB???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1.0s
?=>?[2/4]?RUN?apk?add?--no-cache?ca-certificates????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????2.7s
?=>?[3/4]?RUN?wget?https://get.helm.sh/helm-v3.5.2-linux-amd64.tar.gz?&&?????tar?xvf?helm-v3.5.2-linux-amd64.tar.gz?&&?????rm?helm-v3.5.2-linux-amd64.tar.gz?&&?????mv?linux-amd64??4.7s
?=>?[4/4]?COPY??ks-apiserver?/usr/local/bin/????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????0.2s
?=>?exporting?to?oci?image?format???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????5.9s
?=>?=>?exporting?layers?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????4.6s
?=>?=>?exporting?manifest?sha256:d7eb2a90496678d11ac5c363b7743ffe2b8e23e7071b94556a5e3231f50f5a6e???????????????????????????????????????????????????????????????????????????????????0.0s
?=>?=>?exporting?config?sha256:8eb6a5187ce958e76c8d37e18221d88f25b48dd7e6672021d0fce21bb071f284?????????????????????????????????????????????????????????????????????????????????????0.0s
?=>?=>?sending?tarball??????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????1.3s
unpacking?docker.io/library/ks-apiserver:latest?(sha256:d7eb2a90496678d11ac5c363b7743ffe2b8e23e7071b94556a5e3231f50f5a6e)...done
unpacking?overlayfs@sha256:d7eb2a90496678d11ac5c363b7743ffe2b8e23e7071b94556a5e3231f50f5a6e?(sha256:d7eb2a90496678d11ac5c363b7743ffe2b8e23e7071b94556a5e3231f50f5a6e)...done

查看构建好的镜像:

代码语言:javascript
复制
???→?nerdctl?images

REPOSITORY???????????????????????????????????????????????????TAG???????IMAGE?ID????????CREATED??????????SIZE
alpine???????????????????????????????????????????????????????3.11??????bf5fa774f08a????3?seconds?ago????2.7?MiB
ks-apiserver?????????????????????????????????????????????????latest????d7eb2a904966????6?minutes?ago????57.7?MiB

关于 nerdctl 的更多用法,可以参考官方仓库的 README[10]

总结

从行业趋势来看,Docker 已经和 Kubernetes 社区渐行渐远,以?Containerd?为代表的实现了?CRI?接口的容器运行时将会受到 Kubernetes 的青睐。但纯粹使用 Containerd 还是有诸多困扰,比如不方便通过 CLI 来创建管理容器,有了?nerdctl?这个 CLI 工具,就就可以填补 Containerd 易用性的空缺,让你在单机上也能愉快地使用 Containerd。

脚注

[1]ctr:?https://github.com/containerd/containerd/tree/master/cmd/ctr

[2]crictl:?https://github.com/kubernetes-sigs/cri-tools

[3]nerdctl:?https://github.com/containerd/nerdctl

[4]lazy-pulling:?https://github.com/containerd/nerdctl/blob/master/docs/stargz.md

[5]imgcrypt:?https://github.com/containerd/imgcrypt

[6]Containerd 使用 Stargz Snapshotter 延迟拉取镜像:?https://fuckcloudnative.io/posts/startup-containers-in-lightning-speed-with-lazy-image-distribution-on-containerd/

[7]可能需要几个月甚至几年的时间:?https://github.com/moby/moby/pull/41002

[8]nerdctl 的 release:?https://github.com/containerd/nerdctl/releases

[9]KubeSphere:?https://github.com/kubesphere/kubesphere

[10]官方仓库的 README:?https://github.com/containerd/nerdctl


头图:Unsplash

作者:米开朗基杨

原文:https://mp.weixin.qq.com/s/Bjn0s5qRh2H9I__mAYh4jg

原文:终于可以像使用 Docker 一样丝滑地使用 Containerd 了!

来源:KubeSphere 云原生 - 微信公众号 [ID:gh_f5606464ef2f]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/4fywdLmCo9qSRVKcWaZ4
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券
http://www.vxiaotou.com