gVisor 和 KataContainers

简介: gVisor 和 KataContainers

目前的容器技术仍然有许多广为人知的安全挑战,其中一个主要的问题是,从单一共享内核获得效率和性能意味着容器逃逸可能成为一个漏洞。

所以在 2015 年,几乎在同一个星期,Intel OTC (Open Source Technology Center) 和国内的 HyperHQ 团队同时开源了两个基于虚拟化技术的容器实现,分别叫做 Intel Clear Container 和 runV 项目。而在 2017 年,借着 Kubernetes 的东风,这两个相似的容器运行时项目在中立基金会的撮合下最终合并,就成了现在大家耳熟能详的 Kata Containers 项目。由于 Kata Containers 的本质就是一个精简后的轻量级虚拟机,所以它的特点,就是“像虚拟机一样安全,像容器一样敏捷”。

2018 年,Google 公司则发布了一个名叫 gVisor 的项目。gVisor 项目给容器进程配置一个用 Go 语言实现的、运行在用户态的、极小的“独立内核”。这个内核对容器进程暴露 Linux 内核 ABI,扮演着“Guest Kernel”的角色,从而达到了将容器和宿主机隔离开的目的。

KataContainers

首先,我们来看 KataContainers。它的工作原理可以用如下所示的示意图来描述。image.pngKata Containers 的本质,就是一个轻量化虚拟机。所以当你启动一个 Kata Containers 之后,你其实就会看到一个正常的虚拟机在运行。这也就意味着,一个标准的虚拟机管理程序(Virtual Machine Manager, VMM)是运行 Kata Containers 必备的一个组件。在我们上面图中,使用的 VMM 就是 Qemu。

Docker使用KataContainers

安装参考链接:https://github.com/kata-containers/documentation/tree/master/install/docker

首先节点需要支持以下四种任意一种cpu虚拟化技术:

安装kataContainer:

ARCH=$(arch)
BRANCH="${BRANCH:-master}"
sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/katacontainers:/releases:/${ARCH}:/${BRANCH}/xUbuntu_$(lsb_release -rs)/ /' > /etc/apt/sources.list.d/kata-containers.list"
curl -sL  http://download.opensuse.org/repositories/home:/katacontainers:/releases:/${ARCH}:/${BRANCH}/xUbuntu_$(lsb_release -rs)/Release.key | sudo apt-key add -
sudo -E apt-get update
sudo -E apt-get -y install kata-runtime kata-proxy kata-shim

设置docker配置文件:

cat > /etc/docker/daemon.json << EOF 
{
  "default-runtime": "kata-runtime",
  "runtimes": {
    "kata-runtime": {
      "path": "/usr/bin/kata-runtime"
    }
  }
}
EOF
systemctl daemon-reload
systemctl restart docker

运行一个容器,可以看到显示的内核版本和宿主机是不一样的:

root@cr7-ubuntu:~# docker run busybox uname -a

Kubernetes使用kataContainer

配置containerd使用kataContainer:

cat > /etc/containerd/config.toml << EOF
disabled_plugins = ["restart"]
[plugins.linux]
  shim_debug = true
[plugins.cri.containerd.runtimes.kata]  #kata这个名字可以自己定义,和runtimeClass指定的名字要一样
  runtime_type = "io.containerd.kata.v2"
[plugins.cri.registry.mirrors."docker.io"]
  endpoint = ["https://frz7i079.mirror.aliyuncs.com"]
EOF
systemctl daemon-reload  
systemctl restart containerd

配置kubelet使用containerd作为容器运行时:

cat > /etc/systemd/system/kubelet.service.d/0-cri-containerd.conf << EOF
[Service]
Environment="KUBELET_EXTRA_ARGS=--container-runtime=remote --runtime-request-timeout=15m -- container-runtime-endpoint=unix:///run/containerd/containerd.sock"
EOF
systemctl daemon-reload 
systemctl restart kubelet

kubernetes创建runtimeClass:

