作者:米开朗基杨
有谋求的工程师个别都是有技术洁癖的,云原生的世界更是如此,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 公布!