超网:为Kubernetes带来安全性和多租户

今天的来宾帖子由HyperHQ的工程师Harry Zhang和Ni Pengfei撰写,描述了一个基于Hypervisor的新容器HyperContainer

尽管许多开发人员和安全专业人员对Linux容器作为有效边界感到满意,但许多用户仍需要更强的隔离度,尤其是对于在多租户环境中运行的用户。可悲的是,如今,这些用户被迫在虚拟机中运行其容器,甚至每个容器一个VM。

不幸的是,这导致失去了原生云部署的许多好处:VM的启动时间慢;对每个容器征收记忆税;利用率低导致资源浪费。

在本文中,我们将介绍基于Hypervisor的容器HyperContainer,并了解它如何自然地融入Kubernetes设计中,并使用户能够直接使用虚拟化容器为客户提供服务,而不是将其包装在完整的VM中。

超级容器

超级容器 是基于管理程序的容器,它允许您使用标准管理程序(KVM,Xen等)启动Docker映像。作为一个开源项目,HyperContainer包含一个 OCI 兼容的运行时实现,命名为 运行,以及名为 海德。 超级容器背后的想法非常简单:将虚拟化和容器的优点结合起来。

We can consider containers as two parts (as Kubernetes does). The first part is the container runtime, where 超级容器 uses virtualization to achieve execution isolation and resource limitation instead of namespaces and cgroups. The second part is the application data, where 超级容器 leverages Docker images. So in 超级容器, virtualization technology makes it possible to build a fully isolated sandbox with an independent guest kernel (so things like top and /proc all work), but from developer’s view, it’s portable and behaves like a standard container.

超级容器作为Pod

超级容器有趣的部分不仅在于它对于多租户环境(例如公共云)足够安全,而且还非常适合Kubernetes哲学。

Pod是Kubernetes中最重要的概念之一。 Pods的设计是一个经验教训(伯格纸节8.1)来自现实世界的工作负载,在许多情况下,人们需要一个由多个容器组成的原子调度单元(请检查此 了解更多信息)。在Linux容器的上下文中,Pod将多个容器包装并封装到一个逻辑组中。但是在HyperContainer中,系统管理程序充当自然边界,而Pod被引入为一等对象:

超级容器包装了一个Pod轻型应用程序容器,并在Pod级别公开了容器接口。在Pod内,引导了名为HyperKernel的极简Linux内核。该HyperKernel内置有一个名为HyperStart的微型Init服务。它将充当PID 1进程,并创建Pod,设置Mount名称空间并从加载的图像启动应用程序。

该模型与Kubernetes很好地配合。如标题所示,HyperContainer与Kubernetes的集成是组成 超网 项目。

超网

Kubernetes最好的部分之一是它被设计为支持多个容器运行时,这意味着用户不会被锁定在单个供应商中。我们非常高兴地宣布,我们已经开始与Kubernetes团队合作,将HyperContainer集成到上游的Kubernetes中。该集成涉及:

  1. 容器运行时优化和重构
  2. 新的客户端-服务器模式运行时界面
  3. 容器集成以支持runV

即使HyperContainer不基于Linux容器技术堆栈,OCI标准和kubelet的多重运行时体系结构也使此集成更加容易。

另一方面,为了在多租户环境中运行HyperContainers,我们还创建了一个新的网络插件并修改了一个现有的卷插件。由于Hypernetes将Pod作为自己的VM运行,因此它可以将您现有的IaaS层技术用于多租户网络和持久卷。当前的Hypernetes实现使用标准的Openstack组件。

下面,我们将详细介绍如何实现上述所有功能。

身份认证

在Hypernetes中,我们选择了 梯形失真 在任何管理操作期间管理不同的租户并执行对租户的标识和身份验证。由于Keystone来自OpenStack生态系统,因此它可以与我们在Hypernetes中使用的网络和存储插件无缝协作。

多租户网络模型

对于多租户容器集群,每个租户都需要彼此之间具有强大的网络隔离。在Hypernetes中,每个租户都有自己的网络。您无需像使用Hypernetes一样使用复杂的OpenStack配置新网络,而只需创建一个Network对象即可。

apiVersion: v1  
kind: Network  
metadata:  
  name: net1  
spec:  
  tenantID: 065f210a2ca9442aad898ab129426350  
  subnets:  
    subnet1:  
      cidr: 192.168.0.0/24  
      gateway: 192.168.0.1

请注意,tenantID由Keystone提供。该Yaml将自动创建一个具有默认路由器和子网192.168.0.0/24的新Neutron网络。