apiVersion: node.k8s.io/v1beta1  # RuntimeClass is defined in the node.k8s.io API group
kind: RuntimeClass
metadata:
  name: kata  
handler: kata  # 这里与containerd配置文件中的 [plugins.cri.containerd.runtimes.{handler}] 匹配

创建pod:

apiVersion: v1
kind: Pod
metadata:
  name: kata-nginx
spec:
  runtimeClassName: kata
  containers:
    - name: nginx
      image: nginx
      ports:
      - containerPort: 80

gVisor

相比之下,gVisor 的设计其实要更加“激进”一些。它的原理,可以用如下所示的示意图来表示清楚。image.pnggVisor 工作的核心,在于它为应用进程、也就是用户容器,启动了一个名叫 Sentry 的进程。而 Sentry 进程的主要职责,就是提供一个传统的操作系统内核的能力,即:运行用户程序,执行系统调用。所以说,Sentry 并不是使用 Go 语言重新实现了一个完整的 Linux 内核,而只是一个对应用进程“冒充”内核的系统组件。

Docker使用gVisor

查看原本的runtime:

root@cr7-ubuntu:~# docker info
...
 Runtimes: runc
 Default Runtime: runc
...

安装gVisor:

(
  set -e
  ARCH=$(uname -m)
  URL=https://storage.googleapis.com/gvisor/releases/release/latest/${ARCH}
  wget ${URL}/runsc ${URL}/runsc.sha512 \
    ${URL}/containerd-shim-runsc-v1 ${URL}/containerd-shim-runsc-v1.sha512
  sha512sum -c runsc.sha512 \
    -c containerd-shim-runsc-v1.sha512
  rm -f *.sha512
  chmod a+rx runsc containerd-shim-runsc-v1
  sudo mv runsc containerd-shim-runsc-v1 /usr/local/bin
)

设置docker配置文件:

cat > /etc/docker/daemon.json << EOF 
{
    "registry-mirrors": ["https://frz7i079.mirror.aliyuncs.com"],
    "runtimes": {
        "gvisor": {  #这个名字可以自己制定,docker run的时候--runtime使用
            "path": "/usr/local/bin/runsc"
        }
    }
}
EOF
systemctl daemon-reload
systemctl restart docker

查看此时的runtime:

root@cr7-ubuntu:~# docker info
...
Runtimes: runc gvisor
Default Runtime: runc
...

运行gvisor为runtime的容器:

docker run -itd --name web1 --runtime=gvisor  nginx

在宿主机上是看不到这个进程的,如果是runc的容器是能看到进程的:

root@cr7-ubuntu:~/gvisor# ps -ef | grep nginx | grep -v grep
#没有输出

Kubernetes使用gVisor

配置containerd使用gvisor:

cat > /etc/containerd/config.toml << EOF
disabled_plugins = ["restart"]
[plugins.linux]
  shim_debug = true
[plugins.cri.containerd.runtimes.gvisor]  #gvisor这个名字可以自己定义,和runtimeClass指定的名字要一样
  runtime_type = "io.containerd.runsc.v1"
[plugins.cri.registry.mirrors."docker.io"]
  endpoint = ["https://frz7i079.mirror.aliyuncs.com"]
EOF
systemctl restart containerd

配置crictl使用containerd作为作为容器运行时:

runtime-endpoint: unix:///var/run/containerd/containerd.sock
image-endpoint: ""
timeout: 0
debug: false

配置kubelet使用containerd作为容器运行时:

cat > /var/lib/kubelet/kubeadm-flags.env  << EOF
KUBELET_KUBEADM_ARGS="--network-plugin=cni --pod-infra-container- image=registry.aliyuncs.com/google_containers/pause:3.2 --container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
EOF
systemctl daemon-reload 
systemctl restart kubelet

kubeadm join将node加入kubernetes集群,master使用docker作为容器运行时,node使用containerd作为容器运行时。

创建runtimeClass:

