这篇文章已经一年多了,较旧的文章可能包含过时的内容。请检查从发表以来,页面中的信息是否变得不正确。

使用 Kubernetes 设备插件和 RuntimeClass 在 Ingress 控制器中实现硬件加速 SSL/TLS 终止

作者: Mikko Ylinen (Intel)

译者: pegasas

摘要

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 技术卡。

关于代理、OpenSSL 引擎和加密硬件

代理服务器在 Kubernetes Ingress 控制器功能中起着至关重要的作用。它将流量代理到每个 Ingress 对象路由的后端。 在高流量负载下,性能变得至关重要,特别是当代理涉及到诸如 SSL 加密之类的 CPU 密集型操作时。

OpenSSL 项目为实现 SSL 协议提供了广泛采用的库。Kubernetes Ingress 控制器使用的常用代理服务器中,Nginx 和 HAproxy 使用 OpenSSL。 CNCF 毕业项目 Envoy 使用 BoringSSL,但是 Envoy 社区似乎也有兴趣使用 OpenSSL 作为替代

OpenSSL SSL 协议库依赖于实现加密功能的 libcrypto。很长一段时间以来(在 0.9.6 版本中首次引入), OpenSSL 提供了一个引擎概念, 允许将这些加密操作卸载到专用的加密加速硬件。后来,一个特殊的动态引擎使加密硬件的特定部分能够在一个独立的可加载模块中实现, 该模块可以在 OpenSSL 代码库之外开发并单独分发。从应用程序的角度来看,这也是理想的,因为他们不需要知道如何使用硬件的细节, 并且当硬件可用时,可以加载/使用特定于硬件的模块。

如前所述,由于 SSL 操作中的硬件加速处理,基于硬件的加密可以极大地提高云应用程序的性能, 并且可以提供密钥/随机数生成等其他加密服务。云可以使用动态引擎轻松地提供硬件,并且存在几种可加载模块实现, 例如 CloudHSMIBMCAQAT Engine

对于云部署,理想的场景是将这些模块作为容器工作负载的一部分交付。工作负载将在提供模块需要访问的底层硬件的节点上调度。 另一方面,不管加密加速硬件是否可用,工作负载都应该以相同的方式运行,并且不需要修改代码。OpenSSL 动态引擎支持这一点。 下面图 1 以一个典型的 Ingress 控制器容器为例说明了这两个场景。红色的框表示启用了加密硬件引擎的容器与“标准”容器之间的区别。 值得指出的是,所显示的配置更改并不一定需要容器的另一个版本,因为配置可以被管理,例如使用 ConfigMap。

图 1. Ingress 控制器容器

图 1. Ingress 控制器容器

硬件资源和隔离

为了能够部署具有硬件依赖关系的工作负载,Kubernetes 提供了优秀的扩展和可配置机制。 让我们进一步研究 Kubernetes 设备插件框架(beta 1.14) 和 RuntimeClass(beta 1.14), 并了解如何利用它们向工作负载暴露加密硬件。

在 Kubernetes 1.8 中首次引入的设备插件框架为硬件供应商提供了一种向 Kubelets 注册和分配节点硬件资源的方法。 插件实现了特定于硬件的初始化逻辑和资源管理。Pod 可以在其 PodSpec 中请求硬件资源, 进而保证 Pod 被调度到能够提供这些资源的节点上。

容器的设备资源分配非常重要。对于处理安全性的应用程序,硬件级别隔离是至关重要的。 基于 PCIe 的加密加速设备功能 可以受益于 IO 硬件虚拟化,通过 I/O 内存管理单元(IOMMU),提供隔离:IOMMU 将设备分组,为工作负载提供隔离的资源 (假设加密卡不与其他设备共享 IOMMU 组)。如果PCIe设备支持单根 I/O 虚拟化(SR-IOV)规范,则可以进一步增加隔离资源的数量。 SR-IOV 允许将 PCIe 设备将 物理功能项(Physical Functions,PF) 设备进一步拆分为 虚拟功能项(Virtual Functions, VF),并且每个设备都属于自己的 IOMMU 组。 要将这些借助 IOMMU 完成隔离的设备功能项暴露给用户空间和容器,主机内核应该将它们绑定到特定的设备驱动程序。 在 Linux 中,这个驱动程序是 vfio-pci, 它通过字符设备将设备提供给用户空间。内核 vfio-pci 驱动程序使用一种称为 PCI 透传(PCI Passthrough) 的机制, 为用户空间应用程序提供了对 PCIe 设备与功能项的直接的、IOMMU 支持的访问。 用户空间框架,如数据平面开发工具包(Data Plane Development Kit,DPDK)可以利用该接口。 此外,虚拟机(VM)管理程序可以向 VM 提供这些用户空间设备节点,并将它们作为 PCI 设备暴露给寄宿内核。 在寄宿内核的支持下,VM 将接近于直接访问底层主机设备的本机性能。

