暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Apache Pulsar — 使用单集群多租户服务整个企业

背井 2021-03-03
1322

译自 Karthikeyan Palanivelu 所写《Apache Pulsar — One Cluster for the Entire Enterprise Using Multi Tenancy》。点击 阅读原文 可查看英文原文。



如前文所述,Apache Pulsar 是由 Yahoo 创建的一个新的开源分布式 pub-sub 消息平台,现在它已经是Apache软件基金会的一部分。Pulsar 提供了各种现成的特性(out-of-the-box features),本文将评估/测试其多租户特性(Multi Tenancy)


多租户是一种允许不同软件、应用程序或平台在共享环境中安全运行的功能。共享环境中的每个单元都称为“租户(Tenant)”,下面我们将深入讨论。


What Are Tenants? 什么是租户


租户可以是组织内的一个客户或团队,也可以是一组保密的生产者或消费者,他们的数据和处理过程要与其他客户或团队隔离开来。租户可以在不同的环境(如开发、测试或生产)管理不同的应用程序。


在一家零售商店中,存货(Inventory)、采购(Purchase)、账单(Billing)、订单(Order)、补货(Replenishment)等都可以是租户。对于金融科技(fintech)公司来说,银行(Bank)、信用卡(Credit Card)、贷款(Loans)等都可以是租户。延续金融科技的例子,信用卡可能涉及付款、信用历史记录等应用程序,为了保密性,这些应用程序在内部被分为多个子系统或环境(如开发、QA或生产)进行部署。在本例中,支付和信用历史记录形成了名称空间(namespaces),名称空间下再基于环境为每个子系统创建话题(topics)。



适用于金融科技公司的多租户示例



What are the advantages of Multi-Tenants? 多租户的优势有哪些


多租户使得一个企业或一家零售商为整个组织提供一个全局集群即可,不同部门之间同样可以拥有数据或硬件隔离。多租户的几个优点:


  • 成本(Cost) —— 多租户允许组织规划较少的集群,这样,在基础设施和维护上花费的金钱和时间将等比例地减少。

  • 集群大小(Cluster Size) —— 这取决于组织的需要。与本地化实例(localized instance)相比,从多集群环境压缩到单个企业集群将导致更大的单集群。Pulsar架构支持可伸缩的水平和垂直扩展,以支持这一需求。

  • 复制和弹性(Replication and Resiliency) —— 答案很简单;Pulsar是从无状态的brokers构建的,由BookKeeper提供持久化存储支持。这意味着Pulsar可以水平和垂直伸缩,以其内置的地理复制(geo-replication)功能支持n-mesh复制。



How do we implement Multi-Tenancy? 怎么使用多租户功能


假设我们的零售组织有两个部门:Inventory 和 Billing。我们可以设计如下租户:


  • Inventory

  • Billing




这两个租户必须通过Pulsar与部门内或部门间的不同系统进行交互。Pulsar支持 TLSAthenzKerberos 进行身份验证和授权,多租户功能也要借助这些工具。在本例中,我们将使用 TLS


要使用 TLS 加密,我们需要生成 trust、server 和 client 证书。


1. Trust Certificate


第一步是创建信任证书。请按照Pulsar文档中的说明进行操作,网址为 https://pulsar.apache.org/docs/en/security-tls-transport


2. Server Certificate


按照上述文档中的描述为 Broker(Pulsar)生成服务端证书(server certificate)私钥(private key)。如果需要带有SAN信息,遵循以下指示:


