外网连接内网kafka-kerberos 报错验证失败!

原来是我昆啊 发表于: 2024-01-19   最后更新时间: 2024-01-19 23:09:44   407 游览

内网有个ambari-hdp3.1的kafka环境 2节点 kafka版本2.0

目前已经映射出去6667 6668 kerberoos通信端口 2181端口
公网ip只有一个ip 58.240.xxx.xxx
节57的6667 6668 映射成外网ip的6667 6668。

内网kafka1配置:

advertised.listeners=SASL_PLAINTEXT://dn9057:6667,EXTERNAL://58.240.xxx.xxx:6668
listeners=SASL_PLAINTEXT://:6667,EXTERNAL://:6668
security.inter.broker.protocol   SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol GSSAPI
listener.security.protocol.map=SASL_PLAINTEXT:SASL_PLAINTEXT,EXTERNAL:SASL_PLAINTEXT

kafka2配置:

advertised.listeners=SASL_PLAINTEXT://dn9057:6667,EXTERNAL://dn_kafka:6668
listeners=SASL_PLAINTEXT://:6667,EXTERNAL://:6668
security.inter.broker.protocol   SASL_PLAINTEXT
sasl.mechanism.inter.broker.protocol GSSAPI
listener.security.protocol.map=SASL_PLAINTEXT:SASL_PLAINTEXT,EXTERNAL:SASL_PLAINTEXT

内网58节点 域名映射

58.240.xxx.xxx dn_kafka

公网1节点 的/etc/hosts都加了域名映射

58.240.xxx.xxx dn9057
58.240.xxx.xxx dn9058
58.240.xxx.xxx dn_kafka

(两个节点外部连接一直会报错,所以节点2绕了一下)

然后再kerberos数据库里添加dn_kafka票据

另外krb5文件也优化了 加了配置改成tcp通信

公网节点:

上传了krb5conf
添加环境变量

export KAFKA_OPTS="-Djava.security.auth.login.config=/usr/hdp/current/kafka-broker/conf/kafka_jaas.conf -Djava.security.krb5.conf=/etc/krb5.conf"
KafkaClient {
com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab = true
    useTicketCache=false
    storeKey = true
    keyTab="/home/kafka.user.keytab"
    principal="kafka@DDP.COM"
    serviceName="kafka";
};


[libdefaults]
  renew_lifetime = 7d
  forwardable = true
  default_realm = DDP.COM
  udp_preference_limit = 1
  ticket_lifetime = 24h
  dns_lookup_realm = false
  dns_lookup_kdc = false
  default_ccache_name = /tmp/krb5cc_%{uid}
  default_tgs_enctypes = aes128-cts
  default_tkt_enctypes = aes128-cts

[logging]
  default = FILE:/var/log/krb5kdc.log
  admin_server = FILE:/var/log/kadmind.log
  kdc = FILE:/var/log/krb5kdc.log

[realms]
  DDP.COM = {
    admin_server = dn9057
    kdc = dn9057
  }

节点上kinit也能通过 klist也能正常显示

然后启动producer连接内网kafka

cd /usr/hdp/3.1.0.0-78/kafka/bin/ && ./kafka-console-producer.sh --broker-list dn9057:6668 --topic hk --producer.config /home/producer.properies

发10条消息能消费5条,其中发到节点57的5条能正常消费,但是其他5条消息:

Connection to node 1002 failed authentication due to: Authentication failed due to invalid credentials with SASL mechanism GSSAPI (org.apache.kafka.clients.NetworkClient)

/home/producer.properies

bootstrap.servers=dn9057:6668
compression.type=none
security.protocol=SASL_PLAINTEXT
sasl.mechanism=GSSAPI
sasl.kerberos.service.name=kafka

我尝试bootstrap.server写多个也没效果。

排查过程:

58开出去一个6669端口 然后58监听端口改用6669 还是一样的错误。

有大佬可以替我解答一下吗。

发表于 2024-01-19
¥20.0

公网ip只有一个,是不行的。因为kafka客户端要与每个node建立长连接,进行数据交换的。
你可以参考:kafka外网访问 ,里面有外网转发的原因。

另外注意,端口不能变,要映射一模一样的。
最后,你做测试的时候,可以先不用kerberos,一步一步来,如果内网、外网消费和生产都可以了,在加上认证。

