Mostrar un entorno de prueba en Kubernetes: Apache Kafka, Kafka Connect, MirrorMaker 2.0 y Jmeter

Soy ingeniero de pruebas de carga y recientemente he estado trabajando en un proyecto en el que se espera que Apache Kafka se utilice activamente. Debido al modo de trabajo remoto, obtener acceso al entorno de prueba llevó semanas. Para no perder el tiempo, decidí implementar un stand local en Kubernetes.



Quienes hayan trabajado con Apache Kafka confirmarán que la documentación oficial no cubre todos los detalles de instalación y configuración. Espero que esta guía paso a paso le ayude a reducir el tiempo que lleva implementar su entorno de prueba. Llamo su atención sobre el hecho de que instalar stateful en contenedores está lejos de ser la mejor idea, por lo que esta instrucción no está destinada a desplegar un stand industrial.



Las instrucciones describen cómo crear una máquina virtual en VirtualBox, instalar y configurar el sistema operativo, instalar Docker, Kubernetes y un sistema de monitoreo. Hay dos clústeres de Apache Kafka implementados en Kubernetes: "producción" y "copia de seguridad". MirrorMaker 2.0 se utiliza para replicar mensajes desde la producción hasta la copia de seguridad. La comunicación entre los nodos del clúster de producción está protegida por TLS. Desafortunadamente, no puedo cargar un script para generar certificados en Git. Como ejemplo, puede utilizar los certificados del archivo certs / certs.tar.gz. Al final del tutorial, describimos cómo implementar un clúster de Jmeter y ejecutar un script de prueba.



Las fuentes están disponibles en el repositorio: github.com/kildibaev/k8s-kafka



Las instrucciones están diseñadas para principiantes en Kubernetes, por lo que si ya tiene experiencia con contenedores, puede ir directamente a la sección "12. Implementación de un clúster de Apache Kafka" .



Preguntas y respuestas:



  • ¿Por qué se usa Ubuntu? Originalmente implementé Kubernetes en CentOS 7, pero después de una de las actualizaciones, el entorno dejó de funcionar. Además, noté que en CentOS, las pruebas de carga que se ejecutan en Jmeter se comportan de manera impredecible. Si lo encontró, escriba en los comentarios una posible solución a este problema. Todo es mucho más estable en Ubuntu.
  • ¿Por qué no k3s o MicroK8s? En resumen, ni k3s ni MicroK8s de fábrica saben cómo trabajar con un repositorio local de Docker.
  • ? .
  • Flannel? kubernetes Flannel — , .
  • Docker, CRI-O? CRI-O .
  • MirrorMaker 2.0 Kafka Connect? Kafka Connect MirrorMaker 2.0 " " REST API.




1.



2. Ubuntu Server 20.04



3. Ubuntu



4. Docker



5. iptables



6. kubeadm, kubelet kubectl



7. Kubernetes



8. Flannel



9. pod- control-plane



10. kubectl



11. Prometheus, Grafana, Alert Manager Node Exporter



12. Apache Kafka



12.1. Apache Zookeeper



12.2. Apache Kafka



13.



13.1.



13.2.



14. MirrorMaker 2.0



14.1. MirrorMaker 2.0 Kafka Connect



14.2.



15. Jmeter



16.






1.



2 6-8 . , Rancher K3S.















2. Ubuntu Server 20.04



, . :



  • IP , ( 10.0.2.15);
  • Kubernetes , swap , ;
  • "Install OpenSSH server".




























3. Ubuntu



3.1. Firewall



sudo ufw disable


3.2. Swap



sudo swapoff -a

sudo sed -i 's/^\/swap/#\/swap/' /etc/fstab


3.3. OpenJDK



OpenJDK keytool, :



sudo apt install openjdk-8-jdk-headless


3.4. ()



DigitalOcean:

https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys-on-ubuntu-20-04-ru



4. Docker []



# Switch to the root user 
sudo su

# (Install Docker CE)
## Set up the repository:
### Install packages to allow apt to use a repository over HTTPS
apt-get update && apt-get install -y \
  apt-transport-https ca-certificates curl software-properties-common gnupg2

# Add Docker’s official GPG key:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -

# Add the Docker apt repository:
add-apt-repository \
  "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) \
  stable"

# Install Docker CE
apt-get update && apt-get install -y \
  containerd.io=1.2.13-2 \
  docker-ce=5:19.03.11~3-0~ubuntu-$(lsb_release -cs) \
  docker-ce-cli=5:19.03.11~3-0~ubuntu-$(lsb_release -cs)

# Set up the Docker daemon
cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

mkdir -p /etc/systemd/system/docker.service.d

# Restart Docker
systemctl daemon-reload
systemctl restart docker

# If you want the docker service to start on boot, run the following command:
sudo systemctl enable docker


5. iptables []



cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF

sudo sysctl --system


6. kubeadm, kubelet kubectl []



sudo apt-get update && sudo apt-get install -y apt-transport-https curl

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF

