天天看點

containerd與安全沙箱的Kubernetes初體驗

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的支援。其架構圖如下:

containerd與安全沙箱的Kubernetes初體驗

在Kubernetes場景下,containerd與完整Docker Engine相比,具有更少的資源占用和更快的啟動速度。

containerd與安全沙箱的Kubernetes初體驗
containerd與安全沙箱的Kubernetes初體驗

來源

containerd

紅帽主導的cri-o是與containerd競争的容器運作時管理項目。containerd與cri-o項目相比,在性能上具備優勢,在社群支援上也更加廣泛。

containerd與安全沙箱的Kubernetes初體驗
ebay的分享

更重要的是containerd提供了靈活的擴充機制,支援各種符合OCI(Open Container Initiative)的容器運作時實作,比如runc容器(也是熟知的Docker容器),KataContainer, gVisor和Firecraker等安全沙箱容器。

containerd與安全沙箱的Kubernetes初體驗

在Kubernetes環境中,可以用不同的API和指令行工具來管理容器/Pod,鏡像等概念。為了便于大家了解,我們可以用下圖說明如何利用不同層次的API和CLI管理容器生命周期管理。

containerd與安全沙箱的Kubernetes初體驗
  • 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 apply -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實作。

containerd與安全沙箱的Kubernetes初體驗

但是Docker Engine包含了更多的開發者工具鍊,比如鏡像建構。也包含了Docker自己的日志、存儲、網絡、Swarm編排等能力。此外,絕大多數容器生态廠商,如安全、監控、開發等對Docker Engine的支援比較完善,對containerd的支援也在逐漸補齊。

是以在Kubernetes運作時環境,對安全和效率和定制化更加關注的使用者可以選擇containerd作為容器運作時環境。對于大多數開發者,繼續使用Docker Engine作為容器運作時也是一個不錯的選擇。

阿裡雲容器服務對containerd的支援

在阿裡雲Kubernetes服務ACK,我們已經采用containerd作為容器運作時管理,來支撐安全沙箱容器和runc容器的混合部署。在現有産品中,我們和阿裡雲作業系統團隊、螞蟻金服一起支援了基于輕量虛拟化的runV沙箱容器,4Q也将和作業系統團隊、安全團隊合作釋出基于Intel SGX的可信加密沙箱容器。

containerd與安全沙箱的Kubernetes初體驗

具體産品資訊可以參考

https://help.aliyun.com/document_detail/140541.html

和Serverless Kubernetes(ASK)中,我們也利用containerd靈活的插件機制定制和剪裁了面向nodeless環境的容器運作時實作。

繼續閱讀