{"id":25999,"date":"2023-09-15T19:38:22","date_gmt":"2023-09-15T17:38:22","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=25999"},"modified":"2023-09-15T19:38:25","modified_gmt":"2023-09-15T17:38:25","slug":"automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes\/","title":{"rendered":"Automate PDF &#8211; A Cloud-Driven Workflow Tool with Cloud Functions and Kubernetes"},"content":{"rendered":"\n<h4 class=\"wp-block-heading\"><strong>Gitlab<\/strong> <\/h4>\n\n\n\n<p>You can find the Project under this link<a href=\"https:\/\/gitlab.mi.hdm-stuttgart.de\/fb089\/automatecloud\"> https:\/\/gitlab.mi.hdm-stuttgart.de\/fb089\/automatecloud<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Wiki<\/strong> <\/h4>\n\n\n\n<p>You can find all the Infos in our Gitlab Wiki (<a href=\"https:\/\/gitlab.mi.hdm-stuttgart.de\/fb089\/automatecloud\/-\/wikis\/AutomateCloud\">https:\/\/gitlab.mi.hdm-stuttgart.de\/fb089\/automatecloud\/-\/wikis\/AutomateCloud<\/a>). You can even try it urself. Feel free <\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Short Description<\/strong><\/h3>\n\n\n\n<p>Automate PDF is a workflow automation tool created in the course \u201cSoftware Development for Cloud Computing\u201d. The application provides a simple graph editor with which a user can create workflows to perform different automation tasks for PDF Files like modifying or mailing a PDF File<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-17.16.45.png\"><img loading=\"lazy\" decoding=\"async\" width=\"603\" height=\"333\" data-attachment-id=\"26005\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes\/bildschirmfoto-2023-09-15-um-17-16-45\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-17.16.45.png\" data-orig-size=\"603,333\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Bildschirmfoto-2023-09-15-um-17.16.45\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-17.16.45.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-17.16.45.png\" alt=\"\" class=\"wp-image-26005\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-17.16.45.png 603w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-17.16.45-300x166.png 300w\" sizes=\"auto, (max-width: 603px) 100vw, 603px\" \/><\/a><figcaption class=\"wp-element-caption\">Automate PDF Workflow<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Architecture<\/strong><\/h2>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Cloud Functions<\/strong>:<\/h4>\n\n\n\n<p>Since workflows are of modular nature, we found that the application of Cloud Functions would be a good use case. The idea was to map every executing <em>Building Block <\/em>to a dedicated Cloud Function.\u00a0<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Gateway<\/strong>:<\/h4>\n\n\n\n<p>While Cloud Functions take care of the core tasks, another service was introduced to interpret the workflow, delegate the tasks to the Cloud Functions and to act as a Gateway for our frontend client. The service was deployed in a Kubernetes Cluster.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Object Storage<\/strong>:<\/h4>\n\n\n\n<p><br>The only persistent part of our application is a S3 bucket that stores the different versions of PDF Files. During the workflow execution, Cloud Functions read and write PDF Files directly to the bucket.<br><\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>SMTP.<\/strong> <\/h4>\n\n\n\n<p><br>To simulate the mailing feature, we are using <a href=\"https:\/\/ethereal.email\/\">ethereal.email<\/a> as a fake SMTP service.<br><\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><br><strong>Kubernetes<\/strong>: <\/h4>\n\n\n\n<p><br>For the option to build a scalable Backend we decided to use Kubernetes<br><br>We decided to go to the IBM Cloud because of a Lite Plan that gave us the freedom to try out a large palette of resources for free.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.04.09.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"643\" data-attachment-id=\"26006\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes\/bildschirmfoto-2023-09-15-um-19-04-09\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.04.09.png\" data-orig-size=\"1300,816\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Bildschirmfoto-2023-09-15-um-19.04.09\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.04.09-1024x643.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.04.09-1024x643.png\" alt=\"\" class=\"wp-image-26006\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.04.09-1024x643.png 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.04.09-300x188.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.04.09-768x482.png 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.04.09.png 1300w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Architecture Overview<\/em><br><br>Since working in a Cloud environment was quite new to us, the learnings from this project are quite fundamental, like What are Cloud Functions? How to use them? How to test? How to deploy with Kubernetes? It was also fun to explore the idea of <em>Serverless <\/em>and the advantages of <em>Platform as a Service<\/em>. Stay tuned for some insights!<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Cloud Functions Learnings<\/strong><\/h3>\n\n\n\n<p>IBM Cloud Functions serve as counterparts to AWS Lambdas. The idea is, to run individual code blocks on the server-side whereby the required resources for running this code are only allocated while the code is executing.\u00a0<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Pay-As-You-Go:<\/strong><\/h4>\n\n\n\n<p><br>This also means, you only have to pay for the seconds and memory you use during the invocation. Here\u2019s an example of how much it costs, when you execute a IBM Cloud Function with 256 MB memory and 1s duration every minute in a month:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.05.46.png\"><img loading=\"lazy\" decoding=\"async\" width=\"606\" height=\"520\" data-attachment-id=\"26008\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes\/bildschirmfoto-2023-09-15-um-19-05-46\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.05.46.png\" data-orig-size=\"606,520\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Bildschirmfoto-2023-09-15-um-19.05.46\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.05.46.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.05.46.png\" alt=\"\" class=\"wp-image-26008\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.05.46.png 606w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.05.46-300x257.png 300w\" sizes=\"auto, (max-width: 606px) 100vw, 606px\" \/><\/a><figcaption class=\"wp-element-caption\">I<em>BM Cloud Function Pricing, <\/em><a href=\"https:\/\/cloud.ibm.com\/functions\/learn\/pricing\"><em>https:\/\/cloud.ibm.com\/functions\/learn\/pricing<\/em><\/a><em> (Sep. 2023)<\/em><br><\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Runtime<\/strong>:<\/h4>\n\n\n\n<p><br>IBM Cloud supports a variety of Runtimes like NodeJS, Java, Go, Python and some more. We chose the NodeJS Runtime environment because we were already familiar with it. One advantage of using such a Runtime off the shelf are the pre-installed packages. No server-side <em>npm install <\/em>or bundling of libraries into your function code is required, if the runtime already provides the needed dependency. <a href=\"https:\/\/github.com\/ibm-functions\/runtime-nodejs\/blob\/master\/nodejs12\/package.json\">Here\u2019s a list of the current npm dependencies that are part of the IBM Cloud Function NodeJS Runtime.<\/a><\/p>\n\n\n\n<p>One downside might be the inflexibility of the Runtime, when a more extensive control is needed. Therefore IBM Cloud Functions offer the opportunity to deploy <a href=\"https:\/\/cloud.ibm.com\/docs\/openwhisk?topic=openwhisk-runtimes#openwhisk_ref_docker\">Docker Containers as Cloud Functions<\/a>.\u00a0<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><br><strong>Code<\/strong>:<\/h4>\n\n\n\n<p><br>Like stated above, the idea was to execute each workflow task in a separate Cloud Function. Therefore, we developed three different Cloud Functions: <em>transform-pdf<\/em>, <em>send-pdf<\/em>, <em>nlu-validate (WIP)<\/em>. In the following example a user triggers a workflow to print a watermark text on a PDF File (<em>transform-pdf<\/em>) and send it afterwards via mail (<em>send-pdf<\/em>). The instructions the <em>Gateway <\/em>then receives is basically a list of commands:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.12.png\"><img loading=\"lazy\" decoding=\"async\" width=\"690\" height=\"548\" data-attachment-id=\"26009\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes\/bildschirmfoto-2023-09-15-um-19-07-12\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.12.png\" data-orig-size=\"690,548\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Bildschirmfoto-2023-09-15-um-19.07.12\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.12.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.12.png\" alt=\"\" class=\"wp-image-26009\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.12.png 690w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.12-300x238.png 300w\" sizes=\"auto, (max-width: 690px) 100vw, 690px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Workflow instructions that are processed by Cloud Functions<\/em><\/figcaption><\/figure>\n\n\n\n<p>Each Cloud Function is then called with a set of parameters including the credentials for accessing the S3 object storage service. Here\u2019s a simplified version of the <em>transform-pdf <\/em>function. The structure is the same for the other functions:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.54.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"541\" data-attachment-id=\"26010\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes\/bildschirmfoto-2023-09-15-um-19-07-54\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.54.png\" data-orig-size=\"1200,634\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Bildschirmfoto-2023-09-15-um-19.07.54\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.54-1024x541.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.54-1024x541.png\" alt=\"\" class=\"wp-image-26010\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.54-1024x541.png 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.54-300x159.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.54-768x406.png 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.07.54.png 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Code Example: transform-pdf<\/em><\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Authentication<\/strong>:<\/h4>\n\n\n\n<p> <br>One of the more painful tasks was authentication. Because every Cloud Functions needs to access the S3 object storage, credentials need to be passed everywhere as parameters. The execution of Cloud Functions through the <em>Gateway <\/em>service also requires authentication. We ended up with a <em>.env<\/em> file and writing our own Authentication Service using the handy <a href=\"http:\/\/@ibm-functions\/iam-token-manager\">iam-token-manager<\/a> package. However, it never felt like the How-to way of doing authentication management in a Cloud environment.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>A better alternative?<\/strong><\/h4>\n\n\n\n<p><br>Instead of introducing the <em>Gateway<\/em> as a none-Cloud Function service, we discovered a public Cloud Function could fulfill the same task. Consequently, we could have saved ourselves some problems regarding deployment and authentication. Additionally, in terms of scalability, we later foresaw the Gateway service as a potential bottleneck. Furthermore, we were not aware that Cloud Functions in combination with a public object storage endpoint can also provide static content to hand out for example our Frontend Web-Client. How we nevertheless went the way with Kubernetes and tackled the problem where the gateway becomes a bottleneck is covered in the next chapter.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Deployment<\/strong>:<\/h4>\n\n\n\n<p><br>A nice aspect of Cloud Functions lies not only in their automatic horizontal up-scaling with increasing user load but also in their deployment simplicity. We decided to bundle our function code with webpack. This gave us the flexibility to mark npm packages in the <em>webpack.config.js<\/em> as external, if they are already part of the runtime, like it is the case with the <em>ibm-cos-sdk<\/em> package for example. The actual deployment then happens by building with the <em>webpack <\/em>command and deploying using the IBM Cloud CLI with <em>ibmcloud fn action update [&#8230;], <\/em>in our case only <em>npm build &amp;&amp; npm deploy<\/em>. <a href=\"https:\/\/cloud.ibm.com\/docs\/openwhisk?topic=openwhisk-prep#prep_js_pkg\">Here is a more detailed description of the setup.<\/a><\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Debugging<\/strong><\/h4>\n\n\n\n<p><br>became manageable by subscribing to the function&#8217;s stdout using the CLI command <em>ibmcloud fn activation poll.<\/em><\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Testing:<\/strong><\/h4>\n\n\n\n<p>We developed tests for our Cloud Functions using the <a href=\"https:\/\/jestjs.io\/\">jest framework<\/a>. Therefore we mocked our S3 object storage. Since the object storage package from IBM Cloud has the same interface as the corresponding package from AWS, we made use of the <a href=\"https:\/\/www.npmjs.com\/package\/mock-aws-s3\">mock-aws-s3<\/a> package. Looking back, it would have helped us a lot to create these tests in an earlier stage of development. Instead we tested our functions by deploying it directly to the cloud.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.15.46.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"293\" data-attachment-id=\"26011\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes\/bildschirmfoto-2023-09-15-um-19-15-46\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.15.46.png\" data-orig-size=\"1204,344\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Bildschirmfoto-2023-09-15-um-19.15.46\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.15.46-1024x293.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.15.46-1024x293.png\" alt=\"\" class=\"wp-image-26011\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.15.46-1024x293.png 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.15.46-300x86.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.15.46-768x219.png 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.15.46.png 1204w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">Cloud Function Tests, local run<\/figcaption><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Setup<\/strong><\/h4>\n\n\n\n<p>Up to\u00a0 this point, we did not use any infrastructure-as-code frameworks such as Terraform, which means that our services must be configured manually either through the cloud portal or by using the CLI. To begin, you should start by creating a bucket for the \u201cCloud Object Storage\u201d. Then, create two \u201cCloud Functions\u201d utilizing NodeJS as the runtime and configure the function parameters <em>apiKeyId, bucket, endpoint <\/em>and<em> serviceInstanceId<\/em>. To launch the <em>Gateway<\/em>, certain updates in the \u201capp\/config.js\u201d file are essential (endpoints and namespaces). Additionally, you will need to create a <em>.env <\/em>file containing the necessary environment variables. Finally, you can access the frontend in the web browser by opening the \u201cworkspace.html\u201d file.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.16.59.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"581\" data-attachment-id=\"26012\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes\/bildschirmfoto-2023-09-15-um-19-16-59\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.16.59.png\" data-orig-size=\"1202,682\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Bildschirmfoto-2023-09-15-um-19.16.59\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.16.59-1024x581.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.16.59-1024x581.png\" alt=\"\" class=\"wp-image-26012\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.16.59-1024x581.png 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.16.59-300x170.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.16.59-768x436.png 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.16.59.png 1202w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\"><em>Cloud Function parameters setup<\/em><br><\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Kubernetes<\/strong><\/h3>\n\n\n\n<p>When you first dive into the world of Kubernetes, it can feel like stepping into a black box. You&#8217;ve heard about it everywhere, and it seems like everyone&#8217;s using it, but what exactly can you do with it? Initially, the concept might seem hazy at best. In this blog, I want to share my experiences with Kubernetes, shedding light on this complex system.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>The Journey<\/strong><\/h4>\n\n\n\n<p>As outlined in the architecture above, our journey began with the decision to run the frontend locally on our machines while setting up a Kubernetes cluster for the backend. This choice was further accentuated by our intention to employ cloud services. In this blog, I will focus solely on the Kubernetes aspect of our project.<\/p>\n\n\n\n<p>With the groundwork laid, I set out to create a cluster with a deployment and various pods as replicas. I aimed to do this within the IBM Cloud environment as part of our project&#8217;s scope.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>The First Hurdle: Cloud Services<\/strong><\/h4>\n\n\n\n<p>However, during the development phase, the IBM Free Trial for students underwent changes. Previously, students could access a free Kubernetes cluster as part of this trial, but this offering was abruptly discontinued mid-project. As a result, we needed to pivot our project strategy.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Finding A Solution in the Kubernetes World<\/strong><\/h4>\n\n\n\n<p>Not one to be deterred by such setbacks, I scoured the internet for an alternative, eventually stumbling upon the concept of a local Kubernetes setup, in the form of MiniKube. MiniKube provides the convenience of running a Kubernetes cluster on your local machine, making it an attractive option. The only caveat was the absence of a load balancer provided by cloud providers, but we&#8217;ll dive into that later.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>The Advantages of the change<\/strong><\/h4>\n\n\n\n<p>Our commitment to using Kubernetes remained unwavering, even though it was now operating locally. This shift did not hinder our project&#8217;s progress. Instead, it opened up the opportunity for everyone involved to run the project locally, provided they had set up the required cloud functions in the IBM Cloud environment. Detailed documentation on this can be found in our GitLab repository.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>The Master Plan<\/strong><\/h4>\n\n\n\n<p>Our plan was now to have the frontend running on localhost:3000, deploy the backend using Kubernetes, and link the frontend, backend, and cloud functions together. Liberated from cost constraints, we could freely experiment with Kubernetes. In the end, following best practices, we formulated the following architecture for our Kubernetes cluster:<\/p>\n\n\n\n<p>Frontend: Localhost 3000<\/p>\n\n\n\n<p>Backend: Kubernetes deployment<\/p>\n\n\n\n<p>Integration: Cloud functions<\/p>\n\n\n\n<p>As we ventured further into the Kubernetes maze, our journey was marked by challenges and discoveries, making it an exciting chapter in our project&#8217;s evolution. Stay tuned for more insights into our Kubernetes adventure.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>The Architecture<\/strong><\/h4>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.23.39.png\"><img loading=\"lazy\" decoding=\"async\" width=\"526\" height=\"733\" data-attachment-id=\"26016\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes\/bildschirmfoto-2023-09-15-um-19-23-39\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.23.39.png\" data-orig-size=\"526,733\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Bildschirmfoto-2023-09-15-um-19.23.39\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.23.39.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.23.39.png\" alt=\"\" class=\"wp-image-26016\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.23.39.png 526w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.23.39-215x300.png 215w\" sizes=\"auto, (max-width: 526px) 100vw, 526px\" \/><\/a><figcaption class=\"wp-element-caption\">deployment.yaml<\/figcaption><\/figure>\n\n\n\n<p>The deployment.yaml file defines two Kubernetes resources: a Service and a Deployment.<\/p>\n\n\n\n<p><strong>Service<\/strong>: This Service is named &#8220;automatecloudservice&#8221; and is responsible for routing traffic to the right pods. It listens on port 8081 and forwards incoming traffic to pods on port 3000. The selector field specifies that it should route traffic to pods with the label &#8220;app: automatecloud.&#8221;<\/p>\n\n\n\n<p><strong>Deployment<\/strong>: The Deployment resource named &#8220;automateclouddeployment&#8221; ensures that there are always five replicas (or instances) of your application running. It uses a selector to find pods with the label &#8220;app: automatecloud&#8221; and ensures that this desired state is maintained. Each pod runs a container with the Docker image &#8220;fevlic\/automatecloud&#8221; on port 3000.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.24.53.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"477\" data-attachment-id=\"26018\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/automate-pdf-a-cloud-driven-workflow-tool-with-cloud-functions-and-kubernetes\/bildschirmfoto-2023-09-15-um-19-24-53\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.24.53.png\" data-orig-size=\"1709,796\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Bildschirmfoto-2023-09-15-um-19.24.53\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.24.53-1024x477.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.24.53-1024x477.png\" alt=\"\" class=\"wp-image-26018\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.24.53-1024x477.png 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.24.53-300x140.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.24.53-768x358.png 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.24.53-1536x715.png 1536w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/Bildschirmfoto-2023-09-15-um-19.24.53.png 1709w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption class=\"wp-element-caption\">ingress.yaml<\/figcaption><\/figure>\n\n\n\n<p>The ingress.yaml file configures how external traffic is routed to your Kubernetes Service through an Ingress resource.<\/p>\n\n\n\n<p><strong>Ingress:<\/strong> The Ingress resource named &#8220;automatecloud-ingress&#8221; defines rules for routing HTTP traffic. It uses annotations to configure behavior, such as enabling CORS (Cross-Origin Resource Sharing) to allow requests from different origins.<\/p>\n\n\n\n<p><strong>Rules:<\/strong> Within the Ingress, there are rules specifying how to handle different URL paths. For example, requests to &#8220;\/workflow&#8221; and &#8220;\/download&#8221; are directed to the &#8220;automatecloudservice&#8221; Service on port 8081, which, in turn, routes them to the respective pods running your application. Requests to the root path (&#8220;\/&#8221;) are also directed to the same Service.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Why we choose Ingress over a Load Balancer<\/strong><\/h4>\n\n\n\n<p>In summary, if you have multiple services running in your Kubernetes cluster and you need to route external traffic to them based on rules like hostnames or paths, Ingress is a more flexible and resource-efficient choice. On the other hand, if you need to expose a single service to external traffic, a LoadBalancer may be more straightforward, but it doesn&#8217;t provide the same level of routing and rule-based control as Ingress. The choice depends on your specific use case and requirements.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Lessons Learned Ingress<\/strong><\/h4>\n\n\n\n<p>In the aftermath, I propose making some architectural improvements to enhance our scalability.<\/p>\n\n\n\n<p>Currently, all our services are running within a single entity. However, by incorporating Ingress, we can precisely determine when each service should come into action.<\/p>\n\n\n\n<p>If I were to return to Kubernetes, I would create individual services for each API endpoint, each with the necessary pods to boost scalability. Currently, each endpoint relies on a shared service and competes for resources. However, if we establish distinct services designated for different functions like \/workload and \/download, the burden on any single service would be significantly reduced.<\/p>\n\n\n\n<p>Nonetheless, it&#8217;s worth noting that the initial challenge of connecting Ingress to the services presented a substantial hurdle.<\/p>\n\n\n\n<p>Lastly, I encountered a problem that was entirely new to me in this process.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>CORS<\/strong><\/h4>\n\n\n\n<p>Until today I still have bad experience with the Cors principle&nbsp;<\/p>\n\n\n\n<p>If you set up everything, you think nothing can go wrong, the cluster runs&#8230; Comes from the depths of the web world still the CORS problem<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>What is CORS<\/strong><\/h4>\n\n\n\n<p>Imagine you&#8217;re on a website (let&#8217;s call it Website A) and you want to load some data or resources from another website (Website B). This could be a font, an image, or even some data from an API. Browsers, to keep things secure, have a same-origin policy. It means they won&#8217;t allow Website A to directly fetch data from Website B unless Website B explicitly says it&#8217;s okay.<\/p>\n\n\n\n<p>Here&#8217;s where CORS comes into play. CORS is a set of rules implemented by web browsers that allows or restricts web applications running at one origin (like Website A) to request resources from a different origin (like Website B). It&#8217;s like a permission slip from Website B to Website A, saying, &#8220;Yes, you can use my stuff.&#8221;<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Why was this an issue?<\/strong><\/h4>\n\n\n\n<p>In our scenario, both the frontend and backend components were running locally, and they needed to communicate with each other. The backend was hosted within the cluster on localhost:8001, while the frontend was on localhost:3000.<\/p>\n\n\n\n<p>The problem arose when we wanted to activate a cloud function that added a watermark to a PDF, resulting in the download being available at localhost:8001\/downloads. However, this function was disabled by Cross-Origin Resource Sharing (CORS), which prevented the PDF download from functioning correctly.<\/p>\n\n\n\n<p>To resolve this issue, we had to enable CORS in both the backend and frontend. This seemingly simple problem ended up consuming several days of effort. Surprisingly, it led me to delve deeper into the Kubernetes ecosystem, even though the core problem initially appeared to be related to web development.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Summary<\/strong> <\/h4>\n\n\n\n<p>Despite facing various challenges, including cloud provider issues, CORS problems, and the choice between Ingress and Load Balancers, I&#8217;ve gained valuable experience from this project. It has been a tremendous learning opportunity, equipping me with knowledge that I can apply to future projects, especially when discussions revolve around concepts like Pods, Services, Deployment, Kubernetes, and the Cloud.<\/p>\n\n\n\n<p>While I may not have all the answers, I now have the skills to identify and troubleshoot errors effectively. This experience has reinforced a fundamental concept in the world of cloud computing: &#8220;The cloud is just someone else&#8217;s computer.&#8221;<\/p>\n\n\n\n<p>Felix and Johannes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Gitlab You can find the Project under this link https:\/\/gitlab.mi.hdm-stuttgart.de\/fb089\/automatecloud Wiki You can find all the Infos in our Gitlab Wiki (https:\/\/gitlab.mi.hdm-stuttgart.de\/fb089\/automatecloud\/-\/wikis\/AutomateCloud). You can even try it urself. Feel free Short Description Automate PDF is a workflow automation tool created in the course \u201cSoftware Development for Cloud Computing\u201d. The application provides a simple graph editor [&hellip;]<\/p>\n","protected":false},"author":1059,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[7,3,154,25],"ppma_author":[671],"class_list":["post-25999","post","type-post","status-publish","format-standard","hentry","category-allgemein","tag-cloud","tag-docker","tag-kubernetes","tag-nodejs"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":5179,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/02\/24\/migrating-to-kubernetes-part-4-create-environments-via-gitlab\/","url_meta":{"origin":25999,"position":0},"title":"Migrating to Kubernetes Part 4 &#8211; Create Environments via Gitlab","author":"Can Kattwinkel","date":"24. February 2019","format":false,"excerpt":"Written by: Pirmin Gersbacher, Can Kattwinkel, Mario Sallat Connect Gitlab with Kubernetes With the Review Apps Gitlab offers an excellent improvement of the Developer Experience. More or less Gitlab enables the management of environments. For each environment, there is a CI task to each set-up and tear down. It is\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":7154,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/08\/31\/setting-up-a-ci-cd-pipeline-in-gitlab\/","url_meta":{"origin":25999,"position":1},"title":"Setting up a CI\/CD pipeline in Gitlab","author":"nr037","date":"31. August 2019","format":false,"excerpt":"Introduction For all my university software projects, I use the HdM Gitlab instance for version control. But Gitlab offers much more such as easy and good ways to operate a pipeline. In this article, I will show how we can use the CI\/CD functionality in a university project to perform\u2026","rel":"","context":"In &quot;Cloud Technologies&quot;","block_context":{"text":"Cloud Technologies","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/cloud-technologies\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/Screenshot-2019-08-26-at-09.53.13.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/Screenshot-2019-08-26-at-09.53.13.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/Screenshot-2019-08-26-at-09.53.13.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/Screenshot-2019-08-26-at-09.53.13.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/Screenshot-2019-08-26-at-09.53.13.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/Screenshot-2019-08-26-at-09.53.13.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":4405,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/01\/04\/radcup-part-3-automation\/","url_meta":{"origin":25999,"position":2},"title":"Radcup Part 3 &#8211; Automation with Gitlab CI\/CD","author":"Immanuel Haag","date":"4. January 2019","format":false,"excerpt":"Written by: Immanuel Haag, Christian M\u00fcller, Marc R\u00fcttler The goal of this blog entry is to automate the previously performed steps. At the end all manual steps should be automated when new code changes are added to the repository. The new version of the backend will be made available in\u2026","rel":"","context":"In &quot;DevOps&quot;","block_context":{"text":"DevOps","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/devops\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/01\/Gesamtstruktur-der-Architektur-Kurzform-1.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/01\/Gesamtstruktur-der-Architektur-Kurzform-1.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/01\/Gesamtstruktur-der-Architektur-Kurzform-1.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/01\/Gesamtstruktur-der-Architektur-Kurzform-1.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/01\/Gesamtstruktur-der-Architektur-Kurzform-1.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":5163,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/02\/24\/migrating-to-kubernetes-part-1-introduction\/","url_meta":{"origin":25999,"position":3},"title":"Migrating to Kubernetes Part 1 &#8211; Introduction","author":"Can Kattwinkel","date":"24. February 2019","format":false,"excerpt":"Written by: Pirmin Gersbacher, Can Kattwinkel, Mario Sallat Introduction The great challenge of collaborative working in a software developer team is to enable a high level of developer activity while ensuring a high product quality. In order to achieve this often CI\/CD processes are utilized. Talking about modern development techniques\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":3348,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/30\/continuous-integration-pipeline-for-unity-development-using-gitlab-ci-and-aws\/","url_meta":{"origin":25999,"position":4},"title":"Continuous Integration Pipeline for Unity Development using GitLab CI and AWS","author":"Jonas Graf, Christian Gutwein","date":"30. March 2018","format":false,"excerpt":"This blog entry describes the implementation of a Continous Integration (CI) pipeline especially adapted for Unity projects. It makes it possible to automatically execute Unity builds on a configured build server and provide it for a further deployment process if required.","rel":"","context":"In &quot;DevOps&quot;","block_context":{"text":"DevOps","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/devops\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/CI_process.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/CI_process.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/CI_process.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/CI_process.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":5177,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/02\/24\/migrating-to-kubernetes-part-3-creating-environments-with-helm\/","url_meta":{"origin":25999,"position":5},"title":"Migrating to Kubernetes Part 3 &#8211; Creating Environments with Helm","author":"Can Kattwinkel","date":"24. February 2019","format":false,"excerpt":"Written by: Pirmin Gersbacher, Can Kattwinkel, Mario Sallat Creating Environments on the Fly The last step has been the deployment of a classic 3 tier application onto a Kubernetes Cluster powered by Minikube. In the next stage it gets a little complicated, since there are two things to do that\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/02\/pexels-photo-379964.jpeg?resize=1050%2C600&ssl=1 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":671,"user_id":1059,"is_guest":0,"slug":"felix_boudnik","display_name":"fb089","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/e224f8167604cf13f64b35fdf32bd734a254e5290ba430bbd444c45763d8b5e5?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/25999","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/users\/1059"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=25999"}],"version-history":[{"count":4,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/25999\/revisions"}],"predecessor-version":[{"id":26022,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/25999\/revisions\/26022"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=25999"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=25999"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=25999"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=25999"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}