<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mark A. Greenslade</title>
    <description>The latest articles on Forem by Mark A. Greenslade (@asladeofgreen).</description>
    <link>https://forem.com/asladeofgreen</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F950383%2F8b73591b-4e21-4fdf-8d36-769a16bf29c3.jpeg</url>
      <title>Forem: Mark A. Greenslade</title>
      <link>https://forem.com/asladeofgreen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/asladeofgreen"/>
    <language>en</language>
    <item>
      <title>Casper Kafka Event Store Pt 2</title>
      <dc:creator>Mark A. Greenslade</dc:creator>
      <pubDate>Fri, 21 Oct 2022 10:58:46 +0000</pubDate>
      <link>https://forem.com/casperblockchain/casper-kafka-event-store-pt-2-4f1</link>
      <guid>https://forem.com/casperblockchain/casper-kafka-event-store-pt-2-4f1</guid>
      <description>&lt;h2&gt;
  
  
  Building a Kafka Cluster in a Kubernetes Cluster
&lt;/h2&gt;

&lt;p&gt;Carl Sagan quoted that If you wish to make an apple pie from scratch, &lt;strong&gt;you must first invent the universe&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Luckily the universe has already been invented, but we still need to build our Kubernetes cluster to host our Kafka cluster.&lt;/p&gt;

&lt;p&gt;For this POC I chose GCP. They’ve done some good work in minimising the UI. Plus the networking works seamlessly behind the scenes.&lt;/p&gt;

&lt;p&gt;Install &lt;strong&gt;gcloud&lt;/strong&gt; and &lt;strong&gt;kubectl&lt;/strong&gt; and run the following command to create the cluster:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud beta container \
 clusters create "[CLUSTER_NAME]" \
 --project "[PROJECT_NAME]"  \
 --zone "[ZONE]" \
 --machine-type "e2-medium" \
 --num-nodes 9 \
 --disk-size "100"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;After about 5 minutes we should have a cluster.&lt;/p&gt;

&lt;p&gt;Now we can add Zookeeper and Kafka.&lt;/p&gt;

&lt;p&gt;Use the installation guide from this GitHub &lt;a href="https://github.com/stormeye2000/cspr-kafka-cluster"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we have no Producers or Consumers configured yet, Kafka will be in a waiting state. No leader has been elected yet. This all happens when topics and partitions are created. More on that later.&lt;/p&gt;
&lt;h3&gt;
  
  
  Things to note in this cluster
&lt;/h3&gt;

&lt;p&gt;Zookeeper is a &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/"&gt;StatefulSet&lt;/a&gt; of three replicas. We need consistently named pods in the cluster. If we used a &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/"&gt;Deployment&lt;/a&gt;, every time a new pod was instantiated, it would be randomly name with a deployment hash suffix.&lt;/p&gt;

&lt;p&gt;With StatefulSets you get consistent pod names. In this case zookeeper-0, zookeeper-1 and zookeeper-2&lt;/p&gt;

&lt;p&gt;Likewise with the Kafka brokers.&lt;/p&gt;

&lt;p&gt;The Kafka broker StatefulSet starts Kafka.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Lines 2–4 define the Dockerfile, source can be viewed &lt;a href="https://github.com/stormeye2000/cspr-kafka-cluster/blob/master/docker/Dockerfile"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I chose to roll my own Dockerfile to allow more control. There are many Kafka Docker images in the hub, but for this project I needed to be able start Kafka with overridden options.&lt;/p&gt;

&lt;p&gt;Lines 5–8 are allocated resources per pod. I used Kenneth Owens excellent templates &lt;a href="https://github.com/kow3ns/kubernetes-kafka/tree/master/manifests"&gt;here&lt;/a&gt; to configure this POC.&lt;/p&gt;

&lt;p&gt;Lines 12–20 are environment variables. Line 13 sets the internal IP of the newly created pod. Lines 17–20 are standard java options.&lt;/p&gt;

&lt;p&gt;Lines 21 onward are Kafka start up options.&lt;/p&gt;

&lt;p&gt;Line 24 starts Kafka with the default server properties files, we then override these properties in the following lines with a mix of Kubernetes and custom env vars&lt;/p&gt;

&lt;p&gt;Line 25 sets the broker id from the pod hostname, eg pod &lt;em&gt;kafka-broker-1&lt;/em&gt; is assigned broker number 1 (StatefulSets give us this naming convention as discussed above)&lt;/p&gt;

&lt;p&gt;Lines 26–29 set the listeners. The brokers need to know how to communicate with each other internally and with external clients. This is difficult to get right. These settings work and will save a lot of pain. Line 26 tells Kafka to use the default 0.0.0.0 which means listen on all interfaces. Line 27 uses the pod ip env var, KAFKA_POD_IP for the advertised listener. Confluent have a good article on listeners &lt;a href="https://www.confluent.io/en-gb/blog/kafka-listeners-explained/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Line 28 tells Kafka to use the text string ‘INSIDE’ as the inter broker listener name. I assumed that when it sees this string it knows that this is an internal listener.&lt;/p&gt;

&lt;p&gt;Line 29 as this POC is an internal Kafka ensemble we can use PLAINTEXT for the security protocol. This is setting it to no encryption or authourisation. This will be changed to SSL for any production cluster.&lt;/p&gt;

&lt;p&gt;Line 30 uses Kubernetes env vars to point to our zookeeper pods. The zookeeper deployment uses a Kubernetes service for gateway access. This is all we need to configure the broker. This gives us the option of *n *zookeepers. We’re just using 3 in this POC&lt;/p&gt;

