Kubernetes (docker) access to Kafka in docker compose - docker

docker-compose.yml
version: '3'
services:
zookeeper:
image: confluentinc/cp-zookeeper:6.0.0
hostname: zookeeper
container_name: zookeeper
restart: unless-stopped
ports:
- "2181:2181"
volumes:
- ./data/zoo/zk-data:/var/lib/zookeeper/data
- ./data/zoo/zk-txn-logs:/var/lib/zookeeper/log
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
broker:
image: confluentinc/cp-server:6.0.0
hostname: broker
container_name: broker
restart: unless-stopped
depends_on:
- zookeeper
volumes:
- ./data/kafka:/var/lib/kafka/data
ports:
- "9092:9092"
- "9101:9101"
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://broker:29092,PLAINTEXT_HOST://localhost:9092
KAFKA_METRIC_REPORTERS: io.confluent.metrics.reporter.ConfluentMetricsReporter
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
KAFKA_CONFLUENT_LICENSE_TOPIC_REPLICATION_FACTOR: 1
KAFKA_CONFLUENT_BALANCER_TOPIC_REPLICATION_FACTOR: 1
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
KAFKA_JMX_PORT: 9101
KAFKA_CONFLUENT_SCHEMA_REGISTRY_URL: http://schema-registry:8081
CONFLUENT_METRICS_REPORTER_BOOTSTRAP_SERVERS: broker:29092
CONFLUENT_METRICS_REPORTER_TOPIC_REPLICAS: 1
CONFLUENT_METRICS_ENABLE: 'true'
CONFLUENT_SUPPORT_CUSTOMER_ID: 'anonymous'
schema-registry:
image: confluentinc/cp-schema-registry:6.0.0
hostname: schema-registry
container_name: schema-registry
restart: unless-stopped
depends_on:
- broker
ports:
- "8081:8081"
environment:
SCHEMA_REGISTRY_HOST_NAME: schema-registry
SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: 'broker:29092'
dev.yml
apiVersion: v1
kind: Service
metadata:
name: auth-server
labels:
app: auth-server
spec:
type: LoadBalancer
ports:
- port: 8882
protocol: TCP
targetPort: 8882
nodePort: 30080
selector:
app: auth-server
status:
loadBalancer:
ingress:
- hostname: localhost
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: auth-server
spec:
selector:
matchLabels:
app: auth-server
replicas: 1
template:
metadata:
labels:
app: auth-server
spec:
containers:
- name: auth-server
image: auth-server:latest
imagePullPolicy: Never
ports:
- containerPort: 8080
volumeMounts:
- name: auth-server
mountPath: "/config"
volumes:
- name: auth-server
configMap:
name: auth-server
I need connect from my app on kubernetes cluser (docker) connect to docker-compose kafka.
I tried change kafka url in properties: http://localhost:9092, http://broker:9092 and
THIS tutorial but won't work too.
In docker ps I see: kafka and auth-server from kubernetes.
Can someone explain me. How can I do it ?

Since I don't know your flavor of local K8s, I can only speculate. But the problem here could be that Kubernetes and docker compose run their containers in different virtual networks.
What you have to do to create connectivity is:
Expose the Kafka port in your compose file with port mappings to the host:
ports:
- 9092:9092
Connect to it from Kubernetes via the IP address of your docker0 interface (typically 172.17.0.1).

Related

Trouble converting docker-compose containing volume to Kubernetes manifest

I am learning Kubernetes and I am starting to convert an existing docker-compose.yml to Kuberbetes manifest one component at a time. Here is the component I am currently trying to convert
version: '3'
services:
mongodb:
container_name: mongodb
restart: always
hostname: mongo-db
image: mongo:latest
networks:
- mynetwork
volumes:
- c:/MongoDb:c:/data/db
ports:
- 27017:27017
networks:
mynetwork:
name: mynetwork
I am able to log into the Mongo instance when the container is running in Docker but I cannot get this working in Kubernetes. Here is the Kubernetes manifests I have tried so far
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb
spec:
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongodb
image: mongo:latest
ports:
- containerPort: 27017
volumeMounts:
- name: mongodb-data
mountPath: /data/db
ports:
- containerPort: 27017
hostPort: 27017
volumes:
- name: mongodb-data
hostPath:
path: "C:\\MongoDb"
With this manifest I see the error Error: Error response from daemon: invalid mode: /data/db when I do a kubectl describe pods.
I understand the mapping of volumes from Docker to Kubernetes isn't 1-to-1, so is this reasonable to do in the Kubernetes space?
Thank you and apologies if this feels like a silly question.

