{"id":78,"date":"2018-10-17T03:23:57","date_gmt":"2018-10-17T03:23:57","guid":{"rendered":"https:\/\/www.appservgrid.com\/paw92\/index.php\/2018\/10\/17\/set-up-a-ci-cd-pipeline-with-a-jenkins-pod-in-kubernetes-part-2-linux-com\/"},"modified":"2018-10-17T03:23:57","modified_gmt":"2018-10-17T03:23:57","slug":"set-up-a-ci-cd-pipeline-with-a-jenkins-pod-in-kubernetes-part-2-linux-com","status":"publish","type":"post","link":"https:\/\/www.appservgrid.com\/paw92\/index.php\/2018\/10\/17\/set-up-a-ci-cd-pipeline-with-a-jenkins-pod-in-kubernetes-part-2-linux-com\/","title":{"rendered":"Set Up a CI\/CD Pipeline with a Jenkins Pod in Kubernetes (Part 2) | Linux.com"},"content":{"rendered":"<p>In <a href=\"https:\/\/www.linux.com\/blog\/learn\/chapter\/Intro-to-Kubernetes\/2017\/5\/set-cicd-pipeline-kubernetes-part-1-overview\">Part 1<\/a> of our series, we got our local Kubernetes cluster up and running with Docker, Minikube, and kubectl. We set up an image repository, and tried building, pushing, and deploying a container image with code changes we made to the Hello-Kenzan app. It\u2019s now time to automate this process. <\/p>\n<p>In Part 2, we\u2019ll set up continuous delivery for our application by running Jenkins in a pod in Kubernetes. We\u2019ll create a pipeline using a Jenkins 2.0 Pipeline script that automates building our Hello-Kenzan image, pushing it to the registry, and deploying it in Kubernetes. That\u2019s right: we are going to deploy pods from a registry pod using a Jenkins pod. While this may sound like a bit of deployment alchemy, once the infrastructure and application components are all running on Kubernetes, it makes the management of these pieces easy since they\u2019re all under one ecosystem. <\/p>\n<p>With Part 2, we\u2019re laying the last bit of infrastructure we need so that we can run our Kr8sswordz Puzzle in Part 3.<\/p>\n<p><em>Read all the articles in the series:<\/em><\/p>\n<table>\n<tbody>\n<tr>\n<td><img loading=\"lazy\" decoding=\"async\" alt=\"RyHz4CL2OgRH4G8M7BLPxwZ7MMAZh-DpmmEuXBoa\" height=\"20\" src=\"https:\/\/lh6.googleusercontent.com\/RyHz4CL2OgRH4G8M7BLPxwZ7MMAZh-DpmmEuXBoayoTGX7qenHTkyCkH1m3oLIPEVKSxu_FUCtFCXzQz1DzeZIgpS-dyVIaF_-WFlIYyat7x9WtqRPJaLY2XuL938wnO_BqvSfR0\" width=\"20\" \/><\/td>\n<td>\n<p>This tutorial only runs locally in Minikube and will not work on the cloud. You\u2019ll need a computer running an up-to-date version of Linux or macOS. Optimally, it should have 16 GB of RAM. Minimally, it should have 8 GB of RAM. For best performance, reboot your computer and keep the number of running apps to a minimum. <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Creating and Building a Pipeline in Jenkins <\/h2>\n<p>Before you begin, you\u2019ll want to make sure you\u2019ve run through the steps in Part 1, in which we set up our image repository running in a pod (to do so quickly, you can run the <a href=\"https:\/\/docs.google.com\/document\/d\/13kscUdwcIYScZgjAo5TtLpYxHJRDX-P6UIxlRywRSgg\/edit#heading=h.uttahhp9vaq6\">npm part1 automated script detailed below<\/a>). <\/p>\n<p>If you previously stopped Minikube, you\u2019ll need to start it up again. Enter the following terminal command, and wait for the cluster to start:<\/p>\n<p>minikube start<\/p>\n<p>You can check the cluster status and view all the pods that are running. <\/p>\n<p>kubectl cluster-info<\/p>\n<p>kubectl get pods &#8211;all-namespaces<\/p>\n<p>Make sure that the registry pod has a Status of Running. <\/p>\n<p>We are ready to build out our Jenkins infrastructure. <\/p>\n<p>Remember, you don\u2019t actually have to type the commands below\u2014just press Enter at each step and the script will enter the command for you!<\/p>\n<p>1. First, let&#8217;s build the Jenkins image we&#8217;ll use in our Kubernetes cluster. <\/p>\n<p>docker build -t 127.0.0.1:30400\/jenkins:latest <\/p>\n<p> -f applications\/jenkins\/Dockerfile applications\/jenkins<\/p>\n<p>2. Once again we&#8217;ll need to set up the Socat Registry proxy container to push images, so let&#8217;s build it. Feel free to skip this step in case the socat-registry image already exists from Part 1 (to check, run <em>docker images<\/em>). <\/p>\n<p>docker build -t socat-registry -f applications\/socat\/Dockerfile applications\/socat<\/p>\n<p>3. Run the proxy container from the image. <\/p>\n<p>docker stop socat-registry; docker rm socat-registry; <\/p>\n<p> docker run -d -e &#8220;REG_IP=`minikube ip`&#8221; -e &#8220;REG_PORT=30400&#8221; <\/p>\n<p> &#8211;name socat-registry -p 30400:5000 socat-registry<\/p>\n<table>\n<tbody>\n<tr>\n<td><img loading=\"lazy\" decoding=\"async\" alt=\"n-z3awvRgVXCO-QIpllgiqXOWtsTeePM62asXPD5\" height=\"20\" src=\"https:\/\/lh5.googleusercontent.com\/n-z3awvRgVXCO-QIpllgiqXOWtsTeePM62asXPD52Y_VH5ZpEaH4-Op_N_XSh8oa1-VpdlFyk6w97uHnsr1_cafUq6VR7pV68nMc5DG2jj7P1yPNRwoywUE7N9tT2x5ec-mTOsAZ\" width=\"20\" \/><\/td>\n<td>\n<p>This step will fail if local port 30400 is currently in use by another process. You can check if there\u2019s any process currently using this port by running the command<br \/>lsof -i :30400<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>4. With our proxy container up and running, we can now push our Jenkins image to the local repository.<\/p>\n<p>docker push 127.0.0.1:30400\/jenkins:latest<\/p>\n<p>You can see the newly pushed Jenkins image in the registry UI using the following command.<\/p>\n<p>minikube service registry-ui<\/p>\n<p>5. The proxy\u2019s work is done, so you can go ahead and stop it.<\/p>\n<p>docker stop socat-registry<\/p>\n<p>6. Deploy Jenkins, which we\u2019ll use to create our automated CI\/CD pipeline. It will take the pod a minute or two to roll out. <\/p>\n<p>kubectl apply -f manifests\/jenkins.yaml; kubectl rollout status deployment\/jenkins<\/p>\n<p>Inspect all the pods that are running. You\u2019ll see a pod for Jenkins now.<\/p>\n<p>kubectl get pods<\/p>\n<table>\n<tbody>\n<tr>\n<td><img loading=\"lazy\" decoding=\"async\" alt=\"_YIHeGg141vkuJmdJZBO0zN2s3pjLdDMgo5pfQFe\" height=\"20\" src=\"https:\/\/lh5.googleusercontent.com\/_YIHeGg141vkuJmdJZBO0zN2s3pjLdDMgo5pfQFeVBSrLRjOJ4-BuWTD6gd6BTBx7S6Gh3Q2d2lgg2M6Hdq8YX8w239GZkgv0o6XXP9sBNXzX2SgCfPlHTwxrRs2urrwReyQjFPC\" width=\"20\" \/><\/td>\n<td>\n<p>Jenkins as a CD tool needs special rights in order to interact with the Kubernetes cluster, so we\u2019ve setup <a href=\"https:\/\/kubernetes.io\/docs\/reference\/access-authn-authz\/rbac\/\">RBAC<\/a> (Role Based Access Control) authorization for it inside the jenkins.yaml deployment manifest. RBAC consists of a Role, a ServiceAccount and a Binding object that binds the two together. Here\u2019s how we configured Jenkins with these resources:<\/p>\n<p>Role: For simplicity we leveraged the pre-existing ClusterRole &#8220;cluster-admin&#8221; which by default has unlimited access to the cluster. (In a real life scenario you might want to narrow down Jenkins&#8217; access rights by creating a new role with the least privileged PolicyRule.)<\/p>\n<p>ServiceAccount: We created a new ServiceAccount named &#8220;Jenkins\u201d. The property &#8220;automountServiceAccountToken&#8221; has been set to true; this will automatically mount the authentication resources needed for a kubeconfig context to be setup on the pod (i.e. Cluster info, User represented by a token and a Namespace). <\/p>\n<p>RoleBinding: We created a ClusterRoleBinding that binds together the &#8220;Jenkins&#8221; serviceAccount to the &#8220;cluster-admin&#8221; ClusterRole.<\/p>\n<p>Lastly, we tell our Jenkins deployment to run as the Jenkins ServiceAccount.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<table>\n<tbody>\n<tr>\n<td><img loading=\"lazy\" decoding=\"async\" alt=\"n-z3awvRgVXCO-QIpllgiqXOWtsTeePM62asXPD5\" height=\"20\" src=\"https:\/\/lh5.googleusercontent.com\/n-z3awvRgVXCO-QIpllgiqXOWtsTeePM62asXPD52Y_VH5ZpEaH4-Op_N_XSh8oa1-VpdlFyk6w97uHnsr1_cafUq6VR7pV68nMc5DG2jj7P1yPNRwoywUE7N9tT2x5ec-mTOsAZ\" width=\"20\" \/><\/td>\n<td>\n<p>Notice our Jenkins deployment has an initContainer. This is a container that will run to completion before the main container is deployed on our pod. The job of this init container is to create a kubeconfig file based on the provided context and to share it with the main Jenkins container through an \u201cemptyDir\u201d volume.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>7. Open the Jenkins UI in a web browser.<\/p>\n<p>minikube service jenkins<\/p>\n<p>8. Display the Jenkins admin password with the following command, and right-click to copy it.<\/p>\n<p>kubectl exec -it `kubectl get pods &#8211;selector=app=jenkins <\/p>\n<p>&#8211;output=jsonpath={.items..metadata.name}` cat <\/p>\n<p>\/var\/jenkins_home\/secrets\/initialAdminPassword<\/p>\n<p>9. Switch back to the Jenkins UI. Paste the Jenkins admin password in the box and click Continue. Click Install suggested plugins. Plugins have actually been pre-downloaded during the Jenkins image build, so this step should finish fairly quickly.<\/p>\n<table>\n<tbody>\n<tr>\n<td><img loading=\"lazy\" decoding=\"async\" alt=\"RyHz4CL2OgRH4G8M7BLPxwZ7MMAZh-DpmmEuXBoa\" height=\"20\" src=\"https:\/\/lh6.googleusercontent.com\/RyHz4CL2OgRH4G8M7BLPxwZ7MMAZh-DpmmEuXBoayoTGX7qenHTkyCkH1m3oLIPEVKSxu_FUCtFCXzQz1DzeZIgpS-dyVIaF_-WFlIYyat7x9WtqRPJaLY2XuL938wnO_BqvSfR0\" width=\"20\" \/><\/td>\n<td>\n<p>One of the plugins being installed is <a href=\"https:\/\/plugins.jenkins.io\/kubernetes-cd\">Kubernetes Continuous Deploy<\/a>, which allows Jenkins to directly interact with the Kubernetes cluster rather than through kubectl commands. This plugin was pre-downloaded with the Jenkins image build. <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>10. Create an admin user and credentials, and click Save and Continue. (Make sure to remember these credentials as you will need them for repeated logins.)<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"s7KGWbFBCOau5gi7G05Fs_mjAtBOVNy7LlEQ4wTL\" height=\"385\" src=\"https:\/\/lh4.googleusercontent.com\/s7KGWbFBCOau5gi7G05Fs_mjAtBOVNy7LlEQ4wTLIezGoFn8-meOxW3WcVZRcIIYBlV9kb3O40hAFc6N4sEnAP-oMB82ppyxRojirfghRNnqgHQD7zO6SsYwRKVeGHCk640QDEKQ\" width=\"576\" \/> <\/p>\n<p>11. On the Instance Configuration page, click Save and Finish. On the next page, click Restart (if it appears to hang for some time on restarting, you may have to refresh the browser window). Login to Jenkins. <\/p>\n<p>12. Before we create a pipeline, we first need to provision the Kubernetes Continuous Deploy plugin with a kubeconfig file that will allow access to our Kubernetes cluster. In Jenkins on the left, click on Credentials, select the Jenkins store, then Global credentials (unrestricted), and Add Credentials on the left menu<\/p>\n<p>13. The following values must be entered precisely as indicated: <\/p>\n<ul>\n<li>\n<p>Kind: Kubernetes configuration (kubeconfig)<\/p>\n<\/li>\n<li>\n<p>ID: kenzan_kubeconfig<\/p>\n<\/li>\n<li>\n<p>Kubeconfig: From a file on the Jenkins master<\/p>\n<\/li>\n<li>\n<p>File: \/var\/jenkins_home\/.kube\/config<\/p>\n<\/li>\n<\/ul>\n<p>Finally click Ok.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"HznE6h9fOjuiv543Oqs5MqiIj0D52wSFJ44a-3An\" height=\"299\" src=\"https:\/\/lh5.googleusercontent.com\/HznE6h9fOjuiv543Oqs5MqiIj0D52wSFJ44a-3Ansg4Vfv4GGVWv8ogjkoQSSamEFwD08FK9el4iXBdNUbeB6XBMJJkDwj8r39Cd5RyQMZTs9EAc0DDk7nw8uvCv4fuW5pJzQjSN\" width=\"624\" \/><\/p>\n<p>13. We now want to create a new pipeline for use with our Hello-Kenzan app. Back on Jenkins Home, on the left, click New Item.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"EdS4p4roTIfvBrg5Fz0n7sx8gTtMiXQMT7mqYqT-\" height=\"191\" src=\"https:\/\/lh4.googleusercontent.com\/EdS4p4roTIfvBrg5Fz0n7sx8gTtMiXQMT7mqYqT-ZyExqeUsFLlvcng8MdRd5U0W-nVqLiqumYLIKDyeHrnhUpMXCIiNU2ryyeB6nYMSyHlkzVzVzqnA6U_xaoI7EGGZZklxJ37b\" width=\"243\" \/><\/p>\n<p>Enter the item name as Hello-Kenzan Pipeline, select Pipeline, and click OK.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"4If4KfHDUj8hGFn8kkaavcX9H8sboABcODIkrVL3\" height=\"215\" src=\"https:\/\/lh4.googleusercontent.com\/4If4KfHDUj8hGFn8kkaavcX9H8sboABcODIkrVL3V9nlWHb55rUsdTtNXsagHncWVXxpQza6ES5NnLiOOMPBD2HWsIWb8s41u75DMwD6-TtbrzLm41OOamNSdmuljHZ7_1ZoNp_c\" width=\"577\" \/><\/p>\n<p>14. Under the Pipeline section at the bottom, change the Definition to be Pipeline script from SCM.<\/p>\n<p>15. Change the SCM to Git. Change the Repository URL to be the URL of your forked Git repository, such as <a href=\"https:\/\/github.com\/%5BGIT\">https:\/\/github.com\/[GIT<\/a> USERNAME]\/kubernetes-ci-cd. <\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"OPuG1YZM70f-TcKx-dkQQLl223gu0PudZe12eQPl\" height=\"415\" src=\"https:\/\/lh3.googleusercontent.com\/OPuG1YZM70f-TcKx-dkQQLl223gu0PudZe12eQPlajtqcquaxMp1f5Sh59VUhqcQ8RyZg9XAfKcXnwZygqUewwoszjrQpUR2lM6M3IIgwXdN8nz7F4GtarI4wKEpUoJaQWNQcaUQ\" width=\"573\" \/><\/p>\n<table>\n<tbody>\n<tr>\n<td><img loading=\"lazy\" decoding=\"async\" alt=\"RyHz4CL2OgRH4G8M7BLPxwZ7MMAZh-DpmmEuXBoa\" height=\"20\" src=\"https:\/\/lh6.googleusercontent.com\/RyHz4CL2OgRH4G8M7BLPxwZ7MMAZh-DpmmEuXBoayoTGX7qenHTkyCkH1m3oLIPEVKSxu_FUCtFCXzQz1DzeZIgpS-dyVIaF_-WFlIYyat7x9WtqRPJaLY2XuL938wnO_BqvSfR0\" width=\"20\" \/><\/td>\n<td>\n<p>Note for the Script Path, we are using a Jenkinsfile located in the root of our project on our Github repo. This defines the build, push and deploy steps for our hello-kenzan application. <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Click Save. On the left, click Build Now to run the new pipeline. You should see it run through the build, push, and deploy steps in a few seconds.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"b4KTpFJ4vnNdFbTKcMxn7Yy3aFr8UTlmQBuVK6YB\" height=\"341\" src=\"https:\/\/lh6.googleusercontent.com\/b4KTpFJ4vnNdFbTKcMxn7Yy3aFr8UTlmQBuVK6YBTxg1MFvYJkMXLA2OkLn5HS5lBoEia3ctLcLc1nNgAm2U7XZ2ztNvKXDdJSy1pIHu3BbQAshQol6ZwZYAGrdnJcd9gmmM_1Hx\" width=\"577\" \/><\/p>\n<p>16. After all pipeline stages are colored green as complete, view the Hello-Kenzan application.<\/p>\n<p>minikube service hello-kenzan<\/p>\n<p>You might notice that you\u2019re not seeing the uncommitted change you previously made to index.html in Part 1. That\u2019s because Jenkins wasn\u2019t using your local code. Instead, Jenkins pulled the code from your forked repo on GitHub, used that code to build the image, push it, and then deploy it. <\/p>\n<h2>Pushing Code Changes Through the Pipeline<\/h2>\n<p>Now let\u2019s see some Continuous Integration in action! try changing the index.html in our Hello-Kenzan app, then building again to verify that the Jenkins build process works. <\/p>\n<p>a. Open applications\/hello-kenzan\/index.html in a text editor.<\/p>\n<p>nano applications\/hello-kenzan\/index.html<\/p>\n<p>b. Add the following html at the end of the file (or any other html you like). (Tip: You can right-click in nano and choose Paste.)<\/p>\n<p>&lt;p style=&#8221;font-family:sans-serif&#8221;&gt;For more from Kenzan, check out our<br \/>\n&lt;a href=&#8221;http:\/\/kenzan.io&#8221;&gt;website&lt;\/a&gt;.&lt;\/p&gt;<\/p>\n<p>c. Press Ctrl+X to close the file, type Y to confirm the filename, and press Enter to write the changes to the file.<\/p>\n<p>d. Commit the changed file to your Git repo (you may need to enter your GitHub credentials):<\/p>\n<p>git commit -am &#8220;Added message to index.html&#8221;<\/p>\n<p>git push<\/p>\n<p>In the Jenkins UI, click Build Now to run the build again.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"Jc8EnFCovLr3FfxWQxfuaeqX4VDJCHaq-mxvBIeC\" height=\"413\" src=\"https:\/\/lh4.googleusercontent.com\/Jc8EnFCovLr3FfxWQxfuaeqX4VDJCHaq-mxvBIeCuWCLnW2I12pqkXPOiX-0WeJR8CNIEhoGrDWzD7y1L0r35yXAF_NhoISFUXbCleZuZv4hGBRAwVqwx737cwTvHCM4ZwST6s23\" width=\"624\" \/><\/p>\n<p>18. View the updated Hello-Kenzan application. You should see the message you added to index.html. (If you don\u2019t, hold down Shift and refresh your browser to force it to reload.)<\/p>\n<p>minikube service hello-kenzan<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" alt=\"ZyyeJWIXiqbBXfNd9MwG25_9Ewb8YmrKFTI-4zUz\" height=\"304\" src=\"https:\/\/lh5.googleusercontent.com\/ZyyeJWIXiqbBXfNd9MwG25_9Ewb8YmrKFTI-4zUzeWw1W2nJ9erU0zaUKppXrtpLlkAv23kb55K5eXMO5bu73Oj_GE-SFdbTAFfxyzSC2XFCMlrLxziPB6vFIRjBnAH9bG59unOc\" width=\"624\" \/><\/p>\n<p>And that\u2019s it! You\u2019ve successfully used your pipeline to automatically pull the latest code from your Git repository, build and push a container image to your cluster, and then deploy it in a pod. And you did it all with one click\u2014that\u2019s the power of a CI\/CD pipeline.<\/p>\n<p>If you\u2019re done working in Minikube for now, you can go ahead and stop the cluster by entering the following command:<\/p>\n<p>minikube stop<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h3>Automated Scripts<\/h3>\n<p>If you need to walk through the steps we did again (or do so quickly), we\u2019ve provided npm scripts that will automate running the same commands in a terminal. <\/p>\n<p>1. To use the automated scripts, you\u2019ll need to install NodeJS and npm. <\/p>\n<p>On Linux, follow the <a href=\"https:\/\/nodejs.org\/en\/download\/package-manager\/\">NodeJS installation steps<\/a> for your distribution. To quickly install NodeJS and npm on Ubuntu 16.04 or higher, use the following terminal commands. <\/p>\n<p>a. curl -sL https:\/\/deb.nodesource.com\/setup_7.x | sudo -E bash &#8211;<\/p>\n<p>b. sudo apt-get install -y nodejs<\/p>\n<p>2. Change directories to the cloned repository and install the interactive tutorial script:<\/p>\n<p>a. cd ~\/kubernetes-ci-cd<\/p>\n<p>b. npm install<\/p>\n<p>3. Start the script<\/p>\n<p>npm run part1 (or part2, part3, part4 of the blog series)<\/p>\n<p>\u200b4. Press Enter to proceed running each command.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Up Next<\/h2>\n<p>In Parts 3 and 4, we will deploy our Kr8sswordz Puzzle app through a Jenkins CI\/CD pipeline. We will demonstrate its use of caching with etcd, as well as scaling the app up with multiple puzzle service instances so that we can try running a load test. All of this will be shown in the UI of the app itself so that we can visualize these pieces in action. <\/p>\n<p><em>Curious to learn more about Kubernetes? <a href=\"https:\/\/www.edx.org\/course\/introduction-kubernetes-linuxfoundationx-lfs158x\">Enroll in Introduction to Kubernetes<\/a>, a FREE training course from The Linux Foundation, hosted on edX.org.<\/em><\/p>\n<p><em>This article was revised and updated by David Zuluaga, a front end developer at Kenzan. He was born and raised in Colombia, where he studied his BE in Systems Engineering. After moving to the United States, he studied received his master\u2019s degree in computer science at Maharishi University of Management. David has been working at Kenzan for four years, dynamically moving throughout a wide range of areas of technology, from front-end and back-end development to platform and cloud computing. David&#8217;s also helped design and deliver training sessions on Microservices for multiple client teams.<\/em><\/p>\n<p> <a href=\"https:\/\/www.linux.com\/blog\/learn\/chapter\/Intro-to-Kubernetes\/2017\/6\/set-cicd-pipeline-jenkins-pod-kubernetes-part-2\" target=\"_blank\">Source<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In Part 1 of our series, we got our local Kubernetes cluster up and running with Docker, Minikube, and kubectl. We set up an image repository, and tried building, pushing, and deploying a container image with code changes we made to the Hello-Kenzan app. It\u2019s now time to automate this process. In Part 2, we\u2019ll &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/www.appservgrid.com\/paw92\/index.php\/2018\/10\/17\/set-up-a-ci-cd-pipeline-with-a-jenkins-pod-in-kubernetes-part-2-linux-com\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Set Up a CI\/CD Pipeline with a Jenkins Pod in Kubernetes (Part 2) | Linux.com&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-78","post","type-post","status-publish","format-standard","hentry","category-linux"],"_links":{"self":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts\/78","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/comments?post=78"}],"version-history":[{"count":0,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/posts\/78\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/media?parent=78"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/categories?post=78"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.appservgrid.com\/paw92\/index.php\/wp-json\/wp\/v2\/tags?post=78"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}