{"id":12789,"date":"2023-01-31T12:18:31","date_gmt":"2023-01-31T06:48:31","guid":{"rendered":"https:\/\/opstree.com\/blog\/\/?p=12789"},"modified":"2023-08-21T11:25:04","modified_gmt":"2023-08-21T05:55:04","slug":"kubernetes-cri-container-runtime-interface","status":"publish","type":"post","link":"https:\/\/opstree.com\/blog\/2023\/01\/31\/kubernetes-cri-container-runtime-interface\/","title":{"rendered":"Kubernetes CRI\u200a\u2014\u200aContainer Runtime Interface"},"content":{"rendered":"\n<p>Kubernetes is one of the most popular projects around container orchestration but it\u2019s quite interesting that Kubernetes itself has no code to run or manage Linux\/windows containers. So, what is running the containers within your Kubernetes pods?<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/01\/think.webp?w=200\" alt=\"\" class=\"wp-image-12815\" style=\"width:200px;height:200px\" width=\"200\" height=\"200\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\">Yes\u2026 Kubernetes doesn\u2019t run your containers<\/h2>\n\n\n\n<p>It\u2019s just an orchestration platform sitting above container runtimes. No code to run a container and to manage the container\u2019s lifecycle on its own, instead, dockershim was implemented (in <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/kubernetes\/kubernetes\/blob\/release-1.20\/pkg\/kubelet\/kubelet.go\" target=\"_blank\">kubelet<\/a> ) for talking to <strong>Docker<\/strong> as <strong>container runtime. <\/strong>I will talk about dockershim in the later section of the blog.<\/p>\n\n\n\n<p>Also, docker has grown and matured over the last few years and has gained a stack of components like <strong>runc<\/strong> (open container initiative), <strong>containerd<\/strong> (CNCF project). <strong>OCI<\/strong> (est. in June,2015) splits docker into two parts:<br><br>1) to handle docker cli &amp; processing requests and <br>2) to handle container running functions i.e runC.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/01\/image-2.png?w=957\" alt=\"\" class=\"wp-image-12792\" style=\"width:800px\" width=\"800\" \/><figcaption class=\"wp-element-caption\">High Level Overview\u200a\u2014\u200aBefore OCI standards<\/figcaption><\/figure>\n\n\n\n<!--more-->\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/01\/image-3.png?w=1000\" alt=\"\" class=\"wp-image-12794\" style=\"width:630px;height:321px\" width=\"630\" height=\"321\" \/><figcaption class=\"wp-element-caption\">High Level Overview\u200a\u2014\u200aAfter OCI standards<\/figcaption><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">But Wait\u2026 what is Container Runtime?<\/h2>\n\n\n\n<p>Container runtime is responsible to execute containers and managing container images on nodes.<\/p>\n\n\n\n<p>To understand the need for Container Runtime in Kubernetes, let\u2019s start with a few basic concepts:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Kubelet<\/h4>\n\n\n\n<ul>\n<li>The kubelet is a daemon that runs on every Kubernetes node. It is responsible for registering worker nodes with the API server and working with the <strong>podSpec<\/strong><\/li>\n\n\n\n<li>The kubelet acts as a client when connecting to the container runtime via gRPC. The Kubernetes Container Runtime Interface (CRI) defines the main <a rel=\"noreferrer noopener\" href=\"https:\/\/grpc.io\/\" target=\"_blank\">gRPC<\/a> protocol for the communication between the <a rel=\"noreferrer noopener\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/overview\/components\/#node-components\" target=\"_blank\">cluster components<\/a>, <a rel=\"noreferrer noopener\" href=\"https:\/\/kubernetes.io\/docs\/reference\/generated\/kubelet\" target=\"_blank\">kubelet<\/a>, and <a rel=\"noreferrer noopener\" href=\"https:\/\/kubernetes.io\/docs\/setup\/production-environment\/container-runtimes\" target=\"_blank\">container runtime<\/a>.<\/li>\n\n\n\n<li>Kubelet is also a controller where it watches for pod changes and utilizes the node\u2019s container runtime to pull images, run containers, etc.<\/li>\n\n\n\n<li>It also exposes an HTTP endpoint to stream logs and provides exec sessions for clients.<\/li>\n\n\n\n<li>Uses the CSI (container storage interface) gRPC to configure block volumes.<\/li>\n\n\n\n<li>It uses the CNI plugin configured in the cluster to allocate the pod IP address and set up any necessary network routes and firewall rules for the pod. (In Kubernetes 1.24, the management of the CNI is <em>no longer in scope for kubelet<\/em>)<\/li>\n<\/ul>\n\n\n\n<p><em>gRPC (open-source<\/em> RPC system developed by Google in 2015) is faster than REST because it uses protocol buffers. Protobuf serializes and de-serializes data into binary thus reducing the <em>size of the messages.<\/em><\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Node Controller<\/h4>\n\n\n\n<p>The node controller is a kubernetes control plane component that manages various aspects of nodes.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Pods<\/strong>\u200a<\/h4>\n\n\n\n<p>\u200aA pod is the smallest unit of reference within kubernetes. Each pod runs one or more containers, which together form a single functional unit.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Pod specs<\/strong>\u200a<\/h4>\n\n\n\n<p>The kubelet reads pod specs from the API server, usually defined in YAML configuration files. The pod specs say which container images the pod should run. It provides no details as to how containers should run\u200a\u2014\u200afor this, kubernetes needs a container runtime.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Other than PodSepcs from the API server, Kubelet can accept podSpec from a file, HTTP endpoint, and HTTP server. A good example of \u201cpodSpec from a file\u201d is \ud835\uddde\ud835\ude02\ud835\uddef\ud835\uddf2\ud835\uddff\ud835\uddfb\ud835\uddf2\ud835\ude01\ud835\uddf2\ud835\ude00 \ud835\ude00\ud835\ude01\ud835\uddee\ud835\ude01\ud835\uddf6\ud835\uddf0 \ud835\uddfd\ud835\uddfc\ud835\uddf1\ud835\ude00. Static pods are pods controlled by Kubelet on its nodes, not the API servers.<\/p>\n<\/blockquote>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Container Runtime<\/strong>\u200a<\/h4>\n\n\n\n<p>\u200aA Kubernetes node must have a container runtime installed. When the kubelet wants to process pod specs, it needs a container runtime to create the actual containers. The runtime is then responsible for managing the container lifecycle and communicating with the operating system kernel.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The network namespace creation is done by the container runtime only&nbsp;. Just before the pod is deployed and container created, it\u2019s the runtime responsibility to create the network namespace. Instead of running <strong>ip netns<\/strong> command and creating the network namespace manually, the container runtime does this automatically with the help of Pod infrastructure container i.e. <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-dark-gray-color\">pause container<\/mark><\/strong>. The command line argument to use is <code>--pod-infra-container-image.<\/code> With <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-dark-gray-color\">pause container<\/mark><\/strong>, app container can die &amp; come back again (restart), and all of the network setup will still be there. Normally if the last process in a network namespace dies the namespace would be destroyed and creating a new app container would require creating all new network setup but this is not the case, pause container remains always there in sleep state inside network namespace keeping that network alive.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">Is Docker the only container runtime?<\/h2>\n\n\n\n<p>The most widely known container runtime is Docker, but it is not the only one in this space. In fact, the container runtime space has been rapidly evolving. Early versions of kubernetes only worked with a specific container runtime i.e. Docker Engine.<\/p>\n\n\n\n<p>Later, kubernetes added support for working with other container runtimes using <strong>C<\/strong>ontainer <strong>R<\/strong>untime <strong>I<\/strong>nterface (est. Dec 2016). It enables interoperability between orchestrators (like Kubernetes) and many different container runtimes like containerd, CRI-O, cri-containerd, Mirantis container runtime etc.<\/p>\n\n\n\n<p>Docker Engine doesn\u2019t implement that interface (CRI), so the Kubernetes project created special code to help with the transition, and made that <strong><em>dockershim<\/em> <\/strong>code a part of Kubernetes itself.<\/p>\n\n\n\n<p>Dockershim is not a real CRI implementation but it is a built-in implementation in <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/kubernetes\/kubernetes\/blob\/v1.20.15\/pkg\/kubelet\/kubelet.go\" target=\"_blank\">kubelet <\/a>code base dedicated for docker as container runtime only. The kubernetes <a rel=\"noreferrer noopener\" href=\"https:\/\/kubernetes.io\/releases\/#release-v1-24\" target=\"_blank\">v1.24 release<\/a> actually removed the dockershim from kubernetes.<\/p>\n\n\n\n<p>Amazon EKS will be ending support for dockershim starting with the Kubernetes version 1.24 launch. Amazon EKS AMIs that are officially published will have containerd as the only runtime starting with version 1.24.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/01\/image-4.png?w=1024\" alt=\"\" class=\"wp-image-12803\" style=\"width:800px\" width=\"800\" \/><figcaption class=\"wp-element-caption\">when dockershim was part of kubelet code<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">That\u2019s How CRI Is&nbsp;born<\/h2>\n\n\n\n<p>Since Kubernetes 1.5 a new API was introduced, the Container Runtime Interface (CRI), allows any container runtime to <a href=\"https:\/\/kubernetes.io\/docs\/setup\/production-environment\/container-runtimes\/\" target=\"_blank\" rel=\"noopener\">plug<\/a> into the kubelet configuration which enables kubelet to use a wide variety of container runtimes, without the need to recompile and provide container runtime services for Kubernetes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Containerd: A core&nbsp;runtime<\/h2>\n\n\n\n<p>Kubernetes could use any container runtime that implements CRI to manage pods, containers and container images. Docker is the most common container runtime used in production Kubernetes environments, but containerd ( initiated by Docker Inc. &amp; donated to CNCF in March of 2017) may prove to be a better option. For more details, you could refer official <a href=\"https:\/\/kubernetes.io\/blog\/2017\/11\/containerd-container-runtime-options-kubernetes\/\" rel=\"noreferrer noopener\" target=\"_blank\">blog<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" src=\"https:\/\/opstree.com\/blog\/\/wp-content\/uploads\/2023\/01\/image-5.png?w=1024\" alt=\"\" class=\"wp-image-12808\" style=\"width:800px\" width=\"800\" \/><figcaption class=\"wp-element-caption\">containerd: A core Runtime<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>Standards allow ecosystems to grow and thrive as we have seen in the case of OCI and CRI. As this ecosystem grows standards will need to evolve to meet the ecosystem\u2019s needs. As everyone is upgrading to the latest version of Kubernetes so I thought CRI is a very important aspect to know before talking about what is being removed and added in newer versions of kubernetes. Hence, this blog talks about the what, why, how, and evolution of CRI in kubernetes since its existence. Thanks for reading. I\u2019d really appreciate your suggestions and feedback.<\/p>\n\n\n\n<p><strong>Blog Pundits: <strong>&nbsp;<a href=\"https:\/\/opstree.com\/blog\/\/author\/shwetatyagiot\/\" target=\"_blank\" rel=\"noreferrer noopener\">Shweta Tyagi<\/a><\/strong> and <a rel=\"noreferrer noopener\" href=\"https:\/\/opstree.com\/blog\/\/author\/sandeep7c51ad81ba\/\" target=\"_blank\">Sandeep Rawat<\/a><\/strong><\/p>\n\n\n\n<p><strong><a href=\"https:\/\/opstree.com\/contact-us\/?utm_source=WordPress&amp;utm_medium=Blog&amp;utm_campaign=Kubernetes_CRI%E2%80%8A%E2%80%94%E2%80%8AContainer_Runtime_Interface\" target=\"_blank\" rel=\"noreferrer noopener\">OpsTree<\/a> is an End-to-End DevOps Solution Provider.<\/strong><\/p>\n\n\n\n<div class=\"wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex\">\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link wp-element-button\" href=\"https:\/\/opstree.com\/contact-us\/?utm_source=WordPress&amp;utm_medium=Blog&amp;utm_campaign=Kubernetes_CRI%E2%80%8A%E2%80%94%E2%80%8AContainer_Runtime_Interface\" target=\"_blank\" rel=\"noreferrer noopener\">Contact Us<\/a><\/div>\n<\/div>\n\n\n\n<p class=\"has-text-align-center\"><strong>Connect with Us<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-social-links aligncenter is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-1 wp-block-social-links-is-layout-flex\"><li class=\"wp-social-link wp-social-link-linkedin  wp-block-social-link\"><a href=\"https:\/\/www.linkedin.com\/company\/opstree-solutions\" class=\"wp-block-social-link-anchor\" target=\"_blank\" rel=\"noopener\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">LinkedIn<\/span><\/a><\/li>\n\n<li class=\"wp-social-link wp-social-link-youtube  wp-block-social-link\"><a href=\"https:\/\/www.youtube.com\/channel\/UCeLma6SpNYH7jjYKSBNSexw\" class=\"wp-block-social-link-anchor\" target=\"_blank\" rel=\"noopener\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">YouTube<\/span><\/a><\/li>\n\n<li class=\"wp-social-link wp-social-link-github  wp-block-social-link\"><a href=\"https:\/\/github.com\/OpsTree\" class=\"wp-block-social-link-anchor\" target=\"_blank\" rel=\"noopener\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">GitHub<\/span><\/a><\/li>\n\n<li class=\"wp-social-link wp-social-link-facebook  wp-block-social-link\"><a href=\"https:\/\/www.facebook.com\/opstree\" class=\"wp-block-social-link-anchor\" target=\"_blank\" rel=\"noopener\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Facebook<\/span><\/a><\/li>\n\n<li class=\"wp-social-link wp-social-link-medium  wp-block-social-link\"><a href=\"https:\/\/medium.com\/buildpiper\" class=\"wp-block-social-link-anchor\" target=\"_blank\" rel=\"noopener\"><svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" version=\"1.1\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M20.962,7.257l-5.457,8.867l-3.923-6.375l3.126-5.08c0.112-0.182,0.319-0.286,0.527-0.286c0.05,0,0.1,0.008,0.149,0.02 c0.039,0.01,0.078,0.023,0.114,0.041l5.43,2.715l0.006,0.003c0.004,0.002,0.007,0.006,0.011,0.008 C20.971,7.191,20.98,7.227,20.962,7.257z M9.86,8.592v5.783l5.14,2.57L9.86,8.592z M15.772,17.331l4.231,2.115 C20.554,19.721,21,19.529,21,19.016V8.835L15.772,17.331z M8.968,7.178L3.665,4.527C3.569,4.479,3.478,4.456,3.395,4.456 C3.163,4.456,3,4.636,3,4.938v11.45c0,0.306,0.224,0.669,0.498,0.806l4.671,2.335c0.12,0.06,0.234,0.088,0.337,0.088 c0.29,0,0.494-0.225,0.494-0.602V7.231C9,7.208,8.988,7.188,8.968,7.178z\"><\/path><\/svg><span class=\"wp-block-social-link-label screen-reader-text\">Medium<\/span><\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Kubernetes is one of the most popular projects around container orchestration but it\u2019s quite interesting that Kubernetes itself has no code to run or manage Linux\/windows containers. So, what is running the containers within your Kubernetes pods? Yes\u2026 Kubernetes doesn\u2019t run your containers It\u2019s just an orchestration platform sitting above container runtimes. No code to &hellip; <a href=\"https:\/\/opstree.com\/blog\/2023\/01\/31\/kubernetes-cri-container-runtime-interface\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Kubernetes CRI\u200a\u2014\u200aContainer Runtime Interface&#8221;<\/span><\/a><\/p>\n","protected":false},"author":175681501,"featured_media":29900,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[28070474],"tags":[44070,644980092,483658163,768739308,676319247,768739309,4996032],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/opstree.com\/blog\/wp-content\/uploads\/2025\/11\/DevSecOps-1.jpg","jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pfDBOm-3kh","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/12789"}],"collection":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/users\/175681501"}],"replies":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/comments?post=12789"}],"version-history":[{"count":25,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/12789\/revisions"}],"predecessor-version":[{"id":15147,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/posts\/12789\/revisions\/15147"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media\/29900"}],"wp:attachment":[{"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/media?parent=12789"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/categories?post=12789"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/opstree.com\/blog\/wp-json\/wp\/v2\/tags?post=12789"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}