共计 6962 个字符,预计需要花费 18 分钟才能阅读完成。
作者:米开朗基杨
有谋求的工程师个别都是有技术洁癖的,云原生的世界更是如此,Kubernetes
尽管制订了容器运行时接口(CRI
)规范,但晚期能用的容器运行时只有 Docker
,而 Docker
又不适配这个规范,于是给 Docker
开了后门,花了大量的精力去适配它。起初有了更多的容器运行时能够抉择后,Kubernetes 就不得不从新考量要不要持续适配 Docker 了,因为每次更新 Kubelet 都要思考与 Docker 的适配问题。
规范这个货色就是这样,我定好规范,你兼容了就一起玩,不兼容就拜拜,它就像两个人在一起的底线,你能够重,你能够丑,你也能够不欠缺,然而你不兼容规范就真的不能一起玩了,于是 Kubernetes 就把 Docker 踢出了群聊。
最终 Kubernetes 抉择了 Containerd
,时至今日 Containerd
曾经变成一个工业级的容器运行时了,它足够简略、强壮,可移植性也很强。
现有 CLI 的有余
尽管 Docker 无能的事件,当初 Containerd
都无能,但 Containerd
还有一个非常明显的缺点:CLI 不够敌对 。它无奈像 Docker 和 Podman 一样通过一条简略的命令启动一个容器,它的两个 CLI 工具 ctr 和 crictl 都无奈实现这么一件非常简单的需要,而这个需要是大多数人都须要的,我总不能为了在本地测试容器而专门部署一个 Kubernetes 集群吧?
ctr 的设计对人类不太敌对,例如短少以下这些和 Docker 相似的性能:
docker run -p <PORT>
docker run --restart=always
- 通过凭证文件
~/.docker/config.json
来拉取镜像 docker logs
除此之外还有一个 CLI 工具叫 crictl
,和 ctr
一样不太敌对。
为了解决这个痛点,Containerd 官网推出了一个新的 CLI 叫 nerdctl。nerdctl 的应用体验和 docker 一样顺滑,例如:
🐳 → nerdctl run -d -p 8080:80 --name=nginx --restart=always nginx
nerdctl 只是 docker 的复制品?
nerdctl
的指标并不是单纯地复制 docker 的性能,它还实现了很多 docker 不具备的性能,例如提早拉取镜像(lazy-pulling)、镜像加密(imgcrypt)等。
提早拉取镜像性能能够参考这篇文章:Containerd 应用 Stargz Snapshotter 提早拉取镜像。
尽管这些性能预计最终也会在 Docker 中实现,但可能须要几个月甚至几年的工夫,因为 Docker 目前的设计只应用一小部分 Containerd
子系统。未来 Docker 有可能重构代码以应用残缺的 Containerd
,但目前还没看到什么实质性停顿。所以 Containerd
社区决定创立一个新的 CLI 来更敌对地应用 Containerd
。
nerdctl 试用
你能够从 nerdctl 的 release 中下载最新的可执行文件,每一个版本都有两种可用的发行版:
nerdctl-<VERSION>-linux-amd64.tar.gz
: 只蕴含 nerdctl。nerdctl-full-<VERSION>-linux-amd64.tar.gz
: 蕴含了 nerdctl 和相干依赖组件(containerd, runc, CNI, …)。
如果你曾经装置了 Containerd,只须要抉择前一个发行版,否则就抉择完整版。
装置好 nerdctl 后,就能够应用 nerdctl 来运行容器了:
🐳 → 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 |
查看创立的容器:
🐳 → 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
:
🐳 → nerdctl network ls | |
NETWORK ID NAME FILE | |
0 bridge | |
k8s-pod-network /etc/cni/net.d/10-calico.conflist | |
host | |
none |
来看下默认的 bridge 配置:
🐳 → 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 的可执行文件:
🐳 → wget https://github.com/moby/buildkit/releases/download/v0.8.2/buildkit-v0.8.2.darwin-amd64.tar.gz
将其解压到 $PATH
中:
🐳 → tar -C /usr/local/ -zxvf buildkit-v0.8.2.linux-amd64.tar.gz
编写 systemd unit 文件:
# /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 并设置开机主动运行:
🐳 → systemctl enable --now buildkit.service
上面以 KubeSphere 我的项目为例,展现如何应用 nerdctl
来构建镜像。
首先克隆 KubeSphere 官网仓库:
🐳 → git clone --depth=1 https://github.com.cnpmjs.org/kubesphere/kubesphere.git
进入仓库目录,编译二进制文件:
🐳 → cd kubesphere | |
🐳 → make ks-apiserver |
将二进制文件拷贝到 Dockerfile
目录:
🐳 → cp bin/cmd/ks-apiserver build/ks-apiserver
进入 Dockerfile
目录,批改 Dockerfile:
# 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"] |
构建镜像:
🐳 → 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 |
查看构建好的镜像:
🐳 → 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。
总结
从行业趋势来看,Docker 曾经和 Kubernetes 社区渐行渐远,以 Containerd
为代表的实现了 CRI
接口的容器运行时将会受到 Kubernetes 的青眼。但纯正应用 Containerd 还是有诸多困扰,比方不不便通过 CLI 来创立治理容器,有了 nerdctl
这个 CLI 工具,就就能够填补 Containerd 易用性的空缺,让你在单机上也能欢快地应用 Containerd。
本文由博客一文多发平台 OpenWrite 公布!