icon-cookie
The website uses cookies to optimize your user experience. Using this website grants us the permission to collect certain information essential to the provision of our services to you, but you may change the cookie settings within your browser any time you wish. Learn more
I agree
blank_error__heading
blank_error__body
Text direction?

containerd与安全沙箱的Kubernetes初体验

已认证的官方帐号


containerd是一个开源的行业标准容器运行时,关注于简单、稳定和可移植,同时支持Linux和Windows。2016年12月14日,Docker公司宣布将Docker Engine的核心组件 containerd 捐赠到一个新的开源社区独立发展和运营。阿里云,AWS, Google,IBM和Microsoft作为初始成员,共同建设 containerd 社区。2017年3月,Docker 将 containerd 捐献给CNCF(云原生计算基金会)。containerd得到了快速的发展和广泛的支持。Docker引擎已经将containerd作为容器生命周期管理的基础,Kubernetes也在2018年5月,正式支持containerd作为容器运行时管理器。2019年2月,CNCF宣布containerd毕业,成为生产可用的项目。

containerd 从1.1版本开始就已经内置了Container Runtime Interface (CRI) 支持,进一步简化了对Kubernetes的支持。其架构图如下:

在Kubernetes场景下,containerd与完整Docker Engine相比,具有更少的资源占用和更快的启动速度。

来源 containerd

红帽主导的cri-o是与containerd竞争的容器运行时管理项目。containerd与cri-o项目相比,在性能上具备优势,在社区支持上也更加广泛。

来源 ebay的分享

更重要的是containerd提供了灵活的扩展机制,支持各种符合OCI(Open Container Initiative)的容器运行时实现,比如runc容器(也是熟知的Docker容器),KataContainer, gVisor和Firecraker等安全沙箱容器。

在Kubernetes环境中,可以用不同的API和命令行工具来管理容器/Pod,镜像等概念。为了便于大家理解,我们可以用下图说明如何利用不同层次的API和CLI管理容器生命周期管理。

  • Kubectl:是集群层面的命令行工具,支持Kubernetes的基本概念
  • crictl:是针对节点上CRI的命令行工具,文档
  • ctr:是针对containerd的命令行工具,文档

体验

Minikube是体验containerd作为Kubernetes容器运行时的最简单方式,我们下面将将其作为Kubernetes容器运行时,并支持runc和gvisor两种不同的实现。

早期由于网络访问原因,很多朋友无法直接使用官方Minikube进行实验。在最新的Minikube 1.5版本中,已经提供了完善的配置化的方式,可以帮助大家利用阿里云的镜像地址来获取所需Docker镜像和配置,同时支持Docker/Containerd等不同容器运行时。

我们创建一个Minikube虚拟机环境,详细信息可以参考 https://yq.aliyun.com/articles/221687 ,注意需要指明 --container-runtime=containerd 参数设置containerd作为容器运行时。同时registry-mirror也要替换成自己的阿里云镜像加速地址。

$ minikube start --image-mirror-country cn \
    --iso-url=https://kubernetes.oss-cn-hangzhou.aliyuncs.com/minikube/iso/minikube-v1.5.0.iso \
    --registry-mirror=https://XXX.mirror.aliyuncs.com \
    --container-runtime=containerd

  Darwin 10.14.6 上的 minikube v1.5.0
  Automatically selected the 'hyperkit' driver (alternates: [virtualbox])
️  您所在位置的已知存储库都无法访问。正在将 registry.cn-hangzhou.aliyuncs.com/google_containers 用作后备存储库。
  正在创建 hyperkit 虚拟机(CPUs=2,Memory=2000MB, Disk=20000MB)...
️  VM is unable to connect to the selected image repository: command failed: curl -sS https://k8s.gcr.io/
stdout:
stderr: curl: (7) Failed to connect to k8s.gcr.io port 443: Connection timed out
: Process exited with status 7
  正在 containerd 1.2.8 中准备 Kubernetes v1.16.2…
  拉取镜像 ...
  正在启动 Kubernetes ...
⌛  Waiting for: apiserver etcd scheduler controller
  完成!kubectl 已经配置至 "minikube"

