<?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" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Amit Maurya on Medium]]></title>
        <description><![CDATA[Stories by Amit Maurya on Medium]]></description>
        <link>https://medium.com/@ammaurya46?source=rss-357aad067a18------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*T_kOHqyGQA2_afBLZAeCiA.jpeg</url>
            <title>Stories by Amit Maurya on Medium</title>
            <link>https://medium.com/@ammaurya46?source=rss-357aad067a18------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 24 May 2026 02:25:53 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@ammaurya46/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Boost GitHub Actions Speed with Effective Dependency Caching]]></title>
            <link>https://towardsaws.com/boost-github-actions-speed-with-effective-dependency-caching-10f79714ca9a?source=rss-357aad067a18------2</link>
            <guid isPermaLink="false">https://medium.com/p/10f79714ca9a</guid>
            <category><![CDATA[devops-practice]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[github-actions]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[cicd]]></category>
            <dc:creator><![CDATA[Amit Maurya]]></dc:creator>
            <pubDate>Mon, 06 Jan 2025 08:02:47 GMT</pubDate>
            <atom:updated>2025-01-06T16:36:17.653Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/799/1*JwgH46qTCYkA4VUyXgKMbg.png" /></figure><p>As DevOps Engineers, we are in the world of “automation.” From writing scripts, whether in BASH or Python, to creating CI/CD pipelines to automate the whole software development process to deployment, CI/CD (Continuous Integration and continuous development) are essential parts of the software development process and GitHub Actions became the most popular tool in automating these process.</p><p>In this blog, we will explore GitHub Actions where we will see the effective caching strategy to follow in multiple applications because caching plays a very important role in making our pipeline execution faster and this improves the software delivery processes. Before, moving forward check out my previous blogs:</p><p><a href="https://medium.com/towards-aws/building-a-serverless-web-application-with-aws-lambda-api-gateway-dynamodb-s3-7e22bfb7a1c4"><strong>Building a Serverless Web Application with AWS Lambda, API Gateway, DynamoDB, S3</strong></a></p><p><a href="https://medium.com/towards-aws/end-to-end-devops-for-a-golang-web-app-docker-eks-aws-ci-cd-f7793e230ae9"><strong>End-to-End DevOps for a Golang Web App: Docker, EKS, AWS CI/CD</strong></a></p><p><a href="https://medium.com/@ammaurya46/deploying-your-website-on-aws-s3-with-terraform-57337a80e729"><strong>Deploying Your Website on AWS S3 with Terraform</strong></a></p><p><a href="https://medium.com/aws-in-plain-english/learn-how-to-deploy-scalable-3-tier-applications-with-aws-ecs-563e476206e4"><strong>Learn How to Deploy Scalable 3-Tier Applications with AWS ECS</strong></a></p><h3>Introduction to GitHub Actions and Dependency Caching</h3><p>Nowadays, most companies are migrating towards GitHub Actions from Jenkins because of security issues and Jenkins is self-hosted for most of the companies so we need to maintain the servers at our data center. GitHub Actions is another CI/CD platform where developers can automate their workflows directly within the GitHub repositories.</p><p>In GitHub Actions many features enhance the security, and fill some of the bottlenecks in the pipeline but when it comes to dependency caching many users often face performance bottlenecks, especially when installing dependencies or repeating tasks across multiple jobs. Dependency Caching is a technique that should be followed to decrease the pipeline build time which will also decrease the resource consumption. By caching the artifacts, and libraries we can use these as artifacts in the other builds also.</p><p>In GitHub Actions, it has the built-in mechanism through the actions/cache actions, where users can cache the dependencies by using this action in the pipeline.</p><h3>Best Practices for Implementing Dependency Caching</h3><ol><li><strong>Use Effective Cache Keys:</strong> Hash key files like package.json or requirements.txt to keep the cache relevant.</li><li><strong>Avoid Cache Conflicts:</strong> Use unique keys for different environments or branches to prevent mix-ups.</li><li><strong>Implement Cache Invalidation:</strong> Change cache keys when dependencies update.</li><li><strong>Manage Cache Size:</strong> Big caches can slow things down, so stick to caching only the essential files.</li></ol><h3>How Caching Works in GitHub Actions</h3><p>Now, we will implement the caching action in the NodeJs application, where it will cache the Docker image layers by using the gha cache, i.e. GitHub Actions cache, which is by default. Bit GitHub Actions cache provides only caching storage of 10GB, so most corporate environments use the remote shared cache to store artifacts on Nexus or AWS CodeArtifacts, and for Docker Builds, they can use Harbor or DockerHub.</p><p>If I had to go with like I want to store node_modules for NodeJs or requirements.txt (venv) for Python we can use GitHub Actions Cache or S3-compatible storage (Minio). For now, let’s implement docker caching layers on the GitHub Actions cache and check the build speed.</p><p>GitHub Code: <a href="https://github.com/amitmaurya07/DevSecOps-GHA">github.com/amitmaurya07/DevSecOps-GHA</a></p><p><strong>.github/workflows/pipeline.yml:</strong></p><pre>name : NodeJs Application and Caching<br>on:<br>    workflow_dispatch:<br>    push:<br>        branches:<br>            - master<br>jobs:<br>    docker-build:<br>        runs-on: ubuntu-latest<br>        steps:<br>            - name: Checkout Code<br>              uses: actions/checkout@v3<br><br>            - name: Cache Docker layers<br>              uses: actions/cache@v3<br>              with:<br>                path: /tmp/.buildx-cache<br>                key: ${{ runner.os }}-buildx-${{ hashFiles(&#39;**/Dockerfile&#39;) }}<br>                restore-keys: |<br>                  ${{ runner.os }}-buildx-<br><br>            - name: Login to docker-hub<br>              uses: docker/login-action@v1<br>              with:<br>                username: ${{ vars.DOCKER_USERNAME }}<br>                password: ${{ secrets.docker_pat }}<br><br>            - name: Set up Docker Buildx<br>              uses: docker/setup-buildx-action@v3<br><br>            - name: Build and Push Image<br>              uses: docker/build-push-action@v6<br>              with:<br>                context: .<br>                push: true<br>                tags: &quot;amaurya07/devsecops_app:${{ github.ref_name }}&quot;<br>                cache-from: type=local,src=/tmp/.buildx-cache<br>                cache-to: type=local,dest=/tmp/.buildx-cache,new=true</pre><p>In the first part, we had given the name of the pipeline “NodeJs Application and Caching“ then we had set the trigger action by defining on when the pipeline will trigger here the pipeline will trigger on push from the master branch and workflow_dispatch means that we can trigger manually pipeline when we want. It means when anything is pushed on the master branch the pipeline is executed automatically.</p><pre>jobs:<br>    docker-build:<br>        runs-on: ubuntu-latest<br>        steps:<br>            - name: Checkout Code<br>              uses: actions/checkout@v3<br><br>            - name: Cache Docker layers<br>              uses: actions/cache@v3<br>              with:<br>                path: /tmp/.buildx-cache<br>                key: ${{ runner.os }}-buildx-${{ hashFiles(&#39;**/Dockerfile&#39;) }}<br>                restore-keys: |<br>                  ${{ runner.os }}-buildx-<br><br>            - name: Login to docker-hub<br>              uses: docker/login-action@v1<br>              with:<br>                username: ${{ vars.DOCKER_USERNAME }}<br>                password: ${{ secrets.docker_pat }}<br><br>            - name: Set up Docker Buildx<br>              uses: docker/setup-buildx-action@v3<br><br>            - name: Build and Push Image<br>              uses: docker/build-push-action@v6<br>              with:<br>                context: .<br>                push: true<br>                tags: &quot;amaurya07/devsecops_app:${{ github.ref_name }}&quot;<br>                cache-from: type=local,src=/tmp/.buildx-cache<br>                cache-to: type=local,dest=/tmp/.buildx-cache,new=true</pre><p>In the second part, we defined the job after the trigger i.e. docker-build then we defined the runs-on which means where the steps in the job that are defined are executed so we defined ubuntu-latest which is provided by GitHub Actions runners. In the Actions tab of the repository navigate to the Runners section and check the name of the runner in Standard GitHub-hosted runners.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2nX9_0_EzOwB0U6m" /></figure><p>Now come, the steps that are defined in a job there are 4 steps in the jobs (Checkout Code, Login to DockerHub, Docker Buildx, then Docker Build and Push)</p><ol><li><strong>Checkout Code:</strong> Actions is actions/checkout@v3 which will checkout the source code from the repository.</li><li><strong>Cache Docker Layers:</strong> Actions is actions/cache@v3 where it will cache the docker layers in locally in the /tmp directory where the key is ${{ runner.os }}-buildx-${{ hashFiles(&#39;**/Dockerfile&#39;) }} that means the compute the hashes of content inside the Dockerfile whenever the Dockerfile changes then a new cache will be used.</li><li><strong>Login to DockerHub:</strong> Actions is docker/login-action@v1 where it uses the variable and secrets that are in the repository for login to dockerhub to push the image.</li><li><strong>Docker Buildx:</strong> Actions is docker/setup-buildx-action@v3 where we need to set up the docker build as we are using the build and push action in the next step and it is also used to cache the docker image layers and it can build multiple stages or architectures in parallel, reducing build time for complex Dockerfiles.</li><li><strong>Docker Build and Push:</strong> In this step set the context to the present working directory where the Dockerfile is present then set the push to true with tags then the cache-from has the type=local where the src is set to the /tmp directory where the cache is stored in the earlier step and in cache-to is also set to type=local which has the new=true means forces the creation of new caches rather than updating the existing caches.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*LOjcAcO5Stc3x0bT" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*rfh5_TkwV52yZWkk" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jh7kMaupPYUNjUi0" /></figure><p>As we can see in the next build it was importing the cache from the gha and all the layers are cached in the next build.</p><h3>Caching Dependency Examples for Popular Languages and Tools</h3><h3>Node.js</h3><pre>- uses: actions/cache@v3<br>  with:<br>    path: node_modules<br>    key: node-${{ hashFiles(&#39;package-lock.json&#39;) }}</pre><h3>Python</h3><pre>- uses: actions/cache@v3<br>  with:<br>    path: ~/.cache/pip<br>    key: pip-${{ hashFiles(&#39;requirements.txt&#39;) }}</pre><h3>Java (Maven)</h3><pre>- uses: actions/cache@v3<br>  with:<br>    path: ~/.m2/repository<br>    key: maven-${{ hashFiles(&#39;pom.xml&#39;) }}</pre><h3>Conclusion: The Future of Fast CI/CD with GitHub Actions</h3><p>Dependency caching is a great way to speed up your CI/CD pipelines with GitHub Actions. By using the right caching strategies, you can cut down build times, get faster feedback, and save on resources. Give caching a try today to create workflows that are more efficient and scalable.</p><p>GitHub Code: <a href="https://github.com/amitmaurya07/DevSecOps-GHA">https://github.com/amitmaurya07/DevSecOps-GHA</a></p><p>Twitter : <a href="http://x.com/amitmau07">x.com/amitmau07</a></p><p>LinkedIn: <a href="http://linkedin.com/in/amit-maurya07">linkedin.com/in/amit-maurya07</a></p><p>If you have any queries you can drop the message on LinkedIn and Twitter.</p><p><strong>Support My Work</strong> ☕️<br>If you found this blog helpful and want to support my work, consider <a href="http://buymeacoffee.com/amit_mau07">buying me a coffee</a>! Your support keeps me motivated to create more content like this.</p><p>Thank you for your support!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=10f79714ca9a" width="1" height="1" alt=""><hr><p><a href="https://towardsaws.com/boost-github-actions-speed-with-effective-dependency-caching-10f79714ca9a">Boost GitHub Actions Speed with Effective Dependency Caching</a> was originally published in <a href="https://towardsaws.com">Towards AWS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why Python is Essential for DevOps Engineers]]></title>
            <link>https://medium.com/@ammaurya46/why-python-is-essential-for-devops-engineers-b2572e7661de?source=rss-357aad067a18------2</link>
            <guid isPermaLink="false">https://medium.com/p/b2572e7661de</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[python]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[devops-practice]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Amit Maurya]]></dc:creator>
            <pubDate>Mon, 30 Dec 2024 06:38:35 GMT</pubDate>
            <atom:updated>2024-12-30T06:38:35.279Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0sc5_eKXO652-5llVnK4dA.png" /></figure><p>In today’s software development world, many programming languages are used for making software, solving real-world problems, creating games, and more. As DevOps engineers, we enter the world of automation, always creating CI/CD pipelines to deploy our code faster and more efficiently. When the word “automation“ comes up in the IT world, Python has proven to be the best way to solve complex problems efficiently. By writing Python programs, IT engineers’ and DevOps engineers’ lives become easier, as they just write the scripts and the output appears in front of them in just a few seconds.</p><p>Python is at the heart of DevOps workflows used to automate tasks such as deleting unused EBS volumes in AWS, managing infrastructure, or filtering out the CRITICAL or ERROR keywords from log files. In this blog, we’ll explore why Python is an indispensable skill for DevOps engineers, its key use cases, and how you can start your Python journey.</p><h3>Role of DevOps in Modern IT</h3><p>DevOps creates a bridge between the Development team and the Operations team. It is a culture or practice aimed at improving the software development lifecycle and contributing to business growth. As a DevOps engineer, automation is crucial for reducing manual work, minimizing errors, and boosting efficiency. This is where Python excels — its simplicity and power make it the preferred language for automating repetitive tasks and building strong workflows.</p><h3>Why Python is Popular in DevOps</h3><p>When we talk about scripting or automating tasks we generally use BASH scripting which is most commonly used in Linux environments but when it comes to complex automation most DevOps engineers follow Python as the scripting language as it has good community support, and extensive libraries.</p><ol><li>Easy to Use</li><li>Cross-Platform Support</li><li>A rich ecosystem of libraries like boto3 for AWS, paramiko for SSH, and kubernetes for container orchestration.</li><li>Integration with other DevOps tools</li></ol><h3>Python Use-Cases in DevOps</h3><h4>1. Automating Repetitive Tasks</h4><ul><li>Setting up servers automatically</li><li>Making it easier to deploy apps</li><li>Using Python scripts to check out logs</li></ul><h4>2. Infrastructure as Code (IaC)</h4><ul><li>Managing infrastructure with code</li><li>Adding more features with Python scripts</li><li>Working with IaC tools like Terraform and Pulumi</li></ul><h4>3. Hooking into CI/CD Pipelines</h4><ul><li>Customizing how builds and deployments work</li><li>Handling API calls</li><li>Creating plugins for tools like Jenkins and GitLab CI/CD</li></ul><h4>4. Cloud Automation</h4><ul><li>Automating tasks in AWS, Azure, and GCP</li><li>Using SDKs like boto3, azure-sdk, and google-cloud-sdk</li><li>Doing things like provisioning resources, scaling, and monitoring</li></ul><h4>5. Easy Monitoring and Logging</h4><ul><li>Collecting metrics with Prometheus-client</li><li>Building dashboards using Flask</li><li>Checking out logs with Loguru</li><li>Integrating with Grafana and Elasticsearch</li></ul><h4>6. Containerization and Orchestration</h4><ul><li>Managing Docker containers with Python APIs</li><li>Automating Kubernetes operations</li><li>Working with Kubernetes custom resources</li></ul><h4>7. Big Ecosystem and Community Support</h4><ul><li>Libraries for API calls: requests</li><li>Testing frameworks: pytest</li><li>An active community for help and updates</li></ul><h4>8. Cross-Platform Compatibility</h4><ul><li>Running scripts easily on Linux, Windows, and macOS</li><li>Great for different infrastructure setups</li></ul><h4>9. Easy to Learn and Read</h4><ul><li>Simple syntax for quick learning</li><li>Good for engineers without a programming background</li><li>Helps junior engineers contribute effectively</li></ul><h3>Python Libraries Every DevOps Engineer Should Know</h3><ul><li>boto3: Easily manage AWS services with code.</li><li>paramiko: Automate SSH and manage remote servers effortlessly.</li><li>kubernetes: Work smoothly with Kubernetes clusters.</li><li>os and subprocess: Perform system tasks and run shell commands with ease.</li><li>fabric: Simplify tasks on remote servers.</li><li>requests: Make HTTP requests for API interactions a breeze.</li></ul><h3>Conclusion</h3><p>Python isn’t just a programming language — it’s like a best friend for DevOps engineers. Its flexibility, simplicity, and strong libraries make it a must-have tool for automating tasks, managing infrastructure, and improving workflows. Whether you’re just beginning or aiming to boost your skills, learning Python can elevate your DevOps career.</p><h3>Resources to follow to learn Python</h3><ol><li><a href="https://automatetheboringstuff.com/">Automate the Boring Stuff with Python</a> by Al Sweigart</li><li><a href="https://youtu.be/ix9cRaBkVe0?si=9rLEIhkbqBi1dwS_">Python Full Course Video</a> By BroCode</li><li><a href="http://python.org/">Python.org</a> Official Documentation</li></ol><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b2572e7661de" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Achieving High Availability and Scalability in AWS: Best Practices for Modern Cloud Architectures]]></title>
            <link>https://towardsaws.com/achieving-high-availability-and-scalability-in-aws-best-practices-for-modern-cloud-architectures-8754e3fa9a0d?source=rss-357aad067a18------2</link>
            <guid isPermaLink="false">https://medium.com/p/8754e3fa9a0d</guid>
            <category><![CDATA[devops-training]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[aws-lambda]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[high-availability]]></category>
            <dc:creator><![CDATA[Amit Maurya]]></dc:creator>
            <pubDate>Sun, 01 Dec 2024 04:11:25 GMT</pubDate>
            <atom:updated>2024-12-01T04:11:25.740Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8y3jJoGi1CdhQj1cxZssTQ.png" /></figure><p>In today’s computing industry these two terms you have heard a lot or you have heard the term how to achieve zero downtime which is very crucial in application and business needs. In this article, we will be learning about High Availability, and Scalability and how we can achieve this in Cloud Modern architectures (AWS).</p><p>By keeping our system highly available and scalable our business would grow more and our end-users would be more happy. These two terms are most asked questions on System Design Interview by big tech companies (FAANG) so it is good to know these two terms in detail and in AWS cloud perspective.</p><p>Before heading to Introduction section, do read my latest blogs:</p><p><a href="https://medium.com/towards-aws/building-a-serverless-web-application-with-aws-lambda-api-gateway-dynamodb-s3-7e22bfb7a1c4"><strong>Building a Serverless Web Application with AWS Lambda, API Gateway, DynamoDB, S3</strong></a></p><p><a href="https://medium.com/towards-aws/end-to-end-devops-for-a-golang-web-app-docker-eks-aws-ci-cd-f7793e230ae9"><strong>End-to-End DevOps for a Golang Web App: Docker, EKS, AWS CI/CD</strong></a></p><p><a href="https://medium.com/@ammaurya46/deploying-your-website-on-aws-s3-with-terraform-57337a80e729"><strong>Deploying Your Website on AWS S3 with Terraform</strong></a></p><p><a href="https://medium.com/aws-in-plain-english/learn-how-to-deploy-scalable-3-tier-applications-with-aws-ecs-563e476206e4"><strong>Learn How to Deploy Scalable 3-Tier Applications with AWS ECS</strong></a></p><h3>High Availability</h3><p>As a DevOps Engineer, our end task is not deploy the only application to the Kubernetes cluster, or on AWS services but to ensure that the system is available every time to the end-user. So, to keep the system available we need to make the system highly available.</p><p>To measure high availability we need to keep the system’s percentage in five 9’s means if the system’s or application has <strong>90%</strong> then the system is down for <strong>36.5 days</strong> which is very bad for the end-user or if the system has <strong>99.999%</strong> then system will be down for <strong>6 minutes a year</strong> which has become standard for achieving the HA for most the companies. Remember any system would not be 100% available.</p><p>To understand this in a better way, let’s take an example of grocery store which is running 24/7. After some-day the grocery store needs an maintenance so he shuts down the grocery store which means that the grocery store would not be available for few days which results in business loss. So to keep the business running every time, what store owner did he opens another grocery store in nearby so that if any customer comes he/she can go to another grocery store during maintenance of another grocery store which keeps the business running smoothly and by this whenever any sales comes like Black Friday the crowd is distributed to 2 stores.</p><p>By this it ensures the <strong>business continues to operate without interruptions</strong>, which is the essence of <strong>High Availability.</strong></p><p>Now, let’s understand this in terms of AWS cloud perspective.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*Luqc1Gjvtrr47TT5.png" /></figure><p>This picture is AWS architecture, which depicts the High Availability on AWS.</p><p>Let’s understand the previous example of grocery store in AWS terms.</p><ol><li><strong>Multiple Stores (Redundancy) → AWS Availability Zones (AZs)</strong></li></ol><ul><li>Like operating the grocery stores in multiple locations keeps the business running smoothly. In AWS we had to deploy the infrastructure in multiple AZ’s (Availability Zones).</li><li>If one AZ fails in AWS like our one store goes in maintenance the other store is operating likewise the other AZ will be working to handle customer’s workloads.</li></ul><p><strong>2. Spreading Demand Across Stores (Load Balancing) → Elastic Load Balancer (ELB)</strong></p><p>Like the festival came Black Friday so the crowd is distributed on 2 stores meanwhile in AWS we use Load Balancing to distribute the traffic efficiently so that one server has not the most requests.</p><p><strong>3. Shared Inventory (Centralized Data) → Shared Databases or S3</strong></p><p>In grocery store it uses the centralized data to keep the stocks updated for every store. Likewise in AWS we use database to keep our data safe, secure and highly available by deploying AWS RDS with Multi-AZ feature or DynamoDB.</p><p><strong>4. Restocking (Scaling) → Auto Scaling</strong></p><p>Just like when any festival season came users increased to buy items which results in huge spikes in users. In AWS to manage the traffic to scale efficiently Auto Scaling is the feature that scale the workload by setting Auto Scaling Groups on AWS so that when the users increases the workloads increased when the user decreases the workload comes to an normal state which also results in cost optimization.</p><p><strong>5. Delivering Popular Items Globally (Global Content Delivery) → CloudFront</strong></p><p>CloudFront is the feature in AWS which enables the static content to make available to every user that is distributed globally. With the help of CDN (CloudFront) it ensures there no downtime to end user to accessing any static website.</p><h3>Scalability</h3><p>Now, let’s talk about scalability. It’s all about how a system or an application can handle more or fewer resources without losing performance, reliability, or availability. Basically, it’s about keeping things running smoothly no matter how much you throw at it.</p><p>There are 3 types of scalability:</p><ol><li><strong>Vertical Scalability:</strong></li></ol><p>Vertical Scalability means <strong>scaling UP and scaling DOWN</strong> which means increasing the capacity of the single resource.</p><p><strong>2. Horizontal Scalability:</strong></p><p>In this type of scalability, means <strong>scale IN and scale OUT</strong> means to increase the resources, multiply the resource adding more servers.</p><p><strong>3. Elastic Scalability:</strong></p><p>In AWS by defining AutoScaling we can achieve the elastic scalability to dynamically adjust the resources based on real-time demands.</p><p>Now, let’s understand the grocery store example in terms of scalability in AWS perspective.</p><ol><li><strong>Adding More Cashiers (Vertical Scaling):</strong></li></ol><p>Like in festive season in High Availability we had increased the stores which balances the crowd. Now, in terms of scalability (Vertical Scaling) we need to increase the capacity to handle more people in the stores. So, we increased cashiers to handle vertical scaling but in terms of AWS in EC2 service we increase the capacity from t2.micro to m5.large.</p><p><strong>2. Opening More Stores (Horizontal Scaling):</strong></p><p>To handle more people not to make the crowd overloaded in one store we opened the another store to handle the crowd efficiently. This what makes horizontal scaling. In AWS we can increase the EC2 instances by setting ASG (Auto Scaling Groups) to increase the workloads based on traffic demands.</p><p><strong>3. Temporary Staff (Elastic Scaling):</strong></p><p>During the busy season, the store hires extra workers and opens another locations. Once the festival season ends, they return to their normal staff levels. In AWS this also done by Auto Scaling which dynamically adds resources based on real-time that saves the cost.</p><p><strong>4. Scaling Data and Storage</strong></p><ol><li>Now, to prevent running out of stock for grocery stores we had to keep the stocks available 24/7 for this in AWS that manages the scaling storage and databases:</li><li><strong>Amazon RDS with Read Replicas:</strong> It add the replicas to distribute database read traffic with Multi-AZ feature.</li><li><strong>Amazon S3:</strong> Automatically scales to store unlimited amounts of data.</li></ol><h3>Conclusion</h3><p>In this article, we learned about High Availability and scalability how to achieve this in AWS cloud. These two are essential pillars in building the resilient system and fault-tolerance that ensures the minimal downtime or zero downtime. In upcoming posts, we will delve into the creation of various AWS services, DevOps tools, CNCF tools and their automation with Terraform and also do projects with DevSecOps approach. Stay tuned for the next blog!</p><p>GitHub Code : <a href="https://github.com/amitmaurya07"><strong>github.com/amitmaurya07</strong></a></p><p>Twitter : <a href="http://x.com/amitmau07"><strong>x.com/amitmau07</strong></a></p><p>LinkedIn : <a href="http://linkedin.com/in/amit-maurya07"><strong>linkedin.com/in/amit-maurya07</strong></a></p><p>If you have any queries you can drop the message on LinkedIn and Twitter.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8754e3fa9a0d" width="1" height="1" alt=""><hr><p><a href="https://towardsaws.com/achieving-high-availability-and-scalability-in-aws-best-practices-for-modern-cloud-architectures-8754e3fa9a0d">Achieving High Availability and Scalability in AWS: Best Practices for Modern Cloud Architectures</a> was originally published in <a href="https://towardsaws.com">Towards AWS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Essential Dockerfile Instructions: Best Practices for Optimized Containers]]></title>
            <link>https://blog.devops.dev/essential-dockerfile-instructions-best-practices-for-optimized-containers-10bae3e29cab?source=rss-357aad067a18------2</link>
            <guid isPermaLink="false">https://medium.com/p/10bae3e29cab</guid>
            <category><![CDATA[development]]></category>
            <category><![CDATA[dockerfiles]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[docker-compose]]></category>
            <category><![CDATA[docker]]></category>
            <dc:creator><![CDATA[Amit Maurya]]></dc:creator>
            <pubDate>Sun, 24 Nov 2024 10:55:32 GMT</pubDate>
            <atom:updated>2024-11-25T14:16:27.585Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*XAOp2Q3FUc9cnK2S.jpeg" /></figure><p>In this article, we will cover important Dockerfile Instructions that should be included in Dockerfile to make the container secure, follows the best practices and optimized for production.</p><p>Before heading to Introduction section, do read my latest blogs:</p><p><a href="https://medium.com/towards-aws/building-a-serverless-web-application-with-aws-lambda-api-gateway-dynamodb-s3-7e22bfb7a1c4">Building a Serverless Web Application with AWS Lambda, API Gateway, DynamoDB, S3</a></p><p><a href="https://medium.com/towards-aws/end-to-end-devops-for-a-golang-web-app-docker-eks-aws-ci-cd-f7793e230ae9">End-to-End DevOps for a Golang Web App: Docker, EKS, AWS CI/CD</a></p><p><a href="https://medium.com/@ammaurya46/deploying-your-website-on-aws-s3-with-terraform-57337a80e729">Deploying Your Website on AWS S3 with Terraform</a></p><p><a href="https://medium.com/aws-in-plain-english/learn-how-to-deploy-scalable-3-tier-applications-with-aws-ecs-563e476206e4">Learn How to Deploy Scalable 3-Tier Applications with AWS ECS</a></p><h3>FROM Instruction</h3><pre>FROM python:3.10-slim</pre><p>Always use smaller size images to make the image more optimized.</p><h3>EXPOSE Instruction</h3><pre>EXPOSE 8080</pre><p>Include EXPOSE instruction to document the port number on which container listens on.</p><h3>USER Instruction</h3><pre>USER nonroot</pre><p>Always avoid to run the container as non-root user because of security reasons.</p><h3>COPY &amp; ADD Instruction</h3><pre>COPY requirements.txt /app/<br>ADD app.tar.gz /app/</pre><p>Always prefer COPY instruction over ADD instruction to copy the files into the image. Use ADD instruction only when you need to extract the files.</p><h3>HEALTHCHECK Instruction</h3><pre>HEALTHCHECK --interval=30s CMD curl -f http://localhost/ || exit 1</pre><p>Include HEALTHCHECK instruction always to test the container is working properly or not.</p><h3>RUN Instruction</h3><pre>RUN apt-get update &amp;&amp; apt-get install -y curl &amp;&amp; rm -rf /var/lib/apt/lists/*</pre><p>Always use single RUN Instruction to minimize the number of layers so that our build will become faster.</p><h3>LABEL Instruction</h3><pre>LABEL maintainer=&quot;Amit Maurya&quot;<br>LABEL version=&quot;1.0&quot;</pre><p>In an organisation there are multiple developers, devops engineers are working there so to check who has made the Dockerfile or to contact you, always use LABEL Instruction for documentation, versioning.</p><h3>WORKDIR Instruction</h3><pre>WORKDIR /app</pre><p>Always use WORKDIR to not to use RUN cd command to get inside the directory. This instruction will set the working directory in the image and copies all the files into this working directory only.</p><h3>ARG Instruction</h3><pre>ARG APP_VERSION=1.0<br>ARG API_KEY<br>ENV API_KEY=${API_KEY}</pre><p>Include ARG instruction to create build-time variables so that when the image is build we can pass the value at build time. It is used for secrets and versioning.</p><pre>docker build --build-arg APP_VERSION=2.0 .<br>docker build --build-arg API_KEY=your_api_key .</pre><h3>CMD Instruction</h3><pre>CMD [&quot;python&quot;, &quot;app.py&quot;]</pre><p>Use CMD Instruction to specify the default command to run when the container starts.</p><h3>ENTRYPOINT Instruction</h3><pre>ENTRYPOINT [&quot;sh&quot;, &quot;-c&quot;]</pre><p>This instruction is use to configure the container to run as executable. CMD command can be override by ENTRYPOINT instruction.</p><h3>Conclusion</h3><p>In upcoming posts, we will delve into the creation of various AWS services, DevOps tools, CNCF tools and their automation with Terraform and also do projects with DevSecOps approach. Stay tuned for the next blog!</p><p>GitHub Code : <a href="https://github.com/amitmaurya07">github.com/amitmaurya07</a></p><p>Twitter : <a href="http://x.com/amitmau07">x.com/amitmau07</a></p><p>LinkedIn : <a href="http://linkedin.com/in/amit-maurya07">linkedin.com/in/amit-maurya07</a></p><p>If you have any queries you can drop the message on LinkedIn and Twitter.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=10bae3e29cab" width="1" height="1" alt=""><hr><p><a href="https://blog.devops.dev/essential-dockerfile-instructions-best-practices-for-optimized-containers-10bae3e29cab">Essential Dockerfile Instructions: Best Practices for Optimized Containers</a> was originally published in <a href="https://blog.devops.dev">DevOps.dev</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a Serverless Web Application with AWS Lambda, API Gateway, DynamoDB, S3]]></title>
            <link>https://towardsaws.com/building-a-serverless-web-application-with-aws-lambda-api-gateway-dynamodb-s3-7e22bfb7a1c4?source=rss-357aad067a18------2</link>
            <guid isPermaLink="false">https://medium.com/p/7e22bfb7a1c4</guid>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[serverless]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[aws-lambda]]></category>
            <category><![CDATA[aws-certification]]></category>
            <dc:creator><![CDATA[Amit Maurya]]></dc:creator>
            <pubDate>Wed, 20 Nov 2024 03:36:07 GMT</pubDate>
            <atom:updated>2024-11-20T03:36:07.120Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*J7pV_W2sfKqCG2r-5afOSQ.png" /></figure><p>In this article we are going to deploy web application on AWS in serverless way means we don’t have to manage servers at all, no scaling of servers nothing. In today’s world, most of the business need serverless architecture where they should mainly focus on building the businesses not managing the time in managing the servers or any kind of downtime.</p><p>Before heading to Introduction section, do read my latest blogs:</p><p><a href="https://medium.com/towards-aws/end-to-end-devops-for-a-golang-web-app-docker-eks-aws-ci-cd-f7793e230ae9">End-to-End DevOps for a Golang Web App: Docker, EKS, AWS CI/CD</a></p><p><a href="https://medium.com/aws-in-plain-english/step-by-step-guide-how-to-create-and-mount-aws-efs-elastic-file-system-15b5e62f5b09">Step-by-Step Guide: How to Create and Mount AWS EFS (Elastic File System)</a></p><p><a href="https://medium.com/@ammaurya46/deploying-your-website-on-aws-s3-with-terraform-57337a80e729">Deploying Your Website on AWS S3 with Terraform</a></p><p><a href="https://medium.com/aws-in-plain-english/learn-how-to-deploy-scalable-3-tier-applications-with-aws-ecs-563e476206e4">Learn How to Deploy Scalable 3-Tier Applications with AWS ECS</a></p><h3>Introduction to Serverless Architecture</h3><p>Serverless means we just don’t have to manage the servers, allowing developers to write the code can deploy the code easily without managing the servers. Serverless is FaaS service means Functions As a Service by this serverless computing is highly available, efficient and makes it scalable.</p><p>Serverless architectures are based on EDA (Event Driven Architectures) that means it will triggered by some events like HTTP requests, file uploads or on schedule basis also.</p><p>As serverless is Pay As You go model that makes the cost-effective which means we are paying for the compute power that we use.</p><h3>PreRequisites and AWS Services</h3><ol><li>AWS Account</li><li>IAM Role</li><li>AWS Lambda for writing functions or code where we will deploy</li><li>AWS API Gateway to create a RestFul API</li><li>NOSQL Database i.e DynamoDB</li></ol><h3>Deployment of Website on AWS</h3><p>Before heading to AWS let me show you how the website look, and what we are going to achieve.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*T4zy5Xt1DUs5dJDu.png" /></figure><p>At the end of our blog, we had deployed this website on AWS and access this website with S3 Static Website Endpoint which means we are hosting this website on S3 (index.html) and when we fill the details it will show “Data Submitted Successfully“ and add the record into DynamoDB table.</p><p>GitHub Code : <a href="https://github.com/amitmaurya07/Serverless-AWS">https://github.com/amitmaurya07/Serverless-AWS</a></p><h3>IAM Role</h3><p>Create the IAM role that will communicate with required services. Navigate to IAM, click on Create Role.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*5ct7F7PJhZ89tCM2.png" /></figure><ol><li>Now, select AWS service and choose Lambda under Usecase then give the required permissions for API Gateway, DynamoDB, S3 Bucket then click on Next and name the role ServerlessWeb and click on Create Role.</li><li>AmazonAPIGatewayInvokeFullAccess</li><li>AmazonDynamoDBFullAccess</li><li>AmazonS3FullAccess</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Td46qQxYlDSDCmm9.png" /></figure><h3>AWS Lambda</h3><p>In AWS, we had EC2 instances which are virtual servers that has limited RAM and CPU where the EC2 instances are continuously running if they are stopped also so we are paying also this, and to scale EC2 instances we create Autoscaling Groups .</p><p>But in AWS Lambda they are virtual function which means we don’t need to manage the servers, don’t need to provision the servers and they run ON-DEMAND where scaling is automated.</p><p>It supports multiple programming languages like Node.js, Python, Golang, Java, C# and Ruby. On AWS Lambda it follows Pay AS You go model. In Free-tier AWS account it provides 1 million free requests.</p><p>Navigate to AWS Management Console and search Lambda</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_XZnZuaIbKeOnnhp.png" /></figure><p>Click on Create Function name Serverless-Web-App, choose Runtime Python 3.13 then change the default execution role. Select <strong>Use an existing role </strong>which you had created earlier ServerlessWeb then click on Create on Create Function.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*UjcWfsHA8gsnjjXq.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*PvPZVhPqE_kUnKql.png" /></figure><p>Don’t worry we will see the API Gateway also when we create API Gateway. Now, paste the code and Deploy the changes.</p><pre>import json<br>import boto3<br><br>dynamodb = boto3.resource(&#39;dynamodb&#39;)<br>table = dynamodb.Table(&#39;serverless-web-app&#39;)  # Replace with your DynamoDB table name<br><br>def lambda_handler(event, context):<br>    print(json.dumps(event)) <br><br>    if event[&#39;httpMethod&#39;] == &#39;OPTIONS&#39;:<br>        return {<br>            &#39;statusCode&#39;: 200,<br>            &#39;headers&#39;: {<br>                &#39;Access-Control-Allow-Origin&#39;: &#39;*&#39;,  # or your frontend domain<br>                &#39;Access-Control-Allow-Headers&#39;: &#39;Content-Type,X-Amz-Date,Authorization,X-Api-Key&#39;,<br>                &#39;Access-Control-Allow-Methods&#39;: &#39;POST,OPTIONS&#39;  # Allow POST and OPTIONS methods<br>            },<br>            &#39;body&#39;: json.dumps(&#39;CORS Preflight Request handled successfully&#39;)<br>        }<br><br>    # POST Request Handling<br>    if event[&#39;httpMethod&#39;] == &#39;POST&#39;:<br>        # Check if the body is present in the event<br>        if &#39;body&#39; not in event:<br>            return {<br>                &#39;statusCode&#39;: 400,<br>                &#39;headers&#39;: {<br>                    &#39;Access-Control-Allow-Origin&#39;: &#39;*&#39;  # Allow all domains or specify one<br>                },<br>                &#39;body&#39;: json.dumps(&#39;Invalid request: No body in the request&#39;)<br>            }<br><br>        try:<br>            body = json.loads(event[&#39;body&#39;])<br>            name = body.get(&#39;name&#39;)<br>            email = body.get(&#39;email&#39;)<br><br>            # Ensure both &#39;name&#39; and &#39;email&#39; are provided<br>            if not name or not email:<br>                return {<br>                    &#39;statusCode&#39;: 400,<br>                    &#39;headers&#39;: {<br>                        &#39;Access-Control-Allow-Origin&#39;: &#39;*&#39;  # Allow all domains or specify one<br>                    },<br>                    &#39;body&#39;: json.dumps(&#39;Invalid input: Name and Email are required&#39;)<br>                }<br><br>            # Save to DynamoDB<br>            table.put_item(<br>                Item={<br>                    &#39;email&#39;: email,<br>                    &#39;name&#39;: name<br>                }<br>            )<br><br>            return {<br>                &#39;statusCode&#39;: 200,<br>                &#39;headers&#39;: {<br>                    &#39;Access-Control-Allow-Origin&#39;: &#39;*&#39;  # Allow all domains or specify one<br>                },<br>                &#39;body&#39;: json.dumps(&#39;Data stored successfully!&#39;)<br>            }<br><br>        except json.JSONDecodeError:<br>            return {<br>                &#39;statusCode&#39;: 400,<br>                &#39;headers&#39;: {<br>                    &#39;Access-Control-Allow-Origin&#39;: &#39;*&#39;<br>                },<br>                &#39;body&#39;: json.dumps(&#39;Invalid JSON format&#39;)<br>            }<br>        except Exception as e:<br>            return {<br>                &#39;statusCode&#39;: 500,<br>                &#39;headers&#39;: {<br>                    &#39;Access-Control-Allow-Origin&#39;: &#39;*&#39;<br>                },<br>                &#39;body&#39;: json.dumps(f&quot;Internal Server Error: {str(e)}&quot;)<br>            }</pre><p>In this code we have to replace our DynamoDB table name in 5th line. After deploying the changes go to <strong>API Gateway</strong></p><h3>API Gateway</h3><p>API Gateway are serverless API’s that provide Restful API’s to the clients and after integrating with Lambda it proxy the requests to our Lambda functions.</p><p>It has 3 endpoint types:</p><ol><li><strong>Regional</strong> — It is for the same region.</li><li><strong>Private</strong> — It can be accessed from private VPC with the help of VPC Endpoint.</li><li><strong>Edge-Optimized (default)</strong> — To improve latency requests are routed through Cloudfront edge locations.</li></ol><p>Now, navigate to AWS Management Console and search for API Gateway.</p><ol><li>Click on Create API and choose the API type REST API.</li><li>Click on Build and name it Web-App , select Regional Endpoint Type then click on Create API.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_vOH9lkILORKOjwv.png" /></figure><p>Now, create the method POST and OPTIONS. Click on Web-App then click on Create Method.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*hlT10yn33qXG9KKY.png" /></figure><p>Select Method Type <strong>POST</strong>, Integration type <strong>Lambda </strong>enable the Lambda Proxy Integration by which entire HTTP request will be forwarded to Lambda function. Choose the Lambda function ARN which we created earlier Serverless-Web-App then click on Create Method.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_OCKhkUejCr98r0U.png" /></figure><p>Now, we have to create another method type <strong>OPTIONS </strong>that will handle CORS error and preflight requests. Select <strong>MOCK</strong> Integration Type and choose the same Lambda function Serverless-Web-App.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*euRubuCiv6yY5QcU.png" /></figure><ol><li>Now, click on <strong>OPTIONS </strong>method and add method Method Response under 200 Status Code. Click on Create Response under Header Name add these headers.</li><li>Access-Control-Allow-Headers</li><li>Access-Control-Allow-Methods</li><li>Access-Control-Allow-Origin</li><li>Then click on Save.</li><li>Go to Integration Response under <strong>OPTIONS </strong>method add the value to the Response headers.</li><li>Access-Control-Allow-Headers &#39;Content-Type, Authorization&#39;</li><li>Access-Control-Allow-Methods &#39;POST, GET, OPTIONS&#39;</li><li>Access-Control-Allow-Origin &#39;*&#39;</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fHVCgBqXY0BqfJZH.png" /></figure><ol><li>Click on Save.</li></ol><p>2. Click on <strong>POST </strong>method and add same Method Response headers.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/925/0*VnYzLqdyfXR2ohcn.png" /></figure><p>Now, click on deploy the API where you need to create New Stage to save the changes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-DD0k76crZ45eccb.png" /></figure><p>Scroll down, you will get the Invoke URL and add this URL in index.html file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qr8U0uTvt0ZtxC0e.png" /></figure><h3>DynamoDB</h3><p>AWS offers DynamoDB which is NoSQL database which is highly scalable, and fully managed serverless database solution that can handle millions of requests per second, offers low latency which stores and retrieve structured data.</p><p>Navigate to AWS Management Console and search DynamoDB</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OfNcDj-066MYfIYZ.png" /></figure><p>Click on Create Table name web-app , write partition key email as we are only storing email that wants to be unique ID then click on Create Table.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*rTNGmDM_GDd5d-Q9.png" /></figure><p>After this, copy the table name web-app and paste in Lambda function where we had defined.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*p32EoxpDIaMjV6wf.png" /></figure><p>After doing changes, paste the same to Lambda function and deploy the changes in Lambda.</p><h3>Host Static Website on S3</h3><p>Now, we are going to host our static website index.html on S3 bucket which is serverless.</p><p>If you want to host static website on S3 with Terraform Modules you can refer to this article.</p><p><a href="https://medium.com/@ammaurya46/deploying-your-website-on-aws-s3-with-terraform-57337a80e729">Deploying Your Website on AWS S3 with Terraform</a></p><p>Navigate to AWS Management Console and search S3. Remember we will be creating the bucket in Mumbai (ap-south-1)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Q3w8ZAH4IE1574_3.png" /></figure><p>Create the bucket with your preferred name as name has to be unique across Global. While creating bucket uncheck the “Block all Public Access” then click on Create bucket and upload <strong>index.html</strong> file in the bucket.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OcoHKXu5-0aB6ZH5.png" /></figure><p>Scroll down in Properties section of S3 bucket and enable the Static Website Hosting type index document <strong>index.html</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ua1skz5alLY3upll.png" /></figure><p>You will receive endpoint to open the website but it will give you error because you hadn’t added the Permissions. Navigate to Permissions tab in S3 bucket and add bucket policy.</p><pre>{<br>    &quot;Version&quot;: &quot;2012-10-17&quot;,<br>    &quot;Statement&quot;: [<br>        {<br>            &quot;Sid&quot;: &quot;PublicReadGetObject&quot;,<br>            &quot;Effect&quot;: &quot;Allow&quot;,<br>            &quot;Principal&quot;: &quot;*&quot;,<br>            &quot;Action&quot;: &quot;s3:GetObject&quot;,<br>            &quot;Resource&quot;: &quot;arn:aws:s3:::serverlesswebapp07/*&quot;<br>        }<br>    ]<br>}</pre><p>In Resource change the bucket name to your bucket name.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Lml4KY6RcOUmp1PS.png" /></figure><p>Now, when you refresh the page you will access the website. So, we hosted the static website successfully on S3 bucket.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qHH8EIffoe7KsrOr.png" /></figure><p>Now, let’s check our API, Lambda and DynamoDB is perfectly working or not.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*NIsXs5o9eZRtGQE_.png" /></figure><p>As we can see data is submitted successfully our API is getting 200 status code. Let’s check also our DynamoDB table recorded the email or not.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/859/0*S8EV9f9mvkV0_jlj.png" /></figure><p>As we can see our email and Name is there in database. We can check also with PostMan, for this select the POST method response and paste the API Gateway URL and in raw select JSON body.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2ooey1wQljTYj7P6.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/861/0*_cR2DSXADMPdlAsX.png" /></figure><h3>Conclusion</h3><p>In this article, we explored the deployment of our website on AWS using a serverless approach. In upcoming posts, we will delve into the creation of various AWS services and their automation with Terraform. Stay tuned for the next blog!</p><p>GitHub Code : <a href="https://github.com/amitmaurya07/Serverless-AWS"><strong>https://github.com/amitmaurya07/Serverless-AWS</strong></a></p><p>Twitter : <a href="http://x.com/amitmau07"><strong>x.com/amitmau07</strong></a></p><p>LinkedIn : <a href="http://linkedin.com/in/amit-maurya07"><strong>linkedin.com/in/amit-maurya07</strong></a></p><p>If you have any queries you can drop the message on LinkedIn and Twitter.</p><h4><a href="https://www.vantage.sh/?utm_source=aws&amp;utm_medium=partner_site&amp;utm_campaign=reinvent2024_banner">Vantage — Cloud Cost Observability and Optimization</a></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*N0ZmYR-WqkT5ZXv6pIcLwA.jpeg" /></figure><p>Vantage is a modern cloud cost management platform that helps companies manage costs across AWS, Azure, Datadog, Google Cloud, and 10 other providers. <a href="https://www.vantage.sh/?utm_source=aws&amp;utm_medium=newsletter&amp;utm_campaign=reinvent2024_banner"><strong>Create a free account</strong></a> in minutes to get an automated savings health check.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7e22bfb7a1c4" width="1" height="1" alt=""><hr><p><a href="https://towardsaws.com/building-a-serverless-web-application-with-aws-lambda-api-gateway-dynamodb-s3-7e22bfb7a1c4">Building a Serverless Web Application with AWS Lambda, API Gateway, DynamoDB, S3</a> was originally published in <a href="https://towardsaws.com">Towards AWS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Automating AWS Cost Reporting with Lambda and SNS]]></title>
            <link>https://towardsaws.com/automating-aws-cost-reporting-with-lambda-and-sns-95222e353b58?source=rss-357aad067a18------2</link>
            <guid isPermaLink="false">https://medium.com/p/95222e353b58</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[lambda]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[cost-optimization]]></category>
            <dc:creator><![CDATA[Amit Maurya]]></dc:creator>
            <pubDate>Tue, 19 Nov 2024 07:51:49 GMT</pubDate>
            <atom:updated>2024-11-20T03:37:16.828Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PeHgGhtBMzsYqEkhqPjs9w.png" /></figure><p>In this article, we are going to build a Lambda Function in which there is Python code that will generate the AWS Cost Report of your specific region and send it to your email through SNS Topic. We had automated this Lambda function by creating CloudWatch that will execute on schedule basis on 1st day of every month.</p><p>Before heading to Introduction section, do read my latest blogs:</p><p><a href="https://medium.com/towards-aws/end-to-end-devops-for-a-golang-web-app-docker-eks-aws-ci-cd-f7793e230ae9"><strong>End-to-End DevOps for a Golang Web App: Docker, EKS, AWS CI/CD</strong></a></p><p><a href="https://medium.com/@ammaurya46/deploying-your-website-on-aws-s3-with-terraform-57337a80e729"><strong>Deploying Your Website on AWS S3 with Terraform</strong></a></p><p><a href="https://medium.com/aws-in-plain-english/learn-how-to-deploy-scalable-3-tier-applications-with-aws-ecs-563e476206e4"><strong>Learn How to Deploy Scalable 3-Tier Applications with AWS ECS</strong></a></p><h3>Overview of AWS Cost Management</h3><p>In today’s modern computing world, most of the companies or startups are switching their traditional servers to virtual servers to reduce their server setup cost and by AWS it reduces upto 50%.</p><p>But as a DevOps Engineer or Cloud Engineer we had to monitor the costs of AWS resources also how to use efficiently AWS resources we had to keep in mind so that unwanted costs can be cut.</p><p>To see the AWS Resources Costs, navigate to Billing and Cost Management Dashboard (<a href="https://us-east-1.console.aws.amazon.com/billing/home#/bills">https://us-east-1.console.aws.amazon.com/billing/home#/bills</a>)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*eRCROxCJu-zRtGWv.png" /></figure><h3>Prerequisites</h3><ol><li>Setup IAM (Identity &amp; Access Management) Role to communicate with other AWS services.</li><li>Write Python Code for specific region that will fetch the cost and sent the report to Email through SNS (Simple Notification Service).</li><li>Lambda Function</li><li>SNS (Simple Notification Service) Topic</li><li>CloudWatch Alarm</li></ol><h3>Implementation</h3><ol><li>Create an IAM role for Lambda Function that will execute the SNS service. Navigate to IAM then select Roles</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*uE23ZA1Lgc18k1tP.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KF_EMfAgPuK_O36r.png" /></figure><ol><li>Click on Create Role then select Lambda as UseCase then Next. Now Add the required Permissions.</li><li>AmazonSNSFullAccess - SNS Full Access</li><li>AWSCostAndUsageReportAutomationPolicy - Cost Explorer Access</li><li>CloudWatchEventsFullAccess - CloudWatch Events Access to create Rules</li><li>Then, add Inline Policy also for GetCostUsage name it cost-optimization.</li></ol><pre>{<br>    &quot;Version&quot;: &quot;2012-10-17&quot;,<br>    &quot;Statement&quot;: [<br>        {<br>            &quot;Effect&quot;: &quot;Allow&quot;,<br>            &quot;Action&quot;: [<br>                &quot;ce:GetCostAndUsage&quot;,<br>                &quot;ce:GetCostForecast&quot;,<br>                &quot;ce:GetDimensionValues&quot;,<br>                &quot;ce:GetUsageForecast&quot;<br>            ],<br>            &quot;Resource&quot;: &quot;*&quot;<br>        }<br>    ]<br>}</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*o30B9g8YSs2VRcnf.png" /></figure><ol><li>Now, IAM role is created setup the AWS Lambda function to execute our Python code.</li><li>AWS Lambda is serverless compute service that enables us to run our code without managing servers. It automatically scales up and down the servers that will be cost-efficient. It follow Event-Driven architecture where we can trigger Lambda by multiple events by integrating CloudWatch or other AWS services.</li></ol><pre>import boto3<br>import datetime<br>from botocore.exceptions import ClientError<br><br># Initialize AWS Cost Explorer and SNS clients<br>cost_explorer = boto3.client(&#39;ce&#39;)<br>sns = boto3.client(&#39;sns&#39;, region_name=&quot;ap-south-1&quot;)<br><br># SNS topic ARN<br>sns_topic_arn = &#39;arn:aws:sns:ap-south-1:880849992790:CostOptimization&#39;  # Replace with your actual SNS topic ARN<br><br># Define the Lambda function<br>def lambda_handler(event, context):<br>    # Get current date and start of the month<br>    today = datetime.date.today()<br>    start_date = today.replace(day=1)<br>    end_date = today<br><br>    try:<br>        # Query AWS Cost Explorer for cost breakdown per service in ap-south-1 region<br>        ap_south_1_response = cost_explorer.get_cost_and_usage(<br>            TimePeriod={<br>                &#39;Start&#39;: start_date.strftime(&#39;%Y-%m-%d&#39;),<br>                &#39;End&#39;: end_date.strftime(&#39;%Y-%m-%d&#39;)<br>            },<br>            Granularity=&#39;MONTHLY&#39;,<br>            Metrics=[&#39;UnblendedCost&#39;],<br>            GroupBy=[{<br>                &#39;Type&#39;: &#39;DIMENSION&#39;,<br>                &#39;Key&#39;: &#39;SERVICE&#39;<br>            }],<br>            Filter={<br>                &#39;Dimensions&#39;: {<br>                    &#39;Key&#39;: &#39;REGION&#39;,<br>                    &#39;Values&#39;: [&#39;ap-south-1&#39;]<br>                }<br>            }<br>        )<br><br>        # Query AWS Cost Explorer for cost breakdown per service for all regions<br>        all_regions_response = cost_explorer.get_cost_and_usage(<br>            TimePeriod={<br>                &#39;Start&#39;: start_date.strftime(&#39;%Y-%m-%d&#39;),<br>                &#39;End&#39;: end_date.strftime(&#39;%Y-%m-%d&#39;)<br>            },<br>            Granularity=&#39;MONTHLY&#39;,<br>            Metrics=[&#39;UnblendedCost&#39;],<br>            GroupBy=[{<br>                &#39;Type&#39;: &#39;DIMENSION&#39;,<br>                &#39;Key&#39;: &#39;SERVICE&#39;<br>            }]<br>        )<br><br>        # Prepare the breakdown of costs for ap-south-1<br>        ap_south_1_total_cost = 0<br>        ap_south_1_details = &quot;Cost Breakdown for the ap-south-1 Region for the Current Month:\n\n&quot;<br>        for result in ap_south_1_response[&#39;ResultsByTime&#39;]:<br>            for group in result[&#39;Groups&#39;]:<br>                service_name = group[&#39;Keys&#39;][0]<br>                cost_amount = float(group[&#39;Metrics&#39;][&#39;UnblendedCost&#39;][&#39;Amount&#39;])<br>                ap_south_1_total_cost += cost_amount<br>                ap_south_1_details += f&quot;{service_name}: ${cost_amount:.2f}\n&quot;<br>        <br>        ap_south_1_details += f&quot;\nTotal Cost for ap-south-1: ${ap_south_1_total_cost:.2f}\n\n&quot;<br><br>        # Prepare the breakdown of costs for all regions<br>        all_regions_total_cost = 0<br>        all_regions_details = &quot;Cost Breakdown for All Regions for the Current Month:\n\n&quot;<br>        for result in all_regions_response[&#39;ResultsByTime&#39;]:<br>            for group in result[&#39;Groups&#39;]:<br>                service_name = group[&#39;Keys&#39;][0]<br>                cost_amount = float(group[&#39;Metrics&#39;][&#39;UnblendedCost&#39;][&#39;Amount&#39;])<br>                all_regions_total_cost += cost_amount<br>                all_regions_details += f&quot;{service_name}: ${cost_amount:.2f}\n&quot;<br>        <br>        all_regions_details += f&quot;\nTotal Cost for All Regions: ${all_regions_total_cost:.2f}&quot;<br><br>        # Combine both reports (ap-south-1 and all regions) into one message<br>        full_report = ap_south_1_details + all_regions_details<br><br>        # Publish the cost report to SNS<br>        sns.publish(<br>            TopicArn=sns_topic_arn,<br>            Subject=&#39;AWS Cost Breakdown Report&#39;,<br>            Message=full_report<br>        )<br>        return {<br>            &#39;statusCode&#39;: 200,<br>            &#39;body&#39;: &#39;Cost report for ap-south-1 and all regions sent successfully via SNS!&#39;<br>        }<br><br>    except ClientError as e:<br>        print(f&quot;Error: {e}&quot;)<br>        return {<br>            &#39;statusCode&#39;: 500,<br>            &#39;body&#39;: f&quot;Failed to send cost report: {e}&quot;<br>        }</pre><p>Search AWS Lambda in AWS Management Console Search Bar</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xxQ550puQ8Y8UFl2.png" /></figure><p>Click on Create Function and select Author From Scratch, name the function CostOptimizationFunction , select Python 3.x Runtime then Open Permissions and select Use Existing Role and select the created IAM role and at last click on Create Function.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*rwRMmzXZ1J-nURZq.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*S4ryeV5eDRsmQqIU.png" /></figure><ol><li>Scroll down and, paste the Source Code in Editor then click on Tests to test the program is working properly or not.</li><li>But, before executing the program navigate to AWS SNS (Simple Notification Service) to create the topic and subscription so that the report will be sent to Email.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*OOtKrXDyNrvMoYUm.png" /></figure><p>Name the topic CostOptimization and create the Subscription where you will verify the Email.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*91tcPYuwo43XrxJ8.png" /></figure><p>Click on Create Subscription and select the protocol “Email“</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*uh68j1KIkHDyuRo7.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9We2zeSPSvvefIn8.png" /></figure><ol><li>Now, go to your Email to verify the subsrciption endpoint. Click on the link that is provided in the Email it will be verified.</li><li>Now, copy the SNS Topic ARN and paste it into Lambda function in variable sns_topic_arn and write the region from which you want the cost like I want the cost of region Mumbai I had written the region (ap-south-1).</li><li>Create the Tests name CostOptimizationFunc then click on Test. It will deploy the template Hello World to deploy the changes of our Python program click on Deploy it will give the output in JSON.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*BMPkQzDysyJBFyel.png" /></figure><p>As we can see 200 status code that means our program is successfully executed. Now check the Email Inbox you will recieve the email of your Cost Report of your specific region and all regions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ngvR9FAIdSAuUMfq.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*S59MqqfHSULjuxVn.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/989/0*N1ERgNvZz_1TbCgV.png" /></figure><ol><li>As we can see in the Security Details it mailed by and signed by AWS.</li><li>After all this, we will automate this so we don’t run the lambda function manually we will integrate CloudWatch with Lambda on schedule basis of every 1st day of month so that lambda will be triggered automatically and cost report sent to Email.</li><li>Navigate to AWS Cloudwatch in AWS Management Console Search Bar.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*q8KtCrvfkfJzduib.png" /></figure><ol><li>Now, in the left hand side we have to create Rules under Events section. Click on Rules, then select default EventBus name it CostOptimizationRule then select the Rule Type Schedule.</li><li>Click on Continue to Create Rule fill the CRON expression (0 0 1 <em>* ? *)</em></li><li>and select Local Time Zone. You will see the Next trigger dates means the Lambda will trigger on which date.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*yg3kzu1rveMAhL_Q.png" /></figure><p>Click on Next and select AWS service type on which service you want to trigger. In our case it is Lambda function, so select Lambda then select the Lambda Function ARN.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YNvVltRNc8LCzLm_.png" /></figure><p>Click on Next and create the Rule.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CDY3_FJUvM8WsCX-.png" /></figure><h3>Conclusion</h3><p>In this article, we had learnt how to create Lambda function, CloudWatch Rules to automatically trigger then generate the cost report and sent it to the Email. Meanwhile in the upcoming blogs you will see a lot of AWS Services creation and automating it with terraform. Stay tuned for the next blog !!!</p><p>GitHub Code : <a href="https://github.com/amitmaurya07"><strong>https://github.com/amitmaurya07</strong></a></p><p>Twitter : <a href="http://x.com/amitmau07"><strong>x.com/amitmau07</strong></a></p><p>LinkedIn : <a href="http://linkedin.com/in/amit-maurya07"><strong>linkedin.com/in/amit-maurya07</strong></a></p><p>If you have any queries you can drop the message on LinkedIn and Twitter.</p><h4><a href="https://www.vantage.sh/?utm_source=aws&amp;utm_medium=partner_site&amp;utm_campaign=reinvent2024_banner">Vantage — Cloud Cost Observability and Optimization</a></h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*N0ZmYR-WqkT5ZXv6pIcLwA.jpeg" /></figure><p>Vantage is a modern cloud cost management platform that helps companies manage costs across AWS, Azure, Datadog, Google Cloud, and 10 other providers. <a href="https://www.vantage.sh/?utm_source=aws&amp;utm_medium=newsletter&amp;utm_campaign=reinvent2024_banner"><strong>Create a free account</strong></a> in minutes to get an automated savings health check.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=95222e353b58" width="1" height="1" alt=""><hr><p><a href="https://towardsaws.com/automating-aws-cost-reporting-with-lambda-and-sns-95222e353b58">Automating AWS Cost Reporting with Lambda and SNS</a> was originally published in <a href="https://towardsaws.com">Towards AWS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[End-to-End DevOps for a Golang Web App: Docker, EKS, AWS CI/CD]]></title>
            <link>https://towardsaws.com/end-to-end-devops-for-a-golang-web-app-docker-eks-aws-ci-cd-f7793e230ae9?source=rss-357aad067a18------2</link>
            <guid isPermaLink="false">https://medium.com/p/f7793e230ae9</guid>
            <category><![CDATA[cicd]]></category>
            <category><![CDATA[development]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[aws-certification]]></category>
            <category><![CDATA[aws]]></category>
            <dc:creator><![CDATA[Amit Maurya]]></dc:creator>
            <pubDate>Sat, 16 Nov 2024 20:10:39 GMT</pubDate>
            <atom:updated>2024-11-17T10:08:42.593Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_KXHE3CjjHwYMLmxzfjHrA.png" /></figure><p>In this article, we are going to learn how to deploy Golang application end to end with on AWS EKS (Elastic Kubernetes Service) with AWS CI/CD. This will enhance your skills and you can add this project in your resume.</p><p>Before heading to Introduction section, do read my latest blogs:</p><p><a href="https://medium.com/aws-in-plain-english/step-by-step-guide-how-to-create-and-mount-aws-efs-elastic-file-system-15b5e62f5b09">Step-by-Step Guide: How to Create and Mount AWS EFS (Elastic File System)</a></p><p><a href="https://medium.com/@ammaurya46/deploying-your-website-on-aws-s3-with-terraform-57337a80e729">Deploying Your Website on AWS S3 with Terraform</a></p><p><a href="https://medium.com/aws-in-plain-english/learn-how-to-deploy-scalable-3-tier-applications-with-aws-ecs-563e476206e4">Learn How to Deploy Scalable 3-Tier Applications with AWS ECS</a></p><h3>Introduction</h3><p>Starting from the Project understanding we have a simple Golang application that will shorten the URL it has the main.go file and one index.html which will serve as frontend.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*B7WHI6wa2BmojeZx" /></figure><p>So, this will look like this which is running locally on http://localhost:8080 To run locally first we need to build go.mod file which is used for dependency management.</p><pre>go mod init my-url-shortener<br>go mod tidy<br>go get github.com/gin-gonic/gin</pre><p>This will generate the go.mod and go.sum file. In go.mod file we have the dependencies that is used in code with the specific Golang version. The go get command is installing the gin package HTTP web framework.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*JdPnlur_vWF5l03E" /></figure><p>After this execute the command to run go file i.e. main.go</p><pre>go run main.go</pre><h3>Tools and Technologies Used</h3><ol><li>Golang Programming Language</li><li>Docker for Containerization</li><li>Kubernetes for Orchestration</li><li>CodePipeline and CodeBuild</li><li>Argo CD for Continuous Deployments</li></ol><h3>Multi-Stage Docker Build</h3><p>As a DevOps engineer our responsibility is to automate everything and reach to zero downtime. It all starts from building the Dockerfile where we package all code dependencies in single binary file and run it. To build Dockerfile we need some points to be considered like build the Dockerfile with a small size, always use best-practices means use smaller size or distroless images.</p><p>For our golang code, we are building Multi-Stage Dockerfile that will reduce the size from 1 GB to 33 MB !! Yes, we can achieve this to learn about best practices for creating a Dockerfile follow this article</p><p><a href="https://amitmaurya.hashnode.dev/dockerfile-best-practices-how-to-optimize-your-docker-images">Dockerfile Best Practices: How to Optimize Your Docker Images</a></p><h3>Creating Dockerfile</h3><pre>FROM golang:1.23 AS base<br>WORKDIR /app<br>COPY go.mod ./<br>RUN go mod download<br>COPY . .<br>RUN go build -o main .<br><br>FROM gcr.io/distroless/base<br>COPY --from=base /app/main .<br>COPY --from=base /app/static ./static<br>EXPOSE 8080<br>CMD [&quot;./main&quot;]</pre><p>In this Dockerfile we have used 2 stages in which 1st stage where we are building main by executing go build -o main . and storing in /app directory. The first stage is named as base and in second stage we are using distroless image gcr.io/distroless/base and copying the /app working directory from Stage 1 to Stage 2 by using COPY instruction —from=base and in the next stage we are copying static folder which contains index.html file and in last stage we added CMD instruction which will execute the main binary file.</p><p>Now, let’s build the Dockerfile and push it to DockerHub.</p><pre>docker build -t amaurya07/short_url:1 .<br>docker push amaurya07/short_url:1</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*l7gUCRuSpq6W-GVg" /></figure><p>Remember to replace the tag with your own docker hub username/short_url and then give version number. After building the docker image successfully we had reduced the image size to 33 MB.</p><pre>docker images</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Gn9hBSPebUyo0Weo" /></figure><p>Now check that the docker image is successfully running or not, create a container and bind the port 8080.</p><pre>docker run -p 8080:8080 amaurya07/short_url:1</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*R5UxX0fDUKeqMY44" /></figure><p>Open the browser and open http://localhost:8080 it will open the Shorten URL page.</p><h3>Creating Kubernetes Manifests</h3><p>We had created the Dockerfile and pushed to the DockerHub after testing the image by creating the container and we had successfully completed the first stage. Now, we had to deploy this image on EKS Cluster i.e. Elastic Kubenetes Service so for this we need to create Kubernetes manifests file that include deployment.yaml, service.yaml and ingress.yaml.</p><p><strong>deployment.yaml</strong></p><pre>apiVersion: apps/v1<br>kind: Deployment<br>metadata:<br>  name: shorturl<br>spec:<br>  selector:<br>    matchLabels:<br>      app: shorturl<br>  template:<br>    metadata:<br>      labels:<br>        app: shorturl<br>    spec:<br>      containers:<br>      - name: shortenurlapp<br>        image: amaurya07/short_url:1<br>        resources:<br>          limits:<br>            memory: &quot;128Mi&quot;<br>            cpu: &quot;500m&quot;<br>        ports:<br>        - containerPort: 8080</pre><p>In this deployment.yaml file we will create 1 pod of image amaurya07/short_url:1 on the container Port 8080.</p><p><strong>service.yaml</strong></p><pre>apiVersion: v1<br>kind: Service<br>metadata:<br>  name: shorturl<br>spec:<br>  selector:<br>    app: shorturl<br>  ports:<br>    - port: 8080<br>      targetPort: 8080 <br>  type: NodePort</pre><p>Now, to access the application outside we need to create service of type NodePort that will assign the ports between 30000 to 32000.</p><p><strong>ingress.yaml</strong></p><pre>apiVersion: networking.k8s.io/v1<br>kind: Ingress<br>metadata:<br>  name: shorturl<br>  annotations:<br>    alb.ingress.kubernetes.io/scheme: internet-facing <br>    alb.ingress.kubernetes.io/target-type: ip        <br>spec:<br>  ingressClassName: alb <br>  rules:<br>     - http:<br>        paths:<br>        - path: /<br>          pathType: Prefix<br>          backend:<br>            service:<br>              name: shorturl <br>              port:<br>                number: 8080</pre><p>In ingress.yaml file we had defined the annotations of alb i.e. Application Load Balancer which will create the Application Load Balancer of IP and then define the ingressClassName “alb”. But before this we need to install Ingress controller that will create the Ingress resource and load balancer.</p><h3>Steps to create EKS Cluster</h3><p>AWS provides a managed Kubernetes cluster, i.e., EKS. With this, we can configure a Kubernetes managed cluster in minutes on AWS. In AWS, we don’t need to manage the Control Plane nodes like provisioning, scaling, and management of the Kubernetes control plane node as they are managed by AWS. We only need to manage the worker nodes if we create self-managed node groups, i.e., EC2; otherwise, in Fargate, it becomes serverless.</p><p>We need to install the kubectl, eksctl and aws CLI to create Kubernetes Cluster on EKS.</p><p>I am using Windows so these installations are for Windows.</p><p>kubectl Installation: <a href="https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/">https://kubernetes.io/docs/tasks/tools/install-kubectl-windows/</a></p><p>aws CLI: <a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html">https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html</a></p><p>eksctl Install: <a href="https://eksctl.io/installation/">https://eksctl.io/installation/</a></p><ol><li>By installing these pre-requisites now configure the AWS CLI with Access Keys, Secret Keys and region where we want to deploy our cluster.</li><li>In this article I created the AWS Access and Secret Keys and assign the permissions for Administrator access for now.</li><li><a href="https://amitmaurya.hashnode.dev/learn-how-to-deploy-scalable-3-tier-applications-with-aws-ecs">https://amitmaurya.hashnode.dev/learn-how-to-deploy-scalable-3-tier-applications-with-aws-ecs</a></li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*hj5cYmTt6g56re3S" /></figure><p>Now create EKS cluster where we are creating the Self Managed NodeGroups by eksctl CLI.</p><pre>eksctl create cluster --name demo-eks-cluster --region ap-south-1 --nodes 3 --node-type t3.medium</pre><p>By executing this command it will create 3 worker nodes in the region Mumbai (ap-south-1) and it is all created by CloudFormation Stack.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*PmduByfldXtXs4w7" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ii5WWKF6ocVGbyBI" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*RIlty2njEcMprKBB" /></figure><p>Now, the EKS cluster is ready execute the commands to check the nodes</p><pre>kubectl get nodes</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fw2dKl_HqkUl7ANZ" /></figure><p>Let’s deploy the Kubernetes manifests yaml files on EKS cluster.</p><pre>kubectl apply -f ./manifests</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3ZLUq5M-tG1xazqH" /></figure><p>So our deployment.yaml, service.yaml and ingress.yaml are created in the default namespace.</p><pre>kubectl get pods  kubectl get deployment</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Ri-9E6CAfFLbAxpG" /></figure><p>Now, check service it was assigned the NodePort number and we will check that our application is working or not.</p><pre>kubectl get service</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gp54CfZ5CWer6_39" /></figure><p>To access the application check the pod is scheduled on which node as we had created 3 nodes and get the External IP of the node.</p><pre>kubectl get pods -owide</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*VhaNfRTir3U5SCyU" /></figure><p>Now, check the External IP of this node by executing</p><pre>kubectl get node -owide</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gXWOq_4HE-eXd5bC" /></figure><p>The pod is scheduled on the first node so the External IP is 13.200.207.219. But before this open All traffic of the instance where the Pod is scheduled. Navigate to EKS Cluster and go to Compute section and open the Instance security Group.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fSPI4i5NYdOWE-04" /></figure><p>Now open the browser and go to http://13.200.207.219:30911 with nodePort.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EUtygUePU3BWk-UR" /></figure><p>Now, check the ingress resource is created or not.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/991/0*i_3pyj69U4STOwDC" /></figure><p>As we can see there is no Address is there because we have not deployed the Ingress Controller of ALB. Let’s deploy this, we will be using <a href="http://readme.md/">Readme.md</a> instructions to deploy this:</p><p><a href="https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/main/helm/aws-load-balancer-controller/README.md">https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/main/helm/aws-load-balancer-controller/README.md</a></p><ul><li>Install Helm so that we can deploy the ALB Ingress Controller on EKS cluster. As I am using Windows OS I am installing with chocolatey.</li><li><a href="https://helm.sh/docs/intro/install/">https://helm.sh/docs/intro/install/</a></li></ul><pre>choco install kubernetes-helm</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/895/0*LIg-kMvQR_sIYm-Z" /></figure><p>Now, we need to create OIDC (Open ID Connect) IAM provider.</p><pre>  eksctl utils associate-iam-oidc-provider \<br>      --region ap-south-1 \<br>      --cluster demo-eks-cluster \<br>      --approve</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*NnA4_nrNfrR2kxgJ" /></figure><p>Then we need to download the IAM policy for ALB Ingress controller.</p><pre>curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/main/docs/install/iam_policy.json</pre><p>After the policy is downloaded we need to create the IAM policy.</p><pre>  aws iam create-policy \<br>      --policy-name AWSLoadBalancerControllerIAMPolicy \<br>      --policy-document file://iam_policy.json</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*z3npEfTjXaD0fMO_" /></figure><p>Now, we need to create IAM role and service account to interact with other AWS service from EKS.</p><pre>  eksctl create iamserviceaccount \<br>  --cluster=&lt;cluster-name&gt; \<br>  --namespace=kube-system \<br>  --name=aws-load-balancer-controller \<br>  --attach-policy-arn=arn:aws:iam::&lt;AWS_ACCOUNT_ID&gt;:policy/AWSLoadBalancerControllerIAMPolicy \<br>  --approve</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*hRs-7buQVdJQwb79" /></figure><p>After all this, we have to install the helm charts.</p><pre>helm repo add eks https://aws.github.io/eks-charts</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Por4CeHU3MYJcqcd" /></figure><pre>helm repo update eks</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*FbGXkRLAA8ldSh6M" /></figure><pre>  helm install aws-load-balancer-controller eks/aws-load-balancer-controller --set clusterName=demo-eks-cluster -n kube-system --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller --set region=ap-south-1 --set vpcId=&lt;vpc-id&gt;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fuwwcdtge1_pIGIj" /></figure><pre>kubectl get pods -nkube-system</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*5uk6-DcAoZ0c3YYT" /></figure><ul><li>As we can see the pods of ALB Ingress controller are deployed in kube-system namespace. Now, let’s check the ingress got the address i.e load balancer DNS name or not.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*szxiCAz2ARJKgoV0" /></figure><ul><li>We can check here we got the address of DNS name of Load Balancer, now let’s copy this and paste it on browser.</li><li>http://<a href="http://k8s-default-shorturl-34b3d7650a-1068404865.ap-south-1.elb.amazonaws.com/">k8s-default-shorturl-34b3d7650a-1068404865.ap-south-1.elb.amazonaws.com</a></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*o69vbSLZY-GmWvmv" /></figure><ul><li>Hurray !! we have achieved the third phase where we deployed the application on EKS and accessed with the Load Balancer DNS name, but now I want my URL to access this, for this we need to modify the ingress.yaml file and add the hosts entry.</li></ul><pre>  apiVersion: networking.k8s.io/v1<br>  kind: Ingress<br>  metadata:<br>    name: shorturl<br>    annotations:<br>      alb.ingress.kubernetes.io/scheme: internet-facing <br>      alb.ingress.kubernetes.io/target-type: ip        <br>  spec:<br>    ingressClassName: alb <br>    rules:<br>      - host: shortenurl.local <br>        http:<br>          paths:<br>          - path: /<br>            pathType: Prefix<br>            backend:<br>              service:<br>                name: shorturl <br>                port:<br>                  number: 8080</pre><h3>AWS CI/CD Pipeline</h3><p>Now, we had dockerize the application, deployed on the EKS Cluster access the application with the ingress by deploying the ALB Ingress Controller but as a DevOps Engineer we had to implement CI/CD pipeline so that developers can run the pipeline if any changes happens in the code it will automatically deploy to EKS Cluster and we can see the new feature or new version of the image is implemented.</p><p>In AWS CI/CD pipeline, AWS offers 4 services by which we can automate the whole CI/CD process.</p><ol><li>CodeCommit — Version Control System</li><li>CodePipeline — CI Process</li><li>CodeBuild — Write buildspec.yaml file that includes stages for the pipeline.</li><li>CodeDeploy — CD Process</li></ol><p>Before heading to CodePipeline, we first create the IAM Role which will be used in CodeBuild to build the phases with necessary permissions.</p><p>For this, copy this script and run the command to execute the script.</p><p><a href="http://iamrole.sh/">iamrole.sh</a>:</p><pre>#!/usr/bin/env bash<br>TRUST=&quot;{   \&quot;Version\&quot;: \&quot;2012-10-17\&quot;,   \&quot;Statement\&quot;: [     {       \&quot;Effect\&quot;: \&quot;Allow\&quot;,       \&quot;Principal\&quot;: {         \&quot;Service\&quot;: \&quot;codebuild.amazonaws.com\&quot;       },       \&quot;Action\&quot;: \&quot;sts:AssumeRole\&quot;     }   ] }&quot;<br>echo &#39;{ &quot;Version&quot;: &quot;2012-10-17&quot;, &quot;Statement&quot;: [ { &quot;Effect&quot;: &quot;Allow&quot;, &quot;Action&quot;: &quot;eks:Describe*&quot;, &quot;Resource&quot;: &quot;*&quot; } ] }&#39; &gt; /tmp/iam-role-policy<br><br>aws iam create-role --role-name CodeBuildKubectlRole --assume-role-policy-document &quot;$TRUST&quot; --output text --query &#39;Role.Arn&#39;<br><br>aws iam put-role-policy --role-name CodeBuildKubectlRole --policy-name eks-describe --policy-document file:///tmp/iam-role-policy<br><br>aws iam attach-role-policy --role-name CodeBuildKubectlRole --policy-arn arn:aws:iam::aws:policy/CloudWatchLogsFullAccess<br><br>aws iam attach-role-policy --role-name CodeBuildKubectlRole --policy-arn arn:aws:iam::aws:policy/AWSCodeBuildAdminAccess<br><br>aws iam attach-role-policy --role-name CodeBuildKubectlRole --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess<br><br>aws iam attach-role-policy --role-name CodeBuildKubectlRole --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess</pre><p>In this script we are attaching the permissions for CloudWatch Logs, AWS Code Build Admin, AWS S3, and if you are using ECR the permission would be AmazonEC2ContainerRegistryFullAccess.</p><p>When you run this shell script go to IAM &gt; Roles &gt; CodeBuildKubectlRole, we will see the attached permissions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*rNSmBlSTB02qNjIc" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EVvdOLHS1eAkWoMM" /></figure><p>Now, Let’s navigate to AWS CodePipeline and create the Pipeline of Build Stage. As you can see I had created the pipeline named short-url-deployment</p><ol><li>Click on Create Pipeline.</li><li>Select Build Custom Pipeline, click on Next.</li><li>Name the pipeline short-url-deployment , choose execution mode Queued.</li><li>In Service Role, create New Service Role, leave it as it is named.</li><li>Scroll Down click on Advanced Settings choose S3 Bucket for Default Location and Default AWS Managed Keys.</li><li>Now, choose the Source Provider where your code is hosted and connect it to respected source provider (VCS). In my case, my code is hosted on GitHub so I choose GitHub via GitHub App. After connecting to GitHub scroll down to trigger select No filter that will execute the pipeline on Code Push.</li><li>Now, you move to the Build Stage where you had to add BuildSource provider, so click on Other Build Provider and choose AWS CodeBuild.</li><li>As you can see click on Project it will open the new window of CodeBuild.</li></ol><ul><li>Name the CodeBuild Provider as short-url</li><li>Scroll Down, leave it as it is Provisioning Model On-demand, Environment Image Managed Instance, Compute EC2.</li><li>Choose Operating System Amazon Linux, Runtime Standard and select latest image.</li><li>In the Service Role choose the Existing Role CodeBuildKubectlRole which we had created earlier.</li><li>Open Additional Configuration select Privileged.</li><li>Scroll down, in buildspec choose Use a buildspec file if you have custom name of buildspec you can specify it otherwise it will automatically look buildspec.yml file in GitHub.</li><li>Select CloudWatch Logs to show logs of phases that we defined in buildspec.yml when it runs.</li><li>Then continue to CodePipeline you will move to codepipeline section</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*pruCKxs_jjpnsXt2" /></figure><p>Click on Next, skip the Continuous Delivery Stage for now.</p><p>As we had talked about the buildspec.yml file in CodeBuild creation what it is ?</p><p>If we had used any other CI tool like Jenkins, GitLab CI it has Jenkinsfile and gitlab-ci.yml file where we write multiple stages like Docker build, push that will be built and deploy to Kubernetes cluster.</p><p>As same as in AWS CI/CD CodeBuild uses buildspec.yml file. So let’s understand this file.</p><pre>version: 0.2<br>run-as: root<br><br>env: <br>  parameter-store:<br>    DOCKER_REGISTRY_USERNAME: /golang-app/docker-credentials/username<br>    DOCKER_REGISTRY_PASSWORD: /golang-app/docker-credentials/password<br>    DOCKER_REGISTRY_URL: /golang-app/docker-credentials/url<br><br>phases:<br>  install: <br>    commands:<br>      - echo Installing dependencies...<br>      - curl -LO &quot;https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl&quot;<br>      - chmod +x kubectl<br>      - mv kubectl /usr/local/bin/<br>  pre_build:<br>    commands:<br>      - echo &quot;Logging to DockerHub&quot;<br>      - echo &quot;$DOCKER_REGISTRY_PASSWORD&quot; | docker login -u &quot;$DOCKER_REGISTRY_USERNAME&quot; --password-stdin $DOCKER_REGISTRY_URL<br>      - aws sts get-caller-identity<br>      - aws eks update-kubeconfig --region ap-south-1 --name demo-eks-cluster<br>      - kubectl config current-context<br><br>  build:<br>    commands: <br>      - echo &quot;Building Docker Image&quot;<br>      - docker build -t &quot;$DOCKER_REGISTRY_USERNAME/short_url:$CODEBUILD_RESOLVED_SOURCE_VERSION&quot; .<br>      - docker push &quot;$DOCKER_REGISTRY_USERNAME/short_url:$CODEBUILD_RESOLVED_SOURCE_VERSION&quot;<br><br>  post_build:<br>    commands:<br>      - echo &quot;Docker Image is Pushed&quot;<br>      - echo &quot;Deploying the application to EKS&quot;<br>      - kubectl set image deployment/shorturl shortenurlapp=$DOCKER_USERNAME/short_url:$CODEBUILD_RESOLVED_SOURCE_VERSION<br>      - kubectl get svc</pre><ol><li>We are defining the version, like in docker-compose we define the version when we create docker-compose.yml file it was same as that.</li><li>Now, this will be build as root.</li><li>In env section, we had defined 3 parameters for Docker Build, Push commands.</li></ol><ul><li>Navigate to AWS Parameter, it is a service of SSM i.e. AWS System Manager.</li><li>Click on Create Parameter and follow this name path so that it can be better understable /golang-app/docker-credentials/url which means our application-name then which kind of credentials then what we need to store.</li><li>Scroll down, select the Type SecureString and fill the value for URL (<a href="http://docker.io/">docker.io</a>).</li><li>Now, create the 2 parameters for Docker Username and Docker Password. Remember in Docker the password is PAT Token.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zZrwWbuBWjs3uLYU" /></figure><p>Add these parameters in buildspec file in env section.</p><pre> env: <br>   parameter-store:<br>     DOCKER_REGISTRY_USERNAME: /golang-app/docker-credentials/username<br>     DOCKER_REGISTRY_PASSWORD: /golang-app/docker-credentials/password<br>     DOCKER_REGISTRY_URL: /golang-app/docker-credentials/url</pre><p>Now we have phases section where we 3 phase install, pre-build, build and post-build.</p><p>In install phase we are installing the required CLI like of kubectl.</p><pre>    install: <br>      commands:<br>        - echo Installing dependencies...<br>        - curl -LO &quot;https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl&quot;<br>        - chmod +x kubectl<br>        - mv kubectl /usr/local/bin/</pre><p>In pre-build phase, first we are logging to DockerHub account so that we can push the image, then we are updating the kubeconfig of our EKS Cluster and at last we check the current-context of kubeconfig.</p><pre>    pre_build:<br>      commands:<br>        - echo &quot;Logging to DockerHub&quot;<br>        - echo &quot;$DOCKER_REGISTRY_PASSWORD&quot; | docker login -u &quot;$DOCKER_REGISTRY_USERNAME&quot; --password-stdin $DOCKER_REGISTRY_URL<br>        - aws sts get-caller-identity<br>        - aws eks update-kubeconfig --region ap-south-1 --name demo-eks-cluster<br>        - kubectl config current-context</pre><p>Now, come to build section in which we are building Docker Image and Pushing to DockerHub.</p><pre>    build:<br>      commands: <br>        - echo &quot;Building Docker Image&quot;<br>        - docker build -t &quot;$DOCKER_REGISTRY_USERNAME/short_url:$CODEBUILD_RESOLVED_SOURCE_VERSION&quot; .<br>        - docker push &quot;$DOCKER_REGISTRY_USERNAME/short_url:$CODEBUILD_RESOLVED_SOURCE_VERSION&quot;</pre><p>In post-build, we are setting the new image of the deployed app on our EKS Cluster with the command kubectl set image</p><pre>    post_build:<br>      commands:<br>        - echo &quot;Docker Image is Pushed&quot;<br>        - echo &quot;Deploying the application to EKS&quot;<br>        - kubectl set image deployment/shorturl shortenurlapp=$DOCKER_USERNAME/short_url:$CODEBUILD_RESOLVED_SOURCE_VERSION<br>        - kubectl get svc</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2XwkwPp52wJh202s" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1JBJh6xsoQepilPl" /></figure><p>As we can see our 2 stages Source and Build both are successful and shows the output in CodePipeline.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*hOFiHQ48KzTJ1k-q" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*59rptiaZZWNUirGq" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*C3Zj7iacjC4sdryV" /></figure><h3>Deploy ArgoCD on EKS Cluster</h3><p>Now, we will deploy the CD part (Continuous Deployment) on EKS cluster so that when any changes happens in kubernetes manifests it will automatically deploy to the EKS cluster.</p><p>ArgoCD is a GitOps tool that will manage the deployments of applications in Kubernetes clusters. It pulls the desired state and sync with the current state and if not matched it update the changes on Kubernetes cluster.</p><p>Create the namespace of ArgoCD</p><pre>kubectl create namespace argocd</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qMSeIQifa6oArqYX" /></figure><p>Now deploy the CRD’s (Custom Resource Definitions), deployments, services in namespace of argocd.</p><pre>kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*VwKkhLrIzUv4t9Ob" /></figure><pre>kubectl get po -n argocd</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gJN9aJmEVvjtd7go" /></figure><p>Edit the service of argocd server to access the ArgoCD outside.</p><pre>kubectl patch svc argocd-server -n argocd -p &#39;{&quot;spec&quot;: {&quot;type&quot;: &quot;NodePort&quot;}}&#39; <br>kubectl get svc -n argocd</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EqZzzeQDEtEBgg1n" /></figure><p>Now, we can access the ArgoCD UI.</p><ul><li>Username: admin</li><li>Password: It is stored in secrets of argocd-initial-admin-secret in namespace of argocd.</li></ul><pre>kubectl get secrets argocd-initial-admin-secret -n argocd -oyaml   echo &quot;Your password&quot; | base64 -d</pre><p>As secrets are stored in base64 encrypted, so we had decoded it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/898/0*VR84D9z-WX0bAkrm" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Ab8NKntBhjZbyxnb" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sm-pYFAW-6JNx_nG" /></figure><p>We need to create an application in ArgoCD, so I had created the file name go-app-deployment.yaml.</p><pre> apiVersion: argoproj.io/v1alpha1<br> kind: Application<br> metadata:<br>   name: go-app-deployment<br>   namespace: default<br> spec:<br>   project: default<br>   source:<br>     repoURL: &#39;https://github.com/amitmaurya07/Golang_AWS_Deployment.git&#39;<br>     targetRevision: main<br>     path: kuberenetes/manifests<br>   destination:<br>     server: &#39;https://kubernetes.default.svc&#39;<br>     namespace: default<br>   syncPolicy:<br>     automated:<br>       prune: true<br>       selfHeal: true</pre><p>In this yaml file see the apiVersion this is the CRD of ArgoCD to create an application of kind. Then we had given the repoURL of our github repository where argocd will check the changes and there is path of kuberenetes manifests where our manifests files are stored. In syncPolicy there is automated selfHeal is true which means it monitors the kubernetes resources if any changes happens it matches the desired state to the current state automatically.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*y3AkbzaEudbD0uqy" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0NJwmDqGeTjlgjML" /></figure><p>As we can see the application on ArgoCD and our pods with service and ingress is shown in ArgoCD UI.</p><h3>Conclusion</h3><p>In this article, we had learnt how to deploy Golang Application on EKS Cluster through CodePipeline and CodeBuild. Meanwhile in the upcoming blogs you will see a lot of AWS Services creation and automating it with terraform. Stay tuned for the next blog !!!</p><p>GitHub Code : <a href="https://github.com/amitmaurya07/Golang_AWS_Deployment">Golang AWS Deployment</a></p><p>Twitter : <a href="http://x.com/amitmau07">x.com/amitmau07</a></p><p>LinkedIn : <a href="http://linkedin.com/in/amit-maurya07">linkedin.com/in/amit-maurya07</a></p><p>If you have any queries you can drop the message on LinkedIn and Twitter.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f7793e230ae9" width="1" height="1" alt=""><hr><p><a href="https://towardsaws.com/end-to-end-devops-for-a-golang-web-app-docker-eks-aws-ci-cd-f7793e230ae9">End-to-End DevOps for a Golang Web App: Docker, EKS, AWS CI/CD</a> was originally published in <a href="https://towardsaws.com">Towards AWS</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Step-by-Step Guide: How to Create and Mount AWS EFS (Elastic File System)]]></title>
            <link>https://aws.plainenglish.io/step-by-step-guide-how-to-create-and-mount-aws-efs-elastic-file-system-15b5e62f5b09?source=rss-357aad067a18------2</link>
            <guid isPermaLink="false">https://medium.com/p/15b5e62f5b09</guid>
            <category><![CDATA[development]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[aws-ec2]]></category>
            <category><![CDATA[aws-certification]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[Amit Maurya]]></dc:creator>
            <pubDate>Wed, 13 Nov 2024 11:06:51 GMT</pubDate>
            <atom:updated>2024-11-13T11:06:51.844Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/838/1*R-AFXbFylu_cWiQIBSXdmA.png" /></figure><p>In this article, we will learn about AWS EC2 Instance Storage i.e. EFS (Elastic File System), how to create it, how to mount it to EC2 instances. In today’s modern world we need a storage solution that is scalable, efficient and flexible to scale our business to handle growing data demands.</p><h3>Overview of AWS EFS (Elastic File System)</h3><p>As we know AWS offers 200+ services which makes the best cloud solution which meets our business needs whether it’s in AI field, DevOps field. If we talk about EC2 i.e. Elastic Compute Cloud storage solutions it offers EBS (Elastic Block Storage) and EFS (Elastic File System).</p><p>Elastic File System is Network Shared Filesystem (NFS) that means multiple 100s of EC2’s in different AZ’s (Availability Zone’s) can talk to single central storage that is mounted where multiple EC2’s can store files on network. In simple, we have 100’s of EC2 in AZ1 and 100’s of EC2 in AZ2 they have single filesystem where they can store files and can see these files in other AZ’s also. That’s make it very highly scalable, flexible and also expensive as it is 3 times of gp2 price.</p><h3>Prerequisites for Setting Up AWS EFS</h3><ol><li>AWS Account</li><li>EFS Client Installed</li><li>IAM Permissions</li></ol><h3>Step-by-Step Guide to Creating an AWS EFS</h3><p>Open AWS Management Console and on top in Search Bar, write EFS.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YTxz1WgsNBCZsQMa" /></figure><p>Open EFS and click on Create Filesystem. Select the default VPC and the Name is optional so keep it blank or you can provide name.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/942/0*2ff6YUmzuoyHjYBU" /></figure><p>Go to Customize you will see the lot of configuration options, we will go step by step understand it what it is.</p><ul><li>Filesystem Type: In filesystem type there are 2 options. This is for Availability and Durability.</li><li>Regional: In regional, the EFS will be available in Multi-AZ which will be great for Production.</li><li>One-Zone: One-Zone means EFS will be available in single AZ which is great for testing purpose or dev environments that will be cost-saving.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*88P1pIBRyDqB0oRc" /></figure><ul><li>Automatic Backups: It will take backup of your data automatically. For now, we will check this.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zQ86fl_iC4d92Is2" /></figure><ul><li>Lifecycle Management: EFS provides lifecycle that means it will automatically move the file to the Storage Tier after N number of days. EFS provides 3 types of storage tiers that are:</li><li>Standard (Default): When we are frequently accessing files it lies in Standard storage tier.</li><li>EFS-IA (Infrequent Access): Infrequent Access means a certain number of days passed but we do not accessing the file frequently. Like if I set 60 Days if the file is not accessed in 60 Days it will automatically move to the EFS-IA that will be cost effective and cheaper.</li><li>Archive: In Archive, it is more 50% cheaper, the data that we are accessing very few times in a year so it will automatically move to Archive storage tier.</li><li>Archive Storage Tier is not available in One-Zone.</li></ul><p>This all done by setting lifecycle management on EFS, we will leave it default.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3H1ONKhPvMXqQjjD" /></figure><p>In this, we had set the Transition to Standard to On First Access means whenever the file is accessed first time it will automatically to Standard Storage tier.</p><ul><li>Performance Settings: EFS provides 2 throughput modes i.e. Enhanced and Bursting.</li><li>In Enhanced Throughput mode there are 2 methods:</li></ul><ol><li>Elastic: This is the recommended one because it automatically scales the throughput UP and DOWN on workload.</li><li>Provisioned: In provisioned one, we had to decide the throughput size.</li></ol><ul><li>In Bursting Mode it has the General Purpose and Max I/O performance settings. General Purpose is recommended for Web Servers and Max I/O is recommended where we need low latency like for data analytics.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*VoGPVBgUk_EkDQqn" /></figure><ul><li>For now, we are going with default settings Elastic Throughput Mode and General Purpose Performance Setting. Click on “Next”</li></ul><p>Now, we will move to the Network Access where we choose the VPC and set the Mount Targets. As it is One-Zone so, we will set the Mount Target in single Availability Zone (AZ)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*iJ19TqJlXS8VnGLq" /></figure><p>But, before attaching this security group we will create new Security Group for EFS where we will allow ALL-TRAFFIC.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/996/0*cgfJZvzXE8sAfhNV" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*E45J1dcYdrOecKOv" /></figure><p>After this, select the security group of EFS-Demo in Mount Target.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Ufmv875xBAxf4G7D.png" /></figure><p>Then, click on Next where the page opens Filesystem Policy leave it as it is then you will reach to Review and Create and click on Create.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YnKb9muk_xvxY26v" /></figure><p>Now, the EFS filesystem is successfully created. Let’s move to the EC2 section where we will create 2 EC2 instances in different Availability Zone’s.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*r7mcvPCd2Dxafo0c" /></figure><ol><li>In EFS Filesystem we only Pay what we use and one thing more only Linux distributions can be attached to EFS filesystem not Windows.</li><li>Create EC2 Instance name EFS-Demo-1 in us-west-1a (N.California), then select the AMI (Amazon Machine Image)OS of Ubuntu 22.04 you can select anyone of Linux distribution, then select t2.micro Instance Type and select Proceed without KeyPair.</li><li>Now, here comes the Network Settings Part, click on Edit and choose Subnet of us-west-1a other things leave it as default.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Rl7XOaMd4hUg6_8d" /></figure><ol><li>Scroll Down to Configure Storage section where EBS volume have 8 Gib of gp2 and scroll down you will see you will see Filesystems click on Edit then you can see our created EFS Filesystem.</li><li>If we don’t want to do this we had to run some commands but for now I am configuring this with EC2 configuration settings.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*w9ycgCK54DYFmP3K" /></figure><p>Now click on Add Shared Filesystem it will automatically set the mount point and create Security Groups and attach it to EFS.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Zle0Py46CMJrPV0Z" /></figure><ol><li>Now, click on Create the Instance and with same settings click 2nd instance in another Availability zone us-west-1c and select the existing security group that is attached to Instance 1 and use the same EFS Filesystem.</li><li>Here, now you see security group (efs-sg-1) is automatically attached to EFS Mount Targets.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*JvvUvtRZt1IZ1GCC" /></figure><p>In newly created Security Group the Inbound Rules is NFS of port 2049 where the destination is Instance Security Group ID.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AGCIjXB5TmmT8wUQ" /></figure><p>Now our 2 instances are ready which are in different Availability Zone’s and we can see in mount targets Instance 2nd Security Groups is also attached.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ymf-Z9x0lvPJFkLm" /></figure><ol><li>Let’s connect to Instance 1 and create file on mount target (/mnt/efs/fs1). Go to Instance 1 and click on Connect to Instance, in Ubuntu OS we need to run the commands on both the instances</li><li>Then check the mount point exists or not if not exists create this.</li><li>Check that the filesystem is mounted or not by executing the command.</li></ol><pre>df -h | grep efs</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*N5g1ubjcBOrS6nCg" /></figure><p>Create Sample hello.txt in this folder in Instance 1 and checks that the file is created in Instance 1 is we can see or not.</p><pre>echo &quot;hello-world from Instance 1&quot; &gt; /mnt/efs/fs1/hello.txt</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Zdq9uR3zx8dBRWc0" /></figure><p>Now connect to Instance-2 and check that the file is accessible or not.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/709/0*VJGkn8eSo58Mdwou" /></figure><h3>Conclusion</h3><p>In this article, we had learnt how to create EFS (Elastic File System) and mount it to EC2 instances. EFS can scale up to Petabytes automatically. Meanwhile in the upcoming blogs you will see a lot of AWS Services creation and automating it with terraform. Stay tuned for the next blog !!!</p><p>GitHub Code : <a href="http://github.com/amitmaurya07/AWS-Terraform/tree/">github.com/amitmaurya07/AWS-Terraform/tree</a>..</p><p>Twitter : <a href="http://x.com/amitmau07">x.com/amitmau07</a></p><p>LinkedIn : <a href="http://linkedin.com/in/amit-maurya07">linkedin.com/in/amit-maurya07</a></p><p>If you have any queries you can drop the message on LinkedIn and Twitter.</p><h3>In Plain English 🚀</h3><p><em>Thank you for being a part of the </em><a href="https://plainenglish.io/"><strong><em>In Plain English</em></strong></a><em> community! Before you go:</em></p><ul><li>Be sure to <strong>clap</strong> and <strong>follow</strong> the writer ️👏<strong>️️</strong></li><li>Follow us: <a href="https://x.com/inPlainEngHQ"><strong>X</strong></a> | <a href="https://www.linkedin.com/company/inplainenglish/"><strong>LinkedIn</strong></a> | <a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong>YouTube</strong></a> | <a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Discord</strong></a> | <a href="https://newsletter.plainenglish.io/"><strong>Newsletter</strong></a> | <a href="https://open.spotify.com/show/7qxylRWKhvZwMz2WuEoua0"><strong>Podcast</strong></a></li><li><a href="https://differ.blog/"><strong>Create a free AI-powered blog on Differ.</strong></a></li><li>More content at <a href="https://plainenglish.io/"><strong>PlainEnglish.io</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=15b5e62f5b09" width="1" height="1" alt=""><hr><p><a href="https://aws.plainenglish.io/step-by-step-guide-how-to-create-and-mount-aws-efs-elastic-file-system-15b5e62f5b09">Step-by-Step Guide: How to Create and Mount AWS EFS (Elastic File System)</a> was originally published in <a href="https://aws.plainenglish.io">AWS in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Learn How to Deploy Scalable 3-Tier Applications with AWS ECS]]></title>
            <link>https://aws.plainenglish.io/learn-how-to-deploy-scalable-3-tier-applications-with-aws-ecs-563e476206e4?source=rss-357aad067a18------2</link>
            <guid isPermaLink="false">https://medium.com/p/563e476206e4</guid>
            <category><![CDATA[ecs-fargate]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[terraform]]></category>
            <category><![CDATA[aws-lambda]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[Amit Maurya]]></dc:creator>
            <pubDate>Sun, 10 Nov 2024 14:17:28 GMT</pubDate>
            <atom:updated>2024-11-11T14:27:25.815Z</atom:updated>
            <content:encoded><![CDATA[<h3>Deploy Three-tier Application on ECS with Terraform</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7I0FYhXOJbiAqLdtv9E9aQ.png" /></figure><p>In the previous article, we deployed the 3-tier architecture on GKE (Google Kubernetes Engine) using Jenkins (CI/CD). In this article, we will deploy the same application, Wanderlust, on AWS ECS (Elastic Container Service) with ALB (Application Load Balancer).</p><p>GitHub Terraform Code : <a href="https://github.com/amitmaurya07/AWS-Terraform/tree/master">github.com/amitmaurya07/AWS-Terraform/tree/..</a></p><p>GitHub Application Code : <a href="https://github.com/amitmaurya07/wanderlust-devsecops/tree/aws-ecs-deployment">https://github.com/amitmaurya07/wanderlust-devsecops/tree/aws-ecs-deployment</a></p><h3>Overview of 3-Tier Architecture</h3><p>As we had already discussed the 3 tier architecture in previous article so let’s again discuss this.</p><p>A three-tier application is a software architecture pattern which includes the Application Layer, Data Layer, and Presentation Layer. It enhances the maintainability, scalability, and flexibility.</p><p>1) Presentation Layer: When we open the web browser and then opens any website it means we are interacting with the website that will take inputs from client side. In simple the frontend part, or GUI (Graphical User Interface) is the presentation layer.</p><p>2) Application Layer: We have heard the term business logic in the tech industry a lot. The application layer contains the logic part, i.e., the backend. When we give any input on the frontend, this layer processes some logic against that input and provides the result.</p><p>3) Data Layer: As we had heard the data word that means it consists the information which is stored in database that is connected to Presentation Layer and Application Layer.</p><h3>AWS ECS (Elastic Container Service)</h3><p>Before diving into benefits of AWS ECS, let’s first understand or take the overview of ECS (Elastic Container Service).</p><p>ECS (Elastic Container Service) is one of the container services that is used to deploy your application code, binaries, dependencies in a container like docker does. In ECS there are three components -</p><ol><li>Capacity : Decide the Infrastructure on which you want to deploy the container (EC2, or AWS Fargate)</li><li>Controller : Here, ECS Scheduler comes in place that deploys the application.</li><li>Provisioning : After deploying containers on ECS, from this we can manage the containers.</li></ol><p>ECS provides scalability that will automatically scale containers based on the demand.</p><h3>Prerequisites</h3><ol><li>AWS Account: AWS account with permissions to use ECS, ECR, DocumentDB (MongoDb), VPC. For now we will assign Administrative permissions to user.</li><li>Docker: Ensure Docker is installed locally to build and push container images.</li><li>Terraform: Install Terraform CLI in your terminal. (<a href="https://releases.hashicorp.com/terraform/1.9.8/terraform_1.9.8_windows_386.zip">Terraform For Windows</a>)</li></ol><h3>Setting Up AWS Environment</h3><p>Creating IAM User with Required Permissions for Terraform</p><ul><li>Navigate to Search Bar of AWS Console and search IAM (Identity Access and Management)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Yq8PObI20UPa6CQG" /></figure><ul><li>Click on IAM, in left side go to Users section and click on Create User.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/406/0*nCDlfVaj3rIcJWZ0" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_2PMhl581bHTq9zB" /></figure><ul><li>After naming the user “terraform“, assign permissions for now Administrator Access.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*p4VY61ATdGQoqLae" /></figure><ul><li>Now, click on terraform user go to Security Credentials and scroll down for Access Key.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*BjCNxC5sV3KPn4vZ" /></figure><ul><li>As we can see there is no Access Keys so let’s create access key, choose CLI for usecase and click on Next provide Description and then Next you will get Access and Secret Key.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/987/0*nzIgz8akLiZZ9UoO" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sDl4oC76pAW-WI7i" /></figure><ul><li>Download the CSV file and now copy the Secret and Access Key for usage in terraform.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/976/0*lqx6v-dLMC8q4D4Q" /></figure><h3>Networking Creation with Terraform</h3><p>Let’s create the infrastructure on AWS by creating VPC, Subnets, Route Tables, Internet Gateway by Terraform Modules.</p><ol><li>Create the directory structure for module VPC creation vpc-module in which it contains the VPC Creation, Subnets, Interet Gateway and Route Table.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/367/0*tS1tqJvhfZQV9YyG" /></figure><p>Inside the VPC module we have <a href="http://main.tf/">main.tf</a>, <a href="http://variables.tf/">variables.tf</a> and <a href="http://output.tf/">output.tf</a>. In the <a href="http://main.tf/">main.tf</a> file we are going to create VPC, then Public and Private Subnet, then Internet Gateway and Route Table for Private and Public and then attach it with Subnets and Internet gateway.</p><p>vpc-module/main.tf:</p><pre> resource &quot;aws_vpc&quot; &quot;three-tier&quot; {<br>   cidr_block       = &quot;10.0.0.0/16&quot;<br>   instance_tenancy = &quot;default&quot;<br><br>   tags = {<br>     Name = &quot;three-tier&quot;<br>   }<br> }<br><br> data &quot;aws_availability_zones&quot; &quot;available&quot; {<br> }<br><br> resource &quot;aws_subnet&quot; &quot;public&quot; {<br>   vpc_id = aws_vpc.three-tier.id<br>   cidr_block = cidrsubnet(aws_vpc.three-tier.cidr_block, 8, count.index + 1)<br>   count = 2<br>   availability_zone = element(data.aws_availability_zones.available.names, count.index)<br>   map_public_ip_on_launch = true<br><br>   tags = {<br>     Name = &quot;three-tier-public&quot;<br>   }<br> }<br><br> resource &quot;aws_subnet&quot; &quot;private&quot; {<br>   vpc_id = aws_vpc.three-tier.id<br>   cidr_block = cidrsubnet(aws_vpc.three-tier.cidr_block, 8, count.index + 4)<br>   count = 2<br><br>   tags = {<br>     Name = &quot;three-tier-private&quot;<br>   }<br> }<br><br> resource &quot;aws_internet_gateway&quot; &quot;three-tier-igw&quot; {<br>   vpc_id = aws_vpc.three-tier.id<br>   tags = {<br>     &quot;Name&quot; = &quot;three-tier-igw&quot;<br>   }<br> }<br><br> resource &quot;aws_route_table&quot; &quot;public-rt&quot; {<br>   vpc_id = aws_vpc.three-tier.id<br>   route {<br>     cidr_block = &quot;0.0.0.0/0&quot;<br>     gateway_id = aws_internet_gateway.three-tier-igw.id<br>   }<br>   tags = {<br>     &quot;Name&quot; = &quot;three-tier-public-rt&quot;<br>   }<br> }<br><br> resource &quot;aws_route_table&quot; &quot;private-rt&quot; {<br>   vpc_id = aws_vpc.three-tier.id<br>   tags = {<br>     &quot;Name&quot; = &quot;three-tier-private-rt&quot;<br>   }<br> }<br><br> resource &quot;aws_route_table_association&quot; &quot;public-rt-association&quot; {<br>   count = length(aws_subnet.public)<br>   subnet_id = aws_subnet.public[count.index].id<br>   route_table_id = aws_route_table.public-rt.id<br> }<br><br> resource &quot;aws_route_table_association&quot; &quot;private-rt-association&quot; {<br>   count = length(aws_subnet.private)<br>   subnet_id = aws_subnet.private[count.index].id<br>   route_table_id = aws_route_table.private-rt.id<br> }</pre><p>Let’s break each resource block to proper understand what each resource block is going to create on AWS.</p><pre> resource &quot;aws_vpc&quot; &quot;three-tier&quot; {<br>   cidr_block       = &quot;10.0.0.0/16&quot;<br>   instance_tenancy = &quot;default&quot;<br><br>   tags = {<br>     Name = &quot;three-tier&quot;<br>   }<br> }<br><br> data &quot;aws_availability_zones&quot; &quot;available&quot; {<br> }</pre><p>There are 2 blocks in <a href="http://main.tf/">main.tf</a> file of VPC Module:</p><ul><li>Resource Block name three-tier is going to create VPC (Virtual Private Cloud) of CIDR (Classless-InterDomain Routing) “10.0.0.0/16“.</li><li>Data block is going to fetch the availaiblity zones.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*KdNdP18VZQ-6fT2N" /></figure><pre>    resource &quot;aws_subnet&quot; &quot;public&quot; {<br>      vpc_id = aws_vpc.three-tier.id<br>      cidr_block = cidrsubnet(aws_vpc.three-tier.cidr_block, 8, count.index + 1)<br>      count = 2<br>      availability_zone = element(data.aws_availability_zones.available.names, count.index)<br>      map_public_ip_on_launch = true<br><br>      tags = {<br>        Name = &quot;three-tier-public&quot;<br>      }<br>    }<br><br>    resource &quot;aws_subnet&quot; &quot;private&quot; {<br>      vpc_id = aws_vpc.three-tier.id<br>      cidr_block = cidrsubnet(aws_vpc.three-tier.cidr_block, 8, count.index + 4)<br>      count = 2<br><br>      tags = {<br>        Name = &quot;three-tier-private&quot;<br>      }<br>    }</pre><p>In this snippet of terraform code there are 2 resource blocks that will create Public and Private Subnet.</p><ul><li>Resource Block of Public Subnet has the VPC ID that will attach the VPC which will be created next is cidr_block which contains cidrsubnet function that will calculate the subnets in the given network address and subnet mask in CIDR format.</li><li>aws_vpc.three-tier.cidr_block will picks the CIDR block of created VPC.</li><li>8 is the to add subnets in the CIDR block like I have “10.0.0.0/16“ now it will add 8 in subnet mask /16+8 it will become /24 bits.</li><li>count.index + 1 is used to create multiple subnets in AWS with Terraform. In the CIDR block 10.0.0.0/24 is created on index[0] and on index[1] the new CIDR block is there 10.0.1.0/24</li><li>Now next is count which will create 2 resources of Public Subnet in AWS.</li><li>In availability zone there is element function which will take the value from the data block of availability zone [&quot;us-east-1a&quot;, &quot;us-east-1b&quot;, &quot;us-east-1c&quot;] after this it will select the availability zone on basis of count.index</li><li>map_public_ip_on_launch is true means in the Public Subnet the resources that are in this subnet will have Public IP that is automatically assigned on launch.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*nk6Ifo7gpc7sCAUM" /></figure><pre>  resource &quot;aws_internet_gateway&quot; &quot;three-tier-igw&quot; {<br>    vpc_id = aws_vpc.three-tier.id<br>    tags = {<br>      &quot;Name&quot; = &quot;three-tier-igw&quot;<br>    }<br>  }</pre><p>In this resource we are going to create Internet Gateway with the name three-tier-igw that is attached with VPC ID (vpc_id).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*lahfG8lzhwX1UKdR" /></figure><pre>  resource &quot;aws_route_table&quot; &quot;public-rt&quot; {<br>    vpc_id = aws_vpc.three-tier.id<br>    route {<br>      cidr_block = &quot;0.0.0.0/0&quot;<br>      gateway_id = aws_internet_gateway.three-tier-igw.id<br>    }<br>    tags = {<br>      &quot;Name&quot; = &quot;three-tier-public-rt&quot;<br>    }<br>  }<br><br>  resource &quot;aws_route_table&quot; &quot;private-rt&quot; {<br>    vpc_id = aws_vpc.three-tier.id<br>    tags = {<br>      &quot;Name&quot; = &quot;three-tier-private-rt&quot;<br>    }<br>  }</pre><ul><li>Now, there are 2 resources in which Public and Private Route Table is created that is used to route the traffic for the resources lying in Subnets.</li><li>In the Public Route Table (public-rt) as we can see there is a route block that contains the CIDR block of 0.0.0.0/0 which means allowing all traffic and next is gateway ID where Internet Gateway is attached. In the Public Subnet we would attach the IGw (Internet Gateway) to access the resources from Internet.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*AIbOTNmmZQ4GBGq9" /></figure><pre>  resource &quot;aws_route_table_association&quot; &quot;public-rt-association&quot; {<br>    count = length(aws_subnet.public)<br>    subnet_id = aws_subnet.public[count.index].id<br>    route_table_id = aws_route_table.public-rt.id<br>  }<br><br>  resource &quot;aws_route_table_association&quot; &quot;private-rt-association&quot; {<br>    count = length(aws_subnet.private)<br>    subnet_id = aws_subnet.private[count.index].id<br>    route_table_id = aws_route_table.private-rt.id<br>  }</pre><p>In these 2 resource blocks we are attaching the Subnets (Public Subnet in Public Route Table and Private Subnet in Private Route Table).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fXfeA9RDHsB1LuI2" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_YC-HOdsI2WAJL7P" /></figure><p>/vpc-module/variables.tf:</p><pre>  variable &quot;public_subnet_cidrs&quot; {<br>    description = &quot;List of CIDR blocks for public subnets&quot;<br>    type        = list(string)<br>  }<br><br>  variable &quot;private_subnet_cidrs&quot; {<br>    description = &quot;List of CIDR blocks for private subnets&quot;<br>    type        = list(string)<br>  }</pre><p>We had declared two variables for CIDR’s where the type is list.</p><p>/vpc-module/output.tf:</p><pre>  output &quot;vpc_id&quot; {<br>    value = aws_vpc.three-tier.id<br>  }<br><br>  output &quot;public_subnet_id&quot; {<br>    value = aws_subnet.public[*].id<br>  }<br><br>  output &quot;subnet_id&quot; {<br>    value = aws_subnet.private[*].id<br>  }</pre><ul><li>In the <a href="http://output.tf/">output.tf</a> file we are printing the output of vpc_id, public and private Subnet ID.</li></ul><p>Now here comes the parent main.tf file in which we call this vpc-module and the required parameters.</p><pre>module &quot;vpc&quot; {<br>  source = &quot;./modules/vpc-module&quot;<br>  public_subnet_cidrs = var.public_subnet_cidrs<br>  private_subnet_cidrs = var.private_subnet_cidrs<br>}</pre><p>Okay, we have automated the VPC creation on AWS with Terraform now, let’s break down the parent <a href="http://main.tf/">main.tf</a> file.</p><p>If we will going to break all the modules <a href="http://main.tf/">main.tf</a> the blog will become lengthier so we will cover the modules with its proper understanding in the next blog.</p><p>main.tf:</p><pre>provider &quot;aws&quot; {<br>  region = var.region<br>}<br>module &quot;ec2_db&quot; {<br>  source = &quot;./modules/aws_ec2_module&quot;<br>  security_group_ids = [module.aws_security_group.security_group_id]<br>  name = &quot;${var.name}-mogodb&quot;<br>  ami = &quot;ami-09b0a86a2c84101e1&quot;<br>  instance_type = &quot;t2.micro&quot;<br>  subnet_id = module.vpc.public_subnet_id[0]<br>}<br>module &quot;vpc&quot; {<br>  source = &quot;./modules/vpc-module&quot;<br>  public_subnet_cidrs = var.public_subnet_cidrs<br>  private_subnet_cidrs = var.private_subnet_cidrs<br>}<br>module &quot;aws_security_group&quot; {<br>  source = &quot;./modules/security-group&quot;<br>  sg_name = &quot;${var.name}-sg&quot;<br>  vpc_id = module.vpc.vpc_id<br>}<br>module &quot;aws_lb&quot; {<br>  source = &quot;./modules/aws_alb_module&quot;<br>  name = &quot;${var.name}-alb&quot;<br>  security_group_id = module.aws_security_group.security_group_id<br>  subnet_id = module.vpc.public_subnet_id<br>  vpc_id = module.vpc.vpc_id<br>}<br>module &quot;frontend-aws_ecr&quot; {<br>  source = &quot;./modules/aws_ecr_module&quot;<br>  name = &quot;${var.name}-frontend&quot;<br>}<br>module &quot;backend-aws_ecr&quot; {<br>  source = &quot;./modules/aws_ecr_module&quot;<br>  name = &quot;${var.name}-backend&quot;<br>}<br>module &quot;aws_ecs_cluster&quot; {<br>  source = &quot;./modules/aws_ecs_cluster_module&quot;<br>  name = var.name<br>}<br>module &quot;frontend-ecs&quot; {<br>  source = &quot;./modules/aws_ecs_module&quot;<br>  name = &quot;${var.name}-frontend-ecs&quot;<br>  ecr_repo_url = module.frontend-aws_ecr.frontend-repository_url<br>  image_tag = &quot;3&quot;<br>  ecs_cluster_id = module.aws_ecs_cluster.ecs_cluster_id<br>  port = 5173<br>  vpc_id = module.vpc.vpc_id<br>  subnet_id = module.vpc.public_subnet_id<br>  security_group_id = module.aws_security_group.security_group_id<br>  target_group_arn = module.aws_lb.tg-arn<br>}<br>module &quot;backend-ecs&quot; {<br>  source = &quot;./modules/aws_ecs_module&quot;<br>  name = &quot;${var.name}-backend-ecs&quot;<br>  ecr_repo_url = module.backend-aws_ecr.frontend-repository_url<br>  port = 5000<br>  ecs_cluster_id = module.aws_ecs_cluster.ecs_cluster_id<br>  image_tag = &quot;2&quot;<br>  vpc_id = module.vpc.vpc_id<br>  subnet_id = module.vpc.public_subnet_id<br>  security_group_id = module.aws_security_group.security_group_id<br>  target_group_arn = module.aws_lb.tg-arn-backend<br>}</pre><p>This looks so big but not to worry we will understand each module block and how we are taking values from <a href="http://output.tf/">output.tf</a> file and <a href="http://variables.tf/">variables.tf</a> file.</p><p>This is the provider block which contains on which cloud platform we are going to deploy whether it’s AWS, Azure or GCP. So , we are with AWS and defined the region in which var.region is the value where region variable is declared in <a href="http://variables.tf/">variables.tf</a> file.</p><pre>module &quot;ec2_db&quot; {<br>  source = &quot;./modules/aws_ec2_module&quot;<br>  security_group_ids = [module.aws_security_group.security_group_id]<br>  name = &quot;${var.name}-mogodb&quot;<br>  ami = &quot;ami-09b0a86a2c84101e1&quot;<br>  instance_type = &quot;t2.micro&quot;<br>  subnet_id = module.vpc.public_subnet_id[0]<br>}</pre><p>This module creates the EC2 instance for the database server where MongoDB is deployed on Docker. In this block, source indicates where our EC2 module is stored; in our case, it&#39;s locally under the modules folder. Next is security_group_ids, which contains a list []. Within this list, another module is called, specifically the security group module, which outputs the security group id, an attribute of the security group.</p><p>In name the value is &quot;${var.name}-mogodb&quot; which means when we do terraform apply or plan we will give the input for the name variable means if the input is “three-tier“ it will give the name “three-tier-mongodb“ for the EC2 instance.</p><p>In the ami we had given the AMI ID of Ubuntu to create the Ubuntu Operating System.</p><p>Instance Type will be t2.micro that is free-tier in AWS. Now, we are attaching the subnet in which subnet this resource is going to lie this subnet_id will decide for this we are creating in Public Subnet.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0dM2abHb-hSlovy5" /></figure><pre>module &quot;vpc&quot; {<br>  source = &quot;./modules/vpc-module&quot;<br>  public_subnet_cidrs = var.public_subnet_cidrs<br>  private_subnet_cidrs = var.private_subnet_cidrs<br>}</pre><p>This module will create VPC where public and private subnet CIDR’s variables are used.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*im_bPpIoTRp8qD2z" /></figure><pre>module &quot;aws_security_group&quot; {<br>  source = &quot;./modules/security-group&quot;<br>  sg_name = &quot;${var.name}-sg&quot;<br>  vpc_id = module.vpc.vpc_id<br>}</pre><p>This module will create the security group for the EC2 instance and ECS Cluster in which we will use further.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*aaX6qdOrXkkI-NKw" /></figure><pre>module &quot;aws_lb&quot; {<br>  source = &quot;./modules/aws_alb_module&quot;<br>  name = &quot;${var.name}-alb&quot;<br>  security_group_id = module.aws_security_group.security_group_id<br>  subnet_id = module.vpc.public_subnet_id<br>  vpc_id = module.vpc.vpc_id<br>}</pre><p>This module will create loadbalancer which will be used to access the application through the DNS of Network Load Balancer where Subnet ID, security group ID and vpc_id is attached. In Subnet_ID we are calling the module of vpc which prints the attribute of public_subnet_id.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*s4PafDeJ_TIFYboM" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sE2isfBsQ9MMHhAB" /></figure><pre>module &quot;frontend-aws_ecr&quot; {<br>  source = &quot;./modules/aws_ecr_module&quot;<br>  name = &quot;${var.name}-frontend&quot;<br>}</pre><p>Now, this is ECR (Elastic Container Registry) creation for frontend and backend images, we had just changed the name here with -frontend and -backend.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*M3vaM9ygaHtvCPJc" /></figure><pre>module &quot;aws_ecs_cluster&quot; {<br>  source = &quot;./modules/aws_ecs_cluster_module&quot;<br>  name = var.name<br>}</pre><p>Now the AWS ECS (Elastic Container Service) comes in the picture where we deploy the ECS cluster in which 2 services are created for frontend and backend.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*rPePIdgBq4clAnvg" /></figure><pre>module &quot;frontend-ecs&quot; {<br>  source = &quot;./modules/aws_ecs_module&quot;<br>  name = &quot;${var.name}-frontend-ecs&quot;<br>  ecr_repo_url = module.frontend-aws_ecr.frontend-repository_url<br>  image_tag = &quot;3&quot;<br>  ecs_cluster_id = module.aws_ecs_cluster.ecs_cluster_id<br>  port = 5173<br>  vpc_id = module.vpc.vpc_id<br>  subnet_id = module.vpc.public_subnet_id<br>  security_group_id = module.aws_security_group.security_group_id<br>  target_group_arn = module.aws_lb.tg-arn<br>}</pre><p>In these 2 modules we are creating 2 ECS services for frontend and backend which contains ecr_repo_url where the value is taking from backend AWS ECR module which will take the output of frontend repository URL which is defined in parent <a href="http://output.tf/">output.tf</a> file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gCY7pmtvx8z8xX9V" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*4Y-2k6N75kEfYFgN" /></figure><pre>output &quot;backend-repository_url&quot; {<br>  value = module.backend-aws_ecr.frontend-repository_url<br>}</pre><p>Next is image tag which we are declaring, then the ECS cluster ID in which we want to deploy our services the cluster ID is defined in <a href="http://output.tf/">output.tf</a> file and used to call with module of AWS ECS cluster with cluster ID attribute.</p><pre>output &quot;ecs_cluster_id&quot; {<br>  value = module.aws_ecs_cluster.ecs_cluster_id<br>}</pre><p>Next is port, vpc_id, subnet_id and security_group_id and in last target group arn that will be taken from load balancer target group which is defined parent <a href="http://output.tf/">output.tf</a> file.</p><pre>output &quot;tg-arn&quot; {<br>  value = module.aws_lb.tg-arn<br>}</pre><h3>Build Docker Images for Each Tier</h3><h3>Dockerfile Build</h3><p>GitHub Code : <a href="https://github.com/amitmaurya07/wanderlust-devsecops.git">https://github.com/amitmaurya07/wanderlust-devsecops.git</a></p><p>Let’s build the Dockerfile for frontend and push it to ECR (Elastic Container Registry) then deploy it to ECS (Elastic Container Service).</p><p>When the ECR Repository is created go to ECR repository for frontend and click on View Push Commands which will give the commands to build and push the Dockerfile in ECR frontend repository.</p><pre> aws ecr get-login-password --region ap-south-1 | docker login --username AWS --password-stdin 880849992790.dkr.ecr.ap-south-1.amazonaws.com<br> docker build -f .\backend\Dockerfile -t backend:1 .<br> docker tag backend:1 880849992790.dkr.ecr.ap-south-1.amazonaws.com/three-tier-backend:1 <br> docker push 880849992790.dkr.ecr.ap-south-1.amazonaws.com/three-tier-backend:1</pre><ol><li>The first line means aws ecr get-login will login with the AWS Access Key and Secret Key then it is building the backend Dockerfile and then tagging the Dockerfile then pushed to the ECR Registry.</li><li>Now paste the commands in the in VS Code (IDE).</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*m0FbreoLyxnBka6m" /></figure><pre> aws sts get-caller-identity</pre><p>If you recieve this error that the user is not authenticated to perform GetAuthorizationToken then grant the permission to the user. For now, I am adding the permission of “AmazonElasticContainerRegistryPublicFullAccess” to the user.</p><h3>Set Up Database MongoDB on Amazon EC2</h3><p>For cost optimization and we are building this project for article purpose so we will install the MongoDB on EC2 instance otherwise for production environment use DocumentDB that is managed AWS service for mongoDB.</p><p>We had discussed earlier in the <a href="http://main.tf/">main.tf</a> file we are creating EC2 instance with the Terraform module</p><pre> resource &quot;aws_instance&quot; &quot;ec2_instance&quot; {<br>   ami = var.ami <br>   instance_type = var.instance_type<br>   subnet_id = var.subnet_id<br>   vpc_security_group_ids = var.security_group_ids<br><br>   user_data = &lt;&lt;-EOF<br>     #!/bin/bash<br>     sudo apt-get update -y<br>     curl -fsSL https://get.docker.com -o get-docker.sh<br>     sudo sh get-docker.sh<br>     sudo systemctl start docker<br>     sudo systemctl enable docker<br>     sudo docker run -d --name mongodb -p 27017:27017 mongo:4.4<br>   EOF<br>   tags = {<br>     Name = var.name<br>   }<br> }</pre><p>This will install the MongoDB in the EC2 instance from the User Data Script.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Pk0wrd-uQqanq58L" /></figure><h3>Apply the Terraform Modules:</h3><p>As we had discussed about Terraform Modules earlier of parent <a href="http://main.tf/">main.tf</a> file now let’s do the terraform CLI execution.</p><p>Download the AWS dependencies that are in provider section. As we had defined in provider block. It initializes the modules folder and create .terraform directory and module.json file which contains about modules.</p><pre>terraform init</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/922/0*-Yhw3y7AIb5GZmAr" /></figure><p>Now do the terraform plan to check that the infrastructure that is going to create on AWS has right values or not.</p><pre>terraform plan</pre><ol><li>When we execute this command it will ask for the input from the user i.e. it is asking for the name.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/880/0*9GKMig4I4xAZoAe3" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*qR3QIP_VO4e0Kaf8" /></figure><ol><li>As we can see it prints the output which we had defined in the <a href="http://output.tf/">output.tf</a> file.</li><li>It’s the time to create the infrastructure on AWS when we execute Apply command.</li></ol><pre>terraform apply --auto-approve</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1PYjkFkryfev06IN" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*FNlhAgUsObS8eNbn" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9tZa6dKWATX51poJ" /></figure><ol><li>Here it is saying we have 28 resources to add in AWS (Automation) and it starts to creating the resources on AWS.</li><li>When we had seen the Terraform Plan output some of the values are unknown where it has written “known after apply” but when you do terraform apply command it created that infrastructure and prints the outputs.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*c7XREdy3ZZMl62OL" /></figure><ol><li>We got DNS name of ALB, repository URL, cluster ID everything. Now let’s hit the DNS name of ALB and check whether we can access the frontend or not.</li><li>http://<a href="http://three-tier-alb-alb-b35382f79712e765.elb.ap-south-1.amazonaws.com/">three-tier-alb-alb-b35382f79712e765.elb.ap-south-1.amazonaws.com</a>:5173</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Nm3Rf5hkUuhJ0KNp" /></figure><p>Hurray !!! We had successfully deployed the frontend service, now let’s check the backend service but right now it will not be accessible because we need to change in .env file of backend github repository. After this make changes also in server.js file for CORS ISSUE.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EmhAhgQlZOYpkVw8" /></figure><p>.env file</p><pre> PORT=5000<br> MONGODB_URI=&quot;mongodb://&lt;Public IP of instance&gt;:27017/wanderlust&quot;<br> CORS_ORIGIN=&quot;http://&lt;ALB DNS Name&gt;:5173&quot;</pre><ol><li>After changes has been build Dockerfile again and push and change the image tag in parent <a href="http://main.tf/">main.tf</a> of backend ECS module. As we can see our database MongoDB is connected now let’s check that backend is accessible or not.</li><li>http://<a href="http://three-tier-alb-alb-b35382f79712e765.elb.ap-south-1.amazonaws.com/">three-tier-alb-alb-b35382f79712e765.elb.ap-south-1.amazonaws.com</a>:5000</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Hf4xeg-O-R4kHb87" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/793/0*w9XthVIfKkv321gc" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*PG72OXeze88H8Gfg" /></figure><p>As we can see in ECS Cluster the backend service is updating (1 Pending and 1 Running) after applying terraform apply command.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*3grF7am33ES9o5mE" /></figure><p>When the backend is perfectly deployed with the changes, we have to do little changes in .env file of frontend to add VITE_API_PATH which contains the value of Load Balancer:5000 (Backend URL) then build the new frontend image and change the image tag in terraform parent <a href="http://main.tf/">main.tf</a> frontend ECS module.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0LalDmzyUJjotzJD" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/787/0*4pISzYuRc6JxgEDD" /></figure><p>To get the Load Balancer URL from AWS GUI navigate to AWS Cluster three-tier then click on any service and go to configuration and networking section scroll down you will get Load Balancer DNS and see the status of Target Group is healthy or not.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*n6jLSQtDmCslSeK2" /></figure><p>After everything is done, you have done the deployment of 3 tier application now clean the resources on AWS by executing the command.</p><pre>terraform destroy --auto-approve</pre><h3>Conclusion</h3><p>In this article, we had learnt the deployment of 3 tier application on AWS ECS with Terraform Modules. Another Project will come soon so stay tuned for the next blog !!!</p><p>GitHub Terraform Code : <a href="https://github.com/amitmaurya07/AWS-Terraform/tree/master">github.com/amitmaurya07/AWS-Terraform/tree/..</a></p><p>GitHub Application Code : <a href="https://github.com/amitmaurya07/wanderlust-devsecops/tree/aws-ecs-deployment">https://github.com/amitmaurya07/wanderlust-devsecops/tree/aws-ecs-deployment</a></p><p>Twitter : <a href="http://x.com/amitmau07">x.com/amitmau07</a></p><p>LinkedIn : <a href="http://linkedin.com/in/amit-maurya07">linkedin.com/in/amit-maurya07</a></p><p>If you have any queries you can drop the message on LinkedIn and Twitter.</p><h3>In Plain English 🚀</h3><p><em>Thank you for being a part of the </em><a href="https://plainenglish.io/"><strong><em>In Plain English</em></strong></a><em> community! Before you go:</em></p><ul><li>Be sure to <strong>clap</strong> and <strong>follow</strong> the writer ️👏<strong>️️</strong></li><li>Follow us: <a href="https://x.com/inPlainEngHQ"><strong>X</strong></a> | <a href="https://www.linkedin.com/company/inplainenglish/"><strong>LinkedIn</strong></a> | <a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong>YouTube</strong></a> | <a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Discord</strong></a> | <a href="https://newsletter.plainenglish.io/"><strong>Newsletter</strong></a> | <a href="https://open.spotify.com/show/7qxylRWKhvZwMz2WuEoua0"><strong>Podcast</strong></a></li><li><a href="https://differ.blog/"><strong>Create a free AI-powered blog on Differ.</strong></a></li><li>More content at <a href="https://plainenglish.io/"><strong>PlainEnglish.io</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=563e476206e4" width="1" height="1" alt=""><hr><p><a href="https://aws.plainenglish.io/learn-how-to-deploy-scalable-3-tier-applications-with-aws-ecs-563e476206e4">Learn How to Deploy Scalable 3-Tier Applications with AWS ECS</a> was originally published in <a href="https://aws.plainenglish.io">AWS in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Provision AWS EC2 Instances with Terraform: A Step-by-Step Guide]]></title>
            <link>https://aws.plainenglish.io/how-to-provision-aws-ec2-instances-with-terraform-a-step-by-step-guide-f4419e9730a9?source=rss-357aad067a18------2</link>
            <guid isPermaLink="false">https://medium.com/p/f4419e9730a9</guid>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[aws-ec2]]></category>
            <category><![CDATA[terraform]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[devops-tool]]></category>
            <dc:creator><![CDATA[Amit Maurya]]></dc:creator>
            <pubDate>Mon, 04 Nov 2024 06:11:55 GMT</pubDate>
            <atom:updated>2024-11-04T06:11:55.468Z</atom:updated>
            <content:encoded><![CDATA[<h4>Using Terraform Modules for AWS EC2 Deployment</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WAk3wGfdmBfmLL6zyVDYfw.png" /></figure><p>In this article, we are going to learn about the most used service i.e. AWS EC2 (Elastic Compute Cloud) and Security Group with the Terraform Modules, how to provision with terraform. We all know AWS offers 200 services, and to manage to make it scalable, efficient is what all businesses want but to manage these services manually is a big challenging task and also time-consuming and error-prone.</p><p>By introducing Terraform as IaC (Infrastructure As Code) tool it enables to automate the entire infrastructure within minutes by ensuring consistency and repeatability across all environments.</p><h3>Prerequisites</h3><ol><li>Terraform</li><li>AWS Account</li><li>Little bit of knowledge of AWS and Terraform :)</li></ol><h3>Setting Up Environment</h3><ol><li>Installing Terraform on Windows</li></ol><p><a href="https://releases.hashicorp.com/terraform/1.9.8/terraform_1.9.8_windows_386.zip">Terraform Install on Windows</a></p><ol><li>Creating IAM User with Required Permissions for Terraform</li></ol><ul><li>Navigate to Search Bar of AWS Console and search IAM (Identity Access and Management)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*x1JWB-4UV38wLRpj" /></figure><ul><li>Click on IAM, in left side go to Users section and click on Create User.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/406/0*iIAx__D-74UEZkkR" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*LA_SrCyxsaB_UUyw" /></figure><ul><li>After naming the user “terraform“, assign permissions for now Administrator Access.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*U7BDqBw-Z1hm2jo9" /></figure><ul><li>Now, click on terraform user go to Security Credentials and scroll down for Access Key.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Pxg7mIcCNUGGtIIw" /></figure><ul><li>As we can see there is no Access Keys so let’s create access key, choose CLI for usecase and click on Next provide Description and then Next you will get Access and Secret Key.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/987/0*P7xAktxofYn8tee8" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gGbznNzaLBkV_G30" /></figure><ul><li>Download the CSV file and now copy the Secret and Access Key for usage in terraform.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/976/0*YlpT8sZH_d7deq6t" /></figure><h3>Understanding Terraform Basics</h3><p>In corporate world, if we talk about Terraform it was the most used IaC tool that was also most asked in interviews. We are going to learn about Terraform Modules, <a href="http://variables.tf/">variables.tf</a>, terraform.tfvars.</p><p><strong>Terraform Modules:</strong></p><p>When we start writing Terraform code, we usually have main.tf, variables.tf, and output.tf. But what if we need to use these files every time with different settings? Writing them over and over is a hassle and can lead to mistakes.</p><p>That’s where Terraform Modules come in handy. They let us separate the service code from the main main.tf file and the other two files. For example, if we want to create an EC2 instance, we make a module folder with main.tf, variables.tf, and outputs.tf. Then, we just call this module in the main.tf file in the parent folder.</p><p><strong>Variables:</strong></p><p>In terraform to create variables we create <a href="http://variable.tf/">variable.tf</a> in which we create variable block and call the variables in <a href="http://main.tf/">main.tf</a> file. We will see how we are calling the variables.</p><p><strong>terraform.tfvars:</strong></p><p>It is used to store variables, while <a href="http://variables.tf/">variables.tf</a> is used to declare the variables and in tfvars we assign the values for them.</p><h3>Creating AWS EC2 Instance</h3><h3>Overview of EC2 Instance:</h3><p>Let’s say we want to launch some servers to deploy some applications in organization, for this we need servers in our datacenters that will be costly and we had to handle all the servers manually.</p><p>To reduce this setup of datacenters cost AWS has launched EC2 service that creates virtual servers in our nearby datacenters by this we just need to only manage virtual machines on AWS with minimal cost.</p><p>If you need to check the prices of Amazon EC2, open the AWS Calculator pricing that will give the real time price of AWS EC2.</p><p><a href="https://calculator.aws/">AWS Calculator</a></p><h3>Configuring EC2 Instance with Terraform:</h3><p>Let’s create directory structure for ec2-module and parent folder. As we can see that modules folder contain two ec2-instance and security-group.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/337/0*s2QjttmmpNB6S_XM" /></figure><ol><li>First, let’s create the ec2-instance module in which it contains <a href="http://main.tf/">main.tf</a>, <a href="http://variable.tf/">variable.tf</a> and <a href="http://outputs.tf/">outputs.tf</a>.</li></ol><p><a href="http://main.tf/">main.tf</a>:</p><pre> resource &quot;aws_instance&quot; &quot;ec2_instance&quot; {<br>   ami = var.ami <br>   instance_type = var.instance_type<br>   vpc_security_group_ids = var.security_group_ids<br><br>   user_data = &lt;&lt;-EOF<br>               #!/bin/bash<br>               apt-get update<br>               apt install nginx -y<br>               systemctl start nginx<br>               systemctl enable nginx<br>               EOF<br>   tags = {<br>     Name = &quot;Terraform Instance&quot;<br>   }<br> }</pre><p>In <a href="http://main.tf/">main.tf</a> folder of ec2-instance module it has the resource block which contains parameter ami, instance_type, and vpc_security_group. It also has the User Data script that contains the commands to install nginx and at last it has tags.</p><p><a href="http://variables.tf/">variables.tf</a>:</p><pre> variable &quot;ami&quot; {<br>   description = &quot;AMI ID for the EC2 instance&quot;<br>   type        = string<br> }<br><br> variable &quot;instance_type&quot; {<br>   description = &quot;Type of EC2 instance&quot;<br>   type        = string<br> }<br><br> variable &quot;security_group_ids&quot; {<br>   description = &quot;List of security group IDs to attach to the instance&quot;<br>   type        = list(string)<br> }</pre><p>In <a href="http://variables.tf/">variables.tf</a> we declare the variables ami, instance_type and security_group_ids. To call the variables in <a href="http://main.tf/">main.tf</a> we write var.ami or var.instance_type</p><p><a href="http://output.tf/">output.tf</a>:</p><pre> output &quot;instance_id&quot; {<br>   value = aws_instance.ec2_instance.id<br> }<br><br> output &quot;public_ip&quot; {<br>   value = aws_instance.ec2_instance.public_ip<br> }</pre><ol><li>In <a href="http://output.tf/">output.tf</a> file we are printing outputs of attributes of EC2 instance like public_ip and instance_id.</li><li>Now, let’s do the same for the security group module in which same directory structure is there <a href="http://main.tf/">main.tf</a>, <a href="http://variables.tf/">variables.tf</a> and <a href="http://output.tf/">output.tf</a></li></ol><p><a href="http://main.tf/">main.tf</a>:</p><pre> resource &quot;aws_security_group&quot; &quot;ec2_sg&quot; {<br>   name        = var.sg_name<br>   description = &quot;Security group for EC2 instance&quot;<br><br>   ingress {<br>     from_port   = 22<br>     to_port     = 22<br>     protocol    = &quot;tcp&quot;<br>     cidr_blocks = [var.allowed_ssh_cidr] <br>   }<br><br>   ingress {<br>     from_port   = 80<br>     to_port     = 80<br>     protocol    = &quot;tcp&quot;<br>     cidr_blocks = [var.allowed_ssh_cidr]<br>   }<br><br>   egress {<br>     from_port   = 0<br>     to_port     = 0<br>     protocol    = &quot;-1&quot;<br>     cidr_blocks = [var.allowed_ssh_cidr]<br>   }<br><br>   tags = {<br>     Name = var.sg_name<br>   }<br> }</pre><p>In the <a href="http://main.tf/">main.tf</a> of security group we have resource block in which we are creating inbound rules (ingress) that allows the port 80 and SSH port 22.</p><p><a href="http://variables.tf/">variables.tf</a>:</p><pre> variable &quot;sg_name&quot; {<br>   description = &quot;Name of the security group&quot;<br>   type        = string<br>   default     = &quot;ec2_security_group&quot;<br> }<br><br> variable &quot;allowed_ssh_cidr&quot; {<br>   description = &quot;CIDR block allowed to SSH&quot;<br>   type        = string<br>   default     = &quot;0.0.0.0/0&quot; <br> }</pre><p>In the <a href="http://variables.tf/">variables.tf</a> we had declared two variables that is sg_name and allowed_ssh_cidr which contains default “0.0.0.0/0“ that will allow all incoming traffic.</p><p><a href="http://output.tf/">output.tf</a>:</p><pre> output &quot;security_group_id&quot; {<br>   description = &quot;The ID of the security group&quot;<br>   value       = aws_security_group.ec2_sg.id<br> }</pre><p>In the <a href="http://output.tf/">output.tf</a> file we are getting the output of sg_id. aws_security_group is the parameter name and ec2_sg is the local name which had taken from the resource block of security group and id is the attribute.</p><p>Now we had done the creation of modules, but how we call them in <a href="http://main.tf/">main.tf</a> which is in parent folder. Let’s see this</p><p><a href="http://main.tf/">main.tf</a>:</p><pre> provider &quot;aws&quot; {<br>   region = var.region<br>   access_key = var.aws_access_key_id<br>   secret_key = var.aws_secret_access_key<br> }<br><br> module &quot;ec2_instance&quot; {<br>   source = &quot;./modules/ec2-instance&quot;<br>   ami = &quot;ami-09b0a86a2c84101e1&quot;<br>   instance_type = var.instance_type<br>   security_group_ids = [module.ec2_sg.security_group_id]<br> }<br><br> module &quot;ec2_sg&quot; {<br>   source = &quot;./modules/security-group&quot;<br>   sg_name = &quot;EC2-securitygroup&quot;<br> }<br><br> output &quot;instance_id&quot; {<br>   value = module.ec2_instance.instance_id<br> }<br><br> output &quot;public_ip&quot; {<br>   value = module.ec2_instance.public_ip<br> }<br><br> output &quot;security_group_id&quot; {<br>   value = module.ec2_sg.security_group_id<br> }</pre><ol><li>In this <a href="http://main.tf/">main.tf</a> file we had first block of provider which will install aws dependencies then there are 2 blocks of module which contain source which is calling the ec2-instance module and same for security group and at last there are 3 blocks of output.</li><li>GitHub Code: <a href="https://github.com/amitmaurya07/AWS-Terraform/tree/master">https://github.com/amitmaurya07/AWS-Terraform/tree/master</a></li><li>Okay, we discussed a lot now let’s do the creation of AWS EC2 instance.</li><li>First initialize the terraform by executing the command. It will download the plugins of AWS and store in .terraform folder and also creates modules folder which contains the module.json</li></ol><pre>terraform init</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/964/0*uL2524e0eXvpgJ2D" /></figure><p>Now execute to plan the infrastructure by executing which will ask the value of Type of instance and AWS Region as we had declared in the <a href="http://variables.tf/">variables.tf</a> file in parent folder.</p><pre>terraform plan</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*NnDw6zDo7hWIeqj-" /></figure><ol><li>While executing terraform plan it prints the result that you are going to create on AWS.</li><li>At last we will create the EC2 instance and security group on AWS by executing</li></ol><pre>terraform apply --var-file=&quot;terraform.tfvars&quot;</pre><p>In terraform.tfvars file I declared the access key and secret key which is not pushed in the GitHub for security purposes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Etw2wvmDneu0GBpf" /></figure><p>When we type “yes” it will start creating the EC2 instance and Security Group on AWS that will print the output which we had given in the output file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*l27StyLweAD0gE5Z" /></figure><p>Let’s copy and paste the Public IP of instance and see the “Welcome to Nginx“ page. Navigate to http://&lt;Your Public IP&gt;</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*a9cqD-0b8ykj4n0-" /></figure><p>After this do the most important thing clean all the resources on AWS Just execute the command.</p><pre>terraform destroy --var-file=&quot;terraform.tfvars&quot;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ijDtmDNKT42GO7vd" /></figure><p>As we can see the line “Destroy complete! Resources: 2 destroyed.“ that means the resources are deleted. See so simple just execute one command and destroys all in seconds.</p><h3>Conclusion</h3><p>In this article, we had learnt the creation of EC2 instance and security group with terraform. Meanwhile in the upcoming blogs you will see a lot of AWS Services creation and automating it with terraform. Stay tuned for the next blog !!!</p><p>GitHub Code : <a href="https://github.com/amitmaurya07/AWS-Terraform/tree/master">https://github.com/amitmaurya07/AWS-Terraform/tree/master</a></p><p>Twitter : <a href="https://x.com/amitmau07">x.com/amitmau07</a></p><p>LinkedIn : <a href="http://www.linkedin.com/in/amit-maurya07">linkedin.com/in/amit-maurya07</a></p><p>If you have any queries you can drop the message on LinkedIn and Twitter.</p><h3>In Plain English 🚀</h3><p><em>Thank you for being a part of the </em><a href="https://plainenglish.io/"><strong><em>In Plain English</em></strong></a><em> community! Before you go:</em></p><ul><li>Be sure to <strong>clap</strong> and <strong>follow</strong> the writer ️👏<strong>️️</strong></li><li>Follow us: <a href="https://x.com/inPlainEngHQ"><strong>X</strong></a> | <a href="https://www.linkedin.com/company/inplainenglish/"><strong>LinkedIn</strong></a> | <a href="https://www.youtube.com/channel/UCtipWUghju290NWcn8jhyAw"><strong>YouTube</strong></a> | <a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Discord</strong></a> | <a href="https://newsletter.plainenglish.io/"><strong>Newsletter</strong></a> | <a href="https://open.spotify.com/show/7qxylRWKhvZwMz2WuEoua0"><strong>Podcast</strong></a></li><li><a href="https://differ.blog/"><strong>Create a free AI-powered blog on Differ.</strong></a></li><li>More content at <a href="https://plainenglish.io/"><strong>PlainEnglish.io</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f4419e9730a9" width="1" height="1" alt=""><hr><p><a href="https://aws.plainenglish.io/how-to-provision-aws-ec2-instances-with-terraform-a-step-by-step-guide-f4419e9730a9">How to Provision AWS EC2 Instances with Terraform: A Step-by-Step Guide</a> was originally published in <a href="https://aws.plainenglish.io">AWS in Plain English</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>