apiVersion: node.k8s.io/v1beta1
kind: RuntimeClass
metadata:
  name: gvisor
handler: gvisor  #对应CRI配置的名称

创建pod使用gvisor作为runtime:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-gvisor
spec:
  runtimeClassName: gvisor
  containers:
  - name: nginx
    image: nginx
  nodeName: cks3

对比

在性能上,KataContainers 和 KVM 实现的 gVisor 基本不分伯仲,在启动速度和占用资源上,基于用户态内核的 gVisor 还略胜一筹。但是,对于系统调用密集的应用,比如重 I/O 或者重网络的应用,gVisor 就会因为需要频繁拦截系统调用而出现性能急剧下降的情况。此外,gVisor 由于要自己使用 Sentry 去模拟一个 Linux 内核,所以它能支持的系统调用是有限的,只是 Linux 系统调用的一个子集。


相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
目录
相关文章
|
存储 缓存 安全
virtiofs per-inode DAX 介绍
## 背景信息 1. 什么是 virtiofs? virtiofs 是一种用于在 host/guest 之间共享文件的文件系统,由 Redhat 开源,它使得不同 guest 之间能够以快速、一致、安全的方式共享同一个 host 目录树结构,目前广泛应用于 Kata Container 作为容器的 rootfs。 2. 什么是 DAX? DAX (Direct Access) 最初是针对于
2222 0
virtiofs per-inode DAX 介绍
|
Kubernetes Linux API
[没接触过kubevirt?]15分钟快速入门kubevirt
什么是kubevirt? kubevirt是一个容器方式运行虚拟机的项目。`kubevirt`是附加`kubernetes`集群上的,它是通过 `CustomResourceDefinition(CRD)`部署到`Kubernetes API`变成资源对象。使用方式类似创建`deploy、pod`......这些资源清单。
3262 0
[没接触过kubevirt?]15分钟快速入门kubevirt
|
Cloud Native Serverless 容器
袋鼠:云原生底层系统探索和实践
随着云计算的发展,云原生概念已经开始成为一种被广泛接受的开发理念。本文将概述我们面向云原生场景在底层技术方面做的探索以及实践。文章根据云栖大会系统软件专场内容整理,演讲者:韩伟东
3763 0
|
并行计算 Kubernetes Cloud Native
用尽每一寸GPU,阿里云cGPU容器技术白皮书重磅发布!
云原生已经成为业内云服务的一个趋势。在云原生上支持异构计算有助于提升CPU的利用率。一文分析业内主流GPU共享方案,并告诉你阿里云cGPU牛在哪里!阿里云异构计算推出的cGPU(container GPU)容器技术,创新地提出了一种不同于以往的GPU容器方案,克服了业内主流方案的一些常见的缺陷,在保证性能的前提下,做到了容器之间的GPU显存隔离和任务隔离,为客户充分利用GPU硬件资源进行训练和推理提供的有效保障。
7553 0
用尽每一寸GPU,阿里云cGPU容器技术白皮书重磅发布!
|
存储 资源调度 安全
ATC'22顶会论文RunD:高密高并发的轻量级 Serverless 安全容器运行时 | 龙蜥技术
RunD可以在88毫秒内启动,并且在104核384GB内存的单节点上每秒启动超过200个安全容器。
ATC'22顶会论文RunD:高密高并发的轻量级 Serverless 安全容器运行时 | 龙蜥技术
|
11月前
|
存储 人工智能 安全
|
Rust 安全 Go
如何在Anolis OS上轻松使用 Kata 安全容器
本篇文章我们将详细介绍怎么轻松在 Anolis OS 上使用 Kata Containers 安全容器
如何在Anolis OS上轻松使用 Kata 安全容器
|
存储 人工智能 Kubernetes
龙蜥云原生社区发展思考&KataContainers社区共建
刘奖/彭涛 阿里云资深技术专家/蚂蚁集团高级技术专家
龙蜥云原生社区发展思考&KataContainers社区共建