$ minikube dashboard
  Verifying dashboard health ...
  Launching proxy ...
  Verifying proxy health ...
  Opening http://127.0.0.1:54438/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...

部署测试应用

我们通过Pod部署一个nginx应用

$ cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx

$ kubectl apply -f nginx.yaml
pod/nginx created

$ kubectl exec nginx -- uname -a
Linux nginx 4.19.76 #1 SMP Fri Oct 25 16:07:41 PDT 2019 x86_64 GNU/Linux

然后,我们开启 minikube 对 gvisor 支持

$ minikube addons enable gvisor
  gvisor was successfully enabled

$ kubectl get pod,runtimeclass gvisor -n kube-system
NAME         READY   STATUS    RESTARTS   AGE
pod/gvisor   1/1     Running   0          60m

NAME                              CREATED AT
runtimeclass.node.k8s.io/gvisor   2019-10-27T01:40:45Z

$ kubectl get runtimeClass
NAME     CREATED AT
gvisor   2019-10-27T01:40:45Z

gvisor pod进入 Running 状态的时候,可以部署gvisor测试应用。

我们可以看到K8s集群中已经注册了一个gvisor的“runtimeClassName“。

之后,开发者可以通过在Pod声明中的 ”runtimeClassName“来选择不同类型的容器运行时实现。比如,如下我们创建一个运行在 gvisor 沙箱容器中的 nginx 应用。

$ cat nginx-untrusted.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-untrusted
spec:
  runtimeClassName: gvisor
  containers:
  - name: nginx
    image: nginx

$ kubectl delete -f nginx-untrusted.yaml
pod/nginx-untrusted created

$ kubectl exec nginx-untrusted -- uname -a
Linux nginx-untrusted 4.4 #1 SMP Sun Jan 10 15:06:54 PST 2016 x86_64 GNU/Linux

我们可以清楚地发现:由于基于runc的容器与宿主机共享操作系统内核,runc容器中查看到的OS内核版本与Minikube宿主机OS内核版本相同。而gvisor的runsc容器采用了独立内核,它和Minikube宿主机OS内核版本不同。

正是因为每个沙箱容器拥有独立的内核,减小了安全攻击面,具备更好的安全隔离特性。适合隔离不可信的应用,或者多租户场景。

注意:gvisor在minikube中,通过ptrace对内核调用进行拦截,其性能损耗较大。此外gvisor的兼容性还有待增强。

使用ctl和crictl工具

我们现在可以进入进入Minikube虚拟机

$ minikube ssh

containerd支持通过名空间对容器资源进行隔离,查看现有 containerd 名空间

$ sudo ctr namespaces ls
NAME   LABELS
k8s.io
# 列出所有容器镜像
$ sudo ctr --namespace=k8s.io images ls
...

# 列出所有容器列表
$ sudo ctr --namespace=k8s.io containers ls

在Kubernetes环境更加简单的方式是利用 crictl 对pods进行操作

# 查看pod列表
$ sudo crictl pods
POD ID              CREATED             STATE               NAME                                         NAMESPACE              ATTEMPT
78bd560a70327       3 hours ago         Ready               nginx-untrusted                              default                0
94817393744fd       3 hours ago         Ready               nginx                                        default                0
...

# 查看名称包含nginx的pod的详细信息
$ sudo crictl pods --name nginx -v
ID: 78bd560a70327f14077c441aa40da7e7ad52835100795a0fa9e5668f41760288
Name: nginx-untrusted
UID: dda218b1-d72e-4028-909d-55674fd99ea0
Namespace: default
Status: Ready
Created: 2019-10-27 02:40:02.660884453 +0000 UTC
Labels:
    io.kubernetes.pod.name -> nginx-untrusted
    io.kubernetes.pod.namespace -> default
    io.kubernetes.pod.uid -> dda218b1-d72e-4028-909d-55674fd99ea0
Annotations:
    kubectl.kubernetes.io/last-applied-configuration -> {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"nginx-untrusted","namespace":"default"},"spec":{"containers":[{"image":"nginx","name":"nginx"}],"runtimeClassName":"gvisor"}}

    kubernetes.io/config.seen -> 2019-10-27T02:40:00.675588392Z
    kubernetes.io/config.source -> api

