簡體   English   中英

如何在Kafka連接器中正確連接Elastic Operator部署的Elasticsearch?

[英]How to connect Elasticsearch deployed by Elastic Operator correctly in a Kafka connector?

我在 Kafka 中有一些 CDC 數據。 現在我正試圖從 Kafka 下沉到 Elasticsearch。 這是我到目前為止所做的:

步驟 1 - 在 Kubernetes 中部署 Elasticsearch(成功)

我按照本教程使用 Elastic Operator 將 Elasticsearch 部署在 Kubernetes 中:

  1. 在您的 Kubernetes 集群中部署 ECK: https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-deploy-eck.ZFC35FDC70D5FC69D269EZA538A
  2. 部署 Elasticsearch 集群: https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-deploy-elasticsearch.ZFC35FDC70D5FC69D2639883A822CZC7
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
  name: hm-elasticsearch
  namespace: elastic
spec:
  version: 7.14.0
  nodeSets:
    - name: default
      count: 1
      config:
        node.store.allow_mmap: false

根據教程,我可以通過在 header 中提供用戶名elastic和密碼passw0rd來成功調用

curl -u "elastic:passw0rd" -k "https://hm-elasticsearch-es-http.elastic:9200"

返回

{
    "name": "hm-elasticsearch-es-default-0",
    "cluster_name": "hm-elasticsearch",
    "cluster_uuid": "TWgIk0YGR_GVr7IJZcW62g",
    "version": {
        "number": "7.14.0",
        "build_flavor": "default",
        "build_type": "docker",
        "build_hash": "dd5a0a2acaa2045ff9624f3729fc8a6f40835aa1",
        "build_date": "2021-07-29T20:49:32.864135063Z",
        "build_snapshot": false,
        "lucene_version": "8.9.0",
        "minimum_wire_compatibility_version": "6.8.0",
        "minimum_index_compatibility_version": "6.0.0-beta1"
    },
    "tagline": "You Know, for Search"
}

第 2 步 - 添加 ElasticsearchSinkConnector(連接 Elasticsearch 失敗)

現在我正在嘗試添加 ElasticsearchSinkConnector,但是,我在設置它時遇到了問題。

我看到了如何將 Elasticsearch 與 SSL 連接起來? . Elastic Cloud 只需要傳遞用戶名和密碼。 所以我想它會和我的相似。

另外,基於這個 ElasticsearchSinkConnector 配置,我編寫了我的配置,然后嘗試通過

curl --location --request PUT 'http://hm-connect-cluster-connect-api.kafka:8083/connector-plugins/io.confluent.connect.elasticsearch.ElasticsearchSinkConnector/config/validate' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "elasticsearch-sink",
    "connector.class": "io.confluent.connect.elasticsearch.ElasticsearchSinkConnector",
    "tasks.max": "1",
    "topics": "opa_db_server.public.roles",
    "connection.url": "https://hm-elasticsearch-es-http.elastic:9200",
    "connection.username": "elastic",
    "connection.password": "passw0rd",
    "transforms": "unwrap,key",
    "transforms.unwrap.type": "io.debezium.transforms.ExtractNewRecordState",
    "transforms.unwrap.drop.tombstones": "false",
    "transforms.key.type": "org.apache.kafka.connect.transforms.ExtractField$Key",
    "transforms.key.field": "role_id",
    "key.ignore": "false",
    "behavior.on.null.values": "delete"
}'

它返回錯誤

{
    "name": "io.confluent.connect.elasticsearch.ElasticsearchSinkConnector",
    "error_count": 3,
    "groups": [
        "Common",
        "Transforms",
        "Predicates",
        "Error Handling",
        "Transforms: unwrap",
        "Transforms: key",
        "Connector",
        "Data Conversion",
        "Proxy",
        "Security",
        "Kerberos",
        "Data Stream"
    ],
    "configs": [
        // ...
        {
            "definition": {
                "name": "connection.url",
                "type": "LIST",
                "required": true,
                "default_value": null,
                "importance": "HIGH",
                "documentation": "The comma-separated list of one or more Elasticsearch URLs, such as ``http://eshost1:9200,http://eshost2:9200`` or ``https://eshost3:9200``. HTTPS is used for all connections if any of the URLs starts with ``https:``. A URL without a protocol is treated as ``http``.",
                "group": "Connector",
                "width": "LONG",
                "display_name": "Connection URLs",
                "dependents": [],
                "order": 1
            },
            "value": {
                "name": "connection.url",
                "value": "https://hm-elasticsearch-es-http.elastic:9200",
                "recommended_values": [],
                "errors": [
                    "Could not connect to Elasticsearch. Error message: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"
                ],
                "visible": true
            }
        },
        {
            "definition": {
                "name": "connection.username",
                "type": "STRING",
                "required": false,
                "default_value": null,
                "importance": "MEDIUM",
                "documentation": "The username used to authenticate with Elasticsearch. The default is the null, and authentication will only be performed if  both the username and password are non-null.",
                "group": "Connector",
                "width": "SHORT",
                "display_name": "Connection Username",
                "dependents": [],
                "order": 2
            },
            "value": {
                "name": "connection.username",
                "value": "elastic",
                "recommended_values": [],
                "errors": [
                    "Could not authenticate the user. Check the 'connection.username' and 'connection.password'. Error message: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"
                ],
                "visible": true
            }
        },
        {
            "definition": {
                "name": "connection.password",
                "type": "PASSWORD",
                "required": false,
                "default_value": null,
                "importance": "MEDIUM",
                "documentation": "The password used to authenticate with Elasticsearch. The default is the null, and authentication will only be performed if  both the username and password are non-null.",
                "group": "Connector",
                "width": "SHORT",
                "display_name": "Connection Password",
                "dependents": [],
                "order": 3
            },
            "value": {
                "name": "connection.password",
                "value": "[hidden]",
                "recommended_values": [],
                "errors": [
                    "Could not authenticate the user. Check the 'connection.username' and 'connection.password'. Error message: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"
                ],
                "visible": true
            }
        },
        // ...
    ]
}

