<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Priya's AWS DevOps Diary]]></title><description><![CDATA[A beginner's blog sharing simple AWS DevOps projects. Learn with me as I navigate MySQL clusters, S3 logs, and cloud operations. Let's grow together!]]></description><link>https://devops-notes.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 06 Oct 2026 14:34:44 GMT</lastBuildDate><atom:link href="https://devops-notes.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[DevOpsified Project - 1]]></title><description><![CDATA[This project involved containerizing a Go web application, deploying it to a Kubernetes cluster using EKS, and setting up a CI/CD pipeline using GitHub Actions and ArgoCD. Below is a detailed breakdown of the steps taken, including commands, outputs,...]]></description><link>https://devops-notes.hashnode.dev/devopsified-project-1</link><guid isPermaLink="true">https://devops-notes.hashnode.dev/devopsified-project-1</guid><category><![CDATA[Devops]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Helm]]></category><category><![CDATA[ArgoCD]]></category><category><![CDATA[nginx]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Priya T]]></dc:creator><pubDate>Mon, 19 Aug 2024 09:20:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724058665981/279b4f37-d772-40d5-9fa8-f2562505bd66.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This project involved containerizing a Go web application, deploying it to a Kubernetes cluster using EKS, and setting up a CI/CD pipeline using GitHub Actions and ArgoCD. Below is a detailed breakdown of the steps taken, including commands, outputs, architectural diagrams, and explanations.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>Before we begin, ensure you have the following installed:</p>
<ul>
<li><p><strong>Go</strong> (version 1.15 or later)</p>
</li>
<li><p><strong>Docker</strong></p>
</li>
<li><p><strong>kubectl</strong></p>
</li>
<li><p><strong>AWS CLI</strong></p>
</li>
<li><p><strong>eksctl</strong></p>
</li>
<li><p><strong>Helm</strong></p>
</li>
<li><p><strong>Git</strong></p>
</li>
</ul>
<p>You'll also need accounts on:</p>
<ul>
<li><p><strong>GitHub</strong></p>
</li>
<li><p><strong>Docker Hub</strong></p>
</li>
<li><p><strong>AWS</strong></p>
</li>
</ul>
<h3 id="heading-step-1-containerizing-the-application-with-docker">Step 1: Containerizing the Application with Docker</h3>
<p><strong>Commands Used:</strong></p>
<ul>
<li><p>Cloning the Git repository:</p>
<p>  <code>git clone &lt;repo_url&gt;</code></p>
<p>  <code>cd &lt;repo_name&gt;</code></p>
</li>
<li><p>Building and running the application locally:</p>
<p>  <code>go build -o main.exe</code></p>
<p>  <code>./main.exe</code></p>
</li>
<li><p>Creating a Dockerfile using a multi-stage build:</p>
<pre><code class="lang-dockerfile">  <span class="hljs-keyword">FROM</span> golang:<span class="hljs-number">1.22</span>.<span class="hljs-number">5</span> as base
  <span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>
  <span class="hljs-keyword">COPY</span><span class="bash"> go.mod .</span>
  <span class="hljs-keyword">RUN</span><span class="bash"> go mod download</span>
  <span class="hljs-keyword">COPY</span><span class="bash"> . .</span>
  <span class="hljs-keyword">RUN</span><span class="bash"> go build -o main.exe .</span>

  <span class="hljs-keyword">FROM</span> gcr.io/distroless/base
  <span class="hljs-keyword">COPY</span><span class="bash"> --from=base /app/main.exe .</span>
  <span class="hljs-keyword">COPY</span><span class="bash"> --from=base /app/static ./static</span>
  <span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">8080</span>
  <span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"./main.exe"</span>]</span>