感谢大佬回复解答。之前确实一直怀疑过公网ip只有一个的环境问题,但不是很有把握。
后续打算采纳先关闭kerberos的建议,也许关了之后发现就是连接不上,目前报的验证失败其实可能就是连接失败的异常抛出。

看了上述提到的文章 认真看了一遍 有解释单个公网ip不可以 也有称解决了的
重新提问一个问题和我的验证思路
我新找了个无kerberos的kafka环境
90.86

port=26667
advertised.listeners=PLAINTEXT://dn86:26667
listeners=PLAINTEXT://dn86:26667

90.87

port=26668
advertised.listeners=PLAINTEXT://dn86:26668
listeners=PLAINTEXT://dn86:26668

将dn86的26667映射到外网的26667
将dn87的26668映射成外网的26668

在客户端90.86的/etc/hosts中配置

58.240.115.226 dn86
58.240.115.226 dn87

启动

cd /usr/hdp/3.1.0.0-78/kafka/bin/ && ./kafka-console-producer.sh --broker-list dn86:26667 --topic test_kk

这样的话 不管从zk中返回的是dn86:26667 还是dn87:26668 那么访问的都是dn86 dn87两个节点 两个端口。

想问一下 这种方案 理论上是否可行

补充:因为90.86-87节点和测试的客户端节点70.110本身是能访问的,所以为了排除风险。

在86 87上开了防火墙 86 87互为白名单,开放26667 26668 2181 端口,最后把70.110拉入黑名单,70.110直接访问86 87是不通的。

截至目前是可以消费了(无kerberos)但是之前报错太多了 不是很确定,所以请大佬帮忙再看一下目前的方案理论上是否ok。

有点乱,你提供的配置。

90.86

listeners=PLAINTEXT://dn86:26667

90.87

listeners=PLAINTEXT://dn86:26668

这个dn86是一样的?

另外,你应该一个kafka集群走内网,客户端走外网,否则全走外网,kafka集群性能很差的。

例如:

port=26667
advertised.listeners=PLAINTEXT://外网ip:26667
listeners=PLAINTEXT://内网ip:26667

不好意思 环境配置 提供的有点问题
实际是这样的
dn86:

port=26667
advertised.listeners=PLAINTEXT://dn86:26667
listeners=PLAINTEXT://内网ip:26667

dn87:

port=26668
advertised.listeners=PLAINTEXT://dn87:26668
listeners=PLAINTEXT://内网ip:26668

然后在客户端添加dn86 dn87的域名映射
我自己测试的结果写

58.240.115.226 dn86
58.240.115.226 dn87

是不是这样就可以实现一个公网ip下的 “外网访问内网集群”

配置没问题,可以的。

感谢大佬的指点,目前已经全部调通,包括kerberos环境!

非kerberos环境最后配置的格式就是上面贴的。
kerberos环境 大致还需要以下几点。

1、kafka-server端加了环境变量

export KAFKA_OPTS="-Djava.security.auth.login.config=/usr/hdp/current/kafka-broker/conf/kafka_jaas.conf"

2、/etc/krb5.conf文件可能需要加一行udp_preference_limit = 1 将udp改成tcp防止丢包(这个不一定需要)

3、客户端需要一个kafka_client_jaas.conf

KafkaClient {
   com.sun.security.auth.module.Krb5LoginModule required
   useTicketCache=true
   renewTicket=true
   serviceName="kafka";
};
Client {
   com.sun.security.auth.module.Krb5LoginModule required
   useTicketCache=true
   renewTicket=true
   serviceName="zookeeper";
};

4、然后一些sasl的配置,监听器的配置就不赘述了

总结:之前对“主动发现集群机制”了解不够,也不知道消费时要对每一个broker都开一个长连接* 加上报错一直都是权限验证失败让人感觉是kerberos的问题,绕了很久。后面排除无关的因素,就很明显了。另外提醒ambari安装的kafka不管界面上配置的advertised.listeners是多少,内部代码还是会强行将listeners的值赋给advertised.listeners。

还是很感谢大佬的及时回复 耐心指导。期待以后更多的交流

你的答案

查看kafka相关的其他问题或提一个您自己的问题