kafka broker connection failed when create new topic with a cluster of 3 brokers

I'm trying to setup a kafka cluster with 3 brokers on Docker.
The problem is: when I do an operation (i.e create/list/delete topics), there's always 1 broker fails to be connected and restart Docker container. This problem doesn't happen on a cluster of 2 or single broker.
My steps to reproduce is:
Run docker-compose up
Open shell of 1 of kafka containers and create a topic kafka-topics --bootstrap-server ":9092" --create --topic topic-name --partitions 3 --replication-factor 3
After this, 1 random broker is disconnected and deleted from the cluster. Sometimes the reponse of the above execution is the error said that replication factor cannot be larger than 2 (since 1 broker has removed from cluster)
I'm new to Kafka. I think I'm just having some silly mistakes but I don't have any clue of what it is. I search through docs but haven't found yet.
Here is my docker-compose file:
version: "3.9"
networks:
kafka-cluster:
driver: bridge
services:
zookeeper:
image: confluentinc/cp-zookeeper:latest
environment:
# ZOOKEEPER_SERVER_ID: 1
ZOOKEEPER_CLIENT_PORT: 2181
# ZOOKEEPER_TICK_TIME: 2000
# ZOOKEEPER_SERVERS: "zookeeper:22888:23888"
KAFKA_OPTS: "-Dzookeeper.4lw.commands.whitelist=*"
ports:
- 2181:2181
restart: unless-stopped
networks:
- kafka-cluster
kafka1:
image: confluentinc/cp-kafka:latest
container_name: kafka1
depends_on:
- zookeeper
ports:
- "9093:9093"
environment:
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENERS: CLIENT://:9092,EXTERNAL://:9093
KAFKA_ADVERTISED_LISTENERS: CLIENT://kafka1:9092,EXTERNAL://localhost:9093
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CLIENT:PLAINTEXT,EXTERNAL:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: CLIENT
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
restart: unless-stopped
networks:
- kafka-cluster
kafka2:
image: confluentinc/cp-kafka:latest
container_name: kafka2
depends_on:
- zookeeper
ports:
- "9094:9094"
environment:
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENERS: CLIENT://:9092,EXTERNAL://:9094
KAFKA_ADVERTISED_LISTENERS: CLIENT://kafka2:9092,EXTERNAL://localhost:9094
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CLIENT:PLAINTEXT,EXTERNAL:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: CLIENT
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
restart: unless-stopped
networks:
- kafka-cluster
kafka3:
image: confluentinc/cp-kafka:latest
container_name: kafka3
depends_on:
- zookeeper
ports:
- "9095:9095"
environment:
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENERS: CLIENT://:9092,EXTERNAL://:9095
KAFKA_ADVERTISED_LISTENERS: CLIENT://kafka3:9092,EXTERNAL://localhost:9095
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CLIENT:PLAINTEXT,EXTERNAL:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: CLIENT
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
restart: unless-stopped
networks:
- kafka-cluster
kafdrop:
image: obsidiandynamics/kafdrop:latest
container_name: kafdrop
ports:
- "9000:9000"
environment:
- KAFKA_BROKERCONNECT=kafka1:9092,kafka2:9092,kafka3:9092
- JVM_OPTS="-Xms32M -Xmx64M"
- SERVER_SERVLET_CONTEXTPATH="/"
depends_on:
- kafka1
networks:
- kafka-cluster
Here is the error log on the other 2 brokers:
[2022-01-17 04:32:40,078] WARN [ReplicaFetcher replicaId=1002, leaderId=1001, fetcherId=0] Error in response for fetch request (type=FetchRequest, replicaId=1002, maxWait=500, minBytes=1, maxBytes=10485760, fetchData={test-topic-3-1=PartitionData(fetchOffset=0, logStartOffset=0, maxBytes=1048576, currentLeaderEpoch=Optional[0], lastFetchedEpoch=Optional.empty), test-topic-2-1=PartitionData(fetchOffset=0, logStartOffset=0, maxBytes=1048576, currentLeaderEpoch=Optional[0], lastFetchedEpoch=Optional.empty)}, isolationLevel=READ_UNCOMMITTED, toForget=, metadata=(sessionId=28449961, epoch=INITIAL), rackId=) (kafka.server.ReplicaFetcherThread)
java.io.IOException: Connection to kafka1:9092 (id: 1001 rack: null) failed.
at org.apache.kafka.clients.NetworkClientUtils.awaitReady(NetworkClientUtils.java:71)
at kafka.server.ReplicaFetcherBlockingSend.sendRequest(ReplicaFetcherBlockingSend.scala:104)
at kafka.server.ReplicaFetcherThread.fetchFromLeader(ReplicaFetcherThread.scala:218)
at kafka.server.AbstractFetcherThread.processFetchRequest(AbstractFetcherThread.scala:321)
at kafka.server.AbstractFetcherThread.$anonfun$maybeFetch$3(AbstractFetcherThread.scala:137)
at kafka.server.AbstractFetcherThread.$anonfun$maybeFetch$3$adapted(AbstractFetcherThread.scala:136)
at scala.Option.foreach(Option.scala:437)
at kafka.server.AbstractFetcherThread.maybeFetch(AbstractFetcherThread.scala:136)
at kafka.server.AbstractFetcherThread.doWork(AbstractFetcherThread.scala:119)
at kafka.utils.ShutdownableThread.run(ShutdownableThread.scala:96)
[2022-01-17 04:32:42,088] WARN [ReplicaFetcher replicaId=1002, leaderId=1001, fetcherId=0] Connection to node 1001 (kafka1/192.168.48.3:9092) could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
[2022-01-17 04:32:42,088] INFO [ReplicaFetcher replicaId=1002, leaderId=1001, fetcherId=0] Error sending fetch request (sessionId=28449961, epoch=INITIAL) to node 1001: (org.apache.kafka.clients.FetchSessionHandler)
java.io.IOException: Connection to kafka1:9092 (id: 1001 rack: null) failed.
at org.apache.kafka.clients.NetworkClientUtils.awaitReady(NetworkClientUtils.java:71)
at kafka.server.ReplicaFetcherBlockingSend.sendRequest(ReplicaFetcherBlockingSend.scala:104)
at kafka.server.ReplicaFetcherThread.fetchFromLeader(ReplicaFetcherThread.scala:218)
at kafka.server.AbstractFetcherThread.processFetchRequest(AbstractFetcherThread.scala:321)
at kafka.server.AbstractFetcherThread.$anonfun$maybeFetch$3(AbstractFetcherThread.scala:137)
at kafka.server.AbstractFetcherThread.$anonfun$maybeFetch$3$adapted(AbstractFetcherThread.scala:136)
at scala.Option.foreach(Option.scala:437)
at kafka.server.AbstractFetcherThread.maybeFetch(AbstractFetcherThread.scala:136)
at kafka.server.AbstractFetcherThread.doWork(AbstractFetcherThread.scala:119)
at kafka.utils.ShutdownableThread.run(ShutdownableThread.scala:96)
Assuming you don't need host connections (since you're running the Kafka CLI commands directly in the containers), you could greatly simplify your Compose file
Remove host ports
Remove non-CLIENT listeners, and stick to the defaults.
Remove the Compose network (for debugging) since one is automatically created
All in all, you'd end up with something like this
x-kafka-setup: &kafka-setup
KAFKA_CFG_ZOOKEEPER_CONNECT: zookeeper:2181
ALLOW_PLAINTEXT_LISTENER: 'yes'
version: "3.8"
services:
zookeeper:
image: docker.io/bitnami/zookeeper:3.7
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka1:
image: &broker-image docker.io/bitnami/kafka:3
environment:
KAFKA_BROKER_ID: 1
<<: *kafka-setup
depends_on:
- zookeeper
kafka2:
image: *broker-image
environment:
KAFKA_BROKER_ID: 2
<<: *kafka-setup
depends_on:
- zookeeper
kafka3:
image: *broker-image
environment:
KAFKA_BROKER_ID: 3
<<: *kafka-setup
depends_on:
- zookeeper
kafdrop:
image: obsidiandynamics/kafdrop:latest
ports:
- "9000:9000"
environment:
KAFKA_BROKERCONNECT: kafka1:9092,kafka2:9092,kafka3:9092
JVM_OPTS: "-Xms32M -Xmx64M"
SERVER_SERVLET_CONTEXTPATH: /
depends_on:
- kafka1
- kafka2
- kafka3

