用Supertubes管理ksqlDB的操作示例

113 阅读9分钟

自成立以来,Supertubes一直在问一个问题:"如果?"如果我们把Kafka建立在Istio的坚实基础上,并利用它和Envoy代理的强大网络功能,把两者结合起来,变成更强大的东西,会怎么样?今天,伴随着发布对Supertubes的ksqlDB支持,我们对Istio和Kafka能做什么,一起改善我们的生活进行了更多猜测。

多年来,Kafka已经成长为一个完整的平台,围绕它建立了一个完整的生态系统,由Kafka Connect、Kafka Schema Registry和Mirror Maker 2等组件组成。KsqlDB是该生态系统中最后一个被Supertubes支持的东西,也就是直到今天。

当然,像往常一样,我们想在配方中加入Banzai Cloud的秘方,并将其提升到新的水平。在这种情况下,这意味着用Istio使它更安全,并把ksqlDB管理的一些更繁琐的部分从我们客户的肩上拿下来。

那么,盒子里有什么呢? 🔗︎

在Supertubes中,我们让ACL成为Kubernetes的一等公民。这应该是很有意义的,因为我们喜欢模糊Kafka、Istio和Kubernetes之间的界限,使它们成为一个大的生态系统,一起工作,而不是互相对抗,更重要的是,不是对抗我们。作为这个过程的一部分,我们往往能节省很多挫折、时间和金钱。

这也有助于将Kafka与我们预先存在的、日常的Kubernetes工具(如kubectl)越来越多地结合起来。此外,在运营商的帮助下,我们可以从CI/CD管道中声明性地部署它们,并以动态的方式自动处理它们--我相信你们中的大多数人都不会错过这样做,丝毫没有。

假设你已经有一个Kubernetes集群,上面安装了最新的Supertubes,并且有一个工作的ksqlDB安装,你所要做的就是在集群上部署一个KsqlDB 的自定义资源。幸运的是,Supertubes CLI--在这种情况下,它提供了一些验证--使之很容易做到。

supertubes cluster ksqldb create -f  -n my-namespace

或者只是用普通的kubectl apply 来应用自定义资源文件。

这里有一个简单的例子,它将在交互式模式下创建一个预配置的ksqlDB集群,它引用了预先存在的Schema Registry和Kafka Connect自定义资源。

apiVersion: kafka.banzaicloud.io/v1beta1
kind: KsqlDB
metadata:
  name: ksqldb-sample
spec:
  clusterRef:
    name: "my-kafka-cluster"
  schemaRegistryRef:
    name: "my-schema-regitry"
  kafkaConnectRef:
    name: "my-kafka-connect"

这也将创建所有的ACL,这些ACL是ksqlDB内部操作的交互式和无头模式所需要的,允许ksqlDB管理它的记录处理日志主题,并且也产生命令主题。

为了让ksqlDB集群在我们的输入和输出主题上工作,我们首先要在自定义资源的Spec部分提供它们。

输入主题是你想从中读取数据的主题,而输出主题是你想写入的主题--这些也可以是新创建的主题,例如,当你创建一个流时。如果你想把查询连在一起,使一个查询的输出主题成为另一个查询的输入主题,你必须在这两个地方提供它们。

然后Supertubes会生成所需的ACL,以便ksqlDB对其进行操作。如果你在无头模式下操作ksqlDB实例时,事先知道你的输入和输出主题,那就更容易了--因为当你启动实例时,查询已经在那里了--但我们在交互模式下提供了同样的功能,如果你有一些喜欢的主题,你总是想从中读取。

...
Spec:
  inputTopics:
  - kafkacat-airports
  outputTopics:
  - AIRPORTS_ALL
...

只需扩展它 🔗︎

我们使用HPA 来处理 ksqlDB 的扩展问题。这里的转折点是,默认情况下,HPA只支持通过基本的CPU或内存使用量进行扩展,虽然这对大多数工作负载来说通常是足够的,但对于ksqlDB来说,通过consumer lag ,这是一个更好的主意。

当ksqlDB不能跟上Kafka主题上产生的消息的速度时,它在处理传入数据时就会落后。通过消费者的滞后性进行扩展将有助于解决这个问题,远比通过任何传统的指标进行扩展要好。在Supertubes生态系统中,我们已经在我们的Prometheus实例中跟踪消费者滞后。你只需要通过部署kube-metrics-adapter helm chart来启用HPA来了解这些指标。一个已经部署和配置好的HPA将为你做剩下的事情。

让我们看看另一种方法,当涉及到ksqlDB安全时,Supertubes可以改善我们的生活。

确保ksqlDB的安全 🔗︎

当涉及到保护ksqlDB的安全时,我们必须区分两种模式:无头模式和互动模式。在交互式模式下运行ksqlDB比在无头模式下运行ksqlDB更为复杂。

确保以交互式模式运行的ksqlDB的安全 🔗︎

