{"id":30,"date":"2023-02-07T11:14:00","date_gmt":"2023-02-07T11:14:00","guid":{"rendered":"https:\/\/www.cloudtechner.com\/blog\/?p=30"},"modified":"2024-06-13T11:02:22","modified_gmt":"2024-06-13T11:02:22","slug":"setting-up-apache-kafka-replication-and-disaster-recovery-using-kafka-mirrormaker","status":"publish","type":"post","link":"https:\/\/cloudtechner.com\/blog\/setting-up-apache-kafka-replication-and-disaster-recovery-using-kafka-mirrormaker\/","title":{"rendered":"Setting up Apache Kafka Replication and Disaster Recovery using Kafka MirrorMaker"},"content":{"rendered":"\n<p>Author: <a href=\"https:\/\/www.linkedin.com\/in\/mohinder-kumar-0b622010\/\">Mohinder Kumar<\/a>, Director, CloudTechner<\/p>\n\n\n<div class=\"taxonomy-post_tag wp-block-post-terms\"><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/aws\/\" rel=\"tag\">AWS<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/aws-msk\/\" rel=\"tag\">AWS MSK<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/cloud\/\" rel=\"tag\">Cloud<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/disaster-recovery\/\" rel=\"tag\">Disaster Recovery<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/high-availability\/\" rel=\"tag\">High Availability<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/kafka\/\" rel=\"tag\">Kafka<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/mirrormaker\/\" rel=\"tag\">MirrorMaker<\/a><span class=\"wp-block-post-terms__separator\">, <\/span><a href=\"https:\/\/cloudtechner.com\/blog\/tag\/replication\/\" rel=\"tag\">Replication<\/a><\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h5 class=\"wp-block-heading\">Problem Statement<\/h5>\n\n\n\n<p id=\"01be\">Amazon Managed Streaming for Apache Kafka (Amazon MSK) is an AWS streaming data service that manages Apache Kafka infrastructure and operations, making it easy for developers and DevOps managers to run Apache Kafka applications and Kafka Connect connectors on AWS, without the need to become experts in operating Apache Kafka.<\/p>\n\n\n\n<p id=\"be9a\">Now a days modernised applications try to use Apache Kafka due to distributed system, scalability and real time processing capabilities. Although Amazon MSK is fully managed Streaming for Apache Kafka but the&nbsp;<strong>real challenge comes when we need to setup Disaster Recovery<\/strong>&nbsp;for it for business continuity. Unlike other AWS Managed services like RDS, AWS doesn\u2019t support OOTB replication\/failover feature for Kafka topics and messages to another region.<\/p>\n\n\n\n<p id=\"7ec6\">This blog describes setting up Disaster Recovery for AWS Managed Streaming for Apache Kafka(Amazon MSK) using too called&nbsp;<strong>Kafka Mirror Maker<\/strong><\/p>\n\n\n\n<p id=\"584a\">Before we deep dive, lets revisit some basic concepts of<strong>&nbsp;Apache Kafka&nbsp;<\/strong>and&nbsp;<strong>Kafka Mirror Maker<\/strong>&nbsp;tool<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-1 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<h5 class=\"wp-block-heading\">What is Apache Kafka?<\/h5>\n<\/div>\n<\/div>\n\n\n\n<p id=\"71ec\">Apache Kafka is a distributed data store optimised for ingesting and processing streaming data in real-time. Streaming data is data that is continuously generated by thousands of data sources, which typically send the data records in simultaneously. A streaming platform needs to handle this constant influx of data, and process the data sequentially and incrementally.<\/p>\n\n\n\n<p id=\"9c36\">Kafka provides three main functions to its users:<\/p>\n\n\n\n<ul>\n<li>Publish and subscribe to streams of records<\/li>\n\n\n\n<li>Effectively store streams of records in the order in which records were generated<\/li>\n\n\n\n<li>Process streams of records in real time<\/li>\n<\/ul>\n\n\n\n<p id=\"ac92\">Kafka is primarily used to build real-time streaming data pipelines and applications that adapt to the data streams. It combines messaging, storage, and stream processing to allow storage and analysis of both historical and real-time data.<\/p>\n\n\n\n<h6 class=\"wp-block-heading\" id=\"e319\">Brokers and Clusters<\/h6>\n\n\n\n<p id=\"6017\">Kafka runs on clusters where each cluster consists of multiple servers, generally called brokers (and sometimes called nodes). That\u2019s what makes Kafka a distributed system: data in the Kafka cluster is distributed amongst multiple brokers. And multiple copies (replicas) of the same data exist in a Kafka cluster. This mechanism makes Kafka more stable, fault-tolerant, and reliable; if an error or failure occurs with one broker, another broker steps in to perform the functions of the malfunctioning component, and the information is not lost.<\/p>\n\n\n\n<h6 class=\"wp-block-heading\" id=\"c0bb\">Topics<\/h6>\n\n\n\n<p id=\"22ea\">A Kafka&nbsp;<strong>topic<\/strong>&nbsp;is an immutable log of events (sequences). Producers publish events to Kafka topics; consumers subscribe to topics to access their desired data. Each topic can serve data to many consumers. Continuing with our example, the registration component of the website publishes \u201cnew user\u201d events (via Kafka) into the \u201cregistration\u201d topic. Subscribers such as analytics apps, newsfeed apps, monitoring apps, databases, and so on in turn consume events from the \u201cregistration\u201d topic and use it with other data as the foundation for delivering their own products or services.<\/p>\n\n\n\n<h6 class=\"wp-block-heading\" id=\"f2aa\">Partitions<\/h6>\n\n\n\n<p id=\"c3ca\">A&nbsp;<strong>partition<\/strong>&nbsp;is the smallest storage unit in Kafka. Partitions serve to split data across brokers to accelerate performance. Each Kafka topic is divided into partitions and each partition can be placed on a separate broker.<\/p>\n\n\n\n<h5 class=\"wp-block-heading\">Kafka Mirror Maker<\/h5>\n\n\n\n<p id=\"0e7b\">Kafka MirrorMaker is a stand-alone tool for copying data between two Apache Kafka clusters. Mirror Maker automatically replicates existing topics and messages and also detects new topics and partitions, while also ensuring the topic configurations are synced between clusters. Data will be read from topics in the origin cluster and written to a topic with the same name in the destination cluster. You can run many such mirroring processes to increase throughput and for fault-tolerance.<\/p>\n\n\n\n<p id=\"2d61\">Mirror Maker comes with a default replication policy that can be customised by providing a custom replication policy class. Remote topics in Mirror Maker are replicated topics on the target cluster. These topics reference the source cluster using a naming convention as shown in the following figure.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"471\" height=\"221\" src=\"https:\/\/www.cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_1.webp\" alt=\"\" class=\"wp-image-46\" srcset=\"https:\/\/cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_1.webp 471w, https:\/\/cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_1-300x141.webp 300w\" sizes=\"(max-width: 471px) 100vw, 471px\" \/><\/figure><\/div>\n\n\n<ul>\n<li><\/li>\n<\/ul>\n\n\n\n<p id=\"0c57\">Mirror maker supports multi directional flows to replicate data from source to target<\/p>\n\n\n\n<ul>\n<li><strong>fan-out<\/strong>&nbsp;\u2014 fan-out is a replication strategy where you have a single source cluster and multiple target clusters<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"341\" height=\"251\" src=\"https:\/\/www.cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_2.webp\" alt=\"\" class=\"wp-image-47\" srcset=\"https:\/\/cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_2.webp 341w, https:\/\/cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_2-300x221.webp 300w\" sizes=\"(max-width: 341px) 100vw, 341px\" \/><\/figure><\/div>\n\n\n<ul>\n<li><strong>aggregation<\/strong>&#8211; aggregation is a replication strategy where you have multiple source clusters and a single target cluster<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"365\" height=\"241\" src=\"https:\/\/www.cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_3.webp\" alt=\"\" class=\"wp-image-48\" srcset=\"https:\/\/cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_3.webp 365w, https:\/\/cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_3-300x198.webp 300w\" sizes=\"(max-width: 365px) 100vw, 365px\" \/><\/figure><\/div>\n\n\n<ul>\n<li><strong>active\/active<\/strong>, where you have a bidirectional flow between a source cluster and a target cluster<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"355\" height=\"61\" src=\"https:\/\/www.cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_4.webp\" alt=\"\" class=\"wp-image-49\" srcset=\"https:\/\/cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_4.webp 355w, https:\/\/cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_4-300x52.webp 300w\" sizes=\"(max-width: 355px) 100vw, 355px\" \/><\/figure><\/div>\n\n\n<ul>\n<li><strong>active\/passive<\/strong>, where you have a unidirectional flow from a source cluster to a target cluster<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"355\" height=\"61\" src=\"https:\/\/www.cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_5.webp\" alt=\"\" class=\"wp-image-50\" srcset=\"https:\/\/cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_5.webp 355w, https:\/\/cloudtechner.com\/blog\/wp-content\/uploads\/2024\/06\/Kafka_5-300x52.webp 300w\" sizes=\"(max-width: 355px) 100vw, 355px\" \/><\/figure><\/div>\n\n\n<h5 class=\"wp-block-heading\">Setting up Kafka Mirror Maker on AWS EKS Cluster<\/h5>\n\n\n\n<h6 class=\"wp-block-heading\" id=\"721a\">Pre-requisites<\/h6>\n\n\n\n<p id=\"cda5\">Following prerequisites should be met before setting up Mirror Maker between two clusters<\/p>\n\n\n\n<ul>\n<li>AWS MSK Kafka Clusters is already setup in Primary and DR region<\/li>\n\n\n\n<li>Connectivity is established between Primary and DR region using VPC Peering<\/li>\n\n\n\n<li>All the necessary routes have been established to allow traffic between Primary and DR Region<\/li>\n\n\n\n<li>Allow EKS Cluster CIDR range of Primary region in AWS MSK Kafka Cluster Security group of both Primary and DR region so that Mirror Maker can talk to AWS MSK Kafka Cluster in both regions<\/li>\n\n\n\n<li>Docker Installed on local machine\/or any AWS EC2<\/li>\n\n\n\n<li>Helm Installed on the local machine\/or AWS EC2<\/li>\n\n\n\n<li>Kafka CLI utilities installed on the local machine\/or AWS EC2<\/li>\n<\/ul>\n\n\n\n<h6 class=\"wp-block-heading\" id=\"1e95\">Setup Instructions<\/h6>\n\n\n\n<p id=\"1eef\">We have created Helm Chart templates for deploying Kakfa Mirror Maker on Kubernetes Cluster. These helm charts are fully templatized and requires to update few values in values yaml along with mirror maker properties having kafka cluster details.<\/p>\n\n\n\n<ol>\n<li>Clone GIT Repository<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/cloudtechner\/ct-kafka-mm-k8s-setup\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/cloudtechner\/ct-kafka-mm-k8s-setup&nbsp;<\/a>. This repository contains the dockerfile to create the base image for Kafka Mirror Maker and Helm charts templates for deploying mirror-maker into Kubernetes cluster<\/li>\n\n\n\n<li>Build docker image with&nbsp;<strong>Dockerfile<\/strong>&nbsp;and push to Private Image registry<br><code><strong>docker build -t &lt;IMAGE_NAME:TAG&gt; .<\/strong><\/code><\/li>\n\n\n\n<li>Update following details in&nbsp;<strong><em>mm2.properties<\/em><\/strong>&nbsp;file<br>&#8211; Source (primary cluster) and target (secondary) kafka clusters names<br>&#8211; Source and target kafka clusters bootstrap servers details<\/li>\n\n\n\n<li>Modify&nbsp;<strong>values.yaml<\/strong>&nbsp;and update image name and image tag for kafka mirror maker with your own docker registry details<\/li>\n\n\n\n<li>Connect to Kubernetes Cluster and install helm charts on Kubernetes with updated&nbsp;<strong>values.yaml<\/strong>&nbsp;file from the current directory<br><code><strong>helm install mirror-maker .<\/strong><\/code><\/li>\n\n\n\n<li>Once helm charts are installed successfully, check the status of pods. You should see mirror-maker and zookeeper pods running<br><code><strong>kubectl get pods<\/strong><\/code><\/li>\n<\/ol>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*Vsu3Qwj28QRC7K6lyT2pyw.png\" alt=\"\"\/><\/figure>\n\n\n\n<h6 class=\"wp-block-heading\" id=\"4d03\">Testing<\/h6>\n\n\n\n<p id=\"cb2e\">Now that the MirrorMaker setup is done, we can replicate changes done on primary Kafka cluster to secondary cluster.<\/p>\n\n\n\n<p id=\"c682\">Get the brokers list deployed in Kafka Cluster. In case of self managed Kafka Cluster get IP and port of the Kafka Nodes<br><code><strong>aws kafka get-bootstrap-brokers --cluster-arn \"kafka-cluster-arn\"<\/strong><\/code><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*T5HnzMg5280-ixeNC1L2qw.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\"><strong>Kafka Brokers List<\/strong><\/figcaption><\/figure>\n\n\n\n<ul>\n<li>Create a topic in Primary Kafka Cluster using one of the broker IP<br><code><strong>kafka-topics --bootstrap-server &lt;primary-cluster-broker-host:9092&gt; --create --topic sampletopic<\/strong><\/code><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*xfY62KuEzhuHvsHczxwafg.png\" alt=\"\"\/><\/figure>\n\n\n\n<ul>\n<li>List Topics in Primary Kafka Cluster and validate if topic is successfully created or not<br><code><strong>kafka-topics --bootstrap-server &lt;primary-cluster-broker-host:9092&gt; --list<\/strong><\/code><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*mBeSZ5uRkoOzrNARaONykA.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\"><strong>List of Kafka Topics in Primary Kafka Cluster<\/strong><\/figcaption><\/figure>\n\n\n\n<ul>\n<li>List Topics in Secondary Kafka Cluster and validate if same topic is successfully replicated<br><code><strong>kafka-topics --bootstrap-server &lt;secondary-cluster-broker-host:9092&gt; --list<\/strong><\/code><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*5dfinjtN4wMNnbj8hjSkrw.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\"><strong>List of Kafka Topics in Secondary Kafka Cluster<\/strong><\/figcaption><\/figure>\n\n\n\n<p id=\"aec9\"><strong>Now lets produce some messages and validate messages replication<\/strong><\/p>\n\n\n\n<ul>\n<li>Add messages in Primary Kafka Cluster Topic<br><code><strong>kafka-console-producer --bootstrap-server &lt;primary-cluster-broker-host:9092&gt; --topic &lt;topic_name&gt;<\/strong><\/code><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*N1VWRoirtXgzU9bGHnc5GQ.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\"><strong>Kafka Producer (Primary Kafka Cluster)<\/strong><\/figcaption><\/figure>\n\n\n\n<ul>\n<li>Enter Messages and validate in secondary cluster if messages are getting successfully replicated<br><code><strong>kafka-console-consumer --bootstrap-server &lt;secondary-cluster-borker-host:9092&gt; --topic &lt;topic-created-in-primary-cluster&gt; --from-beginning<\/strong><\/code><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:1400\/1*PcPLTmMN147NQGnrRxW5eg.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\"><strong>Kafka Consumer (Secondary Kafka Cluster)<\/strong><\/figcaption><\/figure>\n\n\n\n<p id=\"06bc\">The above example shows the&nbsp;<strong>unidirectional<\/strong>&nbsp;Kafka replication (active-passive). For&nbsp;<strong>bi-directional<\/strong>&nbsp;or any other replication topology, we just need to modify&nbsp;<strong><em>mm2. properties<\/em><\/strong>&nbsp;as per requirement.<\/p>\n\n\n\n<p id=\"9d39\">This shows how to setup Disaster recovery environment for AWS MSK (Amazon Managed Service for Kafka) using MirrorMaker 2.0 with the help of helm charts on a Kubernetes Cluster. It does not need a running Connect cluster, and leverages a high-level driver which generates a set of Connect workers based on the mm2.properties configuration file.<\/p>\n\n\n\n<div class=\"wp-block-comments\">\n\n\n\n\n\n\t<div id=\"respond\" class=\"comment-respond wp-block-post-comments-form\">\n\t\t<h3 id=\"reply-title\" class=\"comment-reply-title\">Leave a Reply <small><a rel=\"nofollow\" id=\"cancel-comment-reply-link\" href=\"\/blog\/wp-json\/wp\/v2\/posts\/30#respond\" style=\"display:none;\">Cancel reply<\/a><\/small><\/h3><form action=\"https:\/\/cloudtechner.com\/blog\/wp-comments-post.php\" method=\"post\" id=\"commentform\" class=\"comment-form\"><p class=\"comment-notes\"><span id=\"email-notes\">Your email address will not be published.<\/span> <span class=\"required-field-message\">Required fields are marked <span class=\"required\">*<\/span><\/span><\/p><p class=\"comment-form-comment\"><label for=\"comment\">Comment <span class=\"required\">*<\/span><\/label> <textarea id=\"comment\" name=\"comment\" cols=\"45\" rows=\"8\" maxlength=\"65525\" required=\"required\"><\/textarea><\/p><p class=\"comment-form-author\"><label for=\"author\">Name <span class=\"required\">*<\/span><\/label> <input id=\"author\" name=\"author\" type=\"text\" value=\"\" size=\"30\" maxlength=\"245\" autocomplete=\"name\" required=\"required\" \/><\/p>\n<p class=\"comment-form-email\"><label for=\"email\">Email <span class=\"required\">*<\/span><\/label> <input id=\"email\" name=\"email\" type=\"text\" value=\"\" size=\"30\" maxlength=\"100\" aria-describedby=\"email-notes\" autocomplete=\"email\" required=\"required\" \/><\/p>\n<p class=\"comment-form-url\"><label for=\"url\">Website<\/label> <input id=\"url\" name=\"url\" type=\"text\" value=\"\" size=\"30\" maxlength=\"200\" autocomplete=\"url\" \/><\/p>\n<p class=\"comment-form-cookies-consent\"><input id=\"wp-comment-cookies-consent\" name=\"wp-comment-cookies-consent\" type=\"checkbox\" value=\"yes\" \/> <label for=\"wp-comment-cookies-consent\">Save my name, email, and website in this browser for the next time I comment.<\/label><\/p>\n<p class=\"form-submit\"><span class=\"bloghash-submit-form-button\"><input name=\"submit\" type=\"submit\" id=\"submit\" class=\"submit\" value=\"Post Comment\" \/><\/span> <input type='hidden' name='comment_post_ID' value='30' id='comment_post_ID' \/>\n<input type='hidden' name='comment_parent' id='comment_parent' value='0' \/>\n<\/p><\/form>\t<\/div><!-- #respond -->\n\t<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Author: Mohinder Kumar, Director, CloudTechner Problem Statement Amazon Managed Streaming for Apache Kafka (Amazon MSK) is an AWS streaming data service that manages Apache Kafka infrastructure and operations, making it&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,18,23,17,19],"tags":[9,14,10,12,13,7,8,15],"_links":{"self":[{"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/posts\/30"}],"collection":[{"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/comments?post=30"}],"version-history":[{"count":4,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/posts\/30\/revisions"}],"predecessor-version":[{"id":143,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/posts\/30\/revisions\/143"}],"wp:attachment":[{"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/media?parent=30"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/categories?post=30"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudtechner.com\/blog\/wp-json\/wp\/v2\/tags?post=30"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}