可以在此處找到包含所有字段的完整驗證響應,其中包含可以使用配置字段的所有信息。

更新 1(2021 年 12 月 8 日):

我發現這個文檔有更多關於 SSL 的配置

"elastic.security.protocol": "SSL"
"elastic.https.ssl.keystore.location": "/path/to/keystore.jks"
"elastic.https.ssl.keystore.password": "xxx"
"elastic.https.ssl.key.password": "xxx"
"elastic.https.ssl.keystore.type": "JKS"
"elastic.https.ssl.truststore.location": "/path/to/truststore.jks"
"elastic.https.ssl.truststore.password": "xxx"
"elastic.https.ssl.truststore.type": "JKS"
"elastic.https.ssl.protocol": "TLS"

就我而言,我只需要提供者用戶名和密碼即可成功。 但是在上面的配置中,沒有地方提供用戶名。 所以我不確定如何真正正確地編寫它。

更新 2(2021 年 12 月 9 日):

我有這些豆莢正在運行

> kubectl get pods --namespace=elastic
NAME                                 READY   STATUS    RESTARTS   AGE
hm-kibana-kb-77d4d9b456-m6th9        1/1     Running   0          6d3h
hm-elasticsearch-es-default-0        1/1     Running   0          35h

還有這些秘密

kubectl get secrets --namespace=elastic
NAME                                             TYPE                                  DATA   AGE
hm-kibana-kibana-user                            Opaque                                1      6d3h
elastic-hm-kibana-kibana-user                    Opaque                                3      6d3h
hm-kibana-kb-http-ca-internal                    Opaque                                2      6d3h
hm-elasticsearch-es-http-ca-internal             Opaque                                2      6d3h
hm-elasticsearch-es-http-certs-internal          Opaque                                3      6d3h
hm-elasticsearch-es-http-certs-public            Opaque                                2      6d3h
hm-kibana-kb-es-ca                               Opaque                                2      6d3h
hm-kibana-kb-http-certs-internal                 Opaque                                3      6d3h
hm-kibana-kb-http-certs-public                   Opaque                                2      6d3h
hm-elasticsearch-es-transport-ca-internal        Opaque                                2      6d3h
hm-elasticsearch-es-transport-certs-public       Opaque                                1      6d3h
hm-elasticsearch-es-remote-ca                    Opaque                                1      6d3h
hm-elasticsearch-es-elastic-user                 Opaque                                1      6d3h
hm-elasticsearch-es-internal-users               Opaque                                3      6d3h
hm-elasticsearch-es-xpack-file-realm             Opaque                                3      6d3h
hm-elasticsearch-es-default-es-config            Opaque                                1      6d3h
hm-elasticsearch-es-default-es-transport-certs   Opaque                                3      6d3h
hm-kibana-kb-config                              Opaque                                2      6d3h

我可以通過以下方式在本地保存ca.crttls.crttls.key

kubectl get secret hm-elasticsearch-es-http-certs-public \
  --namespace=elastic \
  --output=go-template='{{index .data "ca.crt" | base64decode }}' \
  > ca.crt

kubectl get secret hm-elasticsearch-es-http-certs-public \
  --namespace=elastic \
  --output=go-template='{{index .data "tls.crt" | base64decode }}' \
  > tls.crt

kubectl get secret hm-elasticsearch-es-http-certs-internal \
  --namespace=elastic \
  --output=go-template='{{index .data "tls.key" | base64decode }}' \
  > tls.key

在我必須使用-k標志禁用證書驗證以讓curl成功之前。 現在在 Kubernetes 中,我可以在沒有標志的情況下成功:

curl --request GET \
     --url https://hm-elasticsearch-es-http.elastic:9200 \
     --cacert ca.crt \
     --key tls.key \
     --cert tls.crt \
     --header 'Content-Type: application/json' \
     -u "elastic:passw0rd"

另外,我成功生成了keystore.jks