Create kubernetes yml file from docker-compose.yml file

I have this docker-compose.yml file which I am using to run up three microservices and one api gateway
version: '3'
services:
serviceone:
container_name: serviceone
restart: always
build: serviceone/
ports:
- '3000:3000'
servicetwo:
container_name: servicetwo
restart: always
build: servicetwo/
ports:
- '3001:3001'
servicethree:
container_name: servicethree
restart: always
build: servicethree/
ports:
- '3002:3003'
apigateway:
container_name: timezoneapigateway
restart: always
build: timezone/
ports:
- '8080:8080'
links:
- serviceone
- servicetwo
- servicethree
Now I want to deploy these dockerimages in one pod in kubernetes so that the api gateway can connect with all the three microservices ,current version of api gateway is working but I am really not getting even a slightest hint of doing this in kubernetes. I am really new to kubernetes can anyone tell me how to design a kubernetes yml file to achieve this
You don't have to run all your service in the same pod. The standard in Kubernetes is to have separate deployments and services for all apps. Here is a deployment manifest for serviceone but you can easily modify it for servicetwo, servicethree and apigateway
apiVersion: apps/v1
kind: Deployment
metadata:
name: serviceone
labels:
app: serviceone
spec:
replicas: 1
selector:
matchLabels:
app: serviceone
template:
metadata:
labels:
app: serviceone
spec:
containers:
- name: serviceone
image: serviceone:latest
ports:
- containerPort: 3001
And the same goes for the service manifest
apiVersion: v1
kind: Service
metadata:
name: serviceone
spec:
selector:
app: serviceone
ports:
- protocol: TCP
port: 3001
targetPort: 3001
Your services will be accessible within the cluster like this:
serviceone:3001
servicetwo:3002
servicethree:3003
timezoneapigateway:8080