&lt;p&gt;After running the steps in on the GitHub &lt;a href="https://github.com/stormeye2000/cspr-kafka-cluster"&gt;page&lt;/a&gt; we will have a sucesfully running Kafka/Zookeeper ensemble within a Kubernetes cluster. The ensemble will be in a waiting state. Part 3 of these articles will discuss and demonstrate how to use the cluster, with Casper node events.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>kafka</category>
      <category>web3</category>
      <category>casper</category>
    </item>
    <item>
      <title>Casper Kafka Event Store Pt 1</title>
      <dc:creator>Mark A. Greenslade</dc:creator>
      <pubDate>Thu, 20 Oct 2022 15:58:11 +0000</pubDate>
      <link>https://forem.com/casperblockchain/casper-kafka-event-store-pt-1-lk8</link>
      <guid>https://forem.com/casperblockchain/casper-kafka-event-store-pt-1-lk8</guid>
      <description>&lt;h2&gt;
  
  
  The Description
&lt;/h2&gt;

&lt;p&gt;Casper nodes emit events on state changes. These events in the platform are categorised into three event stream types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deploy Events&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finality Signature Event&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Main Events&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Within each stream type there are multiple event types such as &lt;strong&gt;DeployAccepted&lt;/strong&gt; or &lt;strong&gt;BlockAdded&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;See the Casper &lt;a href="https://docs.casperlabs.io/dapp-dev-guide/building-dapps/monitoring-events/"&gt;documentation&lt;/a&gt; for a full description.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;As can be seen from the diagram below, there will be n nodes emitting 3 event stream types.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Ot890GX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2306/1%2A_O3qGUeJ9rRfae7dswh3vg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Ot890GX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2306/1%2A_O3qGUeJ9rRfae7dswh3vg.png" alt="Casper Node Events" width="880" height="821"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a lot of events.&lt;/p&gt;

&lt;p&gt;Even if the event stream is restricted to one or a group of nodes we are still seeing many events.&lt;/p&gt;

&lt;p&gt;Casper clients use these events to build up a picture of state changes in the node and smart contracts.&lt;/p&gt;

&lt;p&gt;These state changes can notify audit tools of any discrepancies, such as suspicious transactions, asset mutation or chain failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;How can we handle so many events?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To reliably consume these event streams we need a high throughput, highly available messaging service.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We need to differentiate the event types.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need to load balance the event stream types into separate silos (Finality Signature events are the majority of events by many multiples)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need to be able to replay the events in the case of any data loss or DR&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need confidence in our architecture&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enter &lt;a href="https://kafka.apache.org"&gt;Kafka&lt;/a&gt;, which will satisfy the concerns above.&lt;/p&gt;

&lt;p&gt;Kafka has concepts such as Brokers, Partitions, Replicas, Topics which will all be discussed in details in later sections.&lt;/p&gt;

&lt;p&gt;For now we just need to know that Kafka will be running n brokers acting as a cluster. The Kafka cluster will use &lt;a href="https://zookeeper.apache.org"&gt;Zookeeper&lt;/a&gt; to orchestrate the brokers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xtIO_VBN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2Ajry044f8MLzRdBDjI21Gcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xtIO_VBN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2Ajry044f8MLzRdBDjI21Gcw.png" alt="Kafka Zookeeper setup" width="880" height="840"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kafka uses the leader/follower pattern where it will decide amongst itself who is the leader and who follows. If the leader is lost, a new leader will be elected. An odd number is preferred as is always the case with clusters.&lt;/p&gt;

&lt;p&gt;Like all messaging systems, we need to produce and consume messages, Kafka like RabbitMQ handily names these as Producers and Consumers. Lets look into how these fit into our architecture:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H6nXWZrP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3194/1%2AVBmi5Q2PwS2EZmeAviTfSw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H6nXWZrP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3194/1%2AVBmi5Q2PwS2EZmeAviTfSw.png" alt="Event flow" width="880" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A simple and clean architecture.&lt;/p&gt;

&lt;p&gt;The event streams are read by the producer, any transformations are made, eg text to json, and the event is added to a Kafka topic.&lt;/p&gt;

&lt;p&gt;The consumer will then retrieve this event via its topic and process it accordingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Where can we host this architecture?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io"&gt;Kubernetes&lt;/a&gt;. Whatever the question in DevOps, Kubernetes is usually the answer.&lt;/p&gt;

&lt;p&gt;For all it’s minor annoyances (looking at you YAML), what other system can give us guaranteed uptime, replicated apps, ease of deployment/updates etc etc. What else are we going to use? Docker Swarm….&lt;/p&gt;

&lt;p&gt;So that being said, with K8s we can run multiple instances of the producer and consumer. We can also run the Kafka cluster within the K8s cluster to further guarantee its availability. Here’s what the final architecture diagram looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fv-74cpy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4216/1%2Aei4OK2obobdMFjNMl7phFQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fv-74cpy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/4216/1%2Aei4OK2obobdMFjNMl7phFQ.png" alt="Proof of concept ready architecture" width="880" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consumer groups are a very useful concept added to our solution. They each read a message from a topic once, so both Consumer Group A and B will both read the same message exactly once. Any other consumers can also read the message (Kafka has a time to live on messages)&lt;/p&gt;

&lt;p&gt;As can be seen, we are writing to both an Audit and UI document store. Audit will be used to replay the event history in case of DR, UI will be a structured store which can be used by any UI or reporting tools.&lt;/p&gt;

&lt;p&gt;Implementation details will follow in the coming articles&lt;/p&gt;

</description>
      <category>kafka</category>
      <category>casper</category>
      <category>blockchain</category>
      <category>eventdriven</category>
    </item>
  </channel>
</rss>