网络控制器将负责用户创建的任何网络实例的生命周期管理。可以将该网络分配给一个或多个命名空间,并且属于同一网络的任何Pod都可以直接通过IP地址相互访问。

apiVersion: v1  
kind: Namespace  
metadata:  
  name: ns1  
spec:  
  network: net1

如果命名空间没有网络规范,它将使用默认的Kubernetes网络模型,包括默认的kube-proxy。因此,如果用户在具有关联网络的命名空间中创建Pod,则Hypernetes将遵循 Kubernetes网络插件模型 为此Pod建立一个Neutron网络。这是一个高级示例:

超网网络工作流{:HyperContainer包装了一个li.big-img豆荚}

超网使用名为kubestack的独立gRPC处理程序将Kubernetes Pod请求转换为Neutron网络API。此外,kubestack还负责处理另一个重要的网络功能:多租户服务代理。

在多租户环境中,基于默认iptables的kube-proxy无法到达各个Pod,因为它们被隔离在不同的网络中。相反,Hypernetes使用 每个HyperContainer中都内置HAProxy 作为门户。该HAproxy将代理该Pod命名空间中的所有Service实例。 Kube-proxy将负责通过遵循标准的OnServiceUpdate和OnEndpointsUpdate流程来更新这些后端服务器,以便用户不会注意到任何差异。这种方法的缺点是HAproxy必须侦听某些可能与用户容器冲突的特定端口。这就是为什么我们计划在下一个版本中使用LVS替换此代理的原因。

借助基于Neutron的网络插件,Hypernetes Service能够提供OpenStack负载均衡器,就像“外部”负载均衡器在GCE上所做的一样。当用户使用外部IP创建服务时,将创建一个OpenStack负载均衡器,并且将通过上述kubestack工作流自动更新端点。

永久储存

考虑存储时,我们实际上是在Kubernetes中构建一个可感知租户的持久卷。我们决定不使用Kubernetes的现有Cinder卷插件的原因是,其模型在虚拟化情况下不起作用。特别:

Cinder卷插件需要OpenStack作为Kubernetes提供程序。

OpenStack提供程序将找到目标Pod在哪个VM上运行

Cinder卷插件会将Cinder卷安装到Kubernetes主机VM内部的路径上。

Kubelet将将此路径作为卷绑定安装到目标Pod的容器中。

但是在Hypernetes中,事情变得简单得多。由于Pods的物理边界,HyperContainer可以将Cinder卷作为块设备直接安装到Pods中,就像普通的VM一样。这种机制消除了在上面列出的现有Cinder卷工作流程中查询Nova来查找目标Pod的VM的额外时间。

超网中Cinder插件的当前实现基于Ceph RBD后端,并且与所有其他Kubernetes卷插件相同,只需要记住事先创建Cinder卷(在下面由volumeID引用)即可。

apiVersion: v1  
kind: Pod  
metadata:  
  name: nginx  
  labels:  
    app: nginx  
spec:  
  containers:  
  - name: nginx  
    image: nginx  
    ports:  
    - containerPort: 80  
    volumeMounts:  
    - name: nginx-persistent-storage  
      mountPath: /var/lib/nginx  
  volumes:  
  - name: nginx-persistent-storage  
    cinder:  
      volumeID: 651b2a7b-683e-47e1-bdd6-e3c62e8f91c0  
      fsType: ext4

因此,当用户为Pod Yaml提供Cinder卷时,Hypernetes将检查kubelet是否正在使用Hyper容器运行时。如果是这样,则可以将Cinder卷直接安装到Pod,而无需任何其他路径映射。然后,将卷元数据作为HyperContainer规范的一部分传递给Kubelet RunPod进程。做完了!

得益于Kubernetes网络和卷的插件模型,我们可以轻松地在HyperContainer之上构建我们自己的解决方案,尽管它与传统的Linux容器本质上有所不同。我们还计划在完成运行时集成之后遵循CNI模型和卷插件标准,向上游Kubernetes提出这些解决方案。

我们相信所有这些 开源项目 是容器生态系统的重要组成部分,它们的增长在很大程度上取决于Kubernetes团队的开源精神和技术远见。

结论

这篇文章介绍了有关HyperContainer和Hypernetes项目的一些技术细节。我们希望人们会对这一新类别的安全容器及其与Kubernetes的集成感兴趣。如果您想试用Hypernetes和HyperContainer,我们刚刚宣布了我们新的安全容器云服务的公开测试版(超_)(基于这些技术)。但是,即使您在内部运行,我们相信Hypernetes和HyperContainer也可以让您以更安全的方式运行Kubernetes。

〜HyperHQ的工程师Harry Zhang和Pengfei Ni