本文超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否未变得不正确。
使用 Kubernetes 设备插件和 RuntimeClass 在 Ingress 控制器中进行硬件加速 SSL/TLS 终止
摘要
Kubernetes Ingress 是一种将集群服务连接到集群外部世界的方式。为了将流量正确路由到服务后端,集群需要一个 Ingress 控制器。Ingress 控制器负责根据 Ingress API 对象的信息将正确的目标设置为后端。实际流量通过代理服务器进行路由,该服务器负责负载平衡和 SSL/TLS(以下简称“SSL”指 SSL 或 TLS)终止等任务。由于涉及加密操作,SSL 终止是一项 CPU 密集型操作。为了将一些 CPU 密集型工作从 CPU 中卸载,基于 OpenSSL 的代理服务器可以利用 OpenSSL Engine API 和专用加密硬件。这可以释放 CPU 周期用于其他任务,并提高代理服务器的整体吞吐量。
在这篇博文中,我们将展示如何使用一些最近创建的 Kubernetes 构建块:设备插件框架和 RuntimeClass,轻松地为运行 Ingress 控制器代理的容器提供硬件加速加密。最后,给出了一个使用基于 HAproxy 的 Ingress 控制器的参考设置,该控制器使用 Intel® QuickAssist Technology 卡进行加速。
关于代理、OpenSSL 引擎和加密硬件
代理服务器在 Kubernetes Ingress 控制器功能中起着至关重要的作用。它根据 Ingress 对象路由将流量代理到后端。在高流量负载下,性能变得至关重要,尤其是在代理涉及 CPU 密集型操作(如 SSL 加密)时。
OpenSSL 项目提供了广泛采用的库来实现 SSL 协议。在 Kubernetes Ingress 控制器常用的代理服务器中,Nginx 和 HAproxy 使用 OpenSSL。CNCF 毕业的 Envoy 代理使用 BoringSSL,但似乎社区有兴趣将 OpenSSL 作为替代方案。
OpenSSL SSL 协议库依赖于实现加密功能的 libcrypto。很长一段时间以来(在 0.9.6 版本中首次引入),OpenSSL 提供了ENGINE 概念,允许将这些加密操作卸载到专用加密加速硬件。后来,一个特殊的*动态*引擎使加密硬件特定部分能够在一个独立的可加载模块中实现,该模块可以在 OpenSSL 代码库之外开发并单独分发。从应用程序的角度来看,这也是理想的,因为它们不需要知道如何使用硬件的详细信息,并且可以在硬件可用时加载/使用硬件特定模块。
如前所述,基于硬件的加密可以极大地提高云应用程序的性能,因为它在 SSL 操作中进行了硬件加速处理,并且可以提供其他加密服务,如密钥/随机数生成。云可以使用动态引擎轻松提供硬件,并且存在多个可加载模块实现,例如,CloudHSM、IBMCA 或QAT Engine。
对于云部署,理想的情况是将这些模块作为容器工作负载的一部分进行交付。工作负载将被安排在一个提供模块需要访问的底层硬件的节点上。另一方面,无论加密加速硬件是否可用,工作负载都应该以相同的方式运行,并且无需修改代码。OpenSSL 动态引擎支持这一点。下面的图 1 使用典型的 Ingress 控制器容器作为示例说明了这两种情况。红色框表示启用加密硬件引擎的容器与“标准”容器之间的区别。值得指出的是,所示的配置更改不一定需要另一个版本的容器,因为可以使用例如 ConfigMaps 来管理配置。

