Kafka
最近在 OpenStack 環境下需要部署消息隊列集羣,包括 RabbitMQ 和 Kafka,這篇記述一下 Kafka 集羣的部署過程。
本文所用的環境包括:
軟件版本
- OpenStack 版本: Pike release
- Kafka 版本:2.11-2.0.0
- Zookeeper 版本:3.4.8-1
- 虛擬機系統:Ubuntu 16.04
- Java 版本:openjdk 1.8.0_181
虛擬機信息:
- 一共用到三臺虛擬機;
- zookeeper 和 Kafka 共用統一虛擬機;
- 三臺虛擬機信息:
- hostname:kafka-1,IP:10.0.0.1,ID:1
- hostname:kafka-2,IP:10.0.0.2,ID:2
- hostname:kafka-3,IP:10.0.0.3,ID:3
注意:由於用到了多臺服務器,所以以下操作步驟如無特殊說明,需要在全部三臺虛擬機上執行。
0. 服務器配置
在進行 Kafka 和 zookeeper 集羣配置之前要先做一些服務器的基礎配置,主要是主機名的修改。
首先要先修改 hostname:
$ cat /etc/hostname kafka-1/2/3
然後修改 hosts 文件,當然下面文件的內容是根據前面給出的配置信息進行填寫的,大家需要根據自己服務器的 IP 和實際主機名進行對應修改。
$ cat /etc/hosts ...... 10.0.0.1 kafka-1 10.0.0.2 kafka-2 10.0.0.3 kafka-3
1. Zookeeper 集羣
Kafka 目前專注於消息處理方面的功能,大部分其他能力都是靠外部組件來實現的,比如搭建集羣就需要依賴於 zookeeper,鑑權則用到了 Kerberos 和 SASL。所以第一步自然是要搭建 zookeeper 了。
當然 Kafka 是自帶 Zookeeper 的,如果用自帶 Zookeeper 的方式,可以實現單節點的 Kafka 集羣,但本文討論的是集羣環境,所以不詳細描述單節點的部署方式。
1.1 zookeeper 集羣安裝
之所以要用三個虛擬機,是因爲 Zookeeper 集羣需要至少三個節點才能正常工作,所以 zookeeper 的安裝步驟當然是所有三臺上都要執行。Zookeeper 用的是 Ubuntu 16.04 的默認版本,所以大家再去安裝時,可以版本對不上,這不是問題,基本步驟應該沒什麼變化。
$ sudo apt update $ sudo apt upgrade -y $ sudo apt install -y openjdk-8-jre $ sudo apt install -y zookeeperd
接下來要修改 zookeeper 的配置信息,第一步是要修改 zoo.cfg 中全部 zookeeper 器羣服務器的地址信息。下面配置中的 kafka-* 這部分需要根據大家的環境信息替換爲主機名或主機 IP。
$ cat /etc/zookeeper/conf/zoo.cfg ... # specify all zookeeper servers # The fist port is used by followers to connect to the leader # The second one is used for leader election #server.1=zookeeper1:2888:3888 #server.2=zookeeper2:2888:3888 #server.3=zookeeper3:2888:3888 server.1=kafka-1:2888:3888 server.2=kafka-2:2888:3888 server.3=kafka-3:2888:3888 ...
最後要修改 /etc/zookeeper/conf/myid,這個文件就是集羣的中的特殊標識,一般來講,三臺服務器的集羣,三臺服務器分別使用 1、2、3 就可以了。所以爲了避免大家配置錯誤,下面把三臺服務器的配置示例都貼了上來。
$ cat /etc/zookeeper/conf/myid # on kafka-1 1 $ cat /etc/zookeeper/conf/myid # on kafka-2 2 $ cat /etc/zookeeper/conf/myid # on kafka-3 3
到這裏 zookeeper 的基本配置就完成了。
1.2 SASL 鑑權
完成基本配置後 zookeeper 就可以正常使用了,但問題是只要能訪問到 zookeeper 的端口,誰都可以使用,沒有校驗機制,這是不可接受的。zookeeper 和 kafka 提供了兩種安全驗證機制:SSL 和 SASL,本文中使用的是 SASL,安全性上應該是 SSL 更好,不過 SASL 配置起來相對簡單,所以暫時選用了 SASL。
zookeeper 爲了實現 SASL 功能,需要引入一些 JAR 包,我把這些文件上傳到了百度雲盤,大家可以通過這個鏈接進行下載: zookeeper-sasl-jar.tar.gz
下載後解壓,並放到 zookeeper 的安裝目錄:
$ tar zxvf zookeeper-sasl-jar.tar.gz $ sudo mv sasl /etc/zookeeper/
然後修改 zoo.cfg 文件:
$ cat /etc/zookeeper/conf/zoo.cfg ...... authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider requireClientAuthScheme=sasl jaasLoginRenew=3600000
接下來添加 jaas.conf 文件:
$ cat /etc/zookeeper/conf/jaas.conf Server { org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="admin-sec" user_kafka="kafka-sec" user_producer="prod-sec" user_consumer="cons-sec"; };
最後修改還需要修改 environment 文件,來加載之前的 jar 文件和 jaas.conf 文件。
$ cat /etc/zookeeper/conf/environment ...... JAVA_OPTS=" -Djava.security.auth.login.config=$ZOOCFGDIR/jaas.conf " for i in "$ZOOCFGDIR"/../sasl/*.jar; do CLASSPATH="$i:$CLASSPATH" done SERVER_JVMFLAGS=" -Djava.security.auth.login.config=$ZOOCFGDIR/jaas.conf "
重啓 zookeeper 完成配置:
$ sudo systemctl restart zookeeper.service
1.3 修改 systemd service 文件
zookeeper 的默認 systemd service 是自動生成的,爲了實現 zookeeper service 啓動失敗後,可以自動重試,需要對配置文件做些修改。
$ cat /lib/systemd/system/zookeeper.service [Unit] Documentation=customized zookeeper service unit file SourcePath=/etc/init.d/zookeeper Description=LSB: centralized coordination service Before=multi-user.target Before=graphical.target Before=shutdown.target After=remote-fs.target Conflicts=shutdown.target [Service] Type=forking Restart=no TimeoutSec=5min IgnoreSIGPIPE=no KillMode=process GuessMainPID=no RemainAfterExit=yes ExecStart=/etc/init.d/zookeeper start ExecStop=/etc/init.d/zookeeper stop ExecReload=/etc/init.d/zookeeper restart KillMode=process Restart=on-failure RestartSec=5s
$ sudo systemctl daemon-reload $ sudo systemctl restart zookeeper.service
1.4 驗證
最後驗證一下 zookeeper 集羣是否正常運行,在三臺服務器上分別執行執行腳本 zkServer.sh,集羣中應該有顯示爲 leader,也有顯示爲 follower 的服務器。
$ /usr/share/zookeeper/bin/zkServer.sh status ZooKeeper JMX enabled by default Using config: /etc/zookeeper/conf/zoo.cfg leader
2. Kafka 集羣
有了 Zookeeper,接下來要安裝 Kafka 集羣了,先下載 Kafka,從清華的源下載,國內會快很多。
$ wget https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/2.0.0/kafka_2.11-2.0.0.tgz $ tar zxvf kafka_2.11-2.0.0.tgz $ sudo mv kafka_2.11-2.0.0 /opt/ $ cd /opt $ sudo ln -s kafka_2.11-2.0.0 kafka
Kafka 同樣要配置 JAAS,設置用戶名和密碼。
$ cat /opt/kafka/config/jaas.conf KafkaServer { org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="admin-sec" user_admin="admin-sec" user_kafka="kafka-sec" user_producer="prod-sec" user_consumer="cons-sec"; }; Client { org.apache.kafka.common.security.plain.PlainLoginModule required username="kafka" password="kafka-sec"; };
接下來配置服務器設置,尤其要注意一下這三個參數:
offsets.topic.replication.factor=3 transaction.state.log.replication.factor=3 transaction.state.log.min.isr=3
這三個參數都是用來配置 Kafka 的默認 Topic:__consumer_offsets,用來存儲消費者狀態,這三個參數的默認配置爲 1,也就是說數據只有一個備份,這在生產環境下當然是不夠安全的,建議改爲 3。
$ cat /opt/kafka/config/server.properties ...... listeners=SASL_PLAINTEXT://kafka-1:9092 security.inter.broker.protocol=SASL_PLAINTEXT sasl.enabled.mechanisms=PLAIN sasl.mechanism.inter.broker.protocol=PLAIN authorizer.class.name=kafka.security.auth.SimpleAclAuthorizer allow.everyone.if.no.acl.found=true zookeeper.connect=kafka-1:2181,kafka-2:2181,kafka-3:2181 broker.id=0 advertised.listeners=SASL_PLAINTEXT://kafka-1:9092 offsets.topic.replication.factor=3 transaction.state.log.replication.factor=3 transaction.state.log.min.isr=3
然後設置 producer 和 consumer 的配置,主要也是設置連接 kafka 的密鑰。
$ cat /opt/kafka/config/producer.properties ...... security.protocol=SASL_PLAINTEXT sasl.mechanism=PLAIN sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \ username="kafka" \ password="kafka-sec";
$ cat /opt/kafka/config/consumer.properties ...... sasl.mechanism=PLAIN sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \ username="kafka" \ password="kafka-sec";
最後是 Kafka 的 systemd 文件,設置好後,在三臺服務器上啓動 Kafka 。
$ cat /lib/systemd/system/kafka.service [Unit] Description=Apache Kafka server (broker) Documentation=http://kafka.apache.org/documentation.html Requires=network.target remote-fs.target After=network.target remote-fs.target [Service] Type=simple User=root Group=root Environment=JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-amd64 Environment=KAFKA_OPTS=-Djava.security.auth.login.config=/opt/kafka/config/jaas.conf ExecStart=/opt/kafka/bin/kafka-server-start.sh /opt/kafka/config/server.properties ExecStop=/opt/kafka/bin/kafka-server-stop.sh ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target
$ sudo systemctl enable kafka.service $ sudo systemctl start kafka.service
最後通過該命令來驗證一下 Kafka 集羣是否正常工作。
$ /opt/kafka/bin/zookeeper-shell.sh localhost:2181 <<< "ls /brokers/ids" Connecting to localhost:2181 Welcome to ZooKeeper! JLine support is disabled WATCHER:: WatchedEvent state:SyncConnected type:None path:null [1, 2, 3]
3. 參考文檔
- Setting up Apache ZooKeeper Cluster | Apache ZooKeeper Tutorials
- how to check if zookeeper is running or up from command prompt
- How to Configure an Apache Kafka Cluster on Ubuntu 16.04
- Kafka And Zookeeper Multi Node Cluster Setup
- Client-Server mutual authentication
- 集羣Kafka配置SASL用戶名密碼認證
- Kafka認證處理,ACL訪問控制
- Authentication using SASL
- Zookeeper權限管理之坑
- Introduction to Apache Kafka Security
- Zookeeper - Super User Authentication and Authorization