{"id":4299,"date":"2018-12-31T14:12:38","date_gmt":"2018-12-31T14:12:38","guid":{"rendered":"http:\/\/howk.de\/w1\/blog-grpc-load-balancing-on-kubernetes-without-tears\/"},"modified":"2018-12-31T14:12:38","modified_gmt":"2018-12-31T14:12:38","slug":"blog-grpc-load-balancing-on-kubernetes-without-tears","status":"publish","type":"post","link":"https:\/\/howk.de\/?p=4299","title":{"rendered":"Blog: gRPC Load Balancing on Kubernetes without Tears"},"content":{"rendered":"<p><strong>Author<\/strong>: William Morgan (Buoyant)<\/p>\n<p>Many new gRPC users are surprised to find that Kubernetes&rsquo;s default load<br \/>\nbalancing often doesn&rsquo;t work out of the box with gRPC. For example, here&rsquo;s what<br \/>\nhappens when you take a <a href=\"https:\/\/github.com\/sourishkrout\/nodevoto\" target=\"_blank\">simple gRPC Node.js microservices<br \/>\napp<\/a> and deploy it on Kubernetes:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/kubernetes.io\/images\/blog\/grpc-load-balancing-with-linkerd\/Screenshot2018-11-0116-c4d86100-afc1-4a08-a01c-16da391756dd.34.36.png\" alt=\"\" \/><\/p>\n<p>While the <code>voting<\/code> service displayed here has several pods, it&rsquo;s clear from<br \/>\nKubernetes&rsquo;s CPU graphs that only one of the pods is actually doing any<br \/>\nwork&mdash;because only one of the pods is receiving any traffic. Why?<\/p>\n<p>In this blog post, we describe why this happens, and how you can easily fix it<br \/>\nby adding gRPC load balancing to any Kubernetes app with<br \/>\n<a href=\"https:\/\/linkerd.io\" target=\"_blank\">Linkerd<\/a>, a <a href=\"https:\/\/cncf.io\" target=\"_blank\">CNCF<\/a> service mesh and service sidecar.<\/p>\n<h1 id=\"why-does-grpc-need-special-load-balancing\">Why does gRPC need special load balancing?<\/h1>\n<p>First, let&rsquo;s understand why we need to do something special for gRPC.<\/p>\n<p>gRPC is an increasingly common choice for application developers. Compared to<br \/>\nalternative protocols such as JSON-over-HTTP, gRPC can provide some significant<br \/>\nbenefits, including dramatically lower (de)serialization costs, automatic type<br \/>\nchecking, formalized APIs, and less TCP management overhead.<\/p>\n<p>However, gRPC also breaks the standard connection-level load balancing,<br \/>\nincluding what&rsquo;s provided by Kubernetes. This is because gRPC is built on<br \/>\nHTTP\/2, and HTTP\/2 is designed to have a single long-lived TCP connection,<br \/>\nacross which all requests are <em>multiplexed<\/em>&mdash;meaning multiple requests can be<br \/>\nactive on the same connection at any point in time. Normally, this is great, as<br \/>\nit reduces the overhead of connection management. However, it also means that<br \/>\n(as you might imagine) connection-level balancing isn&rsquo;t very useful. Once the<br \/>\nconnection is established, there&rsquo;s no more balancing to be done. All requests<br \/>\nwill get pinned to a single destination pod, as shown below:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/kubernetes.io\/images\/blog\/grpc-load-balancing-with-linkerd\/Mono-8d2e53ef-b133-4aa0-9551-7e36a880c553.png\" alt=\"\" \/><\/p>\n<h1 id=\"why-doesn-t-this-affect-http-1-1\">Why doesn&rsquo;t this affect HTTP\/1.1?<\/h1>\n<p>The reason why this problem doesn&rsquo;t occur in HTTP\/1.1, which also has the<br \/>\nconcept of long-lived connections, is because HTTP\/1.1 has several features<br \/>\nthat naturally result in cycling of TCP connections. Because of this,<br \/>\nconnection-level balancing is &ldquo;good enough&rdquo;, and for most HTTP\/1.1 apps we<br \/>\ndon&rsquo;t need to do anything more.<\/p>\n<p>To understand why, let&rsquo;s take a deeper look at HTTP\/1.1. In contrast to HTTP\/2,<br \/>\nHTTP\/1.1 cannot multiplex requests. Only one HTTP request can be active at a<br \/>\ntime per TCP connection. The client makes a request, e.g. <code>GET \/foo<\/code>, and then<br \/>\nwaits until the server responds. While that request-response cycle is<br \/>\nhappening, no other requests can be issued on that connection.<\/p>\n<p>Usually, we want lots of requests happening in parallel. Therefore, to have<br \/>\nconcurrent HTTP\/1.1 requests, we need to make multiple HTTP\/1.1 connections,<br \/>\nand issue our requests across all of them. Additionally, long-lived HTTP\/1.1<br \/>\nconnections typically expire after some time, and are torn down by the client<br \/>\n(or server). These two factors combined mean that HTTP\/1.1 requests typically<br \/>\ncycle across multiple TCP connections, and so connection-level balancing works.<\/p>\n<h1 id=\"so-how-do-we-load-balance-grpc\">So how do we load balance gRPC?<\/h1>\n<p>Now back to gRPC. Since we can&rsquo;t balance at the connection level, in order to<br \/>\ndo gRPC load balancing, we need to shift from connection balancing to <em>request<\/em><br \/>\nbalancing. In other words, we need to open an HTTP\/2 connection to each<br \/>\ndestination, and balance <em>requests<\/em> across these connections, as shown below:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/kubernetes.io\/images\/blog\/grpc-load-balancing-with-linkerd\/Stereo-09aff9d7-1c98-4a0a-9184-9998ed83a531.png\" alt=\"\" \/><\/p>\n<p>In network terms, this means we need to make decisions at L5\/L7 rather than<br \/>\nL3\/L4, i.e. we need to understand the protocol sent over the TCP connections.<\/p>\n<p>How do we accomplish this? There are a couple options. First, our application<br \/>\ncode could manually maintain its own load balancing pool of destinations, and<br \/>\nwe could configure our gRPC client to <a href=\"https:\/\/godoc.org\/google.golang.org\/grpc\/balancer\" target=\"_blank\">use this load balancing<br \/>\npool<\/a>. This approach gives<br \/>\nus the most control, but it can be very complex in environments like Kubernetes<br \/>\nwhere the pool changes over time as Kubernetes reschedules pods. Our<br \/>\napplication would have to watch the Kubernetes API and keep itself up to date<br \/>\nwith the pods.<\/p>\n<p>Alternatively, in Kubernetes, we could deploy our app as <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/service\/#headless-services\" target=\"_blank\">headless<br \/>\nservices<\/a>.<br \/>\nIn this case, Kubernetes <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/service\/#headless-services\" target=\"_blank\">will create multiple A<br \/>\nrecords<\/a><br \/>\nin the DNS entry for the service. If our gRPC client is sufficiently advanced,<br \/>\nit can automatically maintain the load balancing pool from those DNS entries.<br \/>\nBut this approach restricts us to certain gRPC clients, and it&rsquo;s rarely<br \/>\npossible to only use headless services.<\/p>\n<p>Finally, we can take a third approach: use a lightweight proxy.<\/p>\n<h1 id=\"grpc-load-balancing-on-kubernetes-with-linkerd\">gRPC load balancing on Kubernetes with Linkerd<\/h1>\n<p><a href=\"https:\/\/linkerd.io\" target=\"_blank\">Linkerd<\/a> is a <a href=\"https:\/\/cncf.io\" target=\"_blank\">CNCF<\/a>-hosted <em>service<br \/>\nmesh<\/em> for Kubernetes. Most relevant to our purposes, Linkerd also functions as<br \/>\na <em>service sidecar<\/em>, where it can be applied to a single service&mdash;even without<br \/>\ncluster-wide permissions. What this means is that when we add Linkerd to our<br \/>\nservice, it adds a tiny, ultra-fast proxy to each pod, and these proxies watch<br \/>\nthe Kubernetes API and do gRPC load balancing automatically. Our deployment<br \/>\nthen looks like this:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/kubernetes.io\/images\/blog\/grpc-load-balancing-with-linkerd\/Linkerd-8df1031c-cdd1-4164-8e91-00f2d941e93f.io.png\" alt=\"\" \/><\/p>\n<p>Using Linkerd has a couple advantages. First, it works with services written in<br \/>\nany language, with any gRPC client, and any deployment model (headless or not).<br \/>\nBecause Linkerd&rsquo;s proxies are completely transparent, they auto-detect HTTP\/2<br \/>\nand HTTP\/1.x and do L7 load balancing, and they pass through all other traffic<br \/>\nas pure TCP. This means that everything will <em>just work.<\/em><\/p>\n<p>Second, Linkerd&rsquo;s load balancing is very sophisticated. Not only does Linkerd<br \/>\nmaintain a watch on the Kubernetes API and automatically update the load<br \/>\nbalancing pool as pods get rescheduled, Linkerd uses an <em>exponentially-weighted<br \/>\nmoving average<\/em> of response latencies to automatically send requests to the<br \/>\nfastest pods. If one pod is slowing down, even momentarily, Linkerd will shift<br \/>\ntraffic away from it. This can reduce end-to-end tail latencies.<\/p>\n<p>Finally, Linkerd&rsquo;s Rust-based proxies are incredibly fast and small. They<br \/>\nintroduce &lt;1ms of p99 latency and require &lt;10mb of RSS per pod, meaning that<br \/>\nthe impact on system performance will be negligible.<\/p>\n<h1 id=\"grpc-load-balancing-in-60-seconds\">gRPC Load Balancing in 60 seconds<\/h1>\n<p>Linkerd is very easy to try. Just follow the steps in the <a href=\"https:\/\/linkerd.io\/2\/getting-started\/\" target=\"_blank\">Linkerd Getting<br \/>\nStarted Instructions<\/a>&mdash;install the<br \/>\nCLI on your laptop, install the control plane on your cluster, and &ldquo;mesh&rdquo; your<br \/>\nservice (inject the proxies into each pod). You&rsquo;ll have Linkerd running on your<br \/>\nservice in no time, and should see proper gRPC balancing immediately.<\/p>\n<p>Let&rsquo;s take a look at our sample <code>voting<\/code> service again, this time after<br \/>\ninstalling Linkerd:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/kubernetes.io\/images\/blog\/grpc-load-balancing-with-linkerd\/Screenshot2018-11-0116-24b8ee81-144c-4eac-b73d-871bbf0ea22e.57.42.png\" alt=\"\" \/><\/p>\n<p>As we can see, the CPU graphs for all pods are active, indicating that all pods<br \/>\nare now taking traffic&mdash;without having to change a line of code. Voila,<br \/>\ngRPC load balancing as if by magic!<\/p>\n<p>Linkerd also gives us built-in traffic-level dashboards, so we don&rsquo;t even need<br \/>\nto guess what&rsquo;s happening from CPU charts any more. Here&rsquo;s a Linkerd graph<br \/>\nthat&rsquo;s showing the success rate, request volume, and latency percentiles of<br \/>\neach pod:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/kubernetes.io\/images\/blog\/grpc-load-balancing-with-linkerd\/Screenshot2018-11-0212-15ed0448-5424-4e47-9828-20032de868b5.08.38.png\" alt=\"\" \/><\/p>\n<p>We can see that each pod is getting around 5 RPS. We can also see that, while<br \/>\nwe&rsquo;ve solved our load balancing problem, we still have some work to do on our<br \/>\nsuccess rate for this service. (The demo app is built with an intentional<br \/>\nfailure&mdash;as an exercise to the reader, see if you can figure it out by<br \/>\nusing the Linkerd dashboard!)<\/p>\n<h1 id=\"wrapping-it-up\">Wrapping it up<\/h1>\n<p>If you&rsquo;re interested in a dead simple way to add gRPC load balancing to your<br \/>\nKubernetes services, regardless of what language it&rsquo;s written in, what gRPC<br \/>\nclient you&rsquo;re using, or how it&rsquo;s deployed, you can use Linkerd to add gRPC load<br \/>\nbalancing in a few commands.<\/p>\n<p>There&rsquo;s a lot more to Linkerd, including security, reliability, and debugging<br \/>\nand diagnostics features, but those are topics for future blog posts.<\/p>\n<p>Want to learn more? We\u2019d love to have you join our rapidly-growing community!<br \/>\nLinkerd is a <a href=\"https:\/\/cncf.io\" target=\"_blank\">CNCF<\/a> project, <a href=\"https:\/\/github.com\/linkerd\/linkerd2\" target=\"_blank\">hosted on<br \/>\nGitHub<\/a>, and has a thriving community<br \/>\non <a href=\"https:\/\/slack.linkerd.io\" target=\"_blank\">Slack<\/a>, <a href=\"https:\/\/twitter.com\/linkerd\" target=\"_blank\">Twitter<\/a>,<br \/>\nand the <a href=\"https:\/\/lists.cncf.io\/g\/cncf-linkerd-users\" target=\"_blank\">mailing lists<\/a>. Come and<br \/>\njoin the fun!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Author: William Morgan (Buoyant) Many new gRPC users are surprised to find that Kubernetes&rsquo;s default load balancing often doesn&rsquo;t work out of the box with gRPC. For example, here&rsquo;s what happens when you take a simple gRPC Node.js microservices app and deploy it on Kubernetes: While the voting service displayed here has several pods, it&rsquo;s [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.9.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Blog: gRPC Load Balancing on Kubernetes without Tears - Howk IT-Dienstleistungen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/howk.de\/?p=4299\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Blog: gRPC Load Balancing on Kubernetes without Tears - Howk IT-Dienstleistungen\" \/>\n<meta property=\"og:description\" content=\"Author: William Morgan (Buoyant) Many new gRPC users are surprised to find that Kubernetes&rsquo;s default load balancing often doesn&rsquo;t work out of the box with gRPC. For example, here&rsquo;s what happens when you take a simple gRPC Node.js microservices app and deploy it on Kubernetes: While the voting service displayed here has several pods, it&rsquo;s [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/howk.de\/?p=4299\" \/>\n<meta property=\"og:site_name\" content=\"Howk IT-Dienstleistungen\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/howk.de\" \/>\n<meta property=\"article:published_time\" content=\"2018-12-31T14:12:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kubernetes.io\/images\/blog\/grpc-load-balancing-with-linkerd\/Screenshot2018-11-0116-c4d86100-afc1-4a08-a01c-16da391756dd.34.36.png\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/howk.de\/?p=4299#article\",\"isPartOf\":{\"@id\":\"https:\/\/howk.de\/?p=4299\"},\"author\":{\"name\":\"admin\",\"@id\":\"https:\/\/howk.de\/#\/schema\/person\/b029bd02d4f35dce869ef54c81a100c5\"},\"headline\":\"Blog: gRPC Load Balancing on Kubernetes without Tears\",\"datePublished\":\"2018-12-31T14:12:38+00:00\",\"dateModified\":\"2018-12-31T14:12:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/howk.de\/?p=4299\"},\"wordCount\":1347,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/howk.de\/#organization\"},\"articleSection\":[\"Hi Tech\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/howk.de\/?p=4299#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/howk.de\/?p=4299\",\"url\":\"https:\/\/howk.de\/?p=4299\",\"name\":\"Blog: gRPC Load Balancing on Kubernetes without Tears - Howk IT-Dienstleistungen\",\"isPartOf\":{\"@id\":\"https:\/\/howk.de\/#website\"},\"datePublished\":\"2018-12-31T14:12:38+00:00\",\"dateModified\":\"2018-12-31T14:12:38+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/howk.de\/?p=4299#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/howk.de\/?p=4299\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/howk.de\/?p=4299#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/howk.de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Blog: gRPC Load Balancing on Kubernetes without Tears\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/howk.de\/#website\",\"url\":\"https:\/\/howk.de\/\",\"name\":\"Howk IT-Dienstleistungen\",\"description\":\"Howk IT Services - Howk IT-Dienstleistungen\",\"publisher\":{\"@id\":\"https:\/\/howk.de\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/howk.de\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/howk.de\/#organization\",\"name\":\"HowK\",\"url\":\"https:\/\/howk.de\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/howk.de\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/howk.de\/w1\/wp-content\/uploads\/2013\/12\/howk-logo.png\",\"contentUrl\":\"https:\/\/howk.de\/w1\/wp-content\/uploads\/2013\/12\/howk-logo.png\",\"width\":170,\"height\":170,\"caption\":\"HowK\"},\"image\":{\"@id\":\"https:\/\/howk.de\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/howk.de\",\"http:\/\/de.linkedin.com\/in\/howkde\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/howk.de\/#\/schema\/person\/b029bd02d4f35dce869ef54c81a100c5\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/howk.de\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b5a20f4d07bca1b73f25cff58a1116c4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b5a20f4d07bca1b73f25cff58a1116c4?s=96&d=mm&r=g\",\"caption\":\"admin\"},\"url\":\"https:\/\/howk.de\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Blog: gRPC Load Balancing on Kubernetes without Tears - Howk IT-Dienstleistungen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/howk.de\/?p=4299","og_locale":"en_US","og_type":"article","og_title":"Blog: gRPC Load Balancing on Kubernetes without Tears - Howk IT-Dienstleistungen","og_description":"Author: William Morgan (Buoyant) Many new gRPC users are surprised to find that Kubernetes&rsquo;s default load balancing often doesn&rsquo;t work out of the box with gRPC. For example, here&rsquo;s what happens when you take a simple gRPC Node.js microservices app and deploy it on Kubernetes: While the voting service displayed here has several pods, it&rsquo;s [&hellip;]","og_url":"https:\/\/howk.de\/?p=4299","og_site_name":"Howk IT-Dienstleistungen","article_publisher":"https:\/\/www.facebook.com\/howk.de","article_published_time":"2018-12-31T14:12:38+00:00","og_image":[{"url":"https:\/\/kubernetes.io\/images\/blog\/grpc-load-balancing-with-linkerd\/Screenshot2018-11-0116-c4d86100-afc1-4a08-a01c-16da391756dd.34.36.png"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"Written by":"admin","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/howk.de\/?p=4299#article","isPartOf":{"@id":"https:\/\/howk.de\/?p=4299"},"author":{"name":"admin","@id":"https:\/\/howk.de\/#\/schema\/person\/b029bd02d4f35dce869ef54c81a100c5"},"headline":"Blog: gRPC Load Balancing on Kubernetes without Tears","datePublished":"2018-12-31T14:12:38+00:00","dateModified":"2018-12-31T14:12:38+00:00","mainEntityOfPage":{"@id":"https:\/\/howk.de\/?p=4299"},"wordCount":1347,"commentCount":0,"publisher":{"@id":"https:\/\/howk.de\/#organization"},"articleSection":["Hi Tech"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/howk.de\/?p=4299#respond"]}]},{"@type":"WebPage","@id":"https:\/\/howk.de\/?p=4299","url":"https:\/\/howk.de\/?p=4299","name":"Blog: gRPC Load Balancing on Kubernetes without Tears - Howk IT-Dienstleistungen","isPartOf":{"@id":"https:\/\/howk.de\/#website"},"datePublished":"2018-12-31T14:12:38+00:00","dateModified":"2018-12-31T14:12:38+00:00","breadcrumb":{"@id":"https:\/\/howk.de\/?p=4299#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/howk.de\/?p=4299"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/howk.de\/?p=4299#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/howk.de\/"},{"@type":"ListItem","position":2,"name":"Blog: gRPC Load Balancing on Kubernetes without Tears"}]},{"@type":"WebSite","@id":"https:\/\/howk.de\/#website","url":"https:\/\/howk.de\/","name":"Howk IT-Dienstleistungen","description":"Howk IT Services - Howk IT-Dienstleistungen","publisher":{"@id":"https:\/\/howk.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/howk.de\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/howk.de\/#organization","name":"HowK","url":"https:\/\/howk.de\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/howk.de\/#\/schema\/logo\/image\/","url":"https:\/\/howk.de\/w1\/wp-content\/uploads\/2013\/12\/howk-logo.png","contentUrl":"https:\/\/howk.de\/w1\/wp-content\/uploads\/2013\/12\/howk-logo.png","width":170,"height":170,"caption":"HowK"},"image":{"@id":"https:\/\/howk.de\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/howk.de","http:\/\/de.linkedin.com\/in\/howkde"]},{"@type":"Person","@id":"https:\/\/howk.de\/#\/schema\/person\/b029bd02d4f35dce869ef54c81a100c5","name":"admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/howk.de\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b5a20f4d07bca1b73f25cff58a1116c4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b5a20f4d07bca1b73f25cff58a1116c4?s=96&d=mm&r=g","caption":"admin"},"url":"https:\/\/howk.de\/?author=1"}]}},"_links":{"self":[{"href":"https:\/\/howk.de\/index.php?rest_route=\/wp\/v2\/posts\/4299"}],"collection":[{"href":"https:\/\/howk.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/howk.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/howk.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/howk.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4299"}],"version-history":[{"count":0,"href":"https:\/\/howk.de\/index.php?rest_route=\/wp\/v2\/posts\/4299\/revisions"}],"wp:attachment":[{"href":"https:\/\/howk.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4299"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/howk.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4299"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/howk.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4299"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}