自成立以来,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 🔗︎
Supertubes以一种独特的方式整合了KsqlDB,主要是通过利用Istio。我们试图通过减少客户处理配置的时间来使他们的生活变得更轻松。通过Supertubes,ksqlDB被预先配置为使用mTLS和高级授权,开箱即用。我们抛弃了整个HTTP-Basic授权,用Istio的授权策略取代了它。
正如官方文档所述,授权策略可用于对网格中的工作负载进行访问控制。它同时支持允许和拒绝策略,以实现精细化的访问控制。此外,它允许我们缩小对REST端点的访问控制。用户可以设置对端点的访问/info ,但同时可以拒绝任何POST 的调用。
这个表格有助于澄清HTTP-Basic和授权策略之间的区别。
| HTTP-Basic | Istio的授权策略 | |
|---|---|---|
| 没有证书也能工作 | 有 | 没有 |
| 支持基于角色的访问 | 是的 | 是 |
| 细致的访问控制 | 不支持 | 是 |
| 需要客户端配置 | 是 | 不需要(只有当应用程序在网状结构之外)。 |
授权策略示例。
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/"]
我们根据客户的运行位置区分了三种不同的客户类型。
- 驻扎在与ksqlDB服务器相同的Istio网格内的客户端应用程序
- 驻扎在与ksqlDB服务器相同的Kubernetes集群上但在Istio网状结构之外的客户端应用程序
- 居住在Kubernetes集群之外的客户端应用程序
我们将分别看一下这些。
在网状结构内运行的客户端 🔗︎
当连接到ksqlDB的客户端应用程序在同一个Istio网状结构中运行时,它们不需要发送证书。Istio为它们提供了一个开箱即用的证书。这个证书很特别,因为它带有关于应用程序的命名空间和服务账户的信息。授权策略将从中收集SAN URI 信息,并将其作为应用程序的身份。
运行在网状结构之外的客户端 🔗︎
当客户端应用程序从Istio网格外连接时,SAN URI 字段的值(从客户端应用程序的证书中提取)被用作应用程序的身份。这个证书很特别,因为它必须包含所需的SAN URI 字段。这可以由CertManager或Vault等工具生成,但KafkaUser资源也可以做到这一点。截至目前,KafkaUser自定义资源生成的证书包含了在Supertubes中使用ksqlDB所需的所有字段。
在Kubernetes集群之外运行的客户端 🔗︎
当客户端应用程序在Kubernetes集群外部时,该流程与上述不同,因为来自应用程序的流量会通过LoadBalancer和Ingress网关。
保护以无外设模式运行的ksqlDB 🔗︎
使用无外设模式,ksqlDB将不会初始化任何REST端点。这意味着确保组件之间的通信安全就足够了。由于Supertubes在幕后使用并配置了Istio,所以无论是在ksqlDB端还是在它连接的任何服务上,都不需要额外的改变。因此,当我们使用ksqlDB和Supertubes时,我们可以得到mTLS。