为了向 Kubernetes 发布这些设备资源,我们可以使用一个简单的 Kubernetes 设备插件来运行初始化(绑定), 调用 kubelet 的 Registration gRPC 服务,并实现 kubelet 调用的 DevicePlugin gRPC 服务, 例如,在 Pod 创建时 Allocate 资源。

设备分配和Pod部署

此时,你可能会问容器可以使用 VFIO 设备节点做什么?我们首先快速查看 Kubernetes RuntimeClass 之后,答案会出现。

创建 Kubernetes RuntimeClass 是为了对集群中可用的各种运行时提供更好的控制和可配置性 (前面的一篇博客文章详细介绍了它的需求、状态和路线图)。 本质上,RuntimeClass 为集群用户提供了更好的工具来选择和使用最适合 Pod 用例的运行时。

OCI 兼容的 Kata Containers 运行时为工作负载提供了一个硬件虚拟化隔离层。 除了工作负载隔离之外,Kata Containers VM 还有一个额外的好处,即 VFIO 设备,由设备插件 Allocate 而来, 可以作为硬件隔离设备传递给容器。惟一的要求是,Kata Containers 内核启用了暴露设备的驱动程序。

这就是为容器工作负载启用硬件加速加密所需要的全部。总结:

  1. 集群需要在提供硬件的节点上运行一个设备插件
  2. 设备插件使用 VFIO 驱动程序向用户空间暴露硬件
  3. Pod 在 PodSpec 中请求设备资源并指定 Kata Containers 作为 RuntimeClass
  4. 容器中具有硬件适配库和 OpenSSL 引擎模块

图2显示了使用前面演示的容器的总体设置。

图 2. Deployment 概述

图 2. Deployment 概述

参考设置

最后,我们描述构建图 2 中描述的可以工作的设置所需的构建块和步骤。具体设置使用了 Intel® QuickAssist 技术(QAT) PCIe 设备。 在 Ingress 控制器中启用硬件加速 SSL 终止。应该注意的是,用例并不局限于 Ingress 控制器, 任何基于 OpenSSL 的工作负载都可以加速。

集群配置:

  • Kubernetes 1.14(RuntimeClassDevicePlugin 特性门控已启用(两者在 1.14 中都是 true
  • 配置了 RuntimeClass 就绪运行时和 Kata Containers

主机配置:

  • Intel® QAT 驱动程序发行版,内核驱动程序同时安装在主机内核和 Kata Containers 内核(或在 rootfs 上作为可加载模块)
  • 已部署 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 Deployment .yaml
    • 请求 qat.intel.com: n 资源
    • 请求 runtimeClassName: kata-containers (名称值取决于集群配置)
  • (容器中配置了可用的 OpenSSL 引擎的 QAT 设备配置文件)

一旦构建块可用,就可以按照 TLS 终止示例 步骤测试硬件加速 SSL/TLS。 为了验证硬件的使用,你可以检查主机上的 /sys/kernel/debug/*/fw_counters 文件, 它们会由 Intel® QAT 固件更新。

使用 HAproxy-ingress 和 HAproxy,是因为可以使用 ssl-engine <name> [algo ALGOs] 配置标志直接配置 HAproxy 来使用 OpenSSL 引擎, 而无需修改全局 OpenSSL 配置文件。此外,HAproxy 可以使用异步调用(使用ssl-mode-async)卸载已配置的算法,以进一步提高性能。

呼吁

在这篇博客文章中,我们展示了 Kubernetes 设备插件和 RuntimeClass 如何为 Pod 中的应用程序提供隔离的硬件访问,以便将加密操作卸载给硬件加速器。 硬件加速器可以用来加速加密操作,并将 CPU 周期节省给其他任务。我们演示了使用 HAproxy 的设置, 它已经支持 OpenSSL 中的异步加密卸载。

我们团队的下一步是对 Envoy 重复相同的步骤(使用一个基于 OpenSSL 的 TLS 传输套接字作为扩展构建)。 此外,我们正在努力增强 Envoy 功能,使其能够将 BoringSSL 异步私钥操作卸载到加密加速硬件。 感谢你的反馈和帮助!

当将加密处理卸载到专用加速器时,你的加密应用程序可以为其他任务节省多少 CPU 周期?