在互动模式下,ksqlDB启用了REST API端点,这需要额外的配置,以使其安全。

普通的ksqlDB方式 🔗︎

ksqlDB支持使用HTTP基本认证和TLS对RESTful和WebSocket端点进行认证和加密客户-服务器通信。为了启用加密功能,你需要提供以下配置参数。

listeners=https://hostname:port
ssl.keystore.location=/ssl/certs/keystore.jks
ssl.keystore.password=supersecure

这种配置乍看之下可能并不复杂。然而,将新的或更新的TLS证书导入钥匙库使其维护起来有点麻烦。

ksqlDB的内置认证使用基本的HTTP认证机制。这意味着它可以被配置为要求用户使用用户名和密码进行认证。此外,它通过指定哪些角色可以访问服务器来提供基于角色的授权。

配置认证需要一个标准的jaas 文件,它将定义服务器如何认证用户。最简单的例子是,当jaas 文件包含一个密码文件的路径,它可能看起来像这样。

marty: delorean,user,admin
mcfly: drbrown,user,developer

这个文件也将包含用户的角色,它与ksqlDB服务器中的一个配置值相匹配。从客户端连接到服务器需要你提供一个用户名和密码。

bin/ksql --user marty --password delorean http://localhost:8088

我们刚刚快速浏览了在启用交互模式时如何配置ksqlDB的安全性。现在,让我们深入了解一下Supertubes是如何进行这一切配置的。

用Supertubes保护ksqlDB 🔗︎

image.png

Supertubes以一种独特的方式整合了KsqlDB,主要是通过利用Istio。我们试图通过减少客户处理配置的时间来使他们的生活变得更轻松。通过Supertubes,ksqlDB被预先配置为使用mTLS和高级授权,开箱即用。我们抛弃了整个HTTP-Basic授权,用Istio的授权策略取代了它。

正如官方文档所述,授权策略可用于对网格中的工作负载进行访问控制。它同时支持允许和拒绝策略,以实现精细化的访问控制。此外,它允许我们缩小对REST端点的访问控制。用户可以设置对端点的访问/info ,但同时可以拒绝任何POST 的调用。

这个表格有助于澄清HTTP-Basic和授权策略之间的区别。

HTTP-BasicIstio的授权策略
没有证书也能工作没有
支持基于角色的访问是的
细致的访问控制不支持
需要客户端配置不需要(只有当应用程序在网状结构之外)。

授权策略示例。

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
 name: ...
 namespace: ...
spec:
 selector:
    matchLabels:
      app: ksqldb
 action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/"]
   to:
   - operation:
       methods: ["GET"]
       paths: ["/..."]

为了验证客户端,它使用了证书的SAN URI 字段,如果是Istio生成的秘密形式,其格式为。

spiffe://cluster.local/ns//sa/

为了允许这样的应用程序连接到KsqlDB,KsqlDB部署的AuthorizationPolicy必须包括。

action: ALLOW
 rules:
 - from:
   - source:
       principals: ["cluster.local/ns//sa/"]

我们根据客户的运行位置区分了三种不同的客户类型。

  1. 驻扎在与ksqlDB服务器相同的Istio网格内的客户端应用程序
  2. 驻扎在与ksqlDB服务器相同的Kubernetes集群上但在Istio网状结构之外的客户端应用程序
  3. 居住在Kubernetes集群之外的客户端应用程序

我们将分别看一下这些。

在网状结构内运行的客户端 🔗︎

当连接到ksqlDB的客户端应用程序在同一个Istio网状结构中运行时,它们不需要发送证书。Istio为它们提供了一个开箱即用的证书。这个证书很特别,因为它带有关于应用程序的命名空间和服务账户的信息。授权策略将从中收集SAN URI 信息,并将其作为应用程序的身份。

运行在网状结构之外的客户端 🔗︎

当客户端应用程序从Istio网格外连接时,SAN URI 字段的值(从客户端应用程序的证书中提取)被用作应用程序的身份。这个证书很特别,因为它必须包含所需的SAN URI 字段。这可以由CertManager或Vault等工具生成,但KafkaUser资源也可以做到这一点。截至目前,KafkaUser自定义资源生成的证书包含了在Supertubes中使用ksqlDB所需的所有字段。

在Kubernetes集群之外运行的客户端 🔗︎

当客户端应用程序在Kubernetes集群外部时,该流程与上述不同,因为来自应用程序的流量会通过LoadBalancer和Ingress网关。

保护以无外设模式运行的ksqlDB 🔗︎

image.png

使用无外设模式,ksqlDB将不会初始化任何REST端点。这意味着确保组件之间的通信安全就足够了。由于Supertubes在幕后使用并配置了Istio,所以无论是在ksqlDB端还是在它连接的任何服务上,都不需要额外的改变。因此,当我们使用ksqlDB和Supertubes时,我们可以得到mTLS。