{"id":256,"date":"2019-08-05T16:43:47","date_gmt":"2019-08-05T23:43:47","guid":{"rendered":"http:\/\/blog.nillsf.com\/?p=256"},"modified":"2019-08-18T20:13:57","modified_gmt":"2019-08-19T03:13:57","slug":"ckad-series-part-6-pod-design","status":"publish","type":"post","link":"https:\/\/blog.nillsf.com\/index.php\/2019\/08\/05\/ckad-series-part-6-pod-design\/","title":{"rendered":"CKAD series part 6: Pod Design"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">This is part 5 in a multi-series on my CKAD study efforts. You can find previous entries 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\/18\/ckad-series-part-7-services-and-networking\/\">Part 7: Networking<\/a>  <\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In part 6, we&#8217;re diving into Pod Design, specifically these 4 topics:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Understand how to use Labels, Selectors, and Annotations<\/li><li>Understand Deployments and how to perform rolling updates<\/li><li>Understand Deployments and how to perform rollbacks<\/li><li>Understand Jobs and CronJobs<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">If you remember, we discussed Labels, Selectors and Annotations back in <a href=\"https:\/\/blog.nillsf.com\/index.php\/2019\/07\/11\/ckad-series-part-2-core-concepts\/\">part 2<\/a>, so we&#8217;ll skip that topic in this part of the series. Hence, we&#8217;ll get started with deployments, and how to perform rolling updates. Let&#8217;s get started.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Understand Deployments and how to perform rolling updates<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Up to this point in the series, we&#8217;ve been primarily using pods to deploy our containers. In a production system however, you rarely deploy an individual pod &#8211; you are more likely to deploy a Deployment. With using deployments, you describe your target state in the deployment &#8211; and the deployment controller will ensure this target state is reflected in the cluster.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s quickly demonstrate why you would want a deployment, before we create one and do a rolling update.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s start with a basic Nginx pod.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: Pod\nmetadata:\n  name: simplepod\nspec:\n  containers:\n  - name: web-server\n    image: nginx<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Once we create this pod (<code>kubectl create -f simplepod.yaml<\/code>) , we can see it running using a <code>kubectl get pods<\/code>. Let&#8217;s now try to update our pod, so it contains a volumeMount:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: Pod\nmetadata:\n  name: simplepod\nspec:\n  containers:\n  - name: web-server\n    image: nginx\n    volumeMounts:\n      - name: html\n        mountPath: \/var\/www\n  volumes:  \n  - name: html\n    emptyDir: {}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can update our kubernetes items using <code>kubectl apply -f simplepod.yaml<\/code>. This will give us an error however:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>The Pod \"simplepod\" is invalid: spec: Forbidden: pod updates may not change fields other than `spec.containers[*].image`, `spec.initContainers[*].image`, `spec.activeDeadlineSeconds` or `spec.tolerations` (only additions to existing tolerations)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This would mean we need to delete our pod first and then recreate it. Hence the value of a deployment. With a deployment, you update your deployment (your new target state) and the kubernetes system will get you there. Kubernetes will delete the pods that need to be deleted, and create your new ones. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s try this out with our nginx example, while creating a deployment instead of a pod.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: nginx\n  labels:\n    run: nginx\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      run: nginx\n  template:\n    metadata:\n      labels:\n        run: nginx\n    spec:\n      containers:\n      - image: nginx\n        name: nginx\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can create this using <code>kubectl create -f deploynginx.yaml<\/code>. This will create a deployment for us, as well as a replicaset and finally our pods. We can see all three:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get deployments\nNAME    READY   UP-TO-DATE   AVAILABLE   AGE\nnginx   1\/1     1            1           79s\nkubectl get replicaset\nNAME               DESIRED   CURRENT   READY   AGE\nnginx-7db9fccd9b   1         1         1       82s\nkubectl get pods\nNAME                     READY   STATUS    RESTARTS   AGE\nnginx-7db9fccd9b-t2w6d   1\/1     Running   0          85s\nsimplepod                1\/1     Running   0          9m36s<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can then do our update to our deployment, adding the volumemount.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: nginx\n  labels:\n    run: nginx\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      run: nginx\n  template:\n    metadata:\n      labels:\n        run: nginx\n    spec:\n      containers:\n      - image: nginx\n        name: nginx\n        volumeMounts:\n        - name: html\n          mountPath: \/var\/wwws\n      volumes:  \n      - name: html\n        emptyDir: {}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And we can update this using <code>kubectl apply -f deploynginx.yaml<\/code>. To see the real fun in action, I would recommend to do a <code>kubectl get pods --watch<\/code> in a seperate terminal before doing the updated deployment, to see the fun in action.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods --watch\nNAME                     READY   STATUS    RESTARTS   AGE\nnginx-7db9fccd9b-t2w6d   1\/1     Running   0          3m26s\nsimplepod                1\/1     Running   0          11m\nnginx-5b87b8796b-hsbv5   0\/1     Pending   0          0s\nnginx-5b87b8796b-hsbv5   0\/1     Pending   0          0s\nnginx-5b87b8796b-hsbv5   0\/1     ContainerCreating   0          0s\nnginx-5b87b8796b-hsbv5   1\/1     Running             0          4s\nnginx-7db9fccd9b-t2w6d   1\/1     Terminating         0          3m36s\nnginx-7db9fccd9b-t2w6d   0\/1     Terminating         0          3m38s\nnginx-7db9fccd9b-t2w6d   0\/1     Terminating         0          3m49s\nnginx-7db9fccd9b-t2w6d   0\/1     Terminating         0          3m49s<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As you can see, the deployment created a new pod for us, and once that new pod was running, terminated our old one. This is a rolling update within Kubernetes. Let&#8217;s play around with this some more, shall we? <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s scale our deployment from 1 pod to 12 pods. We can do this by either editing the yaml and doing a new apply &#8211; we could do a <code>kubectl edit deployment nginx<\/code> &#8211; or, because we&#8217;re scaling, we can do this one other way:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl scale deployment\/nginx --replicas=12\nkubectl rollout status deployment\/nginx --watch #to see the updates of the rollout\nWaiting for deployment \"nginx\" rollout to finish: 1 of 12 updated replicas are available...\nWaiting for deployment \"nginx\" rollout to finish: 2 of 12 updated replicas are available...\nWaiting for deployment \"nginx\" rollout to finish: 3 of 12 updated replicas are available...\nWaiting for deployment \"nginx\" rollout to finish: 4 of 12 updated replicas are available...\nWaiting for deployment \"nginx\" rollout to finish: 5 of 12 updated replicas are available...\nWaiting for deployment \"nginx\" rollout to finish: 6 of 12 updated replicas are available...\nWaiting for deployment \"nginx\" rollout to finish: 7 of 12 updated replicas are available...\nWaiting for deployment \"nginx\" rollout to finish: 8 of 12 updated replicas are available...\nWaiting for deployment \"nginx\" rollout to finish: 9 of 12 updated replicas are available...\nWaiting for deployment \"nginx\" rollout to finish: 10 of 12 updated replicas are available...\nWaiting for deployment \"nginx\" rollout to finish: 11 of 12 updated replicas are available...\ndeployment \"nginx\" successfully rolled out<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you also did a watch on kubectl get pods, you will have noticed that no single pod was terminated this time. This is because we just scaled our replicaset from 1 to 12 &#8211; and didn&#8217;t in fact change our pod. Let&#8217;s now do a change to our pod design, for instance change from nginx to apache (httpd). Open your yaml file, edit the image to httpd and the replicacount to 12, and then apply the deployment again:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl apply -f deploynginx.yaml; kubectl rollout status deployment\/nginx --watch<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As you can see in the watching of the rollout status (even better if you watch the kubectl get pods), kubernetes doesn&#8217;t update all 12 replicas at the same time. It does so seemingly in batches of pods, creating new ones and then terminating a couple of old ones, and doing so until all 12 are created.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In your deployment configuration, there is a RollingUpdateStrategy; which informs the Deployment Controller how much pods may be unavailable and how much surge is allowed. This is why you see (certainly in the <code>kubectl get pods<\/code>) that pods get terminated in batches, not all at once. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Understand Deployments and how to perform rollbacks<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ve done a couple of deployments now, and kubernetes actually keeps a history of our deployments. You can see this via:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl rollout history deploy\/nginx\ndeployment.extensions\/nginx\nREVISION  CHANGE-CAUSE\n1         &lt;none>\n2         &lt;none>\n3         &lt;none><\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Because we&#8217;ve been mainly playing around and we haven&#8217;t really paid attention to our change-cause, this is empty thus far. Let&#8217;s try to get some actual history in there. One option to get history in the rollout, is to use the<code> --record<\/code> flag when doing the update:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl scale deploy nginx --replicas=6 --record<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Another option is to use an annotation in our deployment file, such as here:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: nginx\n  labels:\n    run: nginx\n  annotations: \n    kubernetes.io\/change-cause: I wanted a better deployment\nspec:\n  replicas: 4\n  selector:\n    matchLabels:\n      run: nginx\n  template:\n    metadata:\n      labels:\n        run: nginx\n    spec:\n      containers:\n      - image: nginx\n        name: nginx\n        volumeMounts:\n        - name: html\n          mountPath: \/var\/www\n      volumes:  \n      - name: html\n        emptyDir: {}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now we actually see some more history in our rollout history:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl rollout history  deploy\/nginx\ndeployment.extensions\/nginx\nREVISION  CHANGE-CAUSE\n1         &lt;none>\n3         &lt;none>\n4         kubectl scale deploy nginx --replicas=6 --record=true\n5         I wanted a better deployment<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And from here, we can safely roll back. Let&#8217;s do a simple rollback first:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl rollout undo deploy\/nginx #this will undo the latest change\nkubectl rollout history deploy\/nginx\ndeployment.extensions\/nginx\nREVISION  CHANGE-CAUSE\n1         &lt;none>\n3         &lt;none>\n5         I wanted a better deployment\n6         kubectl scale deploy nginx --replicas=6 --record=true<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As you can see here, we went back from revision 5 to revision 4. However, Kubernetes will always increment the revision counter. Let&#8217;s describe our deployment to see some more details:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl describe deploy\/nginx\nName:                   nginx\nNamespace:              deployments\nCreationTimestamp:      Sun, 04 Aug 2019 15:02:23 -0700\nLabels:                 run=nginx\nAnnotations:            <strong>deployment.kubernetes.io\/revision: 6<\/strong>\n                        kubectl.kubernetes.io\/last-applied-configuration:\n                          {\"apiVersion\":\"apps\/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{\"kubernetes.io\/change-cause\":\"<strong>I wanted a better deployment\"<\/strong>},\"label...\n                        <strong>kubernetes.io\/change-cause: kubectl scale deploy nginx --replicas=6 --record=true<\/strong>\nSelector:               run=nginx\nReplicas:               4 desired | 4 updated | 4 total | 4 available | 0 unavailable\nStrategyType:           RollingUpdate\nMinReadySeconds:        0\nRollingUpdateStrategy:  25% max unavailable, 25% max surge\n(...)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You can see the deployment counter in the annotations, as well as the last-applied-configuration (which contained our annotation message). We can also roll back to a more ancient revision. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl rollout undo deploy\/nginx --to-revision=1\nkubectl rollout history deploy\/nginx\ndeployment.extensions\/nginx\nREVISION  CHANGE-CAUSE\n3         &lt;none>\n5         I wanted a better deployment\n6         kubectl scale deploy nginx --replicas=6 --record=true\n7         &lt;none><\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now our we&#8217;re back to our first revision, which has become our seventh revision now. This is an easy mechanism to quickly rollback to a known working state. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Understand Jobs and CronJobs<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/workloads\/controllers\/jobs-run-to-completion\/\">Jobs <\/a>are another way to create &#8220;managed&#8221; pods. A job will create one of more pods to finish a certain body of work. By using a job, you can ensure the successful completion of the work.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/workloads\/controllers\/cron-jobs\/\">A Cron Job<\/a> is a job that runs on a schedule. This is very useful to schedule periodic and recurring jobs. Examples could be taking backups or certain system management tasks (shutting down dev clusters?). <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As an example job (this is the same example as on the kubernetes docs), let&#8217;s try to calculate pi:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: batch\/v1\nkind: Job\nmetadata:\n  name: pi\nspec:\n  template:\n    spec:\n      containers:\n      - name: pi\n        image: perl\n        command: [\"perl\",  \"-Mbignum=bpi\", \"-wle\", \"print bpi(2000)\"]\n      restartPolicy: Never\n  backoffLimit: 4<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As usual, we can create this using <code>kubectl create -f pijob.yaml<\/code>. Let&#8217;s follow our pods using <code>kubectl get pods --watch<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME                     READY   STATUS              RESTARTS   AGE     \npi-vpx8r                 0\/1     ContainerCreating   0          6s                                                                                    pi-vpx8r                 1\/1     Running             0          33s                                                                                   pi-vpx8r                 0\/1     Completed           0          40s<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can see the pod is completed, and as long we don&#8217;t delete the job, the container will remain available. We can get the outcome from our calculation via <code>kubectl logs pi-vpx8r40s<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can automate jobs via Cronjobs. Cronjobs in kubernetes are similar to cronjobs in Linux, they even use the same scheduling syntax. If you&#8217;re not familiar with that, let me share the scheduling syntax:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># .---------------- minute (0 - 59)\n# |  .------------- hour (0 - 23)\n# |  |  .---------- day of month (1 - 31)\n# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...\n# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat\n# |  |  |  |  |\n# *  *  *  *  * <\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s also look into an example of a Cronjob (again, the example from the kubernetes docs). <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: batch\/v1beta1\nkind: CronJob\nmetadata:\n  name: hello\nspec:\n  schedule: \"*\/1 * * * *\"\n  jobTemplate:\n    spec:\n      template:\n        spec:\n          containers:\n          - name: hello\n            image: busybox\n            args:\n            - \/bin\/sh\n            - -c\n            - date; echo Hello from the Kubernetes cluster\n          restartPolicy: OnFailure<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This CronJob will run every minute and will do a simple echo. Let&#8217;s create this using <code>kubectl create -f cronjob.yaml<\/code> and see what this looks like. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We can see a couple of interesting things here. In the <code>kubectl get pods --watch<\/code>, we can see pods getting created and completed. You can see that the pod names are all unique:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>hello-1565047320-bbqq9   0\/1     Pending   0          0s                                                                                              hello-1565047320-bbqq9   0\/1     Pending   0          0s                                                                                              hello-1565047320-bbqq9   0\/1     ContainerCreating   0          0s                                                                                    hello-1565047320-bbqq9   0\/1     Completed           0          4s                                                                                    hello-1565047380-jw7mz   0\/1     Pending             0          0s                                                                                    hello-1565047380-jw7mz   0\/1     Pending             0          0s                                                                                    hello-1565047380-jw7mz   0\/1     ContainerCreating   0          0s                                                                                    hello-1565047380-jw7mz   0\/1     Completed           0          3s  <\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The uniqueness in the pod names is that middle number. That looks like an epoch to me, and this can be converted into a human readable time. That&#8217;s a neat detail.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"905\" height=\"270\" src=\"\/wp-content\/uploads\/2019\/08\/2019-08-05-16_27_33-Epoch-Converter-Unix-Timestamp-Converter-and-3-more-pages-Microsoft-Edge.jpg\" alt=\"\" class=\"wp-image-258\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/2019-08-05-16_27_33-Epoch-Converter-Unix-Timestamp-Converter-and-3-more-pages-Microsoft-Edge.jpg 905w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/2019-08-05-16_27_33-Epoch-Converter-Unix-Timestamp-Converter-and-3-more-pages-Microsoft-Edge-300x90.jpg 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2019\/08\/2019-08-05-16_27_33-Epoch-Converter-Unix-Timestamp-Converter-and-3-more-pages-Microsoft-Edge-768x229.jpg 768w\" sizes=\"auto, (max-width: 905px) 100vw, 905px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We can also have a look at the evolution of the jobs itself. <code>kubectl get jobs --watch<\/code> gives us some detail here.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>hello-1565047320   0\/1                      0s                                                                                                        hello-1565047320   0\/1           0s         0s                                                                                                        hello-1565047320   1\/1           5s         4s                                                                                                        hello-1565047380   0\/1                      0s                                                                                                        hello-1565047380   0\/1           0s         0s                                                                                                        hello-1565047380   1\/1           4s         3s <\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can see that our podname is just the job-name plus a random string at the end. The epoch is appended to our jobname. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In this part of the CKAD series we dove into deployments and jobs. Let&#8217;s stop creating individual pods from now on, and only create deployments or jobs. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Two more topics remaining, we&#8217;re almost at the finish!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is part 5 in a multi-series on my CKAD study efforts. You can find previous entries 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 7: Networking In part 6, we&#8217;re diving into Pod Design, specifically these 4 [&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],"tags":[19,17,18],"class_list":["post-256","post","type-post","status-publish","format-standard","hentry","category-ckad","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\/256","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=256"}],"version-history":[{"count":4,"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/256\/revisions"}],"predecessor-version":[{"id":297,"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/256\/revisions\/297"}],"wp:attachment":[{"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/media?parent=256"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/categories?post=256"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.nillsf.com\/index.php\/wp-json\/wp\/v2\/tags?post=256"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}