将以下内容另存为 csr_server.txt

    [req]
    default_bits = 2048
    prompt = no
    default_md = sha256
    req_extensions = req_ext
    distinguished_name = dn
    [ dn ]
    C=US
    ST=STATE
    L=CITY
    O=COMPANYNAME
    OU=DEPT
    emailAddress=karthik@domain.com
    CN = *.retailer.com
    [ req_ext ]
    subjectAltName = @alt_names
    [ alt_names ]
    DNS.1 = *.abc.cloud.retailer.com
    DNS.2 = *.retailer.com
    DNS.3 = localhost


    使用下面的命令生成服务端证书(server certificate)

      openssl req \
      -newkey rsa:2048 \
      -sha256 \
      -nodes \
      -out broker-cert.csr \
      -keyout privkey.pem \
      -outform PEM \
      -config <( cat csr_server.txt )


      其余步骤遵循Pulsar文档中的描述:https://pulsar.apache.org/docs/en/security-tls-transport


      3. Client Certificate


      同样地,还需要生成三个客户端证书(client certificates)


      • 一个用于 Admin CLI 工具,如 pulsar-admin

      • 一个用于 CN=Inventory 的 Inventory(对于SAN,使用上面的示例)。

      • 一个用于 CN=Billing 的 Billing(对于SAN,使用上面的示例)。


      现在你有了:


      • 用于 Broker 的服务端证书。

      • 用于命令行工具、InventoryBilling 的客户端证书。


      按照Pulsar文档中的说明,配置以下文件(文档地址:https://pulsar.apache.org/docs/en/security-tls-transport/#broker-configuration)


      • broker.conf ( Server Certificate 和 Truststore Certificate )

      • client.conf ( pulsar-admin 用到了该配置 — 使用相应的客户端证书)

      • discovery.conf (Server Certificate 和 Truststore Certificate)



      在 ZooKeeperBookieBroker (Cluster Name=Retailer) 启用身份验证和授权并运行后,使用 pulsar-admin 创建租户:


        ./pulsar-admin tenants create inventory-tenant \
        -admin-roles inventory —allowed-clusters retailer


        对于 Billing


          ./pulsar-admin tenants create billing-tenant \
            -admin-roles billing —allowed-clusters retailer


          现在,让我们考虑一下部门内部的沟通。


          下一步是为每个租户创建 namespace。


          对于 Inventory ns1:


            ./pulsar-admin namespaces create inventory-tenant/ns1
            ./pulsar-admin namespaces set-clusters inventory-tenant/ns1 —clusters retailer


            对于 Billing ns1:


              ./pulsar-admin namespaces create billing-tenant/ns1
              ./pulsar-admin namespaces set-clusters billing-tenant/ns1 —clusters retailer


              接下来是设置 namespace 的访问权限。


              可以使用通配符,但不支持中括号通配符。角色应与相应客户端证书的CN匹配。


                ./pulsar-admin namespaces grant-permission inventory-tenant/ns1 \
                  -actions produce,consume \
                  -role 'inventory*'
                ./pulsar-admin namespaces grant-permission billing-tenant/ns1 \
                  -actions produce,consume \
                  -role 'billing*'


                再然后是创建 topics。


                • 对于 Invetory:Topic1

                • 对于 Billing:Topic1



                In the Cloud or Kubernetes? 云环境,或使用 K8S?


                Pulsar有一个名为 Proxy 的内置功能,在云端或Kubernetes上部署 Pulsar 时需要对其进行配置。Proxy 本身可以提供我们在Broker中讨论过的身份验证和授权功能。Proxy 也可以使用 TLS非TLS 再次与 Broker 通信。


                要在 Proxy 中启用 TLS,将服务端证书配置到 “tlsCertificateFilePath” 和 “tlsKeyFilePath” 下。


                设置:

                  tlsEnabledWithBroker=true
                  tlsEnabledInProxy=true


                  并设置客户端证书,以与 Broker 进行握手:

                    brokerClientAuthenticationPlugin=org.apache.pulsar.client.impl.auth.AuthenticationTls
                    brokerClientAuthenticationParameters=tlsCertFile:<CLIENT-CERT-FILE>,tlsKeyFile:<CLIENT-KEY-FILE>
                    brokerClientTrustCertsFilePath=<TRUST-CERT-FILE>


                    若要允许传递授权token,启用以下属性:

                      forwardAuthorizationCredentials=true


                      要在 Proxy处 终止SSL,设置 tlsEnabledWithBroker=false,并且不要配置客户端证书。你仍然可以将授权令牌传递给 Broker 以验证权限。


                      现在,一切准备就绪。我们分别为 InventoryBilling 编写生产者和消费者,测试多租户特性。下面是生产者和消费者的示例片段。


                      Producer.java

                        public class Producer {
                        public static void main(String[] args) {
                        String localClusterUrl = "pulsar+ssl://localhost:6651";
                        String namespace = "inventory-tenant/ns1";
                        String topic = String.format("persistent://%s/topic1", namespace);
                        Map<String, String> authParams = new HashMap<>();
                        authParams.put("tlsCertFile", "client-inventory-cert.pem");
                        authParams.put("tlsKeyFile", "client-inventory-key.pem");
                        Authentication tlsAuth = AuthenticationFactory
                        .create(AuthenticationTls.class.getName(), authParams);
                        PulsarClient client = PulsarClient.builder().serviceUrl(localClusterUrl)
                        .enableTls(true)
                        .tlsTrustCertsFilePath("/demoCA/cacert.pem")
                        .authentication(tlsAuth)
                        .build();
                        Producer producer = client.newProducer()
                        .topic(topic)
                        .sendTimeout(10, TimeUnit.SECONDS)
                        .create();
                        for (int i = 0; i < 10; i++) {
                        String msg = String.format("Inventory-message-W-%d", i);
                        producer.send(msg.getBytes());
                        System.out.println("Sending Message - -> " + msg);
                        }
                        producer.close();
                        client.close();
                        }
                        }


                        Consumer.java

                          public class Consumer {
                          public static void main(String[] args) {
                          String localClusterUrl = "pulsar+ssl://localhost:6651";
                          String namespace = "inventory-tenant/ns1";
                          String topic = String.format("persistent://%s/topic1", namespace);
                          Map<String, String> authParams = new HashMap<>();
                          authParams.put("tlsCertFile", "client-inventory-cert.pem");
                          authParams.put("tlsKeyFile", "client-inventory-key.pem");
                          Authentication tlsAuth = AuthenticationFactory
                          .create(AuthenticationTls.class.getName(), authParams);\
                          PulsarClient client = PulsarClient.builder().serviceUrl(localClusterUrl)
                          .enableTls(true)
                          .tlsTrustCertsFilePath("/demoCA/cacert.pem")
                          .authentication(tlsAuth).build();\
                          Consumer consumer = client.newConsumer()
                          .topic(topic)
                          .subscriptionName("my-sub")
                          .subscriptionType(SubscriptionType.Exclusive)
                          .subscribe();
                          while (true) {
                          Message msg = consumer.receive();
                          System.out.println("Received message: " + StringUtils.newStringUtf8(msg.getData()));
                          consumer.acknowledge(msg);
                          }
                          }
                          }



                          如果在 Inventory/Billing 之间切换了客户端证书,则生产/消费的应用将抛出 AuthorizationException,这说明生产者/消费者无权在 <tenant>/ns1/topic1 上生产/消费消息,即使 namespacetopic 匹配(但tenant不匹配)


                          Conclusion 总结


                          Apache Pulsar 是一个建立在分层架构上的功能强大的 pub-sub 模型,它提供了开箱即用的地理复制、多租户、零再平衡时间(zero rebalancing time)、统一化的队列和流(streaming)以及持久化等特性。


                          组织可以利用Pulsar多租户的特性,使成本、工作量、维护花费等最小化。多租户将帮助应用程序安全地在共享环境中工作。在本文中,我们配置了多个应用程序,让它们使用TLS传输加密共用一个集群。




                          相关推荐:



                          文章转载自背井,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                          评论