</code></pre>
</li>
<li><p>Building the Docker image:</p>
<p>  <code>docker build -t priyatjs/go-web-app:v1 .</code></p>
</li>
<li><p>Running the container locally:</p>
<p>  <code>doc``ker run -p 8080:8080 priyatjs/go-web-app:v1</code></p>
</li>
</ul>
<p><strong>Screenshots**</strong>:**</p>
<ul>
<li><p>Docker build output showing successful image creation.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724029148269/dab8ac74-6ec5-47c8-8f41-8c737b5d0489.png" alt class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724029183392/faf5073f-41c8-40d0-9f03-fff4e16598bd.png" alt class="image--center mx-auto" /></p>
<p>  Terminal screenshot showing the Docker image being pushed to Docker Hub</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724039576586/acf692b5-9484-4b6c-bc72-dc425077082b.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Browser screenshot accessing the application on <a target="_blank" href="http://localhost:8080/courses"><code>localhost:8080/courses</code></a>.</p>
</li>
</ul>
<p><strong>Explanation of the Multi-Stage Build Process:</strong></p>
<ul>
<li><p><strong>Stage 1: Base Image</strong></p>
<ul>
<li><p><strong>Base Image:</strong> The first stage of the Dockerfile uses a full-featured base image, such as <code>golang:1.22.5</code>. This image includes all the necessary tools and libraries needed to build the application.</p>
</li>
<li><p><strong>Dependencies:</strong> The <code>go mod download</code> command ensures that all Go module dependencies are downloaded.</p>
</li>
<li><p><strong>Application Code:</strong> The application code is copied into the container, and the application is built using the <code>go build</code> command.</p>
</li>
</ul>
</li>
<li><p><strong>Stage 2: Distroless Image</strong></p>
<ul>
<li><p><strong>Distroless Image:</strong> The second stage uses a minimal, "distroless" base image, such as <a target="_blank" href="http://gcr.io/distroless/base"><code>gcr.io/distroless/base</code></a>. This image is designed to be lightweight and secure.</p>
</li>
<li><p><strong>Copy Application:</strong> Only the built application and necessary runtime dependencies are copied from the first stage into this minimal image.</p>
</li>
<li><p><strong>Run Configuration:</strong> The final image is configured to run the application using the <code>CMD</code> command.</p>
</li>
</ul>
</li>
</ul>
<p><strong>Benefits of the Multi-Stage Build:</strong></p>
<ul>
<li><p><strong>Smaller Image:</strong> The final image is much smaller because it only includes the application and its runtime dependencies. All unnecessary build tools and libraries from the first stage are excluded.</p>
</li>
<li><p><strong>Increased Security:</strong> By using a distroless base image, the attack surface is reduced. The final image lacks a shell and other unnecessary tools, making it more secure.</p>
</li>
</ul>
<p><strong>Output:</strong></p>
<ul>
<li><p>The application was successfully built and ran locally, accessible via <a target="_blank" href="http://localhost:8080/courses"><code>localhost:8080/courses</code></a>.</p>
</li>
<li><p>The Docker image was built successfully despite minor warnings regarding the Dockerfile casing.</p>
</li>
</ul>
<p><strong>Explanation:</strong> The Dockerfile was well-constructed using a multi-stage build, which reduced the final image size and increased security by using a distroless base image. One minor issue encountered was a warning about the casing of keywords in the Dockerfile, but this did not affect the build process.</p>
<h3 id="heading-step-2-deploying-the-application-to-kubernetes">Step 2: Deploying the Application to Kubernetes</h3>
<p><strong>Commands Used:</strong></p>
<ul>
<li><p>Creating Kubernetes manifest files (<code>deployment.yaml</code>, <code>service.yaml</code>, <code>ingress.yaml</code>).</p>
</li>
<li><p>Applying Kubernetes manifests:</p>
<p>  <code>kubectl apply -f k8s/manifest/deployment.yaml kubectl apply -f k8s/manifest/service.yaml kubectl apply -f k8s/manifest/ingress.yaml</code></p>
</li>
<li><p>Creating an EKS cluster using <code>eksctl</code>:</p>
<p>  <code>eksctl create cluster --name demo-cluster --region us-east-1</code></p>
</li>
</ul>
<p><strong>Output:</strong></p>
<ul>
<li>Kubernetes resources were successfully created, though initially, the ingress resource did not have an assigned address.</li>
</ul>
<p><strong>Screenshots:</strong></p>
<ul>
<li><p>Terminal screenshot showing the eks cluster created.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724040753575/6606ed1d-c613-44b3-9877-d66679304beb.png" alt class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724040907179/1da0d08f-d522-411a-ac8a-5333f071f7ae.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Kubernetes dashboard showing deployment, service, and ingress resources.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724041238418/f555d4c4-43d2-4d6c-ae3f-7b8f4cd62cba.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<p><strong>Initial Issue:</strong></p>
<ul>
<li>After applying the ingress manifest, I noticed that my ingress resource was not assigned an address. This was because an ingress controller was not yet in place.</li>
</ul>
<p><strong>Steps Taken to Resolve the Issue:</strong></p>
<ul>
<li><p>To address this, I needed to deploy an ingress controller. However, before doing so, I decided to verify that the service was working by exposing it in NodePort mode.</p>
</li>
<li><p>I edited the <code>go-web-app</code> service to NodePort using the following command:</p>
<p>  <code>kubectl edit service go-web-app</code></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724043308249/cd7c1468-cfd5-4145-8065-360caed03ca5.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<p><strong>Finding the Node IP:</strong></p>
<ul>
<li><p>After exposing the service, the <code>go-web-app</code> could be accessed on port <code>30485</code> on my node's IP address. To determine the node IP addresses, I used:</p>
<p>  <code>kubectl get nodes -o wide</code></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724043400459/7b995dce-3cb4-492e-afb3-206444f21284.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>I was able to access the <code>go-web-app</code> on both external IPs by entering the node IP and port in my browser.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724043686154/2ee2207e-4e88-4782-a9ae-c09725846786.png" alt class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724043712117/c022f001-26b5-4d2b-ba35-f6331ec0ebd8.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<h3 id="heading-step-3-configuring-ingress-controller">Step 3: Configuring Ingress Controller</h3>
<p><strong>Commands Used:</strong></p>
<ul>
<li><p>Installing the Nginx ingress controller:</p>
<p>  <code>kubectl apply -f</code> <a target="_blank" href="https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml"><code>https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml</code></a></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724044464111/81c0a5fc-009d-4f45-aae1-a89b4b4f1bad.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Checking the ingress status:</p>
<p>  <code>kubectl get ingress -n ingress-nginx</code></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724044504719/9d0c0d28-0af2-47a3-8fbb-c951475f9aca.png" alt class="image--center mx-auto" /></p>
<p>  Then lets check the details of nginx controller pod using below command.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724044607831/e55b031b-ef36-4631-a2be-9da631b66927.png" alt class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724044693090/8a1600c5-03ca-4a6f-b4b1-fc03559f2994.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<p><strong>Output:</strong></p>
<ul>
<li><p>The ingress resource was successfully assigned an address after setting up the ingress controller.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724044802219/6ff5196a-6c3b-4dd5-b369-7375d257db4e.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<p><strong>Mapping the IP Address to a Domain Name:</strong></p>
<ul>
<li><p>Now, I needed to map the ingress IP address to a DNS host name. I did an <code>nslookup</code> on the assigned address to check the address and then edited the <code>/etc/hosts</code> file on my system for DNS mapping.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724045822175/7895728a-c403-488d-a58d-4c868ae864ea.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>As I had forgotten my system password, I manually updated the <code>/etc/hosts</code> file by adding:</p>
<p>  <code>3.93.102.122 go-web-app.local</code></p>
<ul>
<li><strong>Note:</strong> If you're adding it properly in Notepad on Windows, ensure you run Notepad as an administrator to save the file.</li>
</ul>
</li>
<li><p>Once I saved my <code>/etc/hosts</code> file correctly, I was able to access my application on a web browser using the host name <code>go-web-app.local</code> followed by <code>/courses</code>.</p>
</li>
</ul>
<p><strong>Output:</strong></p>
<ul>
<li><p>Kubernetes resources were successfully created, and after resolving the ingress issue, the application was accessible via the domain name mapped in the <code>/etc/hosts</code> file.</p>
</li>
<li><p>The DNS mapping allowed smooth access to the application using a friendly hostname.</p>
</li>
</ul>
<p><strong>Screenshots:</strong></p>
<ul>
<li><p>Browser screenshot accessing the application using the DNS name mapped to the ingress IP.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724046034947/19ffb359-f88e-47fb-8341-7615daaca720.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<p><strong>Explanation:</strong> Initially, there was a delay in assigning the ingress address, which was fixed by properly configuring the ingress controller. The DNS mapping was manually handled by editing the <code>/etc/hosts</code> file due to the lack of automated DNS management.</p>
<h3 id="heading-step-4-using-helm-to-manage-kubernetes-workflows">Step 4: Using Helm to Manage Kubernetes Workflows</h3>
<p>After successfully deploying the application and setting up the ingress, I moved on to using Helm to create and manage Kubernetes workflows. Helm is a powerful tool that simplifies the deployment and management of applications within Kubernetes by using packaged applications called "charts."</p>
<p><strong>Commands Used:</strong></p>
<ol>
<li><p><strong>Checking if Helm is Installed:</strong></p>
<ul>
<li><p>Before proceeding, I needed to verify if Helm was installed on my system. I ran the following command:</p>
<p>  <code>helm version</code></p>
<ul>
<li>This command returns the version of Helm installed. If Helm isn't installed, you can follow the Helm installation guide to set it up.</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>    <strong>Screenshot:</strong></p>
<ul>
<li><p>Terminal output showing the installed version of Helm.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724046714789/e6aee1a3-490c-4f7f-98fa-d0ac8ec393cb.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<ol start="2">
<li><p><strong>Installing an Application Using a Helm Chart:</strong></p>
<p> I then used Helm to install a chart.</p>
<ul>
<li><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724047335865/c0ec0086-915b-4ae5-8f78-13d2de9841d5.png" alt class="image--center mx-auto" /></li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724048968834/7aa4a67c-b6df-4292-bca0-dd0d2d1ea177.png" alt class="image--center mx-auto" /></p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724049099807/15724cba-ae19-470c-a364-6f44c58d67ac.png" alt class="image--center mx-auto" /></p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724049154567/863e1bfa-dce4-48ff-b367-7b6300d2e463.png" alt class="image--center mx-auto" /></p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724049247682/b21b22bd-455b-4e14-8551-58e04389c2df.png" alt class="image--center mx-auto" /></p>
<p><strong>Explanation:</strong></p>
<p>Helm greatly simplified the deployment of Kubernetes resources by allowing me to use predefined charts. First, I confirmed that Helm was installed on my system. After adding the necessary Helm repository, I was able to deploy applications within Kubernetes using Helm charts.</p>
<p>One of the key benefits of Helm is its ability to manage complex Kubernetes applications with ease. By using Helm charts, I could deploy and manage applications with a single command, avoiding the need to manually create and apply numerous Kubernetes manifest files.</p>
<p>Additionally, Helm allows for easy upgrades and rollbacks of applications, making it an essential tool in a Kubernetes-based CI/CD pipeline.</p>
<p><strong>Output:</strong></p>
<ul>
<li>Successfully installed and managed Kubernetes applications using Helm, demonstrating Helm’s capabilities in streamlining Kubernetes workflows.</li>
</ul>
<h3 id="heading-step-5-setting-up-cicd-with-github-actions-and-argocd">Step 5: Setting Up CI/CD with GitHub Actions and ArgoCD</h3>
<p>To automate and streamline the deployment process, I implemented CI/CD pipelines using GitHub Actions for CI and ArgoCD for CD. Here’s how I set it up:</p>
<h4 id="heading-continuous-integration-ci">Continuous Integration (CI):</h4>
<p>I implemented CI using GitHub Actions, with the following stages:</p>
<ol>
<li><p><strong>Build and Unit Test:</strong></p>
<ul>
<li>The CI pipeline begins by building the Go application and running unit tests.</li>
</ul>
</li>
<li><p><strong>Static Code Analysis:</strong></p>
<ul>
<li>Next, static code analysis is performed to ensure code quality.</li>
</ul>
</li>
<li><p><strong>Docker Image Creation and Pushing:</strong></p>
<ul>
<li><p>The Docker image is created and pushed to Docker Hub. I used the following command to push the image:</p>
<p>  <code>docker push &lt;your_dockerhub_username&gt;/go-web-app: &lt;tag&gt;</code></p>
</li>
</ul>
</li>
<li><p><strong>Update Helm Chart:</strong></p>
<ul>
<li>The new Docker image tag is updated in the <code>values.yaml</code> file of the Helm chart.</li>
</ul>
</li>
</ol>
<p>I created a <code>.github/workflows/ci.yaml</code> file in my GitHub repository to define the CI pipeline. Within this YAML file, I configured the pipeline to trigger on every push to the <code>main</code> branch. I added Docker Hub and GitHub secrets to securely store credentials.</p>
<p>After committing and pushing these changes to the remote repository, the CI pipeline was triggered. It successfully completed all stages after resolving several errors.</p>
<p><strong>Screenshots:</strong></p>
<ul>
<li><p>Screenshot showing the successful CI run on GitHub Actions.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724052082154/34201d4d-1491-4bed-9ca6-37d56b37ff12.png" alt class="image--center mx-auto" /></p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724052298512/5e3bc972-5554-472d-acc2-14905f46f6a1.png" alt class="image--center mx-auto" /></p>
</li>
</ul>
<h4 id="heading-continuous-deployment-cd">Continuous Deployment (CD):</h4>
<p>For CD, I used ArgoCD, which watches the <code>values.yaml</code> file in the Helm chart. Whenever this file is updated, ArgoCD automatically pulls the new version and deploys it to the Kubernetes cluster.</p>
<ol>
<li><p><strong>Installing ArgoCD:</strong></p>
<ul>
<li><p>I installed ArgoCD in the Kubernetes cluster and exposed the ArgoCD server to access the UI:</p>
<p>  <code>kubectl create namespace argocd</code></p>
<p>  <code>kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml</code></p>
<p>  <code>kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'</code></p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724052850622/15cc4baa-fa48-4917-8730-a12c7020876b.png" alt class="image--center mx-auto" /></p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724052957598/24fc6c03-5a9a-47e8-9e05-57afd27728a5.png" alt class="image--center mx-auto" /></p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724052987333/080d6d8b-3b5a-4b52-8057-853df0dd2d36.png" alt class="image--center mx-auto" /></p>
<ol start="2">
<li><p><strong>Accessing ArgoCD UI:</strong></p>
<ul>
<li>I accessed the ArgoCD UI using the external IP obtained from the above command.</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724053077703/db2ef794-3d4b-4464-8aeb-30d63dba420a.png" alt class="image--center mx-auto" /></p>
<ol start="3">
<li><p><strong>Logging into ArgoCD:</strong></p>
<ul>
<li><p>The default username is <code>admin</code>. To retrieve the password, I decoded it from the <code>argocd-initial-admin-secret</code>:</p>
<p>  <code>kubectl get secret argocd-initial-admin-secret -n argocd -o jsonpath="{.data.password}" | base64 --decode</code></p>
</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724053203757/f5cdf8b0-65e1-4d98-a282-6433671bc66b.png" alt class="image--center mx-auto" /></p>
<ol start="4">
<li><p><strong>Creating an ArgoCD Application:</strong></p>
<ul>
<li>I created a new ArgoCD application by filling out the form with details such as app name, sync policy, GitHub repo link, cluster URL, and Helm files. Once created, ArgoCD automatically deployed the application to the Kubernetes cluster.</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724053296579/e05011e3-0a94-453b-bacc-cfc4080cc7e3.png" alt class="image--center mx-auto" /></p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724053963686/896625c8-6c14-419e-ab79-bddd4e0b94bd.png" alt class="image--center mx-auto" /></p>
<ol start="5">
<li><p><strong>Verifying the Deployment:</strong></p>
<ul>
<li>I verified that the application was deployed successfully by accessing it via the domain name mapped earlier.</li>
</ul>
</li>
</ol>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724053998287/313450e1-d1ec-4bbd-885c-e3aaa47932a1.png" alt class="image--center mx-auto" /></p>
<p>    <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724054040777/6ff2e8bd-9de0-4b69-82ce-86ae91c50a22.png" alt class="image--center mx-auto" /></p>
<ol start="6">
<li><p><strong>Testing the CI/CD Pipeline:</strong></p>
<ul>
<li><p>To ensure the CI/CD pipeline was working correctly, I made a small change to a static file (<code>home.html</code>) in the application, adding "by Abhishek Veeramalla" to the website home page. After committing this change to the <code>main</code> branch, the CI pipeline was triggered, which updated the Docker image tag and Helm chart.</p>
</li>
<li><p>ArgoCD detected the change and deployed the updated application to the Kubernetes cluster. I verified the deployment by checking the web application, which reflected the changes I made.</p>
</li>
</ul>
</li>
</ol>
<p><strong>Screenshots:</strong></p>
<ul>
<li>Screenshot of CI pipeline triggered after committing changes in GIT.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724054226397/41b5def2-784b-4f14-8175-ca5ea19a9bc9.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Screenshot of updated tag in values.yaml file and recently created tag within Docker hub.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724054340358/215ae752-8d67-42c7-b5fc-60e04c2961f6.png" alt class="image--center mx-auto" /></p>
<ul>
<li>Screenshot of web app accessed using host link with updated change in home page.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1724054445800/09225e59-58f1-4e51-a715-6e912300a9cb.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>This project provided hands-on experience with containerization, Kubernetes deployment, and CI/CD integration. There were challenges, particularly with ingress configuration and synchronization between CI/CD tools, but these were resolved through careful troubleshooting and configuration. The resulting deployment is secure, scalable, and automated, making it a robust solution for managing cloud-native applications.</p>
]]></content:encoded></item><item><title><![CDATA[Muggling Through with Kubernetes]]></title><description><![CDATA[🥣 The Struggling Potter
Once upon a time, there was a talented artist named Harry who crafted exquisite ceramic mugs. As word of his artistry spread far and wide, orders came pouring in. However, Harry soon struggled to keep up with the overwhelming...]]></description><link>https://devops-notes.hashnode.dev/muggling-through-with-kubernetes</link><guid isPermaLink="true">https://devops-notes.hashnode.dev/muggling-through-with-kubernetes</guid><category><![CDATA[#Mumshad Mannambeth]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Google]]></category><dc:creator><![CDATA[Priya T]]></dc:creator><pubDate>Mon, 22 Apr 2024 01:17:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1713744156685/1703285b-55cc-4a6f-bdde-d71f45dcc2f7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-the-struggling-potter">🥣 The Struggling Potter</h2>
<p>Once upon a time, there was a talented artist named Harry who crafted exquisite ceramic mugs. As word of his artistry spread far and wide, orders came pouring in. However, Harry soon struggled to keep up with the overwhelming demand and ensure safe delivery of the delicate mugs.</p>
<h2 id="heading-a-magical-solution-appears">A Magical Solution Appears ✨</h2>
<p>Desperate for help, Harry sought advice from a wise logistics expert, who introduced him to the wonders of Kubernetes, a powerful system that could transform his shipping process.</p>
<h3 id="heading-packaging-the-mugs-docker">Packaging the Mugs 📦(Docker)</h3>
<p>Before using Kubernetes, the consultant explained that it works best when applications are packaged into containers. Just as mugs need sturdy packaging to protect them during transit, applications need a consistent and isolated environment to run reliably in different shipping facilities (clusters). Among the various container technologies available, the consultant recommended Docker, which provides a lightweight, portable, and consistent way to package applications, ensuring they run seamlessly across different environments.</p>
<p><img src="https://pebpung.github.io/assets/img/2022/docker_image.png" alt="Docker로 쾌적한 딥러닝 실험 환경 구성하기 · ML감자" /></p>
<h3 id="heading-wrapping-the-packagespods">Wrapping the Packages🎁(Pods)</h3>
<p>After packing the mugs (applications) in Docker containers, Kubernetes wrapped these containers in gift-wrapped packages (Pods), adding an extra layer of protection, like wrapping a fragile mug in bubble wrap. Each Pod could contain one or more containers. However, it is recommended to have one container in a pod until it is a supporting container that is required to run the other container.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713737676787/8346e7de-4ff3-464a-8b81-236a86268878.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-the-shipping-fleet-nodes">The Shipping Fleet 🚚 (Nodes)</h3>
<p>Kubernetes then placed these Pods into vehicles or trucks (Nodes). Each Node could carry multiple Pods, and each Pod could contain one or more containers. The Nodes were responsible for transporting the cargo.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713738063516/1e2100b9-488b-4b5a-9e0f-63306ec49eaf.png" alt class="image--center mx-auto" /></p>
<p><strong>The Vehicle Crew 👷(Node Components)</strong></p>
<p>Each Node had its own crew to ensure smooth operations:</p>
<ul>
<li><p>The driver <strong>(Kubelet)</strong>, responsible for managing the Pods on their assigned Node and communicating with the Master Node.</p>
</li>
<li><p>The loading bay <strong>(Container Runtime)</strong>, preparing and loading the containers onto the Node.</p>
</li>
<li><p>The navigation system <strong>(Kube Proxy)</strong>, facilitating efficient communication between Pods and guiding the vehicles along optimal routes.</p>
</li>
</ul>
<h3 id="heading-the-logistics-headquartersmaster-node">The Logistics Headquarters🏢(Master Node)</h3>
<p>However, before the Nodes could begin their journey, they needed instructions and coordination from a central logistics headquarters (Master Node).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1713738132409/b67ee228-a0da-428d-9e67-0f84fa65fc1b.png" alt class="image--center mx-auto" /></p>
<p><strong>The Logistics Team 🧑‍✈️(Master Components)</strong></p>
<p>At the heart of the Master Node, there was a dedicated logistics team:</p>
<ul>
<li><p>The communication hub <strong>(API Server)</strong>, receiving and processing all incoming orders and requests.</p>
</li>
<li><p>The central database <strong>(etcd)</strong>, storing and tracking every detail about the cargo, vehicles, routes, and more.</p>
</li>
<li><p>The expert route planner <strong>(Scheduler)</strong>, strategically assigning Pods to the most suitable Nodes based on available resources and requirements.</p>
</li>
<li><p>The operations manager <strong>(Controller Manager)</strong>, continuously monitoring the shipping process and taking corrective actions when needed.</p>
</li>
</ul>
<h3 id="heading-the-shipping-networkcluster">The Shipping Network🌲(Cluster)</h3>
<p>Together, the Master Node and Nodes formed a vast shipping network (Cluster) capable of transporting and managing Pods across multiple locations.</p>
<p><img src="https://www.researchgate.net/publication/353390819/figure/fig3/AS:1048498610905088@1626992957043/Kubernetes-cluster-architecture.ppm" alt="Kubernetes cluster architecture. | Download Scientific Diagram" /></p>
<h3 id="heading-customer-access-points-services">Customer Access Points 🏪(Services)</h3>
<p>As orders poured in, Harry utilized access points called Services, which acted as retail stores or outlets, providing a single point for customers to purchase and receive their mugs. Services not only served as entry points or gateways, allowing customers to access Harry's shipping operation from outside, but also offered load balancing capabilities by distributing incoming traffic across multiple Pods running the same application. This ensured no single Pod was overwhelmed, providing better reliability and scalability. Moreover, Services facilitated service discovery, making it easier for different components within the shipping operation to communicate with each other, even if their locations or IP addresses changed.</p>
<p><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTN8esSMR8BV33ZTdNhtzyL3ghW93TqjGxSQ5Y8t4tTlg&amp;s" alt="Learn Kubernetes Service Load Balancer with Examples" /></p>
<p>Service Types:</p>
<ul>
<li><p><strong>ClusterIP Service</strong>: An internal access point, accessible only within the shipping network (cluster).</p>
</li>
<li><p><strong>NodePort Service</strong>: A dedicated access point on each Node, allowing direct access from outside the shipping network.</p>
</li>
<li><p><strong>LoadBalancer Service</strong>: An advanced access point with an external load balancer, distributing traffic across multiple Nodes for high availability and scalability.</p>
</li>
</ul>
<p>Service discovery enabled Pods and Nodes to locate and communicate with each other seamlessly, even as their underlying infrastructure changed, ensuring a resilient and efficient shipping operation.</p>
<h3 id="heading-the-management-tools"><strong>The Management Tools 💻📄</strong></h3>
<p>To manage this intricate shipping operation, Harry relied on two essential tools:</p>
<ul>
<li><p><strong>Kubectl</strong> 💻: The trusty shipping management software, allowing Harry to interact with the Kubernetes cluster and issue commands to deploy, scale, or manage their mugs (applications) and associated resources (Pods, Nodes, Services, etc.).</p>
</li>
<li><p><strong>Manifest Files (YAML Files)</strong> 📄: Acting as detailed shipping instructions, these YAML files specified the desired state of Harry's Kubernetes resources, from the number of replicas required to resource allocations and configurations.</p>
</li>
</ul>
<h3 id="heading-the-resilient-and-efficient-operation">The Resilient and Efficient Operation ⚡⚡</h3>
<p>Harry's business could effortlessly scale by adding or removing Nodes (trucks) to match demand. In case of vehicle breakdowns, Kubernetes automatically rescheduled affected Pods to healthy Nodes, ensuring minimal disruption. Communication between Nodes was seamless, with the navigation system (Kube Proxy) enabling efficient coordination and load balancing.</p>
<h3 id="heading-a-thriving-shipping-empire">A Thriving Shipping Empire 🌍☕</h3>
<p>Thanks to the well-orchestrated shipping operation of Kubernetes, Harry's ceramic mug business flourished, delighting customers with prompt and secure deliveries. As the tale spread, businesses embraced Kubernetes, recognizing its benefits and challenges.</p>
<h2 id="heading-key-takeaways-and-drawbacks">Key Takeaways and Drawbacks:</h2>
<ul>
<li><p>Kubernetes simplified the management of complex, distributed applications by abstracting away underlying infrastructure details.</p>
</li>
<li><p>Services provided an isolation layer, allowing Harry to scale, update, or replace shipping components without disrupting customer experience.</p>
</li>
<li><p>However, Kubernetes introduced a steep learning curve due to its complexity and required diligent configuration and monitoring for security.</p>
</li>
<li><p>Running and maintaining the control plane and system components added overhead, potentially leading to vendor lock-in (vendors like Amazon Web Services (AWS), Google Cloud Platform (GCP), or Microsoft Azure).</p>
</li>
</ul>
<p>Despite these drawbacks, for businesses needing to manage and scale containerized applications efficiently, Kubernetes emerged as the go-to solution, particularly in scenarios involving multiple interconnected applications, mission-critical workloads demanding high availability, rapidly fluctuating demand, and the need for consistent packaging and deployment across different environments.</p>
<p>As the magical tale spread, more businesses recognized the transformative power of Kubernetes, embracing it as the de facto standard for container orchestration and ushering in a new era of seamless application shipping, just like Harry's precious mugs reaching delighted customers worldwide! 🌍☕</p>
]]></content:encoded></item></channel></rss>