{"id":81593,"date":"2020-05-15T01:42:36","date_gmt":"2020-05-14T23:42:36","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/tonkaya-nastrojka-marshrutizaczii-dlya-metallb-v-rezhime-l2"},"modified":"2020-05-15T01:42:36","modified_gmt":"2020-05-14T23:42:36","slug":"tonkaya-nastrojka-marshrutizaczii-dlya-metallb-v-rezhime-l2","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/tonkaya-nastrojka-marshrutizaczii-dlya-metallb-v-rezhime-l2","title":{"rendered":"Fine-tuning routing for MetalLB in L2 mode.","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Fine-tuning routing for MetalLB in L2 mode.\" src=\"\/wp-content\/uploads\/2020\/05\/d03a56702a85f4c8c80a6cac3e489980.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nNot long ago, I encountered a rather unconventional task of configuring routing for MetalLB. Normally, MetalLB doesn\u2019t require any additional steps, but in our case, we have a fairly large cluster with a rather simple network configuration.<\/p>\n<p><\/p>\n<p>In this article, I will explain how to configure source-based and policy-based routing for the external network of your cluster.<\/p>\n<p><\/p>\n<p>I won\u2019t go into detail about installing and setting up MetalLB, as I assume you already have some experience. Let\u2019s get straight to the point: the routing configuration. So, we have four scenarios:<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h1 id=\"sluchay-1-kogda-nastroyka-ne-trebuetsya\">Scenario 1: No configuration is required<\/h1>\n<p><\/p>\n<p>Let\u2019s analyze a simple case.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Fine-tuning routing for MetalLB in L2 mode.\" src=\"\/wp-content\/uploads\/2020\/05\/f79cc1169741b899c95e76d5d4cf60fc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Additional routing configuration is not required when the IP addresses provided by MetalLB are in the same subnet as your nodes' addresses.<\/p>\n<p><\/p>\n<p>For example, you have a subnet <code>192.168.1.0\/24<\/code>, there is a router <code>192.168.1.1<\/code>, and your nodes receive addresses: <code>192.168.1.10-30<\/code>, then for MetalLB, you can configure a range <code>192.168.1.100-120<\/code> and be sure that they will work without any additional settings.<\/p>\n<p><\/p>\n<p>Why is that? Because your nodes already have routes configured:<\/p>\n<p><\/p>\n<pre><code class=\"bash\"># ip route\ndefault via 192.168.1.1 dev eth0 onlink \n192.168.1.0\/24 dev eth0 proto kernel scope link src 192.168.1.10<\/code><\/pre>\n<p><\/p>\n<p>And addresses from the same range will reuse them without any additional effort.<\/p>\n<p><\/p>\n<h1 id=\"sluchay-2-kogda-trebuetsya-dopolnitelnaya-nastroyka\">Scenario 2: Additional configuration is required<\/h1>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Fine-tuning routing for MetalLB in L2 mode.\" src=\"\/wp-content\/uploads\/2020\/05\/02392fbc3c16bdf52f0c5ddaf5688e7d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>You should configure additional routes whenever your nodes do not have a configured <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/en\/lir\/ipv4\/\"   title=\"an IP address\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"666\">an IP address<\/a> or a route to the subnet for which MetalLB is issuing addresses.<\/p>\n<p><\/p>\n<p>Let me explain in more detail. Whenever MetalLB assigns an address, it can be compared to a simple command like:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ip addr add 10.9.8.7\/32 dev lo<\/code><\/pre>\n<p><\/p>\n<p>Note that:<\/p>\n<p><\/p>\n<ul>\n<li><strong>a)<\/strong> The address is assigned with a prefix <code>\/32<\/code> meaning that a route to the subnet will not be automatically added (it\u2019s just an address)<\/li>\n<li><strong>b)<\/strong> The address is assigned to any node interface (for example, loopback). It\u2019s worth mentioning the peculiarity of the Linux networking stack. It doesn\u2019t matter on which interface you add the address; the kernel will always process ARP requests and send ARP replies on any of them. This behavior is considered correct and is widely used in a dynamic environment like Kubernetes.<\/li>\n<\/ul>\n<p><\/p>\n<p>This behavior can be configured, for example, by enabling strict ARP:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">echo 1 &gt; \/proc\/sys\/net\/ipv4\/conf\/all\/arp_ignore\necho 2 &gt; \/proc\/sys\/net\/ipv4\/conf\/all\/arp_announce<\/code><\/pre>\n<p><\/p>\n<p>In this case, ARP responses will be sent only if the interface explicitly contains a specific IP address. This setting is mandatory if you plan to use MetalLB and your kube-proxy operates in IPVS mode.<\/p>\n<p><\/p>\n<p>However, MetalLB does not use the kernel to process ARP requests; it does this itself in user space, so this option will not affect MetalLB's operation.<\/p>\n<p><\/p>\n<p>Let's return to our task. If there is no route for the issued addresses on your nodes, add it in advance to all nodes:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ip route add 10.9.8.0\/24 dev eth1<\/code><\/pre>\n<p><\/p>\n<h1 id=\"sluchay-3-kogda-ponadobitsya-source-based-routing\">Case 3: When source-based routing is needed<\/h1>\n<p><\/p>\n<p>You will need to configure source-based routing when you receive packets through a separate gateway, not the one set up as default. Consequently, response packets must also go through this same gateway.<\/p>\n<p><\/p>\n<p>For example, you have the same subnet <code>192.168.1.0\/24<\/code> allocated for your nodes, but you want to issue external addresses using MetalLB. Let's assume you have several addresses from the subnet <code>1.2.3.0\/24<\/code> located in VLAN 100, and you want to use them to access Kubernetes services from the outside.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Fine-tuning routing for MetalLB in L2 mode.\" src=\"\/wp-content\/uploads\/2020\/05\/9360f35c4bfae25b12fc5aab2644b775.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>When accessing <code>1.2.3.4<\/code> you will be making requests from a different subnet than <code>1.2.3.0\/24<\/code> and expecting a response. The node that is currently the master for the issued MetalLB address <code>1.2.3.4<\/code>will receive a packet from the router <code>1.2.3.1<\/code>, but the response must definitely go back the same way, through <code>1.2.3.1<\/code>.<\/p>\n<p><\/p>\n<p>Since our node already has a configured default gateway <code>192.168.1.1<\/code>, by default, the response will go to it instead of <code>1.2.3.1<\/code>, through which we received the packet.<\/p>\n<p><\/p>\n<p>How can we handle this situation?<\/p>\n<p><\/p>\n<p>In this case, you need to prepare all your nodes so that they are ready to service external addresses without additional configuration. That is, for the above example, you need to create a VLAN interface on the node in advance:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">ip link add link eth0 name eth0.100 type vlan id 100\nip link set eth0.100 up<\/code><\/pre>\n<p><\/p>\n<p>And then add the routes:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">ip route add 1.2.3.0\/24 dev eth0.100 table 100\nip route add default via 1.2.3.1 table 100<\/code><\/pre>\n<p><\/p>\n<p>Note that we are adding routes to a separate routing table <code>100<\/code> it will contain only two routes necessary for sending the response packet through the gateway <code>1.2.3.1<\/code>, which is behind the interface <code>eth0.100<\/code>.<\/p>\n<p><\/p>\n<p>Now we need to add a simple rule:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">ip rule add from 1.2.3.0\/24 lookup 100<\/code><\/pre>\n<p><\/p>\n<p>which explicitly states: if the source address of the packet is in <code>1.2.3.0\/24<\/code>, then the routing table should be used. <code>100<\/code>It describes a route that will send it through <code>1.2.3.1<\/code><\/p>\n<p><\/p>\n<h1 id=\"sluchay-4-kogda-ponadobitsya-policy-based-routing\">Case 4: When policy-based routing is needed<\/h1>\n<p><\/p>\n<p>The network topology is the same as in the previous example, but let's say you also want the ability to access external addresses from the pool <code>1.2.3.0\/24<\/code> of your pods:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Fine-tuning routing for MetalLB in L2 mode.\" src=\"\/wp-content\/uploads\/2020\/05\/46f1f7c2826d87ec1fe8499862ccdd1a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>The peculiarity is that when accessing any address in <code>1.2.3.0\/24<\/code>, the response packet arriving at the node, with the source address in the range <code>1.2.3.0\/24<\/code> , will obediently be sent to <code>eth0.100<\/code>, but we want Kubernetes to redirect it to our first pod that generated the initial request.<\/p>\n<p><\/p>\n<p>Solving this problem turned out to be difficult, but it became possible thanks to policy-based routing:<\/p>\n<p><\/p>\n<p>To better understand the process, here\u2019s a netfilter block diagram:<br \/>\n<img decoding=\"async\" alt=\"Fine-tuning routing for MetalLB in L2 mode.\" src=\"\/wp-content\/uploads\/2020\/05\/6b2f117c2dcddad85190156d566231c8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>First, as in the previous example, we will create an additional routing table:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">ip route add 1.2.3.0\/24 dev eth0.100 table 100\nip route add default via 1.2.3.1 table 100<\/code><\/pre>\n<p><\/p>\n<p>Now let's add several rules in iptables:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">iptables -t mangle -A PREROUTING -i eth0.100 -j CONNMARK --set-mark 0x100\niptables -t mangle -A PREROUTING  -j CONNMARK --restore-mark\niptables -t mangle -A PREROUTING -m mark ! --mark 0 -j RETURN\niptables -t mangle -A POSTROUTING -j CONNMARK --save-mark<\/code><\/pre>\n<p><\/p>\n<p>These rules will mark incoming connections on the interface <code>eth0.100<\/code>, tagging all packets with the tag <code>0x100<\/code>, this same tag will be assigned to the responses within the same connection.<\/p>\n<p><\/p>\n<p>Now we can add a routing rule:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">ip rule add from 1.2.3.0\/24 fwmark 0x100 lookup 100<\/code><\/pre>\n<p><\/p>\n<p>That is, all packets with the source address <code>1.2.3.0\/24<\/code> and the tag <code>0x100<\/code> should be routed using the table <code>100<\/code>.<\/p>\n<p><\/p>\n<p>Thus, other packets received on a different interface will not fall under this rule, allowing them to be routed by standard Kubernetes methods.<\/p>\n<p><\/p>\n<p>There\u2019s another issue, in Linux there is a so-called reverse path filter, which creates problems as it performs a simple check: for all incoming packets, it changes the source address of the packet to that of the sender and checks if the packet can leave through the same interface it was received on; if not, it filters it out.<\/p>\n<p><\/p>\n<p>The problem is that in our case it will not operate correctly, but we can disable it:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">echo 0 &gt; \/proc\/sys\/net\/ipv4\/conf\/all\/rp_filter\necho 0 &gt; \/proc\/sys\/net\/ipv4\/conf\/eth0.100\/rp_filter<\/code><\/pre>\n<p><\/p>\n<p>Note that the first command controls the global behavior of rp_filter; if it is not disabled, the second command will have no effect. However, other interfaces will remain with rp_filter enabled.<\/p>\n<p><\/p>\n<p>To avoid completely restricting the filter's functionality, we can use the rp_filter implementation for netfilter. By using rpfilter as an iptables module, it's possible to set up quite flexible rules, for example:<\/p>\n<p><\/p>\n<pre><code class=\"bash\">iptables -t raw -A PREROUTING -i eth0.100 -d 1.2.3.0\/24 -j RETURN\niptables -t raw -A PREROUTING -i eth0.100 -m rpfilter --invert -j DROP<\/code><\/pre>\n<p><\/p>\n<p>enable rp_filter on the interface <code>eth0.100<\/code> for all addresses except <code>1.2.3.0\/24<\/code>.<\/p>\n<p>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/501842\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0432\u0435\u0441\u044c\u043c\u0430 \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0449\u0430\u0446\u0438\u0438 \u0434\u043b\u044f MetalLB. \u0412\u0441\u0451 \u0431\u044b \u043d\u0438\u0447\u0435\u0433\u043e, \u0442.\u043a. \u043e\u0431\u044b\u0447\u043d\u043e \u0434\u043b\u044f MetalLB \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439, \u043d\u043e \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u0441 \u0432\u0435\u0441\u044c\u043c\u0430 \u043d\u0435\u0445\u0438\u0442\u0440\u043e\u0439 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 \u0441\u0435\u0442\u0438. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c source-based \u0438 policy-based routing \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0439 \u0441\u0435\u0442\u0438 \u0432\u0430\u0448\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430. \u042f [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":81594,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-81593","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0432\u0435\u0441\u044c\u043c\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/tonkaya-nastrojka-marshrutizaczii-dlya-metallb-v-rezhime-l2\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0422\u043e\u043d\u043a\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f MetalLB \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 L2 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0432\u0435\u0441\u044c\u043c\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/tonkaya-nastrojka-marshrutizaczii-dlya-metallb-v-rezhime-l2\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-05-14T23:42:36+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-05-14T23:42:36+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Fine-tuning routing for MetalLB in L2 mode | ProHoster","description":"Not long ago, I encountered quite a few.","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/tonkaya-nastrojka-marshrutizaczii-dlya-metallb-v-rezhime-l2","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0422\u043e\u043d\u043a\u0430\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f MetalLB \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 L2 | ProHoster","og:description":"\u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f \u0441 \u0432\u0435\u0441\u044c\u043c\u0430.","og:url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/tonkaya-nastrojka-marshrutizaczii-dlya-metallb-v-rezhime-l2","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-05-14T23:42:36+00:00","article:modified_time":"2020-05-14T23:42:36+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"81593","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 15:55:42","updated":"2026-02-08 20:23:59","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/81593","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=81593"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/81593\/revisions"}],"predecessor-version":[{"id":157857,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/81593\/revisions\/157857"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media\/81594"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=81593"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=81593"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=81593"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}