Docker Swarm Nginx Service behind Traefik giving a 502 Error

I have a docker swarm configured to use Traefik as reverse proxy. One of the containers in my swarm is running an Nginx server but I am getting a 502 Bad Gateway error when I navigate to that particular endpoint. Traefik is setup as follows:
version: '3.5'
services:
traefik:
image: traefik:alpine
command: |-
--entryPoints="Name:http Address::80 Redirect.EntryPoint:https"
--entryPoints="Name:https Address::443 TLS"
--defaultentrypoints="http,https"
--accesslogsfile="/var/log/access.log"
--acme
--acme.acmelogging="true"
--acme.domains="${SERVER},${SANS1}"
--acme.email="${ACME_EMAIL}"
--acme.entrypoint="https"
--acme.httpchallenge
--acme.httpchallenge.entrypoint="http"
--acme.storage="/opt/traefik/acme.json"
--acme.onhostrule="true"
--docker
--docker.swarmmode
--docker.domain="${SERVER}"
--docker.network="frontend"
--docker.watch
--api
networks:
- frontend
ports:
- target: 80
published: 80
mode: host
- target: 443
published: 443
mode: host
- target: 8080
published: 8080
mode: host
volumes:
- traefik_acme:/opt/traefik
- traefik_logs:/var/log/access.log
- /var/run/docker.sock:/var/run/docker.sock:ro
deploy:
replicas: 1
placement:
constraints: [node.role == manager]
networks:
frontend:
name: "frontend"
driver: overlay
volumes:
traefik_acme:
traefik_logs:
This compose file provides the overlay network and the Traefik service. The rest of my swarm is defined in the following compose file:
version: "3.5"
services:
test:
image: emilevauge/whoami
deploy:
labels:
traefik.enable: "true"
traefik.frontend.rule: "Host:${SERVER};PathPrefixStrip:/test"
traefik.port: 80
networks:
- frontend
octeditor:
image: ${DOCKER_OCTEDITOR_IMAGE_TAG}
deploy:
replicas: 1
labels:
traefik.enable: "true"
traefik.frontend.rule: "Host:${SERVER}"
traefik.port: 3000
networks:
- frontend
ports:
- "3000:80"
octserver:
image: ${DOCKER_OCTSERVER_IMAGE_TAG}
deploy:
replicas: 1
labels:
traefik.enable: "true"
traefik.frontend.rule: "Host:${SERVER};PathPrefixStrip:/api"
traefik.port: 4000
networks:
- frontend
ports:
- "4000:4000"
visualizer:
image: dockersamples/visualizer:stable
deploy:
placement:
constraints:
- 'node.role == manager'
labels:
traefik.enable: "true"
traefik.frontend.rule: "Host:${SERVER};PathPrefixStrip:/visualizer"
traefik.port: 8001
networks:
- frontend
ports:
- "8001:8080"
stop_grace_period: 1m30s
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
networks:
frontend:
external: true
The relevant configuration is for the octeditor service:
octeditor:
image: ${DOCKER_OCTEDITOR_IMAGE_TAG}
deploy:
replicas: 1
labels:
traefik.enable: "true"
traefik.frontend.rule: "Host:${SERVER}"
traefik.port: 3000
networks:
- frontend
ports:
- "3000:80"
I'm mapping port 80 (which Nginx listens to by default) to port 3000 where Traefik is configured to locate this service. This is the Dockerfile for the service running Nginx:
FROM node:latest as builder
WORKDIR /usr/src/app
COPY package.json .
RUN npm install
COPY . .
RUN npm run build
FROM nginx
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
I simply build a react app and copy the build folder to the /usr/share/nginx/html folder. I've tried building and running this Dockerfile as a standalone container and it works, also I've checked the contents of the html folder and everything looks correct. The other services, apart from the visualizer service, are running correctly. Only this octedtior service and the visualizer service are giving me 502 errors. Can anyone suggest a solution or even how to check the traffic being sent to the nginx container? I've tried docker ps servicename but I can't see any errors coming from the service.
Edit:
If I change the configuration of the octeditor to this:
octeditor:
image: ${DOCKER_OCTEDITOR_IMAGE_TAG}
deploy:
replicas: 1
labels:
traefik.enable: "true"
traefik.frontend.rule: "Host:${SERVER}"
traefik.port: 80
networks:
- frontend
ports:
- "80:80"
And remove the test service that was previously listening on port 80 it seems to work. I don't understand what was wrong with the previous configuration however? I thought I was mapping traffic from port 3000 to port 80 of the container before, whereas now I'm mapping from port 80 to 80, but nothing should have changed from the perspective of the container, right?
The relevant configuration is for the octeditor service:
octeditor:
image: ${DOCKER_OCTEDITOR_IMAGE_TAG}
deploy:
replicas: 1
labels:
traefik.enable: "true"
traefik.frontend.rule: "Host:${SERVER}"
traefik.port: 3000
networks:
- frontend
ports:
- "3000:80"
I'm mapping port 80 (which Nginx listens to by default) to port 3000
where Traefik is configured to locate this service.
The traefik port needs to be 80, not 3000. The port mapping will create a forward from the host on 3000 to the container on 80. However traefik talks directly to the container over a shared network (frontend) and you need to provide it the container port.
There is no need to publish a host port for services accessed through traefik or any other reverse proxy unless you need to access them directly without the proxy (which brings into question whether you need a reverse proxy in those scenarios). In other words, this could be written without the ports:
octeditor:
image: ${DOCKER_OCTEDITOR_IMAGE_TAG}
deploy:
replicas: 1
labels:
traefik.enable: "true"
traefik.frontend.rule: "Host:${SERVER}"
traefik.port: 80
networks:
- frontend