sudo apt-get update

sudo apt-get install -y kubelet kubeadm kubectl

sudo apt-mark hold kubelet kubeadm kubectl


7. Kubernetes



control-plane: []



# Pulling images required for setting up a Kubernetes cluster
# This might take a minute or two, depending on the speed of your internet connection
sudo kubeadm config images pull

# Initialize a Kubernetes control-plane node
sudo kubeadm init --pod-network-cidr=10.244.0.0/16


( root): []



mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config


8. Flannel []



kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml


9. pod- control-plane []



Kubernetes standalone, pod- control-plane:



kubectl taint nodes --all node-role.kubernetes.io/master-


10. kubectl []



alias k='kubectl'

echo "alias k='kubectl'" >> ~/.bashrc


11. Prometheus, Grafana, Alert Manager Node Exporter



kube-prometheus: []



curl -O -L https://github.com/coreos/kube-prometheus/archive/master.zip

sudo apt install -y unzip

unzip master.zip

cd kube-prometheus-master

kubectl create -f manifests/setup

kubectl create -f manifests/


, pod-. pod- Running:



kubectl get pods -w -n monitoring


Kafka Zookeeper JMX Exporter. Prometheus ServiceMonitor:



k apply -f https://raw.githubusercontent.com/kildibaev/k8s-kafka/master/servicemonitor/jmx-exporter-servicemonitor.yaml


, - Grafana :



kubectl apply -f https://raw.githubusercontent.com/kildibaev/k8s-kafka/master/service/grafana-svc.yaml


Grafana http://localhost:32000



, Grafana :





- Grafana http://127.0.0.1:3000



Grafana . http://127.0.0.1:3000/dashboard/import "Import via panel json" grafana-dashboard.json



12. Apache Kafka



#   
git clone https://github.com/kildibaev/k8s-kafka.git $HOME/k8s-kafka
cd $HOME/k8s-kafka


12.1. Apache Zookeeper



Statefulset. Apache Zookeeper : zookeeper-0.zookeeper, zookeeper-1.zookeeper zookeeper-2.zookeeper



#   zookeeper-base
sudo docker build -t zookeeper-base:local-v1 -f dockerfile/zookeeper-base.dockerfile .

#   Zookeeper
k apply -f service/zookeeper-svc.yaml

#   Apache Zookeeper
k apply -f statefulset/zookeeper-statefulset.yaml

#          pod-    Running.   pod-   :
k get pods -w


12.2. Apache Kafka



Apache Kafka : kafka-0.kafka kafka-1.kafka



#   kafka-base
sudo docker build -t kafka-base:local-v1 -f dockerfile/kafka-base.dockerfile .

#   Kafka
k apply -f service/kafka-svc.yaml

#   Apache Kafka
k apply -f statefulset/kafka-statefulset.yaml

#         pod-    Running.   pod-   :
k get pods -w


13.



13.1.



, 10 . 100 . 30000 .



#   pod - producer
k run --rm -i --tty producer --image=kafka-base:local-v1 -- bash

#   topicname     
bin/kafka-producer-perf-test.sh \
   --topic topicname \
   --num-records 30000 \
   --record-size 100 \
   --throughput 10 \
   --producer.config /config/client.properties \
   --producer-props acks=1 \
   bootstrap.servers=kafka-0.kafka:9092,kafka-1.kafka:9092 \
   buffer.memory=33554432 \
   batch.size=8196


13.2.



#   pod - consumer
k run --rm -i --tty consumer --image=kafka-base:local-v1 -- bash 

#     topicname
bin/kafka-consumer-perf-test.sh \
--broker-list kafka-0.kafka:9092,kafka-1.kafka:9092 \
--consumer.config /config/client.properties \
--messages 30000 \
--topic topicname \
--threads 2


14. MirrorMaker 2.0



14.1. MirrorMaker 2.0 Kafka Connect



Apache Kafka, , production. pod, : Apache Zookeeper, Apache Kafka Kafka Connect. Apache Kafka backup production backup.



k apply -f service/mirrormaker-svc.yaml

#  pod,      : Apache Zookeeper, Apache Kafka  Kafka Connect
k apply -f statefulset/mirrormaker-statefulset.yaml

#    pod   mirrormaker-0    Running
k get pods -w

#    connect  pod- mirrormaker-0    
k exec -ti mirrormaker-0 -c connect -- bash

