{"id":262,"date":"2019-08-18T20:10:39","date_gmt":"2019-08-19T03:10:39","guid":{"rendered":"http:\/\/blog.nillsf.com\/?p=262"},"modified":"2019-08-18T20:10:49","modified_gmt":"2019-08-19T03:10:49","slug":"ckad-series-part-7-services-and-networking","status":"publish","type":"post","link":"https:\/\/blog.nillsf.com\/index.php\/2019\/08\/18\/ckad-series-part-7-services-and-networking\/","title":{"rendered":"CKAD series part 7: Services and Networking"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">This is part 7 in a series of blog posts covering my learning experience for the CKAD exam. You can find the other parts in the series here:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/blog.nillsf.com\/index.php\/2019\/07\/09\/ckad-series-part-1-intro-exam-topics-my-study-plan\/\">Part 1: intro, exam topics and my study plan<\/a> <\/li><li><a href=\"https:\/\/blog.nillsf.com\/index.php\/2019\/07\/11\/ckad-series-part-2-core-concepts\/\">Part 2: Core concepts<\/a><\/li><li><a href=\"https:\/\/blog.nillsf.com\/index.php\/2019\/07\/21\/ckad-series-part-3-configuration\/\">Part 3: Configuration <\/a><\/li><li><a href=\"https:\/\/blog.nillsf.com\/index.php\/2019\/07\/28\/ckad-series-part-4-multi-container-pods\/\">Part 4: Multi-container pods<\/a><\/li><li><a href=\"https:\/\/blog.nillsf.com\/index.php\/2019\/08\/01\/ckad-part-5-observability\/\">Part 5: Observability<\/a><\/li><li><a href=\"https:\/\/blog.nillsf.com\/index.php\/2019\/08\/05\/ckad-series-part-6-pod-design\/\">Part 6: Pod Design<\/a><\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">After <a href=\"https:\/\/blog.nillsf.com\/index.php\/2019\/08\/14\/a-quick-look-at-the-ballerina-language\/\">a quick look at Ballerina<\/a> earlier this week, let&#8217;s start our sprint towards the end of the CKAD series! In this part we&#8217;ll touch on Services and Networking, specifically covering these two exam objectives:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Understand Services<\/li><li>Demonstrate basic understanding of NetworkPolicies<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A special note on NetworkPolicies: There is an <a href=\"https:\/\/github.com\/Azure\/AKS\/issues\/1158\">inconsistency<\/a> between Azure and Calico NetworkPolicies on AKS. I have a <a href=\"https:\/\/blog.nillsf.com\/?p=281\">seperate post<\/a> explaining the troubleshooting I did to figure that out. I believe Calico to be implemented correctly, and that&#8217;s what I&#8217;ll describe in this post.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But, let&#8217;s start with Services. We&#8217;ve used Services a couple of times before, but let&#8217;s cover the topic a little more in depth now.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Understand Services<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/service\/\">service<\/a> within kubernetes is a way to expose applications. This can either be exposing them within the cluster or to the outside world. A service name will also act as a DNS record.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So why would we need services? Why not just send traffic straight to our pods? There&#8217;s a couple of reasons you don&#8217;t want to do that: first and foremost, pods are ephemeral, meaning pods can dynamically be rescheduled on new hosts, or could even be deleted and recreated when you update a deployment. A second reason is that &#8211; depending on your networking model &#8211; your pods might only be reachable within the cluster. The default networking in Kubernetes is kubenet, which is an overlay on top of a physical network. This means, outside actors cannot reach your pods.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Enter services with a solution. A service acts as a network abstraction on top of your pods. A service is both a DNS record and an IP address; and has a port assigned to it. When you communicate to a service, you communicate to the service IP on the service port, which will be translated to a pod (load balanced) and the ports actual port. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are 4 types of services:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>ClusterIP<\/strong>: exposes your service on an IP that is available within the cluster.<\/li><li><strong>NodePort<\/strong>: this makes a port on each nodes IP address translate those connections to your service.<\/li><li><strong>LoadBalancer<\/strong>: this will manage an external load balancer (typically a cloud provider&#8217;s load balancer). This will (in the backend) create a clusterIP and a NodePort as well. <\/li><li><strong>ExternalName<\/strong>: this maps the service name to an CNAME. <\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Note that there are 3 ports in play end the end:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Port<\/strong>: The port the service will be listening on;<\/li><li><strong>NodePort<\/strong>: A port on each node that translates connections to your service;<\/li><li><strong>TargetPort<\/strong>: The port your pods are listening on.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Now that we&#8217;ve done this, let&#8217;s play around with services a bit. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s start off with a simple nginx deployment:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: nginx-deployment\n  labels:\n    app: nginx\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: nginx\n  template:\n    metadata:\n      labels:\n        app: nginx\n    spec:\n      containers:\n      - name: nginx\n        image: nginx\n        ports:\n        - containerPort: 80<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As usual, we can create this via <code>kubectl create -f nginx-deploy.yaml<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s now create a ClusterIP service to connect to our nginx. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: Service\nmetadata:\n  name: clusterip-service\nspec:\n  type: ClusterIP\n  selector:\n    app: nginx\n  ports:\n    - protocol: TCP\n      port: 8080\n      targetPort: 80<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once created, we can see our service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl create -f service.yaml\nkubectl get service                                                                                                       NAME                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE\nclusterip-service   ClusterIP   10.0.197.167   &lt;none>        8080\/TCP   3s<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And from within the cluster, we should be able to connect to our service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl run -i --tty busybox-shell --image=busybox -- sh\nwget 10.0.197.167:8080\n#or even fancier, use the service name, which is a DNS record:\nwget clusterip-service:8080<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">But we won&#8217;t be able to connect to this from the outside. For this, we&#8217;ll create a new service with the type Load Balancer:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: Service\nmetadata:\n  name: lb-service\nspec:\n  type: LoadBalancer\n  selector:\n    app: nginx\n  ports:\n    - protocol: TCP\n      port: 8080\n      targetPort: 80<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can also create this service, which will take a bit longer as an external load balancer will need to be created:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl create -f service-lb.yaml\nkubectl get service --watch\nNAME                TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE\nclusterip-service   ClusterIP      10.0.197.167   &lt;none>        8080\/TCP         11m\nlb-service          LoadBalancer   10.0.21.91     &lt;pending>     8080:30529\/TCP   18s\nlb-service          LoadBalancer   10.0.21.91     52.183.89.108   8080:30529\/TCP   40s<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now we should be able to connect to our service on that IP, right from our web browser:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"521\" height=\"287\" src=\"\/wp-content\/uploads\/2019\/08\/image-1.png\" alt=\"\" class=\"wp-image-264\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-1.png 521w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-1-300x165.png 300w\" sizes=\"auto, (max-width: 521px) 100vw, 521px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Demonstrate basic understanding of NetworkPolicies<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">By default, all traffic in a kubernetes cluster can flow unrestricted. Even pods in different namespaces can communicate with each other. <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/network-policies\/\">NetworkPolicies <\/a>allow you restrict traffic to only the traffic flows you actually want to allow. NetworkPolicies work on a allow-list, meaning that once a NetworkPolicy is applied to a pod all traffic is denied by default and only allowed traffic will flow.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Within a NetworkPolicy you define which traffic can flow from a certain source to a certain destination. Sources and destinations can either be IP addresses or ranges or can be pods within your cluster. You define which pods with the right selectors. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>If you are planning &#8211; like me &#8211; to run this example on an Azure Kubernetes Cluster, make sure your cluster is enabled for Network Policies. They aren&#8217;t by default. You&#8217;ll want to add the <code>--networkpolicy calico <\/code>flag to your <code>az aks create<\/code>. It cannot be applied after a cluster has already been created.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s build a simple example to demonstrate how NetworkPolicies work. We&#8217;ll create 4 pods within the same namespace. 2 busybox-curl pods, 1 with a trusted label, 1 without a trusted label and 2 nginx web servers, both with label app=web, and 1 with label env=dev and the other with label env=prod.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"608\" src=\"\/wp-content\/uploads\/2019\/08\/image-7-1024x608.png\" alt=\"\" class=\"wp-image-279\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-7-1024x608.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-7-300x178.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-7-768x456.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-7.png 1098w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>My wrong interpretation of Kubernetes NetworkPolicies.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s create a new namespace for our networking work, and set it as the default for our kubectl:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl create ns networking\nkubectl config set-context $(kubectl config current-context) --namespace=networking<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">By now I expect you&#8217;d be able to create the YAML for these pods, so try to write this yourself before checking mine:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: Pod\nmetadata:\n  name: busybox-curl-1\n  labels:\n    trusted: \"yes\"\nspec:\n  containers:\n  - name: busybox\n    image: yauritux\/busybox-curl\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  name: busybox-curl-2\nspec:\n  containers:\n  - name: busybox\n    image: yauritux\/busybox-curl\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  name: nginx-dev\n  labels:\n    app: \"web\"\n    env: \"dev\"\nspec:\n  containers:\n  - name: nginx\n    image: nginx\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  name: nginx-prod\n  labels:\n    app: \"web\"\n    env: \"prod\"\nspec:\n  containers:\n  - name: nginx\n    image: nginx<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can create this with <code>kubectl create -f pods.yaml<\/code>. Let&#8217;s get the IPs of our Nginx servers &#8211; and try if we can connect to both from both our busyboxes:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods -o wide #remember the ip addresses of both your nginx boxes\nkubectl exec -it busybox-curl-1 sh\ncurl *ip1*\ncurl *ip2*\n#both curls should give you the nginx default page\nexit #to go to our next busybox\nkubectl exec -it busybox-curl-2 sh\ncurl *ip1*\ncurl *ip2*\n#both curls should give you the nginx default page<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If your results are the same as mine, all traffic flows, from both busyboxes to both nginx servers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s now define our first NetworkPolicy, which will allow traffic only from busyboxes with the label trusted=true. This will look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: networking.k8s.io\/v1\nkind: NetworkPolicy\nmetadata:\n  name: policy1-allow-trusted-busybox\nspec:\n  podSelector:\n    matchLabels:\n      app: web\n  policyTypes:\n  - Ingress\n  ingress:\n  - from:\n    - podSelector:\n        matchLabels:\n          trusted: \"yes\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can deploy this policy with <code>kubectl create -f policy1.yaml<\/code>. Creating this policy has no impact on the running pods (they remain up and running) but will impact network network almost instantly. Let&#8217;s test it out:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods -o wide #remember the ip addresses of both your nginx boxes\nkubectl exec -it busybox-curl-1 sh\ncurl *ip1*\ncurl *ip2*\n#both curls should give you the nginx default page\nexit #to go to our next busybox\nkubectl exec -it busybox-curl-2 sh\ncurl *ip1*\ncurl *ip2*\n#these two curls should fail, as the busybox-curl-2 doesn't have the trusted label<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s now also deploy our second policy, which will limit egress traffic from our trusted busybox, only to the dev environment. This policy looks like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: networking.k8s.io\/v1\nkind: NetworkPolicy\nmetadata:\n  name: policy2-allow-to-dev\nspec:\n  podSelector:\n    matchLabels:\n      trusted: \"yes\"\n  policyTypes:\n  - Egress\n  egress:\n  - to:\n    - podSelector:\n        matchLabels:\n          env: dev<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s create this policy as well, and see what the effect is. <code>kubectl create -f policy2.yaml<\/code> <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods -o wide #remember the ip addresses of both your nginx boxes\nkubectl exec -it busybox-curl-1 sh\ncurl *nginxdev* #yes it still works\ncurl *ip2* #still no longer works<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">That was cool. Let&#8217;s make our experiment a little more complex by adding two new nginx pods: one with the label <code>env=dev<\/code> (but no longer the app label, so policy1 doesn&#8217;t apply) &#8211; and one with the label <code>trusted=yes<\/code>. And then it&#8217;ll be our job to figure out which traffic flows are allowed in our experiment, those new arrows are the purple arrows in our drawing below:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"739\" src=\"\/wp-content\/uploads\/2019\/08\/image-11-1024x739.png\" alt=\"\" class=\"wp-image-287\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-11-1024x739.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-11-300x217.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-11-768x554.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-11.png 1169w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Adding two new pods to our experiment, and trying to figure out which arrows can flow and which can&#8217;t.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The following YAML will create our new pods:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: Pod\nmetadata:\n  name: nginx-dev-noapp\n  labels:\n    env: \"dev\"\nspec:\n  containers:\n  - name: nginx\n    image: nginx\n---\napiVersion: v1\nkind: Pod\nmetadata:\n  name: nginx-trusted-yes\n  labels:\n    trusted: \"yes\"\nspec:\n  containers:\n  - name: nginx\n    image: nginx<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s start with the two arrows going from busybox-curl-1:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods -o wide #remember the ip addresses\nkubectl exec -it busybox-curl-1 sh\ncurl *nginx-dev-noapp* #this works, as expected. Allowed by the egress policy and there is no ingress to block anything\ncurl *nginx-trusted-yes* #this doesn't work, as expected. Blocked by the egress policy, which doesn't allow traffic to trusted=yes<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s do the same for busybox-curl-2:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods -o wide #remember the ip addresses\nkubectl exec -it busybox-curl-2 sh\ncurl *nginx-dev-noapp* #this works, as there is no policy blocking anything\ncurl *nginx-trusted-yes* #this works, as there is no policy blocking anything. trusted=yes has a policy, but only egress, not ingress<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This will make our picture look like this:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"743\" src=\"\/wp-content\/uploads\/2019\/08\/image-13-1024x743.png\" alt=\"\" class=\"wp-image-290\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-13-1024x743.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-13-300x218.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-13-768x557.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/image-13.png 1171w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Our final picture with the additional pods. <\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusion of the working of NetworkPolicy (<em>using Calico)<\/em><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ve deployed a couple of NetworkPolicies now, and I hope you have the same understanding as I do:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>If there are no policies, all traffic is allowed.<\/li><li>If there is only a ingress policy, traffic from the sources mentioned in the ingress policy is allowed.<\/li><li>If there is only a egress policy, traffic from to the destinations mentioned in the egress policy is allowed.<\/li><li>If there is a combination of ingress and egress policies, only traffic allowed by both will be allowed. <\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this part we repeated some of our work with Services on which we touched earlier. We also took a look into NetworkPolicies. For those of you interested in the ramblings of a mad man looking for answers, I have a <a href=\"https:\/\/blog.nillsf.com\/?p=281\">seperate post<\/a> explaining some of the troubleshooting I went through to figure out something was broken was Azure NetworkPolicies.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is part 7 in a series of blog posts covering my learning experience for the CKAD exam. You can find the other parts in the series here: Part 1: intro, exam topics and my study plan Part 2: Core concepts Part 3: Configuration Part 4: Multi-container pods Part 5: Observability Part 6: Pod Design [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[20,5],"tags":[19,17,18],"class_list":["post-262","post","type-post","status-publish","format-standard","hentry","category-ckad","category-open-source","tag-certification","tag-ckad","tag-kubernetes"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/262","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/comments?post=262"}],"version-history":[{"count":4,"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/262\/revisions"}],"predecessor-version":[{"id":291,"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/262\/revisions\/291"}],"wp:attachment":[{"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/media?parent=262"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/categories?post=262"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/tags?post=262"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}