图 1. Ingress 控制器容器示例
硬件资源和隔离
为了能够部署具有硬件依赖性的工作负载,Kubernetes 提供了出色的扩展和可配置性机制。让我们仔细研究一下 Kubernetes 的设备插件框架(1.14 中的 Beta 版)和RuntimeClass(1.14 中的 Beta 版),并了解如何利用它们将加密硬件公开给工作负载。
设备插件框架最初在 Kubernetes 1.8 中引入,它为硬件供应商提供了一种向 Kubelet 注册和分配节点硬件资源的方法。插件实现了特定于硬件的初始化逻辑和资源管理。Pod 可以在其 PodSpec 中请求硬件资源,这也可以保证 Pod 安排在可以提供这些资源的节点上。
容器的设备资源分配并非易事。对于处理安全性的应用程序,硬件级别的隔离至关重要。基于 PCIe 的加密加速设备功能可以通过 I/O 内存管理单元 (IOMMU) 从 IO 硬件虚拟化中受益,以提供隔离:设备所属的*IOMMU 组*为工作负载提供隔离资源(假设加密卡不与其他设备共享 IOMMU 组)。如果 PCIe 设备支持单根 I/O 虚拟化 (SR-IOV) 规范,则可以进一步增加隔离资源的数量。SR-IOV 允许将 PCIe 设备进一步拆分为从*物理功能* (PF) 设备派生的*虚拟功能* (VF),并且每个功能都属于自己的 IOMMU 组。为了将这些 IOMMU 隔离的设备功能公开给用户空间和容器,主机内核应将它们绑定到特定的设备驱动程序。在 Linux 中,此驱动程序是 vfio-pci,它通过用户空间中的字符设备使每个设备可用。内核 vfio-pci 驱动程序使用称为*PCI 直通*的机制,为用户空间应用程序提供对 PCIe 设备和功能的直接的、IOMMU 支持的访问。用户空间框架(例如数据平面开发工具包 (DPDK))可以利用该接口。此外,虚拟机 (VM) 管理程序可以将这些用户空间设备节点提供给 VM,并将它们作为 PCI 设备公开给客户机内核。假设客户机内核支持,VM 将获得接近本机性能的直接访问底层主机设备的权限。
为了向 Kubernetes 发布这些设备资源,我们可以使用一个简单的 Kubernetes 设备插件,该插件运行初始化(即绑定),调用 kubelet 的 `Registration` gRPC 服务,并实现 DevicePlugin gRPC 服务,kubelet 调用该服务以在 Pod 创建时例如 `Allocate` 资源。
设备分配和 Pod 部署
此时,您可能会问容器可以使用 VFIO 设备节点做什么?在我们快速了解 Kubernetes RuntimeClass 之后,答案就来了。
创建 Kubernetes RuntimeClass 的目的是为了更好地控制和配置集群中可用的各种*运行时*(之前的博文详细介绍了它的需求、状态和路线图)。本质上,RuntimeClass 为集群用户提供了更好的工具来选择和使用最适合 Pod 用例的运行时。
与 OCI 兼容的Kata Containers 运行时为工作负载提供了硬件虚拟化隔离层。除了工作负载隔离之外,Kata Containers VM 还具有额外的好处,即设备插件 `Allocate` 的 VFIO 设备可以通过直通的方式作为硬件隔离设备传递给容器。唯一的要求是 Kata Containers 内核启用了公开设备的驱动程序。
这就是为容器工作负载启用硬件加速加密所需的全部内容。总结一下
- 集群需要在提供硬件的节点上运行设备插件
- 设备插件使用 VFIO 驱动程序将硬件公开给用户空间
- Pod 在 PodSpec 中请求设备资源和 Kata Containers 作为 RuntimeClass
- 容器具有硬件适配库和 OpenSSL 引擎模块
图 2 显示了使用前面说明的容器 A 的整体设置。

图 2. 部署概述
参考设置
最后,我们描述了构建图 2 中描述的功能设置的必要构建块和步骤,该设置使用 Intel® QuickAssist Technology (QAT) PCIe 设备在 Ingress 控制器中启用硬件加速 SSL 终止。应该注意的是,用例不限于 Ingress 控制器,任何基于 OpenSSL 的工作负载都可以加速。
集群配置
- Kubernetes 1.14(启用了 `RuntimeClass` 和 `DevicePlugin` 功能门控(两者在 1.14 中均为 `true`))
- RuntimeClass 就绪运行时和 Kata Containers 已配置
主机配置
- Intel® QAT 驱动程序版本,其中为主机内核和 Kata Containers 内核安装了内核驱动程序(或作为可加载模块安装在根文件系统上)
- 已部署QAT 设备插件 DaemonSet
Ingress 控制器配置和部署
- 修改后的容器中的HAproxy-ingress ingress 控制器,其中包含
- QAT HW HAL 用户空间库(Intel® QAT SW 版本的一部分)和
- 内置的OpenSSL QAT 引擎
- Haproxy-ingress ConfigMap 以启用 QAT 引擎使用
ssl-engine=”qat”
ssl-mode-async=true
- Haproxy-ingress 部署 `.yaml` 以
- 请求 `qat.intel.com: n` 资源
- 请求 `runtimeClassName: kata-containers`(名称值取决于集群配置)
- (容器中提供了每个请求的设备资源的 QAT 设备配置文件,其中配置了 OpenSSL 引擎)
一旦构建块可用,就可以按照 TLS 终止示例 中的步骤测试硬件加速的 SSL/TLS。为了验证是否使用了硬件,您可以检查主机上的 /sys/kernel/debug/*/fw_counters
文件,因为它们会被英特尔® QAT 固件更新。
之所以使用 Haproxy-ingress 和 HAproxy,是因为 HAproxy 可以直接配置为使用 OpenSSL 引擎,只需使用 ssl-engine <name> [algo ALGOs]
配置标志,而无需修改全局 openssl 配置文件。此外,HAproxy 可以使用异步调用(通过 ssl-mode-async
)卸载已配置的算法,以进一步提高性能。
行动号召
在这篇博文中,我们展示了如何使用 Kubernetes 设备插件和 RuntimeClass 为 Pod 中的应用程序提供隔离的硬件访问权限,以便将加密操作卸载到硬件加速器。硬件加速器可用于加速加密操作,还可以将 CPU 周期节省给其他任务。我们使用 HAproxy 演示了该设置,HAproxy 已经支持使用 OpenSSL 进行异步加密卸载。
我们团队的下一步工作是对 Envoy(使用基于 OpenSSL 的 TLS 传输套接字作为扩展构建)重复相同的操作。此外,我们正在努力增强 Envoy,使其能够将 BoringSSL 异步私钥操作卸载 到加密加速硬件。欢迎任何审查反馈或帮助!
将加密处理卸载到专用加速器后,您的加密应用程序可以为其他任务节省多少 CPU 周期?