#   Kafka Connect   MirrorMaker 2.0
curl -X POST -H "Content-Type: application/json" mirrormaker-0.mirrormaker:8083/connectors -d \
'{
    "name": "MirrorSourceConnector",
    "config": {
      "connector.class": "org.apache.kafka.connect.mirror.MirrorSourceConnector",
      "source.cluster.alias": "production",
      "target.cluster.alias": "backup",
      "source.cluster.bootstrap.servers": "kafka-0.kafka:9092,kafka-1.kafka:9092",
      "source.cluster.group.id": "mirror_maker_consumer",
      "source.cluster.enable.auto.commit": "true",
      "source.cluster.auto.commit.interval.ms": "1000",
      "source.cluster.session.timeout.ms": "30000",
      "source.cluster.security.protocol": "SSL",
      "source.cluster.ssl.truststore.location": "/certs/kafkaCA-trusted.jks",
      "source.cluster.ssl.truststore.password": "kafkapilot",
      "source.cluster.ssl.truststore.type": "JKS",
      "source.cluster.ssl.keystore.location": "/certs/kafka-consumer.jks",
      "source.cluster.ssl.keystore.password": "kafkapilot",
      "source.cluster.ssl.keystore.type": "JKS",
      "target.cluster.bootstrap.servers": "localhost:9092",
      "target.cluster.compression.type": "none",
      "topics": ".*",
      "rotate.interval.ms": "1000",
      "key.converter.class": "org.apache.kafka.connect.converters.ByteArrayConverter",
      "value.converter.class": "org.apache.kafka.connect.converters.ByteArrayConverter"
    }
}'


14.2.



, backup production.topicname. ".production" MirrorMaker 2.0 , , , active-active.



#   pod - consumer
k exec -ti mirrormaker-0 -c kafka -- bash

#    
bin/kafka-topics.sh --list --bootstrap-server mirrormaker-0.mirrormaker:9092

#     production.topicname
bin/kafka-console-consumer.sh \
--bootstrap-server mirrormaker-0.mirrormaker:9092 \
--topic production.topicname \
--from-beginning


production.topicname , , Kafka Connect:



k logs mirrormaker-0 connect




ERROR WorkerSourceTask{id=MirrorSourceConnector-0} Failed to flush, timed out while waiting for producer to flush outstanding 1 messages (org.apache.kafka.connect.runtime.WorkerSourceTask:438)

ERROR WorkerSourceTask{id=MirrorSourceConnector-0} Failed to commit offsets (org.apache.kafka.connect.runtime.SourceTaskOffsetCommitter:114)


producer.buffer.memory:



k exec -ti mirrormaker-0 -c connect -- bash

curl -X PUT -H "Content-Type: application/json" mirrormaker-0.mirrormaker:8083/connectors/MirrorSourceConnector/config -d \
'{
  "connector.class": "org.apache.kafka.connect.mirror.MirrorSourceConnector",
  "source.cluster.alias": "production",
  "target.cluster.alias": "backup",
  "source.cluster.bootstrap.servers": "kafka-0.kafka:9092,kafka-1.kafka:9092",
  "source.cluster.group.id": "mirror_maker_consumer",
  "source.cluster.enable.auto.commit": "true",
  "source.cluster.auto.commit.interval.ms": "1000",
  "source.cluster.session.timeout.ms": "30000",
  "source.cluster.security.protocol": "SSL",
  "source.cluster.ssl.truststore.location": "/certs/kafkaCA-trusted.jks",
  "source.cluster.ssl.truststore.password": "kafkapilot",
  "source.cluster.ssl.truststore.type": "JKS",
  "source.cluster.ssl.keystore.location": "/certs/kafka-consumer.jks",
  "source.cluster.ssl.keystore.password": "kafkapilot",
  "source.cluster.ssl.keystore.type": "JKS",
  "target.cluster.bootstrap.servers": "localhost:9092",
  "target.cluster.compression.type": "none",
  "topics": ".*",
  "rotate.interval.ms": "1000",
  "producer.buffer.memory:" "1000",
  "key.converter.class": "org.apache.kafka.connect.converters.ByteArrayConverter",
  "value.converter.class": "org.apache.kafka.connect.converters.ByteArrayConverter"
}'


15. Jmeter



#   jmeter-base
sudo docker build -t jmeter-base:local-v1 -f dockerfile/jmeter-base.dockerfile .

#   Jmeter
k apply -f service/jmeter-svc.yaml

#   pod- Jmeter,     
k apply -f statefulset/jmeter-statefulset.yaml


pod jmeter-producer producer.jmx



k run --rm -i --tty jmeter-producer --image=jmeter-base:local-v1 -- bash ./jmeter -n -t /tests/producer.jmx -r -Jremote_hosts=jmeter-0.jmeter:1099,jmeter-1.jmeter:1099


pod jmeter-consumer consumer.jmx



k run --rm -i --tty jmeter-consumer --image=jmeter-base:local-v1 -- bash ./jmeter -n -t /tests/consumer.jmx -r -Jremote_hosts=jmeter-2.jmeter:1099,jmeter-3.jmeter:1099


16.



statefulset



k delete statefulset jmeter zookeeper kafka mirrormaker




sudo docker rmi -f zookeeper-base:local-v1 kafka-base:local-v1 jmeter-base:local-v1




k delete svc grafana jmeter kafka mirrormaker zookeeper
k delete servicemonitor jmxexporter


linkedin: kildibaev

! .




All Articles