Virtualbox/Swarm - NAT and HOSTonly Network

I’m quite new in docker world.
I have a local virtulbox setup:
vm1=swarm manager (mysql,visualizer) IP: 192.168.99.100
vm2= wordpress service IP: 192.168.99.101
I can reach the application on both IP’s 100/101. But I would like to also use the localhost in order to port forward localhost to NET since 192.168.99.0 subnet is HOST only.
In VBOX I have portforwarding set like this for the NAT interface on the machine where apache runs:
HOST PORT 8888 / GUEST PORT 8888
Currently the YAML looks like this:
version: '3.4'
services:
wordpress:
image: wordpress
depends_on:
- mysql
- wordpress
deploy:
placement:
constraints: [node.labels.application==true]
mode: replicated
replicas: 1
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
ports:
- "80:80"
environment:
WORDPRESS_DB_PASSWORD: "12345"
networks:
- wordpress_net
mysql:
image: mysql:latest
volumes:
- "/mnt/sda1/var/lib/docker/volumes/mysql_data/_data:/var/lib/mysql"
deploy:
placement:
constraints: [node.role == manager]
environment:
MYSQL_ROOT_PASSWORD: "12345"
networks:
- wordpress_net
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
- wordpress_net
networks:
wordpress_net:
How can I attach the eth0 interface to container. So both the swarm network and the NAT-ed network will be reachable ?
I was trying something like this but without success:
services:
wordpress:
image: wordpress
depends_on:
- mysql
- wordpress
deploy:
placement:
constraints: [node.labels.application==true]
mode: replicated
replicas: 1
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
ports:
- target: 80
published: 80
protocol: tcp
mode: ingress
- target: 80
published: 8888
protocol: tcp
mode: host
environment:
WORDPRESS_DB_PASSWORD: "12345"
networks:
- wordpress_net
Thanks !

Resources