{"id":816,"date":"2020-03-30T12:00:00","date_gmt":"2020-03-30T12:00:00","guid":{"rendered":"http:\/\/bullyrooks.com\/index.php\/2020\/04\/02\/simple-spring-boot-service-to-kubernetes-application-step-12-c6423261a93a\/"},"modified":"2021-02-04T01:58:43","modified_gmt":"2021-02-04T01:58:43","slug":"simple-spring-boot-service-to-kubernetes-application-step-12-c6423261a93a","status":"publish","type":"post","link":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-12-c6423261a93a\/","title":{"rendered":"Setting up a Kubernetes Cluster"},"content":{"rendered":"\n<p class=\"graf graf--p graf-after--h3 graf--trailing\" id=\"db05\">Finally, we\u2019re going to be able to deploy our application. We need to get access to a cluster first.<\/p>\n\n\n\n<h3 class=\"graf graf--h3 graf--leading wp-block-heading\" id=\"b08b\">Install Tooling<\/h3>\n\n\n\n<p class=\"graf graf--p graf-after--h3\" id=\"9db6\">We\u2019re going to need more tools in order to get started. Use your OS package management tool to install these tools:<\/p>\n\n\n\n<ul class=\"postList wp-block-list\"><li id=\"03d0\" class=\"graf graf--li graf-after--p\">Kubectl (Interact with a k8s instance)<\/li><li id=\"fa7c\" class=\"graf graf--li graf-after--li\">Minikube (Run a cluster locally)<\/li><\/ul>\n\n\n\n<p class=\"graf graf--p graf-after--li\" id=\"c97e\">I\u2019m not going to cover how to install these tools, there\u2019s plenty of documentation out there and it would take too much time to cover.<\/p>\n\n\n\n<p class=\"graf graf--p graf-after--p\" id=\"874d\">When you startup minikube it will automatically update your kube config file with the correct settings to talk to minikube.<\/p>\n\n\n\n<p class=\"graf graf--p graf-after--p graf--trailing\" id=\"f7f4\">Kubectl is the tool that we\u2019ll use to interact with k8s. Specifically, helm will be using it to apply our deployment files that helm generates.<\/p>\n\n\n\n<h3 class=\"graf graf--h3 graf--leading wp-block-heading\" id=\"13be\">Setting up&nbsp;Security<\/h3>\n\n\n\n<p class=\"graf graf--p graf-after--h3\" id=\"b16c\">First we want to setup some secrets to hold configuration that we don\u2019t want to check into git. We could create deployment files in helm and let helm do it for us, but that runs the risk that we accidentally check in a file that has credentials in it. So lets do that by hand for now.<\/p>\n\n\n\n<h4 class=\"graf graf--h4 graf-after--p wp-block-heading\" id=\"967e\">Docker Registry<\/h4>\n\n\n\n<pre id=\"409e\" class=\"wp-block-code graf graf--pre graf-after--h4\"><code>kubectl create secret docker-registry regcred --docker-server=r.cfcr.io --docker-username=Mcodefresh username&gt; --docker-password=&lt;code fresh docker access key&gt;<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote graf graf--blockquote graf-after--pre is-layout-flow wp-block-quote-is-layout-flow\" id=\"b1f2\"><p>This step tells minikube how to connect to codefresh in order to pull down the images we\u2019ve built.<\/p><\/blockquote>\n\n\n\n<h4 class=\"graf graf--h4 graf-after--blockquote wp-block-heading\" id=\"c219\">Database Credentials<\/h4>\n\n\n\n<pre id=\"06a2\" class=\"wp-block-code graf graf--pre graf-after--h4\"><code>kubectl create secret generic database-secrets --from-literal=SPRING_DATASOURCE_PASSWORD=&lt;postgres user&gt; --from-literal=SPRING_DATASOURCE_USERNAME=&lt;postgres password&gt;<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote graf graf--blockquote graf-after--pre is-layout-flow wp-block-quote-is-layout-flow\" id=\"71fc\"><p>We\u2019re going to store the database credentials in a secret which makes them available to our deployment files later.<\/p><\/blockquote>\n\n\n\n<h3 class=\"graf graf--h3 graf-after--blockquote wp-block-heading\" id=\"a986\">Update Helm&nbsp;Template<\/h3>\n\n\n\n<p class=\"graf graf--p graf-after--h3\" id=\"0e4a\">We need to add some more configuration to helm. Open <code class=\"markup--code markup--p-code\">deployment.yaml<\/code> and update with these additions:<\/p>\n\n\n\n<pre id=\"08c7\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>(line 24)\nspec:\n  imagePullSecrets:\n    - name: regcred<\/code><\/pre>\n\n\n\n<pre id=\"5e6c\" class=\"wp-block-code graf graf--pre graf-after--pre\"><code>(line 51)\n            {{- range $key, $value := .Values.extraEnv }}\n            - name: {{ $key }}\n              value: {{ $value | quote }}\n            {{- end }}\n{{- if .Values.secretsToEnv }}\n{{ toYaml .Values.secretsToEnv | indent 12 }}\n{{- end }}<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote graf graf--blockquote graf-after--pre is-layout-flow wp-block-quote-is-layout-flow\" id=\"defa\"><p>Be very careful of editing yaml. Its very sensitive to indentation. Double check my branch to see what the correct yaml file should look like.<\/p><\/blockquote>\n\n\n\n<p class=\"graf graf--p graf-after--blockquote\" id=\"a74e\">We also need to update the <code class=\"markup--code markup--p-code\">values.yaml<\/code> to add the mapping for our database credentials. Add this under <code class=\"markup--code markup--p-code\">extraEnv: {}<\/code><\/p>\n\n\n\n<pre id=\"66e0\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>extraEnv: {}\n\nsecretsToEnv:\n  - name: SPRING_DATASOURCE_PASSWORD\n    valueFrom:\n      secretKeyRef:\n        name: database-secrets\n        key: SPRING_DATASOURCE_PASSWORD\n  - name: SPRING_DATASOURCE_USERNAME\n    valueFrom:\n      secretKeyRef:\n        name: database-secrets\n        key: SPRING_DATASOURCE_USERNAME<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote graf graf--blockquote graf-after--pre is-layout-flow wp-block-quote-is-layout-flow\" id=\"cad2\"><p>Here we\u2019re reading the secretes file and injecting them into the pod environment. This snake case naming is a spring convention that matches the dot notation in an application properties file. We\u2019re essentially writing <code class=\"markup--code markup--blockquote-code\">spring.datasource.username<\/code> and <code class=\"markup--code markup--blockquote-code\">spring.datasource.password<\/code>. But it a very secure way to do it (as secure as k8s secrets are)<\/p><\/blockquote>\n\n\n\n<p class=\"graf graf--p graf-after--blockquote\" id=\"a517\">The final thing we need to do is point our image configuration at a valid tag. Go into your codefresh docker image registry and pull a tag off of the latest build image<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/02\/13c173K4Aax6bVuzbDyGJug.png?w=960\" alt=\"\" data-recalc-dims=\"1\"\/><\/figure>\n\n\n\n<p class=\"graf graf--p graf-after--figure\" id=\"1216\">and put that into the values.yaml<\/p>\n\n\n\n<pre id=\"f610\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>image:\n  repository: r.cfcr.io\/docketdynamics\/medium-customer\n  tag: \"4165814\"<\/code><\/pre>\n\n\n\n<h3 class=\"graf graf--h3 graf-after--pre wp-block-heading\" id=\"6b8c\">Lets Finally&nbsp;Deploy<\/h3>\n\n\n\n<p class=\"graf graf--p graf-after--h3\" id=\"8fc6\">Everything should be setup now. Lets fire up helm and deploy into minikube<\/p>\n\n\n\n<pre id=\"8d6c\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>helm install medium src\/main\/helm\/medium-customer<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote graf graf--blockquote graf-after--pre is-layout-flow wp-block-quote-is-layout-flow\" id=\"a5e8\"><p>This is telling helm to startup a \u2018release\u2019 called <code class=\"markup--code markup--blockquote-code\">medium <\/code>using the template defined in that directory.<\/p><\/blockquote>\n\n\n\n<p class=\"graf graf--p graf-after--blockquote\" id=\"c062\">startup minikube\u2019s k8s dashboard in a new window<\/p>\n\n\n\n<pre id=\"2f5f\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>minikube dashboard<\/code><\/pre>\n\n\n\n<p class=\"graf graf--p graf-after--pre\" id=\"cff0\">and watch the pods tab to see if our image was pulled down correctly and the pod started up.<\/p>\n\n\n\n<p class=\"graf graf--p graf-after--p\" id=\"8bb9\">We can also get the ip for our cluster<\/p>\n\n\n\n<pre id=\"ab46\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>minikube ip<\/code><\/pre>\n\n\n\n<p class=\"graf graf--p graf-after--pre\" id=\"f206\">and use that in a POST request with our cluster ip and the port we\u2019ve defined this service to listen on<\/p>\n\n\n\n<pre id=\"ff0f\" class=\"wp-block-code graf graf--pre graf-after--p\"><code>POST \/customer\/ HTTP\/1.1\nHost: 172.17.144.73:30001\nContent-Type: application\/json<\/code><\/pre>\n\n\n\n<pre id=\"5ab3\" class=\"wp-block-code graf graf--pre graf-after--pre\"><code>{\n \"firstName\": \"Brian\",\n \"lastName\":  \"Rook\",\n \"phoneNumber\": \"(303)868-5511\",\n \"email\": \"<a class=\"markup--anchor markup--pre-anchor\" href=\"mailto:rook.residences@gmail.com\" target=\"_blank\" rel=\"nofollow noopener\" data-href=\"mailto:rook.residences@gmail.com\">test@test.com<\/a>\"\n}<\/code><\/pre>\n\n\n\n<p class=\"graf graf--p graf-after--pre\" id=\"a0d3\">We should get a 201 back and we can log into the database via the DB Browser to confirm our record was stored.<\/p>\n\n\n\n<h3 class=\"graf graf--h3 graf-after--p wp-block-heading\" id=\"a50d\">Build and&nbsp;Commit<\/h3>\n\n\n\n<pre id=\"253b\" class=\"wp-block-code graf graf--pre graf-after--h3\"><code>git checkout -b deploy\nmvn clean install\ngit add .\ngit commit -m \"deploy to minikube\"\ngit push<\/code><\/pre>\n\n\n\n<pre id=\"9d9d\" class=\"wp-block-code graf graf--pre graf-after--pre\"><code>git checkout master\ngit merge deploy\ngit push<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<div class=\"entry-summary\">\nFinally, we\u2019re going to be able to deploy our application. We need&hellip;\n<\/div>\n<div class=\"link-more\"><a href=\"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-12-c6423261a93a\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &ldquo;Setting up a Kubernetes Cluster&rdquo;<\/span>&hellip;<\/a><\/div>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[41],"tags":[76,5,75,29,79,82,80,50,83,84],"course":[40],"class_list":["post-816","post","type-post","status-publish","format-standard","hentry","category-software-development","tag-codefresh","tag-docker","tag-docker-registry","tag-git","tag-helm","tag-kubectl","tag-kubernetes","tag-maven","tag-minikube","tag-secrets","course-spring-with-kubernetes","entry"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":1188,"url":"https:\/\/bullyrooks.com\/index.php\/2022\/01\/04\/cloud-kube-setup-cloud-hosting\/","url_meta":{"origin":816,"position":0},"title":"Cloud Kube | Setup Cloud Hosting","author":"Bullyrook","date":"January 4, 2022","format":false,"excerpt":"We've got a helm chart and associated docker image. Now we're going to setup a cloud kubernetes provider to deploy our application to. Okteto offers a very generous kubernetes hosting platform that's free for small developer projects. Setup Okteto First register on okteto by creating an account via your github\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-31.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-31.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2022\/01\/image-31.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":817,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-20-fe28a586cdc6\/","url_meta":{"origin":816,"position":1},"title":"Creating an Ingress in Kubernetes","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"We\u2019ve got multiple service available for deployment now. Lets allow them to communicate internally and externally with the cluster. We\u2019ll do that by creating an ingress. Current State of Our Application We\u2019re using our services as nodeports which allows us to expose an external port that will map to the\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":822,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-13-c3d437bb7570\/","url_meta":{"origin":816,"position":2},"title":"Automating Deployment (for CICD)","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"Now that we\u2019ve deployed our application, lets reduce some of the manual steps and make our deployments more reproducible with the intent of eventually making them automated for CI\/CD. Publish our Chart to the Chart Repository Normally, we would need to create a helm chart repository, however, codefresh has given\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":836,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-11-636b842a3c0f\/","url_meta":{"origin":816,"position":3},"title":"Helm for Deployment","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"We\u2019re about ready to deploy into kubernetes. However, deployment is not exactly straightforward. There are a lot of configuration files that we need to create and maintain in order to explain to the container management system how to deploy our application. We can use tools like kubectl to promote these\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":820,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-17-3867eb38d8f1\/","url_meta":{"origin":816,"position":4},"title":"Containerizing our UI","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"We\u2019ve got a simple page that calls one of our endpoints working. Let\u2019s go ahead an containerize it so that we can deploy it into our k8s environment in future steps. Build the Dockerfile I\u2019m following the process laid out here, with some minor differences. Create a Dockerfile # Stage\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":826,"url":"https:\/\/bullyrooks.com\/index.php\/2020\/03\/30\/simple-spring-boot-service-to-kubernetes-application-step-9-55fd26c1dffb\/","url_meta":{"origin":816,"position":5},"title":"Docker Registry","author":"Bullyrook","date":"March 30, 2020","format":false,"excerpt":"In the previous article we created a docker image as part of our build process and stored it into our local repository. In order to deploy it in an automated fashion we should create a remote image repository in the cloud. This will expand the types of tools that we\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/816","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/comments?post=816"}],"version-history":[{"count":3,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/816\/revisions"}],"predecessor-version":[{"id":899,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/816\/revisions\/899"}],"wp:attachment":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/media?parent=816"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/categories?post=816"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/tags?post=816"},{"taxonomy":"course","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/course?post=816"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}