ID: 94817393744fd18b72212a00132a61c6cc08e031afe7b5295edafd3518032f9f
Name: nginx
UID: bfcf51de-c921-4a9a-a60a-09faab1906c4
Namespace: default
Status: Ready
Created: 2019-10-27 02:38:19.724289298 +0000 UTC
Labels:
    io.kubernetes.pod.name -> nginx
    io.kubernetes.pod.namespace -> default
    io.kubernetes.pod.uid -> bfcf51de-c921-4a9a-a60a-09faab1906c4
Annotations:
    kubectl.kubernetes.io/last-applied-configuration -> {"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"nginx","namespace":"default"},"spec":{"containers":[{"image":"nginx","name":"nginx"}]}}

    kubernetes.io/config.seen -> 2019-10-27T02:38:18.206096389Z
    kubernetes.io/config.source -> api

更多信息可以参考

https://kubernetes.io/docs/tasks/debug-application-cluster/crictl/

containerd与Docker的关系

很多同学都关心containerd与Docker的关系,以及是否containerd可以取代Docker?
containerd已经成为容器运行时的主流实现,也得到了Docker社区和Kubernetes社区的大力支持。Docker Engine底层的容器生命周期管理也是基于containerd实现。

但是Docker Engine包含了更多的开发者工具链,比如镜像构建。也包含了Docker自己的日志、存储、网络、Swarm编排等能力。此外,绝大多数容器生态厂商,如安全、监控、开发等对Docker Engine的支持比较完善,对containerd的支持也在逐渐补齐。

所以在Kubernetes运行时环境,对安全和效率和定制化更加关注的用户可以选择containerd作为容器运行时环境。对于大多数开发者,继续使用Docker Engine作为容器运行时也是一个不错的选择。

阿里云容器服务对containerd的支持

在阿里云Kubernetes服务ACK,我们已经采用containerd作为容器运行时管理,来支撑安全沙箱容器和runc容器的混合部署。在现有产品中,我们和阿里云操作系统团队、蚂蚁金服一起支持了基于轻量虚拟化的runV沙箱容器,4Q也将和操作系统团队、安全团队合作发布基于Intel SGX的可信加密沙箱容器。

具体产品信息可以参考 https://help.aliyun.com/document_detail/140541.html

和Serverless Kubernetes(ASK)中,我们也利用containerd灵活的插件机制定制和剪裁了面向nodeless环境的容器运行时实现。

阿里云双11亿元补贴提前领,进入抽取iPhone 11 Pro:https://www.aliyun.com/1111/2019/home?utm_content=g_1000083110

本文作者:易立

原文链接

更多技术干货敬请关注云栖社区知乎机构号:阿里云云栖社区 - 知乎

本文为云栖社区原创内容,未经允许不得转载。

Measure
Measure
Related Notes
Get a free MyMarkup account to save this article and view it later on any device.
Create account

End User License Agreement

Summary | 14 Annotations
containerd作为容器生命周期管理的基础
2020/07/24 10:02
containerd与完整Docker Engine相比,具有更少的资源占用和更快的启动速度。
2020/07/24 10:03
containerd提供了灵活的扩展机制
2020/07/24 10:04
containerd作为Kubernetes容器运行时的最简单方式
2020/07/27 06:28
阿里云的镜像地址来获取所需Docker镜像和配置
2020/07/27 06:29
支持Docker/Containerd等不同容器运行时
2020/07/27 06:29
registry-mirror
2020/07/27 06:29
minikube 对 gvisor
2020/07/27 06:29
Pod声明中的 ”runtimeClassName“
2020/07/27 06:30
namespaces
2020/07/27 06:31
crictl 对pods进行操作
2020/07/27 06:31
containerd已经成为容器运行时的主流实现
2020/07/27 06:31
基于轻量虚拟化的runV沙箱容器
2020/07/27 06:32
Intel SGX的可信加密沙箱容器
2020/07/27 06:32