openssl pkcs12 -export \
  -in tls.crt \
  -inkey tls.key \
  -CAfile ca.crt \
  -caname root \
  -out keystore.p12 \
  -password pass:SFLzyT8DPkGGjDtn \
  -name hm-elasticsearch-keystore

keytool -importkeystore \
  -srckeystore keystore.p12 \
  -srcstoretype PKCS12 \
  -srcstorepass SFLzyT8DPkGGjDtn \
  -deststorepass MPx57vkACsRWKVap \
  -destkeypass MPx57vkACsRWKVap \
  -destkeystore keystore.jks \
  -alias hm-elasticsearch-keystore

我仍然不確定 UPDATE 1 中的信任庫如何。 但現在我可以填寫有關keystore的這一部分:

"elastic.https.ssl.keystore.location": "/path/to/keystore.jks"
"elastic.https.ssl.keystore.password": "MPx57vkACsRWKVap"
"elastic.https.ssl.key.password": "MPx57vkACsRWKVap"
"elastic.https.ssl.keystore.type": "JKS"

但是,我的keystore.jks目前在我本地的筆記本電腦上。 我的 Elasticsearch 和 ElasticsearchSinkConnector 在 Kubernetes 中運行。

這個"elastic.https.ssl.keystore.location": "/path/to/keystore.jks" to/keystore.jks”指的是哪里?

首先添加更多背景。 我部署 Kafka 的方式是使用Strimzi

kubectl create namespace kafka
kubectl apply --filename="https://strimzi.io/install/latest?namespace=kafka" --namespace=kafka
kubectl apply --filename=https://strimzi.io/examples/latest/kafka/kafka-persistent-single.yaml --namespace=kafka

在問題 UPDATE 2 之后,一旦得到keystore.jks ,我通過

kubectl create secret generic hm-elasticsearch-keystore \
  --from-file=keystore.jks \
  --namespace=kafka

我有文件

kafkaconnect.yaml

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnect
metadata:
  name: hm-connect-cluster
  namespace: kafka
  annotations:
    # use-connector-resources configures this KafkaConnect
    # to use KafkaConnector resources to avoid
    # needing to call the Connect REST API directly
    strimzi.io/use-connector-resources: "true"
spec:
  image: hongbomiao/hm-connect-debezium:latest
  replicas: 1
  bootstrapServers: my-cluster-kafka-bootstrap:9093
  tls:
    trustedCertificates:
      - secretName: my-cluster-cluster-ca-cert
        certificate: ca.crt
  config:
    config.storage.replication.factor: 1
    offset.storage.replication.factor: 1
    status.storage.replication.factor: 1
    config.providers: file
    config.providers.file.class: org.apache.kafka.common.config.provider.FileConfigProvider
  externalConfiguration:
    volumes:
      - name: hm-elasticsearch-keystore-volume
        secret:
          secretName: hm-elasticsearch-keystore

elasticsearch-sink-kafkaconnector.yaml

apiVersion: kafka.strimzi.io/v1beta2
kind: KafkaConnector
metadata:
  name: elasticsearch-sink-connector
  namespace: kafka
  labels:
    strimzi.io/cluster: hm-connect-cluster
spec:
  class: io.confluent.connect.elasticsearch.ElasticsearchSinkConnector
  tasksMax: 1
  # https://docs.confluent.io/kafka-connect-elasticsearch/current/configuration_options.html
  config:
    connector.class: "io.confluent.connect.elasticsearch.ElasticsearchSinkConnector"
    tasks.max: "1"
    topics: "opa_db_server.public.roles"
    connection.url: "https://hm-elasticsearch-es-http.elastic:9200"
    connection.username: "elastic"
    connection.password: "passw0rd"
    transforms: "unwrap,key"
    transforms.unwrap.type: "io.debezium.transforms.ExtractNewRecordState"
    transforms.unwrap.drop.tombstones: "false"
    transforms.key.type: "org.apache.kafka.connect.transforms.ExtractField$Key"
    transforms.key.field: "role_id"
    key.ignore: "false"
    behavior.on.null.values: "delete"
    elastic.security.protocol: "SSL"
    elastic.https.ssl.keystore.location: "/opt/kafka/external-configuration/hm-elasticsearch-volume/keystore.jks"
    elastic.https.ssl.keystore.password: "MPx57vkACsRWKVap"
    elastic.https.ssl.key.password: "MPx57vkACsRWKVap"
    elastic.https.ssl.keystore.type: "JKS"
    elastic.https.ssl.truststore.location: "/opt/kafka/external-configuration/hm-elasticsearch-keystore-volume/keystore.jks"
    elastic.https.ssl.truststore.password: "MPx57vkACsRWKVap"
    elastic.https.ssl.truststore.type: "JKS"
    elastic.https.ssl.protocol: "TLS1.3"

注意 keystore 和 truststore 共享同一個。

然后只需要運行

kubectl apply --filename=kafkaconnect.yaml
kubectl apply --filename=elasticsearch-sink-kafkaconnector.yaml

現在它起作用了!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM