在Docker環境下的kafka部署之一:三種基本部署

猛禽大叔發表於2018-10-09

在單獨container中部署使用

首先,kafka依賴zookeeper,即使只是單機使用,也得按叢集的方式來配置……

所以,先下載兩個官方images:

docker pull confluentinc/cp-zookeeper
docker pull confluentinc/cp-kafka
複製程式碼

然後建立一個compose(感謝令狐提供幫助):

version: '2'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper
    container_name: zookeeper
    mem_limit: 1024M
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
  kafka:
    image: confluentinc/cp-kafka
    container_name: kafka
    mem_limit: 1024M
    depends_on:
      - zookeeper
    environment:
      KAFKA_BROKER_NO: 1
      KAFKA_ADVERTISED_HOST_NAME: 127.0.0.1
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://127.0.0.1:9092
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_HEAP_OPTS: "-Xmx512M -Xms16M"
複製程式碼

因為這裡是直接在伺服器上測試的,為安全起見暫不繫結相關埠。

啟動compose:

docker-compose up -d
複製程式碼

現在開啟兩個新的終端視窗,分別用以下命令登入container:

docker exec -it kafka /bin/bash
複製程式碼

在其中一個視窗裡建立topic並執行producer:

kafka-topics --zookeeper zookeeper:2181 --create --replication-factor 1 --partitions 1 --topic kafkatest
kafka-console-producer --broker-list localhost:9092 --topic kafkatest
複製程式碼

在另一個視窗裡執行consumer:

kafka-console-consumer --bootstrap-server localhost:9092 --topic kafkatest --from-beginning
複製程式碼

現在,在producer裡輸入任何內容,都會在consumer裡收到。

跨container的部署

上面的配置只能在單個container裡使用,不實用。這是因為kafka advertised配置在localhost上。

需要跨container訪問,就需要通過docker的網路訪問,要修改這個配置:

version: '2'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper
    container_name: zookeeper
    mem_limit: 1024M
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
  kafka:
    image: confluentinc/cp-kafka
    container_name: kafka
    mem_limit: 1024M
    depends_on:
      - zookeeper
    environment:
      KAFKA_BROKER_NO: 1
      KAFKA_ADVERTISED_HOST_NAME: domain_name  # 修改
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://domain_name:9092  # 修改
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_HEAP_OPTS: "-Xmx512M -Xms16M"
複製程式碼

改完重啟docker-compose,另外,因為zookeeper重啟後,topic不會被持久儲存,所以重啟後需要重新建立topic。

然後啟動兩個新的container模擬網路訪問:

docker run -it --rm --link kafka:domain_name --network kafka_default --name consumer confluentinc/cp-kafka /bin/bash
docker run -it --rm --link kafka:domain_name --network kafka_default --name producer confluentinc/cp-kafka /bin/bash
複製程式碼

注意,需要指定一下docker網路為kafka_default,這是官方image使用的預設網路。

然後分別在consumer和producer兩個container裡測試:

kafka-console-consumer --bootstrap-server domain_name:9092 --topic kafkatest --from-beginning
kafka-console-producer --broker-list domain_name:9092 --topic kafkatest
複製程式碼

效果與單container一樣。

從Docker網路之外訪問的部署

如果需要從docker網路之外訪問,就需要把埠對映到宿主機了。

同樣需要修改配置,增加網路對映等:

version: '2'
services:
  zookeeper:
    image: confluentinc/cp-zookeeper
    container_name: zookeeper
    mem_limit: 1024M
    environment:
      ZOOKEEPER_CLIENT_PORT: 2181
  kafka:
    image: confluentinc/cp-kafka
    container_name: kafka
    mem_limit: 1024M
    depends_on:
      - zookeeper
    ports:  # 增加
      - 9092:9092  # 增加
    environment:
      KAFKA_BROKER_NO: 1
      KAFKA_ADVERTISED_HOST_NAME: domain_name
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://domain_name:9092
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
      KAFKA_HEAP_OPTS: "-Xmx512M -Xms16M"
複製程式碼

然後啟動兩個新的container模擬外部網路訪問:

docker run -it --rm --add-host=domain_name:172.17.0.1 --name consumer confluentinc/cp-kafka /bin/bash
docker run -it --rm --add-host=domain_name:172.17.0.1 --name producer confluentinc/cp-kafka /bin/bash
複製程式碼

其中172.17.0.1為docker宿主機在預設docker網路(注意不是kafka_default)裡的IP,具體可以通過以下命令檢視:

ip route
複製程式碼

然後分別在consumer和producer兩個container裡測試:

kafka-console-consumer --bootstrap-server domain_name:9092 --topic kafkatest --from-beginning
kafka-console-producer --broker-list domain_name:9092 --topic kafkatest
複製程式碼

這裡有一個坑需要注意的是:

如果宿主機上有防火牆,需要增加一條規則,允許docker網路訪問宿主機的埠,否則會連線失敗。比如:

# 取得行號
iptables -L INPUT --line-num
# xx為最後一行DROP的行號,插到它前面
iptables -I INPUT xx -p tcp -m tcp -s 172.17.0.0/16 --dport 9092 -j ACCEPT
複製程式碼

效果與前兩個例子相同。

相關文章