<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[techinthe.cloud by Konstantinos Bessas]]></title><description><![CDATA[techinthe.cloud by Konstantinos Bessas]]></description><link>https://blog.techinthe.cloud</link><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Apr 2026 18:23:25 GMT</lastBuildDate><atom:link href="https://blog.techinthe.cloud/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Looking Back, Building Forward: Dr. Werner Vogels’ Blueprint from re:Invent 2024]]></title><description><![CDATA[The dust has settled on re:Invent 2024, but the echoes of Werner Vogels' keynote continue to resonate through the AWS community. Like a fine whiskey, the insights shared by Amazon's CTO are maturing with time, offering a timeless blueprint for buildi...]]></description><link>https://blog.techinthe.cloud/looking-back-building-forward-dr-werner-vogels-blueprint-from-reinvent-2024</link><guid isPermaLink="true">https://blog.techinthe.cloud/looking-back-building-forward-dr-werner-vogels-blueprint-from-reinvent-2024</guid><category><![CDATA[AWS]]></category><category><![CDATA[reinvent2024]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Fri, 10 Jan 2025 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1736332241939/a42e9fca-aef6-45cc-a1e0-c5321412e9a6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The dust has settled on re:Invent 2024, but the echoes of Werner Vogels' keynote continue to resonate through the AWS community. Like a fine whiskey, the insights shared by Amazon's CTO are maturing with time, offering a timeless blueprint for building and scaling complex systems.</p>
<p>Dr. Werner Vogels delved into the intricate dance between simplicity and complexity, emphasizing the importance of strategic design, organizational alignment, and a relentless pursuit of evolvability. As we embark on a new year, it's time to revisit these principles and apply them to our own architectural endeavors.</p>
<h2 id="heading-a-masterclass-in-system-design">A Masterclass in System Design</h2>
<p>Dr. Werner Vogels, CTO of Amazon, delivered a masterclass in system design. He emphasized the importance of <strong>evolvability</strong> and <strong>manageability</strong> in building scalable systems. He highlighted the significance of <strong>decomposition</strong>, <strong>organizational alignment</strong>, and <strong>cell-based architectures</strong> in achieving these goals.</p>
<p>By breaking down complex systems into smaller, loosely coupled components, organizations can improve their ability to adapt to changing requirements and mitigate the impact of failures. Additionally, aligning organizational structure with system architecture can enhance team autonomy and accelerate innovation. He also advocated for the use of cell-based architectures, which can isolate failures and improve system resilience.</p>
<p>Finally, he stressed the role of <strong>predictability</strong> and <strong>automation</strong> in reducing operational complexity. By automating routine tasks and leveraging machine learning to identify anomalies, organizations can free up engineers to focus on higher-value activities.</p>
<h2 id="heading-the-echoes-of-reinvent-2024-a-blueprint-for-the-future">The Echoes of re:Invent 2024: A Blueprint for the Future</h2>
<p>Dr. Werner Vogels’ keynote wasn’t just theoretical - it resonated deeply with real-world challenges and solutions I’ve seen while working with customers. Many of the principles he outlined, such as managing complexity, designing for evolvability, and leveraging cell-based architectures, align with the strategies I’ve applied in customer projects. Let’s dive into some specific examples where these ideas have been put into practice, showcasing how they can address real business needs and drive innovation.</p>
<h3 id="heading-a-proactive-approach-to-system-design">A Proactive Approach to System Design</h3>
<p>The quote "Plan for failure and nothing will fail," emphasizes the importance of <strong>proactive system design</strong>. Even the best-designed systems can encounter problems. By carefully considering the system's requirements, operational model, and potential failure points, organizations can build more resilient and reliable systems. They often rush to launch products without proper testing or backup plans. This can lead to costly downtime, damaged reputations, and lost revenue.</p>
<p>Key considerations for proactive system design include:</p>
<ul>
<li><p><strong>Thorough Requirements Analysis:</strong> A deep understanding of the system's purpose, users, and constraints is essential.</p>
</li>
<li><p><strong>Realistic Operational Model:</strong> Developing a realistic operational model that accounts for potential challenges and limitations.</p>
</li>
<li><p><strong>Organization's Capabilities:</strong> Assessing the organization's technical expertise, resources, and risk tolerance.</p>
</li>
<li><p><strong>Long-Term Vision:</strong> Considering the system's future evolution and potential scalability needs.</p>
</li>
<li><p><strong>Failure Mitigation Strategies:</strong> Implementing robust error handling, monitoring, and recovery mechanisms.</p>
</li>
</ul>
<p>By taking a proactive approach to system design, organizations can reduce the risk of costly failures and ensure the long-term success of their digital initiatives. While iterative development is crucial for continuous improvement, it's equally important to get certain foundational aspects right from the start. Investing time in upfront planning and design can prevent costly and time-consuming refactors and redesigns later on. By striking a balance between agility and foresight, organizations can build systems that are both adaptable and resilient.</p>
<h3 id="heading-simplexity-the-art-of-balancing-simplicity-and-complexity">Simplexity: The Art of Balancing Simplicity and Complexity</h3>
<p>Dr. Werner Vogels' concept of "simplexity" highlighted the delicate balance between simplicity and complexity in system design. While simplicity is often desirable, it's not always achievable, especially in large-scale systems.</p>
<p>Achieving simplexity involves several key strategies. One approach is adopting a modular architecture, which involves breaking down complex systems into smaller, more manageable components. Another is defining clear and concise interfaces between these components, helping to reduce complexity and improve communication. Automation also plays a critical role, as it minimizes manual effort and reduces the risk of errors in routine tasks. Finally, continuous optimization is essential—regularly reviewing and refining the system helps eliminate unnecessary complexity and ensures it remains efficient and effective.</p>
<p>By embracing simplexity, organizations can build systems that are both efficient and maintainable. However, it's important to strike a balance between simplicity and functionality.</p>
<h3 id="heading-evolvability-building-systems-for-the-future">Evolvability: Building Systems for the Future</h3>
<p>Dr. Werner Vogels emphasized the importance of <strong>evolvability</strong>, or a system's ability to adapt to future needs. In today's rapidly changing technological landscape, it's crucial to design systems that can evolve without significant disruption. By investing in a solid foundation, embracing a culture of continuous improvement, and leveraging modern technologies, organizations can build systems that are not only resilient but also adaptable to the future.</p>
<p>For example, using microservices architecture allows for independent development and deployment of individual services, making it easier to add new features or modify existing ones. Additionally, adopting a DevOps culture can accelerate the development and deployment process, enabling organizations to respond quickly to changing market conditions.</p>
<p>Again, I want to emphasize how a strong foundational baseline can greatly enhance a system’s ability to evolve. Taking the time for thoughtful planning and design upfront can help avoid expensive and time-consuming major refactors down the line. By balancing agility with foresight, organizations can create systems that adapt easily to changing business needs.</p>
<h3 id="heading-the-long-haul-of-system-ownership">The Long Haul of System Ownership</h3>
<p>Dr. Werner Vogels highlighted the often-overlooked reality that the lifespan of a system far exceeds its initial development time. Once deployed, systems require ongoing maintenance, updates, and support.</p>
<p>To ensure the long-term success of a system, organizations should:</p>
<ul>
<li><p><strong>Prioritize Maintainability:</strong> Design systems with maintainability in mind, using clear code, consistent naming conventions, and comprehensive documentation.</p>
</li>
<li><p><strong>Invest in Ongoing Support:</strong> Allocate sufficient resources for ongoing maintenance, monitoring, and troubleshooting.</p>
</li>
<li><p><strong>Embrace Continuous Improvement:</strong> Continuously monitor system performance and identify opportunities for optimization.</p>
</li>
<li><p><strong>Plan for End-of-Life:</strong> Develop a plan for decommissioning or migrating the system when it reaches the end of its useful life.</p>
</li>
</ul>
<p>Many organizations make short-sighted decisions when choosing technology, opting for quick and easy solutions that often lead to long-term problems. When choosing one technology over another with cost in mind, the operational effort is often not included in the decision made. Custom or hacky solutions, while initially cheaper, can require significant operational overhead and maintenance effort. In contrast, managed services offered by cloud providers can significantly reduce operational burden and improve system reliability.</p>
<p>By leveraging managed services, organizations can focus on their core business objectives, rather than spending time and resources on infrastructure management. Additionally, managed services often offer advanced features and security capabilities that would be difficult or expensive to implement in-house. Cost optimization is not about using custom workarounds and cheap unreliable solutions. AWS has a great deal of tools and offerings to help you optimize costs.</p>
<h3 id="heading-the-dilemma-of-service-size-a-balancing-act">The Dilemma of Service Size: A Balancing Act</h3>
<p>For the last point in this list, I am looking at Dr. Werner Vogels’ question about optimal service size which highlights a common challenge in system design. While extending existing services can be tempting, it can lead to monolithic architectures that are difficult to maintain and scale. On the other hand, creating too many small services can increase complexity and overhead.</p>
<p>By carefully considering the trade-offs between simplicity and flexibility, organizations can strike a balance that best suits their specific needs. While it may require more effort upfront to create well-defined services, the long-term benefits in terms of maintainability and scalability will outweigh the initial investment.</p>
<p>This principle can also be applied to Infrastructure as Code (IaC). While it may be tempting to create a single, monolithic repository for all infrastructure configurations, a component-based approach can offer several advantages. By breaking down infrastructure into smaller, independent components, organizations can improve maintainability, testability, and reusability. Additionally, a component-based approach can make it easier to manage changes and reduce the risk of unintended consequences.</p>
<p>Remember, regardless of the specific IaC framework used (e.g., Terraform, Pulumi, AWS CloudFormation), it's important to remember that IaC is essentially code. By applying fundamental programming principles, such as modularity, encapsulation, abstraction, testing, and version control, and using principles like DRY (Don't Repeat Yourself) organizations can write more efficient, maintainable, and reliable IaC. This can lead to significant time and cost savings, as well as improved system reliability and security.</p>
<p>Unfortunately, many organizations internally as well as widely used public solutions, often disregard fundamental programming principles like DRY (Don't Repeat Yourself). This leads to code duplication, inconsistency, and increased maintenance costs. For example, many modules contain redundant code snippets and configuration options, making them difficult to consistently modify. When code is duplicated across multiple environments or workloads, it becomes challenging to maintain consistency and implement changes. This can lead to configuration drift, security vulnerabilities, and operational issues. Additionally, promoting solutions through a DTAP (Development, Test, Acceptance, Production) pipeline becomes more complex, as changes must be applied to multiple locations.</p>
<h2 id="heading-conclusion-building-for-the-future-now">Conclusion: Building for the Future, Now</h2>
<p>In conclusion, Dr. Werner Vogels' keynote at re:Invent 2024 serves as a timeless guide for navigating the complexities of system design and architecture. By embracing principles such as evolvability, proactive planning, and the delicate balance of simplexity, organizations can build resilient, scalable, and adaptable systems. As we move forward, it is crucial to apply these insights to our own projects, ensuring that we not only meet current demands but also anticipate future challenges. When help is needed, don't hesitate to reach out to the solid network of AWS Professionals who can guide you on the right path. The lessons from re:Invent 2024 remind us that thoughtful design, strategic foresight, and leveraging expert support are key to long-term success in the ever-evolving landscape of technology.</p>
]]></content:encoded></item><item><title><![CDATA[Mid-Event Highlights: Key Announcements and Innovations from AWS re:Invent 2024]]></title><description><![CDATA[Even though I couldn’t make it to AWS re:Invent 2024 in person this year, I’ve been following the updates closely. With the event halfway through, there’s already plenty to talk about - new services, enhancements to existing tools, and some interesti...]]></description><link>https://blog.techinthe.cloud/mid-event-highlights-key-announcements-and-innovations-from-aws-reinvent-2024</link><guid isPermaLink="true">https://blog.techinthe.cloud/mid-event-highlights-key-announcements-and-innovations-from-aws-reinvent-2024</guid><category><![CDATA[AWS]]></category><category><![CDATA[reinvent2024]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Wed, 04 Dec 2024 10:21:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733307609306/8d9fe157-61f4-4191-a164-a4afc116a631.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Even though I couldn’t make it to AWS re:Invent 2024 in person this year, I’ve been following the updates closely. With the event halfway through, there’s already plenty to talk about - new services, enhancements to existing tools, and some interesting themes emerging from the keynotes. In this post, I’ll share some of the highlights that intrigued me so far and what they might mean for those of us working with AWS every day.</p>
<p>As done previously, I will split the information shared in this post in the high level categories that AWS recognizes. With no further ado, let’s dive into it!</p>
<h2 id="heading-application-integration">Application Integration</h2>
<p>AWS has announced new features that allow customers to share resources like Amazon EC2 instances, Amazon ECS and EKS container services, and HTTPS services across Amazon VPC and AWS account boundaries. This enables the building of event-driven applications via Amazon EventBridge and orchestration of workflows with AWS Step Functions. These features leverage Amazon VPC Lattice and AWS PrivateLink, providing more options for network design and integration across technology stacks.</p>
<p>The key benefits for AWS customers include:</p>
<ul>
<li><p><strong>Simplified Modernization</strong>: Accelerate modernization efforts by integrating cloud-native apps with on-premises legacy systems.</p>
</li>
<li><p><strong>Enhanced Integration</strong>: Seamlessly connect public and private HTTPS-based applications into event-driven architectures and workflows.</p>
</li>
<li><p><strong>Efficiency</strong>: Replace complex data transfer methods with simpler, more efficient solutions.</p>
</li>
</ul>
<p>These updates aim to help customers drive growth, adapt to the cloud, and reduce costs while meeting security and compliance requirements. Read more about this announcement <a target="_blank" href="https://aws.amazon.com/blogs/aws/securely-share-aws-resources-across-vpc-and-account-boundaries-with-privatelink-vpc-lattice-eventbridge-and-step-functions/">here</a>.</p>
<h2 id="heading-containers">Containers</h2>
<p>Businesses should focus on promoting the business value and not on operational tasks that can be offloaded to a managed services partner or by trying to achieve a no-ops model using key cloud services like the one described below.</p>
<p>AWS announced the general availability of <strong>Amazon Elastic Kubernetes Service (Amazon EKS) Auto Mode</strong>. This new capability streamlines Kubernetes cluster management for compute, storage, and networking, from provisioning to ongoing maintenance with a single click.</p>
<p><strong>Key Benefits for AWS Customers:</strong></p>
<ul>
<li><p><strong>Higher Agility and Performance</strong>: By eliminating the operational overhead of managing cluster infrastructure, businesses can achieve greater agility and performance.</p>
</li>
<li><p><strong>Cost-Efficiency</strong>: EKS Auto Mode continuously optimizes costs, helping businesses manage their budgets more effectively.</p>
</li>
<li><p><strong>Simplified Management</strong>: Automates cluster management without requiring deep Kubernetes expertise, selecting optimal compute instances, dynamically scaling resources, managing core add-ons, patching operating systems, and integrating with AWS security services.</p>
</li>
<li><p><strong>Enhanced Operational Responsibility</strong>: AWS takes on more operational responsibility, configuring, managing, and securing the AWS infrastructure in EKS clusters, allowing customers to focus on building applications that drive innovation.</p>
</li>
<li><p><strong>Support for AI Workloads</strong>: Reduces the work required to acquire and run cost-efficient GPU-accelerated instances, ensuring generative AI workloads have the necessary capacity.</p>
</li>
</ul>
<p>Amazon EKS Auto Mode is now available in all commercial AWS Regions except China Regions where Amazon EKS is available. It supports Kubernetes 1.29 and above, with no upfront fees or commitments. Customers pay for the management of the compute resources provisioned, in addition to regular EC2 costs. You can read more about this announcement <a target="_blank" href="https://aws.amazon.com/blogs/aws/streamline-kubernetes-cluster-management-with-new-amazon-eks-auto-mode/">here</a>.</p>
<h2 id="heading-databases">Databases</h2>
<p>Matt Garman discussed in his keynote on Tuesday the challenges of distributed systems, particularly the difficulty of keeping distributed databases in sync, especially over long distances. Providing highly available applications while maintaining low latency reads and writes across AWS Regions is a common challenge faced by many customers.</p>
<p>Accessing data from different Regions can cause delays of hundreds of milliseconds compared to microseconds within the same Region. The necessity for developers to create complex custom solutions for data replication and conflict resolution can lead to increased operational workload and potential errors. Beyond multi-Region replication, these customers have to implement manual database failover procedures and ensure data consistency and recovery to deliver highly available applications and data durability.</p>
<p>Amazon Web Services (AWS) announced the general availability of Amazon MemoryDB Multi-Region, a fully managed, active-active, multi-Region database that you can use to build applications with up to 99.999 percent availability, microsecond read, and single-digit millisecond write latencies across multiple AWS Regions. MemoryDB Multi-Region is available for Valkey, a Redis Open Source Software (OSS) drop-in replacement stewarded by the Linux Foundation. This new feature builds upon the existing benefits of Amazon MemoryDB, such as multi-AZ durability and high throughput across multiple AWS Regions, and addresses these common challenges faced by many customers.</p>
<p><strong>Benefits of MemoryDB Multi-Region:</strong></p>
<ul>
<li><p><strong>High availability and disaster recovery:</strong> Build applications with up to 99.999 percent availability. If an application cannot connect to MemoryDB in a local Region, it can connect to MemoryDB from another AWS Regional endpoint with full read and write access. MemoryDB Multi-Region will automatically synchronize data across all AWS Regions when the application reconnects to the original endpoint.</p>
</li>
<li><p><strong>Low latency:</strong> Serve both reads and writes locally from the Regions closest to your customers with microsecond read and single-digit millisecond write latency at any scale. Data is typically propagated asynchronously between AWS Regions in less than one second.</p>
</li>
<li><p><strong>Compliance and regulatory adherence:</strong> Meet compliance and regulatory requirements by choosing the specific AWS Region where your data resides.</p>
</li>
</ul>
<p>You can read more about this announcement <a target="_blank" href="https://aws.amazon.com/blogs/aws/amazon-memorydb-multi-region-is-now-generally-available/">here</a>.</p>
<p>AWS also announced the <strong>Amazon Aurora DSQL</strong>, a new serverless distributed SQL database designed for always-available applications. Aurora DSQL offers virtually unlimited scale, highest availability, and zero infrastructure management. It can handle any workload demand without the need for database sharding or instance upgrades.</p>
<p>Key benefits for AWS customers include:</p>
<ul>
<li><p><strong>High Availability</strong>: Aurora DSQL is designed for 99.99% availability in single-Region configurations and 99.999% in multi-Region configurations.</p>
</li>
<li><p><strong>Scalability</strong>: It scales automatically to meet workload demands, eliminating the need for manual scaling.</p>
</li>
<li><p><strong>Ease of Management</strong>: The serverless design removes the operational burden of patching, upgrades, and maintenance.</p>
</li>
<li><p><strong>PostgreSQL Compatibility</strong>: Developers can use familiar PostgreSQL tools and frameworks, making it easy to build and deploy applications.</p>
</li>
</ul>
<p>Aurora DSQL's innovative active-active architecture ensures continuous availability and strong data consistency, making it ideal for building resilient, high-performance applications. You can read more about this announcement <a target="_blank" href="https://aws.amazon.com/blogs/database/introducing-amazon-aurora-dsql/">here</a>.</p>
<p>Looking forward to hearing more about the distributed database challenges in Dr. Werner Vogels’ keynote on Thursday.</p>
<h2 id="heading-developer-tools">Developer Tools</h2>
<p>Wow, more than 30 minutes of Matt Garman’s keynote was reserved on Amazon Q Developer and the latest additions to its capabilities. Let’s see the ones that I think really stand out.</p>
<h3 id="heading-amazon-q-developer-agent-capabilities-include-generating-documentation-code-reviews-and-unit-tests">Amazon Q Developer agent capabilities include generating documentation, code reviews, and unit tests</h3>
<p>AWS expanded Amazon Q Developer with three new features:</p>
<ol>
<li><p><strong>Enhanced documentation</strong>: Automatically generate comprehensive documentation within your IDE.</p>
</li>
<li><p><strong>Code reviews</strong>: Detect and resolve code quality and security issues.</p>
</li>
<li><p><strong>Unit tests</strong>: Automate the creation of unit tests to improve test coverage.</p>
</li>
</ol>
<p>The new features of Amazon Q Developer enhance productivity by automatically generating comprehensive documentation for newly produced code but also existing codebases, saving developers time and ensuring up-to-date information. Automated code reviews improve code quality and security by detecting issues early, while automated unit test generation increases test coverage and reliability. These capabilities streamline the development process, allowing developers to focus more on creating new features and less on repetitive tasks. You can read more about this announcement <a target="_blank" href="https://aws.amazon.com/blogs/aws/new-amazon-q-developer-agent-capabilities-include-generating-documentation-code-reviews-and-unit-tests/">here</a>.</p>
<h3 id="heading-investigate-and-remediate-operational-issues-with-amazon-q-developer">Investigate and remediate operational issues with Amazon Q Developer</h3>
<p>AWS has announced a new capability in Amazon Q Developer, now in preview, designed to help customers investigate and remediate operational issues using generative AI. This new feature automates root cause analysis and guides users through operational diagnostics, leveraging AWS's extensive operational experience. It integrates seamlessly with Amazon CloudWatch and AWS Systems Manager, providing a unified troubleshooting experience. This capability aims to simplify complex processes, enabling faster issue resolution and allowing customers to focus on innovation. Currently, it is available in the US East (N. Virginia) Region.</p>
<p>This and similar products in Generative AI sphere is and will be transforming Managed Services Providers (MSPs) and platform engineering teams by automating routine tasks, enhancing scalability, and improving efficiency while reducing operational costs.</p>
<p>You can read more about this announcement <a target="_blank" href="https://aws.amazon.com/blogs/aws/investigate-and-remediate-operational-issues-with-amazon-q-developer/">here</a>.</p>
<h2 id="heading-generative-ai-machine-learning">Generative AI / Machine Learning</h2>
<h3 id="heading-next-generation-of-amazon-sagemaker">Next generation of Amazon SageMaker</h3>
<p>AWS has announced the next generation of Amazon SageMaker, a comprehensive platform for data, analytics, and AI. This new version integrates various components needed for data exploration, preparation, big data processing, SQL analytics, machine learning (ML) model development, and generative AI application development. The existing Amazon SageMaker has been renamed to Amazon SageMaker AI, which is now part of the new platform but also available as a standalone service.</p>
<p><strong>Key Highlights:</strong></p>
<ul>
<li><p><strong>SageMaker Unified Studio (preview)</strong>: A single environment for data and AI development, integrating tools from Amazon Athena, Amazon EMR, AWS Glue, Amazon Redshift, and more.</p>
</li>
<li><p><strong>Amazon Bedrock IDE (preview)</strong>: Updated tools for building and customizing generative AI applications.</p>
</li>
<li><p><strong>Amazon Q</strong>: AI assistance integrated throughout the SageMaker workflows.</p>
</li>
</ul>
<p><strong>Value for AWS Customers:</strong></p>
<ul>
<li><p><strong>Unified Environment</strong>: Simplifies the development process by bringing together data and AI tools in one place.</p>
</li>
<li><p><strong>Enhanced Capabilities</strong>: Offers advanced tools for data processing, model development, and generative AI, improving efficiency and scalability.</p>
</li>
<li><p><strong>Flexibility</strong>: Allows customers to use SageMaker AI as part of the unified platform or as a standalone service, catering to different needs.</p>
</li>
</ul>
<p>This update aims to streamline workflows and enhance the capabilities available to AWS customers, making it easier to build, train, and deploy AI and ML models at scale. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/introducing-the-next-generation-of-amazon-sagemaker-the-center-for-all-your-data-analytics-and-ai/">here</a>.</p>
<h3 id="heading-amazon-nova">Amazon Nova</h3>
<p>Andy Jassy, welcome back to re:Invent! He delivered a presentation (more of a mini-keynote) within Matt Garman's keynote. And it came with announcements!</p>
<p>Amazon has announced Amazon Nova, a new generation of foundation models available exclusively in Amazon Bedrock. These models offer state-of-the-art intelligence and industry-leading price performance, designed to lower costs and latency for various generative AI tasks. Amazon Nova can handle tasks such as document and video analysis, chart and diagram understanding, video content generation, and building sophisticated AI agents. There are two main categories of models: understanding models and creative content generation models. The understanding models include Amazon Nova Micro, Lite, Pro, and the upcoming Premier, which process text, image, or video inputs to generate text output. The creative content generation models include Amazon Nova Canvas for image generation and Amazon Nova Reel for video generation.</p>
<p>Amazon Nova models can be fine-tuned with text, image, and video inputs to meet specific industry needs, making them highly adaptable for various enterprise applications. Built-in safety controls and content moderation capabilities ensure responsible AI use, with features like digital watermarking. For AWS customers, Amazon Nova offers cost efficiency, as the models are optimized for speed and cost, making them a cost-effective solution for AI tasks. These models set new standards in multimodal intelligence and agentic workflows, achieving state-of-the-art performance on key benchmarks. Supporting over 200 languages, Amazon Nova enables the development of global applications without language barriers. Integration with Amazon Bedrock simplifies deployment and scaling, with features like real-time streaming, batch processing, and detailed monitoring. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/introducing-amazon-nova-frontier-intelligence-and-industry-leading-price-performance/">here</a>.</p>
<h2 id="heading-storage">Storage</h2>
<p>Amazon has introduced <strong>Amazon S3 Tables</strong>, a new feature designed to optimize storage for tabular data such as daily purchase transactions, streaming sensor data, and ad impressions. These tables use the Apache Iceberg format, enabling easy queries with popular engines like Amazon Athena, Amazon EMR, and Apache Spark. Key highlights include:</p>
<ul>
<li><p><strong>Performance</strong>: Up to 3x faster query performance and up to 10x more transactions per second compared to self-managed table storage.</p>
</li>
<li><p><strong>Efficiency</strong>: Fully managed service that handles operational tasks, providing significant operational efficiency.</p>
</li>
</ul>
<p>Amazon S3 Tables are stored in a new type of S3 bucket called <strong>table buckets</strong>. These buckets act like an analytics warehouse, capable of storing Iceberg tables with various schemas. They offer the same durability, availability, scalability, and performance characteristics as standard S3 buckets, while also automatically optimizing storage to maximize query performance and minimize costs.</p>
<p>Each table bucket is region-specific and has a unique name within the AWS account. These buckets use namespaces to logically group tables, simplifying access management. The tables themselves are fully managed, with automatic maintenance tasks such as compaction, snapshot management, and removal of unreferenced files, ensuring that users can focus more on their data rather than on maintenance.</p>
<p><strong>Integration with AWS services</strong> is a key feature of Amazon S3 Tables. Currently in preview, the integration with AWS Glue Data Catalog allows users to query and visualize data using AWS Analytics services like Amazon Athena, Amazon Redshift, Amazon EMR, and Amazon QuickSight. The table buckets support relevant S3 API functions and ensure security by automatically encrypting all stored objects and enforcing Block Public Access. Read more about this announcement <a target="_blank" href="https://aws.amazon.com/blogs/aws/new-amazon-s3-tables-storage-optimized-for-analytics-workloads/">here</a>.</p>
<p>AWS is further using the release above for providing further value to it’s customers: <strong>Introducing queryable object metadata for Amazon S3 buckets.</strong></p>
<p>It automatically generates rich metadata for objects when they are added or modified. This metadata is stored in fully managed Apache Iceberg tables, allowing customers to use tools like Amazon Athena, Amazon Redshift, Amazon QuickSight, and Apache Spark to efficiently query and find objects at any scale.</p>
<p>This new feature simplifies the process of managing and querying metadata, making it easier for AWS customers to locate the data they need for analytics, data processing, and AI training workloads. Additionally, Amazon Bedrock will annotate AI-generated video inference responses with metadata, helping users identify the content and the model used.</p>
<p>Overall, this enhancement aims to reduce the complexity and improve the scalability of systems that capture, store, and query metadata, providing significant value to AWS customers. Read more about this announcement <a target="_blank" href="https://aws.amazon.com/blogs/aws/introducing-queryable-object-metadata-for-amazon-s3-buckets-preview/">here</a>.</p>
<h2 id="heading-to-be-continued"><strong>To be continued...</strong></h2>
<p>That has been something so far. As we take a moment to absorb everything that's happened so far at AWS re:Invent 2024, it's clear that this year's event is already shaping up to be even more exciting than 2023. The CEO's keynote has introduced some impressive new technologies and strategies. With so much already revealed, we're looking forward to what the second half of the event will bring. Stay tuned for more updates and insights.</p>
]]></content:encoded></item><item><title><![CDATA[Create and initialise CodeCommit repositories with Terraform]]></title><description><![CDATA[In today’s fast-paced digital landscape, efficient collaboration and secure version control are indispensable for any software development project. With AWS CodeCommit, developers and cloud engineers are empowered with a robust and scalable solution ...]]></description><link>https://blog.techinthe.cloud/create-and-initialise-codecommit-repositories-with-terraform</link><guid isPermaLink="true">https://blog.techinthe.cloud/create-and-initialise-codecommit-repositories-with-terraform</guid><category><![CDATA[AWS]]></category><category><![CDATA[version control]]></category><category><![CDATA[Git]]></category><category><![CDATA[AWS CODECOMMIT]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Fri, 12 Apr 2024 14:43:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1712932894046/96bf5f92-46af-427c-ab65-a4675dfd7dcf.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In today’s fast-paced digital landscape, efficient collaboration and secure version control are indispensable for any software development project. With AWS CodeCommit, developers and cloud engineers are empowered with a robust and scalable solution for hosting secure Git repositories, seamlessly integrated into or close to their AWS environments.</p>
<p>Creating a repository within AWS CodeCommit is not a difficult process. This can be done either in the console or in code. By using code, one can standardize the creation of the CodeCommit repository as well as perform additional tasks around the repository. An example of this could be an initial sync of files towards newly created repositories. This can facilitate multiple use cases. An example is the initial sync towards the repo of License specific files, <code>.gitignore</code> files specific to the requirements of the company, a structure specific setup when that's appropriate. It could be handy as well when multiple files need to initially synced to a newly create AWS CodeCommit repository from a landing zone specific solution on account vending solution.</p>
<p>So how can we achieve this? We will showcase this below using some Terraform sample code.</p>
<h2 id="heading-solution">Solution</h2>
<p>First we need to create a new AWS CodeCommit repository.</p>
<pre><code class="lang-go">resource <span class="hljs-string">"aws_codecommit_repository"</span> <span class="hljs-string">"repository"</span> {
  repository_name = <span class="hljs-keyword">var</span>.repository_name
  description     = <span class="hljs-string">"In bulk created repositories"</span>
}
</code></pre>
<p>Then we need to create a user that will be used by the pipeline deploying the Terraform code. The files that would typically be available within the pipeline will be synced using Git to the newly create repository. Below you can see a user, policy and attachment of the policy to the user. If the credentials used to create the repository can perform Git pull and push actions, this step can be skipped. Instead we can use the existing credentials in the last step.</p>
<pre><code class="lang-go">resource <span class="hljs-string">"aws_iam_user"</span> <span class="hljs-string">"pipeline_codecommit_user"</span> {
  name = <span class="hljs-string">"codecommit_user"</span>
}

resource <span class="hljs-string">"aws_iam_policy"</span> <span class="hljs-string">"codecommit_pullpush_policy"</span> {
  name        = <span class="hljs-string">"codecommit_pullpush"</span>
  path        = <span class="hljs-string">"/"</span>
  description = <span class="hljs-string">"CodeCommit policy for the pipeline_codecommit_user used by a CI/CD pipeline"</span>

  policy = jsonencode({
    Version = <span class="hljs-string">"2012-10-17"</span>
    Statement = [
      {
        Action = [
          <span class="hljs-string">"codecommit:GitPull"</span>,
          <span class="hljs-string">"codecommit:GitPush"</span>
        ]
        Effect   = <span class="hljs-string">"Allow"</span>
        Resource = aws_codecommit_repository.repository.arn
      },
    ]
  })
}

resource <span class="hljs-string">"aws_iam_user_policy_attachment"</span> <span class="hljs-string">"codecommit_policy_attachment"</span> {
  user       = aws_iam_user.pipeline_codecommit_user.name
  policy_arn = aws_iam_policy.codecommit_pullpush_policy.arn
}
</code></pre>
<p>We then need to create an access key of the aforementioned user. The key will be used in the next steps to sync the files.</p>
<pre><code class="lang-go">resource <span class="hljs-string">"aws_iam_access_key"</span> <span class="hljs-string">"pipeline_codecommit_user"</span> {
  user = aws_iam_user.pipeline_codecommit_user.name
}
</code></pre>
<p>Please note that using the above snippet, the generated access key and secret access key will be available as plain text in the state file, whether that is local or remote. There are ways to encrypt them with using a pgp key, but that goes beyond the scope of this post.</p>
<p>Finally, we can use the <code>local-exec</code> provisioner to sync files to the remote Git repository. Assuming the files are available within a local folder called <code>repo-init</code>, the code that would sync the files can be found below.</p>
<pre><code class="lang-go">resource <span class="hljs-string">"null_resource"</span> <span class="hljs-string">"git_clone"</span> {
  provisioner <span class="hljs-string">"local-exec"</span> {
    command = &lt;&lt;EOT
      export AWS_ACCESS_KEY_ID=${aws_iam_access_key.pipeline_codecommit_user.id}
      export AWS_SECRET_ACCESS_KEY=${aws_iam_access_key.pipeline_codecommit_user.secret}
      git config --global credential.helper <span class="hljs-string">'!aws codecommit credential-helper $@'</span>
      git config --global credential.UseHttpPath <span class="hljs-literal">true</span>
      git clone ${aws_codecommit_repository.repository.clone_url_http} ../temp-location
      cp -r repo-init<span class="hljs-comment">/**/</span>* ../temp-location
      cd ../temp-location
      git add . &amp;&amp; git commit -am <span class="hljs-string">"Initial commit"</span> &amp;&amp; git push origin main
      rm -rf ../temp-location
    EOT
  }
}
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In summary, AWS CodeCommit offers a robust solution for version control. With the aforementioned solution, one can complement it with automation capabilities like syncing files upon creation.</p>
<p>Main image by <a target="_blank" href="https://www.freepik.com/free-vector/hand-drawn-flat-design-api-illustration_25559969.htm#fromView=search&amp;page=1&amp;position=1&amp;uuid=5365c79a-e208-49a3-8f73-134ffc4ab056">Freepik</a></p>
<p>*This article was originally posted <a target="_blank" href="https://xebia.com/blog/create-and-initialise-codecommit-repositories-with-terraform/">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Anti-patterns of using layers with Terraform]]></title><description><![CDATA[In the ever-evolving landscape of cloud computing and infrastructure management, Terraform has emerged as a transformative force, empowering organizations to define, provision, and manage their infrastructure as code (IaC). The versatility of Terrafo...]]></description><link>https://blog.techinthe.cloud/anti-patterns-of-using-layers-with-terraform</link><guid isPermaLink="true">https://blog.techinthe.cloud/anti-patterns-of-using-layers-with-terraform</guid><category><![CDATA[Cloud]]></category><category><![CDATA[Terraform]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Thu, 11 Jan 2024 09:16:35 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1704964276532/e8abb9e1-2722-4699-9cd6-2c3cfb6a4581.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the ever-evolving landscape of cloud computing and infrastructure management, Terraform has emerged as a transformative force, empowering organizations to define, provision, and manage their infrastructure as code (IaC). The versatility of Terraform extends to its project structuring, offering a myriad of approaches, from modular designs and remote state management to utilizing workspaces and version control, providing users with a spectrum of options to tailor their IaC projects to diverse needs.</p>
<p>In Terraform, the typical organizational structure involves modules, which are reusable units of code that encapsulate infrastructure components. These modules can be composed to create more complex infrastructure. There isn't a standardized or official concept referred to as "Terraform layers" in the Terraform documentation. However, the term has gained popularity in the Terraform community. If you search the tern "Terraform layers" various articles will pop up discussing the concept.</p>
<h2 id="heading-early-stages-of-terraform-layers">Early stages of Terraform layers</h2>
<p>One of the first references of using layers with Terraform was a talk by Armin Coralic (you can find it <a target="_blank" href="https://www.hashicorp.com/resources/terraforming-real-world-experience-best-practices">here</a>).</p>
<p>In his talk, Armin discussed the evolution of using Terraform for IaC and introduced a layered approach to address challenges at different stages. He emphasized three key layers in Terraform code: the bootstrap layer, focusing on setting up the infrastructure; the foundation layer, handling global and foundational aspects; and the service layer, responsible for implementing specific services. This layering strategy aims to provide flexibility, simplify testing, and effectively manage organizational changes in large and complex environments. He finally pointed out the significance of considering both the tools as well as the organizational practices for successful implementation of Terraform in varying contexts.</p>
<p>The layered approach in Terraform can work exceptionally well in scenarios where the infrastructure and organizational needs become more complex and sophisticated. This approach is particularly effective in medium-to-large organizations with multiple teams, diverse responsibilities, and varying lifecycles of infrastructure components. It becomes especially beneficial when addressing challenges such as separating work and responsibilities between teams, managing different lifecycles, and avoiding a monolithic structure. The layering concept is advantageous in facilitating easier testing, promoting flexibility, and adapting to changes that commonly occur in complex organizational settings. Therefore, the layered approach is most suited for environments where the scale and complexity of infrastructure demand a structured and modular approach to Terraform code. One, though, would argue that the same could be achieved with using multiple repositories, abstracting and shifting the responsibility for each module completely to a team.</p>
<h2 id="heading-evolution-of-terraform-layers">Evolution of Terraform layers</h2>
<p>In the realm of Terraform architecture, two primary approaches emerge: the single monolith (single repo/module) and multiple modules, either split in different repositories or in multiple layers. Each approach comes with its own set of implications, and it becomes imperative to weigh them against the unique needs of your project. Understanding the intricacies of these alternatives empowers you to make informed decisions based on the specific requirements of your target infrastructure's size, the dynamics of your team, and the desired level of immutability.</p>
<h4 id="heading-monolith">Monolith</h4>
<p>The single monolith approach offers inherent advantages, such as safety, readability, and a straightforward implementation process. It provides a solid foundation, ensuring the stability of your infrastructure code. This approach is well-suited for scenarios where simplicity and ease of management are paramount. With the monolithic approach, all references to other resources can be passed in a native way without the need to hardcode values in environmental variables, or even worse share them through the various parameter and secret stores.</p>
<h4 id="heading-layers">Layers</h4>
<p>On the other hand, opting for multiple layers introduces a new dimension to IaC projects. This approach fosters collaboration, enhances agility, and provides flexibility to cater to future needs. By distributing responsibilities across layers, each dedicated team can focus on a specific aspect of the infrastructure, fostering specialization and efficiency. This approach is particularly valuable for larger-scale projects where the complexity demands a more modular and scalable solution. This is what we discussed in the previous paragraph, right? So where is the problem?</p>
<p>In an era that monolithic approaches do not seem to much the distributed cloud paradigm (unrightfully so as <a target="_blank" href="https://www.primevideotech.com/video-streaming/scaling-up-the-prime-video-audio-video-monitoring-service-and-reducing-costs-by-90">this</a> example points out), there is a trend to split everything into subcomponents. To that end, many teams working with terraform have split their monolithic projects using layers, in an attempt to add modularity. In many cases, teams are using different layers for their networking, compute, database and application components. It could be a lot more layers as well. These layers ([sub-]modules?) have different states  and they have dependencies between each other passed as references to the state further up.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704964240658/40f2d474-07cd-407d-955b-96b0b075b7ae.png" alt class="image--center mx-auto" /></p>
<p>This creates a lot of complexity during the development process. This as an example the case of making a complex change as a result of a new feature request. Such a request could include touching almost all the layers. Due to the nature of the layer structure and the dependency mapping, upper layers need to be applied before lower layers can be planned/applied. Otherwise references to the state may not be found or the actual components may be missing. It also create an issue with carrying out the first deployment which needs to be treated as an edge case making the deployment in brand new environment cumbersome. As a reminder, the initial idea of the layers was to only split in layers components that have different teams as owners, or components that have completely different lifecycles. And as it becomes evident, strong coupling of components between layers can be a really bad idea.</p>
<p>All the previous also complicate the build and deployment process, the flexibility to automate using CI/CD tools. When you need to apply each layer before you can plan the next, you need to split your changes over multiple pull/merge requests, fragmenting next to the IaC also the development process.</p>
<h2 id="heading-a-solid-use-case-for-using-layers">A solid use case for using layers</h2>
<p>Despite all the above, there are some edge cases that the layered approach can really shine. Terraform plan and apply can end up taking really long when a lot of resource changes need to be calculated or applied. Imagine a situation in the thousands of resources of a certain type changed at once. Could be thousands of buckets or dns records or anything else managed with Terraform. When (and only when) these resources do not carry references between each other, they can be partitioned in separate layers, with their name being the partition key. When combining this with the power from certain CI/CD tools that can identify the subfolders that carry changes, then only a sub-portion of the infrastructure needs to be planned and applied speeding things up by a lot.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1704964254699/2e616953-f67e-4ea1-a150-df02422c51b0.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Based on all the above, my advise would be that the layered approach in a single repository is an edge case that should be used with caution and only when it fits the target use case a lot better than the alternative options.</p>
<p>When considering the organization of infrastructure in Terraform, it's crucial to align your approach with the complexity of your project and the dynamics of your team. For simpler projects managed by a single team, opting for a monolithic approach is often the most straightforward choice. It provides a solid foundation for stability, allowing all references to resources to be handled natively without the need for complex configurations or environment variable management. In contrast, for larger and more complex projects involving multiple teams, consider using separate repositories to promote collaboration, specialization, and efficiency across various aspects of the infrastructure. Ultimately, the choice between monolithic and multi-repository approaches should be based on the unique requirements of your project, team structure, and scalability goals.</p>
<p>Keep it simple.</p>
<p>Main image by <a target="_blank" href="https://www.freepik.com/free-vector/self-management-life-coaching-man-doubting-questioning-brainstorming-identity-crisis-delirium-mental-confusion-confused-feelings-concept-pinkish-coral-bluevector-isolated-illustration_11664272.htm#query=confused&amp;position=20&amp;from_view=search&amp;track=sph&amp;uuid=82fb322f-b838-4c7f-9c0b-86da9d1cc281">vectorjuice</a> on Freepik</p>
<p>*This article was originally posted <a target="_blank" href="https://xebia.com/blog/anti-patterns-of-using-layers-with-terraform/">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Revelations and Innovations: Unveiling the Spectacular Journey of re:Invent 2023 - Part 2]]></title><description><![CDATA[Step into the thrilling aftermath of AWS re:Invent 2023 – the grand spectacle where innovation, expertise, and boundless enthusiasm converged to shape the future of cloud computing. As the second half of this extraordinary week unfolds, we find ourse...]]></description><link>https://blog.techinthe.cloud/revelations-and-innovations-unveiling-the-spectacular-journey-of-reinvent-2023-part-2</link><guid isPermaLink="true">https://blog.techinthe.cloud/revelations-and-innovations-unveiling-the-spectacular-journey-of-reinvent-2023-part-2</guid><category><![CDATA[AWS]]></category><category><![CDATA[reInvent2023]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Fri, 01 Dec 2023 08:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1701625266371/788baf83-d55f-4be5-a7f9-dd1db08c22dc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Step into the thrilling aftermath of AWS re:Invent 2023 – the grand spectacle where innovation, expertise, and boundless enthusiasm converged to shape the future of cloud computing. As the second half of this extraordinary week unfolds, we find ourselves at the culmination of an exhilarating journey through the cutting-edge landscape of Amazon Web Services. The air is still buzzing with the excitement of groundbreaking announcements, insightful sessions, and hands-on experiences that have ignited our imaginations. Join us as we reflect on the whirlwind of discoveries, unveilings, and shared insights that defined this year's re:Invent, leaving an indelible mark on the ever-evolving realm of cloud technology. The stage is set, and the stories from re:Invent 2023 are about to unfold – let's relive the moments that shaped the future of the cloud.</p>
<h3 id="heading-generative-ai-machine-learning">Generative AI / Machine Learning</h3>
<p><strong>Amazon Titan, the latest in generative AI, is now available on Amazon Bedrock</strong>. This suite includes Image Generator and Multimodal Embeddings, alongside the already accessible Titan Text Lite and Text Express. Leveraging 25 years of AI innovation, these models offer powerful, customizable options for images, multimodal experiences, and text tasks. Whether using the base models or private customization, access is facilitated through the user-friendly Amazon Bedrock console. The original release blog highlights practical demonstrations of Image Generator and Multimodal Embeddings, emphasizing the seamless integration of Titan into Amazon Bedrock for a comprehensive generative AI solution. Read more about it <a target="_blank" href="https://aws.amazon.com/blogs/aws/amazon-titan-image-generator-multimodal-embeddings-and-text-models-are-now-available-in-amazon-bedrock/">here</a>.</p>
<p><strong>Model Evaluation, a feature introduced by Amazon Bedrock</strong>, is now available in preview, providing developers with the capability to assess, compare, and select foundation models (FMs) for their applications. The automatic evaluation option employs predefined metrics such as accuracy, robustness, and toxicity, while the human evaluation option allows customization for subjective metrics like friendliness and alignment to brand voice. In the playground environment, developers can experiment, iterate with automatic evaluations, and ensure quality through human reviews when preparing for an initial launch. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/evaluate-compare-and-select-the-best-foundation-models-for-your-use-case-in-amazon-bedrock-preview/">here</a>.</p>
<h3 id="heading-management-amp-governance">Management &amp; Governance</h3>
<p>During Werner Vogels' keynote, <strong>AWS unveiled myApplications</strong>, a suite of capabilities now in general availability that streamlines application operations on the AWS platform. This tool, accessible via the AWS Management Console, empowers users to initiate, manage, and monitor applications efficiently, offering insights into cost, health, security, and performance. With features like the Applications widget and a dedicated applications dashboard, myApplications simplifies resource management and allows users to take specific actions based on key metrics. The launch spans various AWS Regions, supported by AWS Premier Tier Services Partners, including <a target="_blank" href="https://xebia.com/">Xebia</a>. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/new-myapplications-in-the-aws-management-console-simplifies-managing-your-application-resources/">here</a>.</p>
<p><strong>Amazon CloudWatch Application Signals</strong>, now in preview, addresses the challenges of monitoring performance in distributed systems. It automatically instruments applications based on best practices, eliminating manual effort and custom coding. Users gain access to a pre-built, standardized dashboard showcasing key metrics like request volume, availability, and latency. The service also facilitates the definition of Service Level Objectives (SLOs) to monitor critical operations. Application Signals correlates telemetry across metrics, traces, logs, real user monitoring, and synthetic monitoring, enhancing troubleshooting efficiency. Collaboration is promoted through features like the Service Map, allowing service owners to share triage tasks seamlessly. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/amazon-cloudwatch-application-signals-for-automatic-instrumentation-of-your-applications-preview/">here</a>.</p>
<h2 id="heading-closing-thoughts">Closing thoughts</h2>
<p>As AWS re:Invent 2023 comes to a close, it leaves in its wake a trail of groundbreaking announcements and innovations. The keynotes, pulsating with energy and anticipation, unleashed a torrent of releases with a resounding emphasis on Generative AI, catering to the evolving needs of developers, businesses, and enterprises.</p>
<p>From the launch of cutting-edge services simplifying application operations to the unveiling of powerful AI models under the Amazon Titan umbrella, AWS re:Invent showcased a commitment to delivering solutions that empower users to build, deploy, and scale with unparalleled efficiency. The myApplications experience introduces a seamless approach to managing and monitoring applications, emphasizing ease of use and operational efficiency.</p>
<p>The unveiling of Amazon CloudWatch Application Signals in preview emerged as a game-changer in the realm of distributed systems monitoring. This service promises to revolutionize how users collect, analyze, and collaborate on application and container telemetry, offering an integrated and standardized dashboard for efficient troubleshooting.</p>
<p>As the curtain falls on re:Invent 2023, the resounding message is clear – Generative AI has taken center stage. The conference has not only showcased the transformative potential of these AI models but has also set the stage for a future where creativity, innovation, and efficiency converge in the cloud computing space. The releases unveiled during re:Invent 2023 collectively underscore AWS's commitment to shaping the future of cloud technology through the lens of Generative AI.</p>
]]></content:encoded></item><item><title><![CDATA[Halfway through AWS re:Invent 2023: A Journey Unveiling Innovation!]]></title><description><![CDATA[As we find ourselves at the exhilarating midpoint of AWS re:Invent 2023, the air is charged with innovation, collaboration, and the unmistakable buzz of cutting-edge technology. It's been a whirlwind of breakthrough announcements, hands-on experience...]]></description><link>https://blog.techinthe.cloud/halfway-through-aws-reinvent-2023-a-journey-unveiling-innovation</link><guid isPermaLink="true">https://blog.techinthe.cloud/halfway-through-aws-reinvent-2023-a-journey-unveiling-innovation</guid><category><![CDATA[reInvent2023]]></category><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Wed, 29 Nov 2023 17:44:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1701279737220/667d9b46-4c87-46cc-8979-de0d3a8e8f86.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As we find ourselves at the exhilarating midpoint of AWS re:Invent 2023, the air is charged with innovation, collaboration, and the unmistakable buzz of cutting-edge technology. It's been a whirlwind of breakthrough announcements, hands-on experiences, and invaluable insights from industry leaders. From mind-bending keynotes to deep-dive technical sessions, the conference has proven to be a kaleidoscope of possibilities, transforming the cloud landscape.</p>
<p>Join me as I reflect on the journey so far, unpacking the game-changing advancements, captivating moments, and the profound impact re:Invent 2023 is already having on the future of cloud computing.</p>
<h3 id="heading-analytics">Analytics</h3>
<p>Amazon QuickSight is ushering in a new era with the <strong>preview of Amazon Q</strong>, introducing Generative BI capabilities that empower business users with enhanced insights and storytelling tools. In this preview, users can leverage three key capabilities: Stories, Executive Summaries, and Data Q&amp;A. Stories enable the creation of visually compelling narratives through natural language prompts. Executive Summaries provide quick snapshots of dashboard highlights, saving time and offering at-a-glance insights. The Data Q&amp;A experience facilitates deeper understanding, allowing users to ask vague questions and receive AI-suggested answers with narrative context. This is just one of the Amazon Q capabilities that were introduced and we will look in a few more further below. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/new-amazon-q-in-quicksight-uses-generative-ai-assistance-for-quicker-easier-data-insights-preview/">here</a>.</p>
<h3 id="heading-containers">Containers</h3>
<p>A new capability was introduced – the <strong>Amazon Managed Service for Prometheus collector</strong> – designed to automatically and agentlessly discover and collect Prometheus metrics from Amazon Elastic Kubernetes Service (EKS). This collector, part of the Amazon Managed Service for Prometheus, eliminates the need to run collectors in-cluster and offers fully managed Prometheus-compatible monitoring and alerting. With the option for AWS-managed or customer-managed collection, users can optimize metric collection costs for monitoring applications and infrastructure on EKS. The setup process involves enabling AWS managed collectors during EKS cluster creation, defining scraper configurations, and visualizing metrics using Amazon Managed Grafana. This new capability is now available to all AWS customers in supported regions. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/amazon-managed-service-for-prometheus-collector-provides-agentless-metric-collection-for-amazon-eks/">here</a>.</p>
<h3 id="heading-databases">Databases</h3>
<p>Several exciting announcements have taken place in the space of Databases (so far) at re:Invent 2023. Amazon introduced <strong>Amazon ElastiCache Serverless</strong>, a groundbreaking serverless option enabling users to create a cache in under a minute and dynamically scale based on application traffic patterns. Compatible with Redis and Memcached, ElastiCache Serverless eliminates the need for capacity planning or caching expertise. It offers fully managed, highly available caches with automatic replication across multiple Availability Zones, providing a 99.99% availability SLA. With a simplified endpoint experience, no upfront costs, and payment for actual resource consumption, ElastiCache Serverless ensures operational excellence. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/amazon-elasticache-serverless-for-redis-and-memcached-now-generally-available/">here</a>.</p>
<p>Next, the preview of <strong>Amazon Aurora Limitless Database</strong> was announced, a groundbreaking capability enabling automated horizontal scaling for processing millions of write transactions per second and managing petabytes of data in a single Aurora database. Unlike traditional read replicas, Limitless Database scales write throughput and storage capacity independently, supporting high-scale applications without the complexity of managing data across multiple instances. The two-layer architecture includes shards for parallel processing and transaction routers for managing distributed transactions. Users can sign up for the preview in select AWS regions, experiencing the power of Aurora Limitless Database for high-performance and scalable applications. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/join-the-preview-amazon-aurora-limitless-database/">here</a>.</p>
<p>Lastly, AWS dives into the world of the <strong>IBM Db2</strong> database! IBM and AWS collaborated to introduce Amazon RDS for Db2, providing a fully managed Db2 database engine on AWS infrastructure. IBM Db2, renowned for its enterprise-grade features, scalability, and security, is widely used for managing data-intensive workloads. Amazon RDS for Db2 simplifies database management, offering features such as fully managed infrastructure, automatic backups, high availability, and scalability. Users can create Db2 databases effortlessly through the AWS Management Console, CLI, or SDKs, allowing AWS to handle infrastructure complexities. The service supports existing applications seamlessly, offering a choice of storage types and flexible scaling options. The preview of Amazon RDS for Db2 is available in various AWS regions but users must bring their own Db2 license. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/getting-started-with-new-amazon-rds-for-db2/">here</a>.</p>
<h3 id="heading-developer-tools">Developer Tools</h3>
<p>Let's take a look at another capability of Amazon Q. Amazon introduced new <strong>generative AI capabilities in Amazon CodeCatalyst</strong>, focusing on feature development acceleration through Amazon Q. The feature development capability in Amazon Q aids in expediting software development tasks, such as adding comments, refining issue descriptions, generating classes and unit tests, and updating workflows. Developers can move from idea to fully tested, merge-ready code with natural language inputs. Amazon Q handles the heavy lifting by converting human prompts into actionable plans, generating code, unit tests, workflows, and summarizing changes in pull requests. Developers can provide feedback to Amazon Q on published pull requests and request new revisions. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/improve-developer-productivity-with-generative-ai-powered-amazon-q-in-amazon-codecatalyst-preview/">here</a>.</p>
<h3 id="heading-generative-ai-machine-learning">Generative AI / Machine Learning</h3>
<p>re:Invent 2023 is Gen AI heavy. Amazon introduced Amazon Q, <strong>a generative AI-powered assistant for business users</strong>. Amazon Q streamlines tasks, aids decision-making, and fosters creativity by connecting to company information repositories, code, data, and enterprise systems. Tailored user-based plans ensure pricing and features align with individual needs, and Amazon Q adapts interactions based on users' existing identities, roles, and permissions. The AI assistant operates without using customers' content for model training, ensuring data security and privacy. Amazon Q supports over 40 built-in connectors for popular data sources and enterprise systems. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/introducing-amazon-q-a-new-generative-ai-powered-assistant-preview/">here</a>.</p>
<p>Next, let's look at improvement to Amazon Bedrock. Amazon announced <strong>Guardrails for Amazon Bedrock</strong> (in preview), allowing users to implement safeguards for generative AI applications to promote responsible AI interactions. As part of AWS's commitment to responsible AI development, Guardrails enable users to define denied topics and content filters, adding an extra layer of control to enhance safety and align applications with company policies. The key controls include:</p>
<ol>
<li><p><strong>Denied Topics:</strong> Users can specify undesirable topics for their applications, providing natural language descriptions. For example, a banking application could avoid providing investment advice.</p>
</li>
<li><p><strong>Content Filters:</strong> Configurable thresholds for harmful content across hate, insults, sexual, and violence categories. Guardrails provide additional controls beyond built-in protections to filter interactions based on user-defined degrees.</p>
</li>
<li><p><strong>PII Redaction (Upcoming):</strong> Users will soon be able to select personally identifiable information (PII), such as name, email address, and phone number, for redaction in responses or block user input containing PII.</p>
</li>
</ol>
<p>Guardrails for Amazon Bedrock integrate with Amazon CloudWatch for monitoring and analysis of inputs and responses violating defined policies. Users can apply these guardrails to innovate safely while adhering to responsible AI goals. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/guardrails-for-amazon-bedrock-helps-implement-safeguards-customized-to-your-use-cases-and-responsible-ai-policies-preview/">here</a>.</p>
<h3 id="heading-security-identity-amp-compliance">Security, Identity, &amp; Compliance</h3>
<p>I am excited to see further updates to AWS Control Tower, the best way to manage your Landing Zone within AWS. AWS has introduced <strong>65 purpose-built controls within AWS Control Tower</strong> to help users meet digital sovereignty requirements. AWS Control Tower allows users to set up and govern secure, multi-account AWS environments efficiently. The new controls support data residency, granular access restriction, encryption, and resilience. Examples of added controls include Operator access, controlling access to data, and encryption at rest and in transit. AWS Control Tower provides a consolidated view of enabled controls, compliance status, and evidence across multiple accounts, helping users manage digital sovereignty needs. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/aws-control-tower-helps-customers-meet-digital-sovereignty-requirements/">here</a>.</p>
<p><strong>Amazon GuardDuty</strong> has introduced <strong>ECS Runtime Monitoring</strong> to detect potential runtime security issues in Amazon Elastic Container Service (ECS) clusters running on AWS Fargate and Amazon EC2. GuardDuty uses machine learning, anomaly detection, network monitoring, and malicious file discovery to identify threats. ECS Runtime Monitoring detects runtime events such as file access, process execution, and network connections, providing over 30 different finding types. It uses a managed and lightweight security agent for individual container runtime behaviors, and when used with AWS Fargate, the agent is automatically managed by AWS. Findings are visible in the console, and GuardDuty can send them to AWS Security Hub, Amazon EventBridge, and Amazon Detective. Amazon Detective now receives security findings from GuardDuty ECS Runtime Monitoring to aid in analysis and investigations. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/introducing-amazon-guardduty-ecs-runtime-monitoring-including-aws-fargate/">here</a>.</p>
<h3 id="heading-serverless">Serverless</h3>
<p><strong>AWS Lambda has improved its scaling capabilities</strong>, allowing each synchronously invoked Lambda function to scale by 1,000 concurrent executions every 10 seconds. This occurs until the aggregate concurrency across all functions reaches the account's concurrency limit. The update ensures that each function within an account scales independently, regardless of how the functions are invoked, enhancing scalability for highly variable traffic and reducing the impact of noisy neighbor scenarios. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/aws-lambda-functions-now-scale-12-times-faster-when-handling-high-volume-requests/">here</a>.</p>
<h3 id="heading-storage">Storage</h3>
<p>Amazon introduced the <strong>Amazon S3 Express One Zone storage class</strong>, aiming to provide up to 10 times better performance than the S3 Standard storage class. This new storage class is designed for frequently accessed data and demanding applications, delivering consistent single-digit millisecond latency while handling hundreds of thousands of requests per second. Objects are stored and replicated within a single AWS Availability Zone, allowing co-location of storage and compute resources to reduce latency. With very low latency, especially beneficial for smaller objects, and 50% lower request costs compared to S3 Standard, the Express One Zone storage class is suitable for data-intensive applications such as AI/ML training, financial modeling, media processing, and more. I guess it remains to see this in action. Read more about the release <a target="_blank" href="https://aws.amazon.com/blogs/aws/new-amazon-s3-express-one-zone-high-performance-storage-class/">here</a>.</p>
<h2 id="heading-to-be-continued">To be continued...</h2>
<p>Strap in for the second half – the stage is set for more revelations, connections, and the uncharted terrain of possibilities that lies ahead!</p>
]]></content:encoded></item><item><title><![CDATA[Managing complex infrastructure using AWS CDK and Go]]></title><description><![CDATA[In a previous article we dove into the topic of "Managing K8S Infrastructure and Applications on AWS". There, using the AWS Cloud Development Kit (CDK) and the Python language, we saw how we can manage a complete solution around Kubernetes (K8s) on A...]]></description><link>https://blog.techinthe.cloud/managing-complex-infrastructure-using-aws-cdk-and-go</link><guid isPermaLink="true">https://blog.techinthe.cloud/managing-complex-infrastructure-using-aws-cdk-and-go</guid><category><![CDATA[AWS]]></category><category><![CDATA[Go Language]]></category><category><![CDATA[aws-cdk]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Tue, 27 Jun 2023 14:08:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1687874837167/39727ed4-548e-46d6-aeed-6416dee4323f.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In a previous article we dove into the topic of "<a target="_blank" href="https://blog.techinthe.cloud/managing-k8s-infrastructure-and-applications-on-aws-the-imperative-way">Managing K8S Infrastructure and Applications on AWS</a>". There, using the AWS Cloud Development Kit (CDK) and the Python language, we saw how we can manage a complete solution around Kubernetes (K8s) on AWS; that is deploying the whole infrastructure as well as the workloads from a single codebase using one high level programming language, namely Python. As promised by the end of that article, I was going to template the same project in other programming languages supported by the CDK family of frameworks. The time has come to reproduce the same solution using Golang.</p>
<p>In this article we are not going to discuss K8s infrastructure and the applications. You can find all this information in the original article referenced above. In the attempt to rewrite code in Go that would produce very similar output to my original project in Python, I stumbled upon several challenges. I would like to share this journey with you and hopefully help anybody who is interested in getting started with the AWS CDK in combination with the Go language.</p>
<h2 id="heading-project-structure"><strong>Project Structure</strong></h2>
<p>There are several examples one can find online on writing Infrastructure as Code (IaC) using the AWS CDK and Go. All of these examples are focused on a single stack solutions that deploys very limited amount of resources. These examples can be very helpful when trying to identify how you can get started with the AWS CDK and the Go language. For me, starting to work on an IaC project that would potentially would end up having a high number of resources, it is very important to structure the solution accordingly. AWS for several years now supports the concept of Nested Stacks. I believe, it is of paramount importance for any production grade project of non trivial complexity on AWS to take advantage of Nested Stacks.</p>
<p>While looking around for best practices of how one would structure an AWS CDK project in Go, to my surprise I could not find any information other than single file - single stack examples. I would like to share with you here my two cents on how I would structure any complex IaC project.</p>
<h3 id="heading-folder-structure"><strong>Folder Structure</strong></h3>
<p>With the idea in mind that I would use many Nested Stacks and different configurations per deployed environment (I have written a separate article on this which can be found <a target="_blank" href="https://xebia.com/blog/managing-multiple-environments-in-the-aws-cdk-using-yaml-configuration-files/">here</a>), this would be a boilerplate of how the folder structure should look like:</p>
<pre><code class="lang-markdown">├── charts/
 │   ├── cdk8s-chart-1.go
 │   ├── cdk8s-chart-2.go
├── config/
 │   ├── development.yaml
 │   ├── test.yaml
 │   ├── acceptance.yaml
 │   ├── production.yaml
├── helper/
 │   ├── helper-functions-1.go
 │   ├── helper-functions-2.go
├── stacks/
 │   ├── nested-stack-1.go
 │   ├── nested-stack-2.go
 │   ├── nested-stack-3.go
├── cdk.context.json
├── cdk.json
├── parent-stack-main.go
└──
</code></pre>
<h3 id="heading-go-packages"><strong>Go Packages</strong></h3>
<p>Go is renowned for its simplicity and ease of use, and one of the fundamental ways it achieves this is through its package system. Packages play a pivotal role in structuring and organizing Go code, making it modular, reusable, and maintainable. They provide a mechanism for code encapsulation, collaboration, and code reusability, which are crucial aspects of any programming language.</p>
<p>The primary purpose of Go packages is to create logical and self-contained units of code that can be imported and utilized in other parts of the application. These packages act as containers for related functions, types, variables, and other components that collectively solve a specific problem or provide a certain functionality.</p>
<p>With the aforementioned folder structure in mind, the application could be split into 4 packages:</p>
<ul>
<li><p>main</p>
</li>
<li><p>charts</p>
</li>
<li><p>helper</p>
</li>
<li><p>stacks</p>
</li>
</ul>
<p>More packages could also be used, for example if someone would want to separate the nested stacks further. The above 4 packages would be the minimum recommended.</p>
<h2 id="heading-passing-values-between-stacks"><strong>Passing values between stacks</strong></h2>
<p>Most of the languages supported by the CDK family of frameworks are employing Object Oriented Programming (OOP) concepts. Although not all of them are pure OOP languages, the concepts behind object-oriented software deployment apply: You can split (nested) stacks in classes and you can expose resources and values by making them publicly available in your application.</p>
<p>Go is not an OOP language. How could you share then resources between stacks?</p>
<blockquote>
<p>You can make them available as return values of the stack functions.</p>
</blockquote>
<p>Let's assume you want to create a <code>NetworkingStack</code> that creates and shares the VPC with all the other Nested Stacks. How can you achieve this in Go?</p>
<p>Let's create a <code>networking-stack.go</code> file within the <code>stacks/</code> folder. The contents of the file should looks like this:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> stacks

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"github.com/aws/aws-cdk-go/awscdk/v2"</span>
    <span class="hljs-string">"github.com/aws/aws-cdk-go/awscdk/v2/awsec2"</span>
    <span class="hljs-string">"github.com/aws/constructs-go/constructs/v10"</span>
    <span class="hljs-comment">// https://docs.aws.amazon.com/sdk-for-go/api/aws/</span>
    <span class="hljs-string">"github.com/aws/aws-sdk-go-v2/aws"</span>
)

<span class="hljs-keyword">type</span> NetworkingNestedStackProps <span class="hljs-keyword">struct</span> {
    awscdk.NestedStackProps
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">NetworkingStack</span><span class="hljs-params">(scope constructs.Construct, id <span class="hljs-keyword">string</span>, props *NetworkingNestedStackProps)</span> <span class="hljs-params">(awscdk.NestedStack, awsec2.IVpc)</span></span> {
    <span class="hljs-keyword">var</span> nsprops awscdk.NestedStackProps
    <span class="hljs-keyword">if</span> props != <span class="hljs-literal">nil</span> {
        nsprops = props.NestedStackProps
    }
    stack := awscdk.NewNestedStack(scope, &amp;id, &amp;nsprops)

    vpc := awsec2.NewVpc(stack, aws.String(<span class="hljs-string">"sample-vpc"</span>), 
        &amp;awsec2.VpcProps{
            IpAddresses: awsec2.IpAddresses_Cidr(aws.String(<span class="hljs-string">"10.0.0.0/16"</span>),
            SubnetConfiguration: &amp;[]*awsec2.SubnetConfiguration{
                {
                    CidrMask: aws.Float64(<span class="hljs-number">28</span>),
                    SubnetType: awsec2.SubnetType_PUBLIC,
                    Name: aws.String(<span class="hljs-string">"public"</span>),
                },
                {
                    CidrMask: aws.Float64(<span class="hljs-number">28</span>),
                    SubnetType: awsec2.SubnetType_PRIVATE_WITH_EGRESS,
                    Name: aws.String(<span class="hljs-string">"private"</span>),
                },
            },
        },
    )

    <span class="hljs-keyword">return</span> stack, vpc
}
</code></pre>
<p>As you can see, the <code>NetworkingStack</code> defines to return values. One is of type <code>awscdk.NestedStack</code> and the other of type <code>awsec2.IVpc</code>. Finally, in the bottom, both values are returned with the <code>return stack, vpc</code> statement.</p>
<p>In the <code>main()</code> function then, we can instantiate a new stack that we want to pass the value of the <code>Vpc</code>. We can do that as follows:</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"parent-stack-main/stacks"</span>
         ...
)

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">defer</span> jsii.Close()

    app := awscdk.NewApp(<span class="hljs-literal">nil</span>)

         stack := NewParentStack(app, <span class="hljs-string">"NewParentStack"</span>, &amp;NewParentStackProps{...})

    _, nsvpc := stacks.NetworkingStack(stack, <span class="hljs-string">"NetworkingStack"</span>, <span class="hljs-literal">nil</span>)
    stacks.MyNewNestedStack(stack, <span class="hljs-string">"MyNewNestedStack"</span>, &amp;stacks.MyNewNestedStackProps{
        Vpc: nsvpc,
    })

    app.Synth(<span class="hljs-literal">nil</span>)
}
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>You can find the whole codebase that replicates the solution described in "<a target="_blank" href="https://blog.techinthe.cloud/managing-k8s-infrastructure-and-applications-on-aws-the-imperative-way">Managing K8S Infrastructure and Applications on AWS</a>" rewritten in Go in <a target="_blank" href="https://github.com/kbessas/aws-cdk-and-cdk8s-example-project">GitHub</a>. By comparing the Python and the Go implementation, you can further identify differences and solutions on how you can implement the same functionality but in these different high level programming languages. I hope you find this useful to get you going in the world of AWS CDK using Go.</p>
<p><a target="_blank" href="https://www.freepik.com/free-photo/digital-cloud-data-storage-digital-concept-cloudscape-digital-online-service-global-network-database-backup-computer-infrastructure-technology-solution_37828059.htm"><strong>Main image by svstudioart on Freepik</strong></a></p>
<p>*This article was originally posted <a target="_blank" href="https://xebia.com/blog/managing-complex-infrastructure-using-aws-cdk-and-go/"><strong>here</strong></a>.</p>
]]></content:encoded></item><item><title><![CDATA[Managing multiple environments in the AWS CDK using YAML configuration files]]></title><description><![CDATA[One specific area where the deployment of Infrastructure as Code holds immense importance is in the context of a DTAP (Development, Testing, Acceptance, Production) environment. The DTAP street refers to the progression of software through different ...]]></description><link>https://blog.techinthe.cloud/managing-multiple-environments-in-the-aws-cdk-using-yaml-configuration-files</link><guid isPermaLink="true">https://blog.techinthe.cloud/managing-multiple-environments-in-the-aws-cdk-using-yaml-configuration-files</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws-cdk]]></category><category><![CDATA[Python]]></category><category><![CDATA[Go Language]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Thu, 22 Jun 2023 13:20:58 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1687439918352/358ba985-a140-47ea-9b44-a7371876f8aa.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One specific area where the deployment of Infrastructure as Code holds immense importance is in the context of a DTAP (Development, Testing, Acceptance, Production) environment. The DTAP street refers to the progression of software through different stages, starting from development and testing to final deployment in the production environment. By adopting IaC principles across the DTAP street, organizations can unlock numerous benefits and overcome the challenges associated with manual infrastructure provisioning and management.</p>
<p>From a programming perspective, there are several key technologies and practices involved in effectively managing multiple environments using IaC.</p>
<p>Let's explore them:</p>
<ul>
<li><p>Configuration Management Tools: Configuration management tools such as Ansible, Chef, or Puppet are commonly used in IaC to automate the provisioning and configuration of infrastructure resources across multiple environments. These tools allow you to define infrastructure configurations as code using a declarative or imperative language. By defining and maintaining infrastructure configurations in a centralized manner, you can easily manage and replicate them across different environments.</p>
</li>
<li><p>Infrastructure Provisioning Tools: Infrastructure provisioning tools like Terraform or AWS CloudFormation and the Cloud Development Kit (CDK) enable you to define and provision infrastructure resources programmatically. These tools use domain-specific languages (DSLs) or configuration files to describe the desired state of your infrastructure. With these tools, you can define resources such as virtual machines, networks, storage, load balancers, and more, and deploy them consistently across multiple environments with a single command.</p>
</li>
<li><p>Version Control Systems: Version control systems, such as Git, play a crucial role in managing Infrastructure as Code. By keeping infrastructure configurations and provisioning scripts under version control, you can track changes, collaborate with teammates, and easily roll back to previous versions if necessary. Version control systems also enable you to manage different branches or environments, allowing you to develop and test infrastructure changes in isolation before merging them into production.</p>
</li>
<li><p>Environment Variables and Parameterization: To accommodate different configurations for each environment, it's essential to leverage environment variables and parameterization techniques. These techniques allow you to define reusable infrastructure templates and dynamically inject environment-specific values during the deployment process. For example, you can use variables to specify the number of instances, network configurations, or credentials for each environment, making it easier to manage and scale environments with minimal manual intervention.</p>
</li>
<li><p>Continuous Integration and Deployment (CI/CD) Pipelines: Implementing CI/CD pipelines is crucial for managing multiple environments using IaC. CI/CD pipelines enable the automation of build, test, and deployment processes, ensuring consistent and reliable deployments across environments. By integrating your infrastructure code into the CI/CD pipeline, you can trigger infrastructure updates or deployments automatically whenever changes are made, reducing manual intervention and minimizing errors.</p>
</li>
</ul>
<p>Diving more into the Environment Variables and Parameterization concept while focusing on the AWS CDK, YAML could be used to manage the configuration of multiple environments within a single codebase. But why YAML?</p>
<p>There are a couple of reasons why to use YAML for managing multiple environments within the AWS CDK:</p>
<ol>
<li><p>Simplicity and Readability: YAML provides a simple and human-readable syntax, making it easier for developers, DevOps engineers, and stakeholders to understand and work with the configuration of infrastructure code. The indentation-based structure of YAML makes it intuitive to define resource configurations and relationships, reducing complexity and providing a single configuration pane per environment.</p>
</li>
<li><p>Integration with AWS CDK: The AWS CDK can integrate with YAML files, by sense of parsing the YAML files and storing the information in native data structures that can hold key-value pairs.</p>
</li>
</ol>
<p>Assuming an AWS CDK project in any language, let's consider the following structure for our environments' configuration:</p>
<pre><code class="lang-plaintext">├── config
│   ├── development.yaml
│   ├── test.yaml
│   ├── acceptance.yaml
│   ├── production.yaml
└──
</code></pre>
<p>For AWS, the contents of each file would typically include a minimum of at least the Account ID, Region and in case we are creating VPCs the CIDR block that will be used for each environment.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">account_id:</span> <span class="hljs-string">'123456789'</span>
<span class="hljs-attr">region:</span> <span class="hljs-string">eu-west-1</span>

<span class="hljs-attr">cidr:</span> <span class="hljs-number">10.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span><span class="hljs-string">/16</span>
</code></pre>
<p>Let's see how we can parse the previous information per environment by diving into the details of how to implement this in the AWS CDK using Python and Go.</p>
<h2 id="heading-defining-the-environment"><strong>Defining the environment</strong></h2>
<p>When synthesizing and deploying AWS CDK code, we can pass runtime context. Context values are key-value pairs that can be associated with an app, stack, or construct. They may be supplied to your app from a file (usually either <code>cdk.json</code> or <code>cdk.context.json</code> in your project directory) or on the command line. More information about runtime context for the AWS CDK can be found <a target="_blank" href="https://docs.aws.amazon.com/cdk/v2/guide/context.html">here</a>.</p>
<p>For example you can synthesize our CDK project using the following command:</p>
<pre><code class="lang-bash">cdk synth --context environment=development
</code></pre>
<p>The above will synthesize CloudFormation code while also passing to the CDK app the key-value pair <code>environment: development</code>.</p>
<p>We will use this approach to define the environment we want to synthesize or deploy to. This can be configured for each environment in a potential CI/CD pipeline that will be used to deploy your Infrastructure.</p>
<h2 id="heading-parsing-yaml-configuration-in-the-aws-cdk-for-python"><strong>Parsing YAML configuration in the AWS CDK for Python</strong></h2>
<p>Let's start by creating a configuration parser. For this we will create a <code>helper/config.py</code> file and create a Config class. An example implementation of such class can be seen below.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> yaml
<span class="hljs-keyword">from</span> yaml.loader <span class="hljs-keyword">import</span> SafeLoader

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Config</span>:</span>

    _environment = <span class="hljs-string">'development'</span>
    data = []

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, environment</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        self._environment = environment
        self.load()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load</span>(<span class="hljs-params">self</span>) -&gt; dict:</span>
        <span class="hljs-keyword">with</span> open(<span class="hljs-string">f'config/<span class="hljs-subst">{self._environment}</span>.yaml'</span>) <span class="hljs-keyword">as</span> f:
            self.data = yaml.load(f, Loader=SafeLoader)
        <span class="hljs-keyword">return</span> self.data

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get</span>(<span class="hljs-params">self, key</span>):</span>
        <span class="hljs-keyword">return</span> self.data[key]
</code></pre>
<p>By leveraging the context we discussed earlier, we can then instantiate our CDK stack in the <a target="_blank" href="http://app.py"><code>app.py</code></a> as follows.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> helper <span class="hljs-keyword">import</span> config

conf = config.Config(app.node.try_get_context(<span class="hljs-string">'environment'</span>))
stack = NameCdkStack(app, <span class="hljs-string">"NameCdkStack"</span>,
    env=cdk.Environment(account=conf.get(<span class="hljs-string">'account_id'</span>), region=conf.get(<span class="hljs-string">'region'</span>)),
)
</code></pre>
<p>Similar to the above we can parse all other values that we want to store in the configuration, including the CIDR block.</p>
<h2 id="heading-parsing-yaml-configuration-in-the-aws-cdk-for-go"><strong>Parsing YAML configuration in the AWS CDK for Go</strong></h2>
<p>Similarly to the Python example, we will create a Config function, our configuration parser. For this we will create a <code>helper/config.go</code> file and create there our Config function. An example implementation of such class can be seen below.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> helper

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"gopkg.in/yaml.v3"</span>
)

<span class="hljs-keyword">type</span> conf <span class="hljs-keyword">struct</span> {
    AccountID <span class="hljs-keyword">string</span> yaml:<span class="hljs-string">"account_id"</span>
    Region    <span class="hljs-keyword">string</span> yaml:<span class="hljs-string">"region"</span>
    CIDR      <span class="hljs-keyword">string</span> yaml:<span class="hljs-string">"cidr"</span>
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Config</span><span class="hljs-params">(yamlFile []<span class="hljs-keyword">byte</span>)</span> <span class="hljs-title">conf</span></span> {
    <span class="hljs-keyword">var</span> c conf
    yaml.Unmarshal(yamlFile, &amp;c)

    <span class="hljs-keyword">return</span> c
}
</code></pre>
<p>By leveraging the context we discussed earlier, we can then define our CDK stack in the <code>name-cdk.go</code> as follows.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-keyword">import</span> (
    <span class="hljs-string">"io/ioutil"</span>
    <span class="hljs-string">"name-cdk/helper"</span>
    <span class="hljs-string">"log"</span>
    <span class="hljs-string">"reflect"</span>

    <span class="hljs-string">"github.com/aws/aws-cdk-go/awscdk/v2"</span>
    <span class="hljs-string">"github.com/aws/constructs-go/constructs/v10"</span>
    <span class="hljs-string">"github.com/aws/jsii-runtime-go"</span>
)

...

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    <span class="hljs-keyword">defer</span> jsii.Close()

    app := awscdk.NewApp(<span class="hljs-literal">nil</span>)
    <span class="hljs-comment">// get environment from context</span>
    envName := app.Node().GetContext(jsii.String(<span class="hljs-string">"environment"</span>))

    NameStack(app, <span class="hljs-string">"NameStack"</span>, &amp;NameStackProps{
        awscdk.StackProps{
            Env: env(reflect.ValueOf(envName).String()),
        },
    })

    app.Synth(<span class="hljs-literal">nil</span>)
}

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">env</span><span class="hljs-params">(environment <span class="hljs-keyword">string</span>)</span> *<span class="hljs-title">awscdk</span>.<span class="hljs-title">Environment</span></span> {
    <span class="hljs-keyword">return</span> &amp;awscdk.Environment{
        Account: jsii.String(config.AccountID),
        Region:  jsii.String(config.Region),
    }
}
</code></pre>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Using YAML can simplify a lot common configuration tasks that need to be done in your AWS CDK codebase without the need to touch the code while at the same time maintaining all the configuration within the same repository in a convenient format. You can use the code snippets shown above to get started within your implementation of the AWS CDK.</p>
<p><a target="_blank" href="https://www.freepik.com/free-vector/developers-using-laptop-smartphone-working-with-cloud-data-illustration_10780413.htm#query=configuration%20cloud&amp;position=2&amp;from_view=search&amp;track=location_fest_v1">Image by vectorjuice</a> on Freepik.</p>
<p>*This article was originally posted <a target="_blank" href="https://xebia.com/blog/managing-multiple-environments-in-the-aws-cdk-using-yaml-configuration-files/">here</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Managing K8S Infrastructure and Applications on AWS: The Imperative Way]]></title><description><![CDATA[This article has been written as a result of a talk I have given recently within the knowledge exchange (XKE) sessions at Xebia in the Netherlands. The question quite simple:

How can we manage K8s infrastructure and applications using one codebase a...]]></description><link>https://blog.techinthe.cloud/managing-k8s-infrastructure-and-applications-on-aws-the-imperative-way</link><guid isPermaLink="true">https://blog.techinthe.cloud/managing-k8s-infrastructure-and-applications-on-aws-the-imperative-way</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws-cdk]]></category><category><![CDATA[cdk8s]]></category><category><![CDATA[k8s]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Tue, 02 May 2023 11:53:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1683027399400/e6ad4904-512d-4180-8fd0-9e79a9c2cd13.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This article has been written as a result of a talk I have given recently within the <a target="_blank" href="https://xke.xebia.com/">knowledge exchange (XKE)</a> sessions at Xebia in the Netherlands. The question quite simple:</p>
<blockquote>
<p>How can we manage K8s infrastructure and applications using one codebase and high level programming languages?</p>
</blockquote>
<p>In the coming paragraphs, we will identify how we can write Infrastructure as Code (IaC) as well as the K8s workload definition for an application that will be deployed on AWS. We will combine the power of AWS CDK and cdk8s in one single codebase to deploy our infrastructure and application.</p>
<h1 id="heading-declarative-vs-imperative-approach-for-iac"><strong>Declarative vs Imperative approach for IaC</strong></h1>
<p>Before we proceed further, let’s first identify the various ways you can write infrastructure as code and the major differences between the imperative and declarative way of working.</p>
<p>Declarative and Imperative approach for programming are two different concepts of developing and delivering code. We will take a closer look at:</p>
<ul>
<li><p>Main differences between the two approaches, only focusing on IaC.</p>
</li>
<li><p>Are we really doing it right?</p>
</li>
<li><p>Dive in the specific case of AWS and see the strengths of Terraform over AWS CDK and vice versa.</p>
</li>
</ul>
<p>There are various tools one can use to write IaC. To name a few well known options:</p>
<ul>
<li><p>YAML</p>
</li>
<li><p>Crossplane</p>
</li>
<li><p>pulumi</p>
</li>
<li><p>Terraform</p>
</li>
<li><p>AWS CDK</p>
</li>
</ul>
<p>So what is the difference between the declarative and the imperative approach and how do the above options fit in?</p>
<p><strong>Declarative approach</strong></p>
<p>The declarative approach focuses on the “what” of the infrastructure. With a declarative approach, you define the desired end-state of the infrastructure without specifying how to get there. This means that you only need to specify what resources you want to create, configure, or delete. Declarative IaC tools include languages like YAML, JSON, and HCL.</p>
<p><strong>Imperative approach</strong></p>
<p>Focuses on the “how” of the infrastructure. With an imperative approach, you write step-by-step instructions for provisioning and configuring resources. This means that you need to define every step required to create and configure the infrastructure. Imperative IaC tools include scripts written in languages like Bash, PowerShell, or Python.</p>
<h2 id="heading-terraform-vs-aws-cdk"><strong>Terraform VS AWS CDK</strong></h2>
<p>Let’s focus for a moment on 2 of the options mentioned above that have most of the markete share in terms of deploying infrastructure in AWS. So what are the differences?</p>
<h3 id="heading-language-and-syntax"><strong>Language and Syntax</strong></h3>
<p>Terraform uses its own declarative configuration language (HCL) that is designed to be cloud-agnostic, while AWS CDK allows you to define infrastructure using familiar programming languages like Python, TypeScript, Java, C#, and Go. This means that with AWS CDK, you can leverage the full power and expressiveness of a programming language to define your infrastructure, whereas with Terraform, you use a dedicated configuration language.</p>
<h3 id="heading-abstraction-level"><strong>Abstraction Level</strong></h3>
<p>Terraform provides a higher level of abstraction, allowing you to define infrastructure resources, providers, and modules in a more abstract and cloud-agnostic way. This means that you can use Terraform to manage resources across multiple cloud providers, not just AWS. AWS CDK is specifically designed for provisioning AWS resources and provides a more AWS-centric approach, with AWS-specific constructs, libraries, and APIs that allow you to define AWS resources in a more native way.</p>
<h3 id="heading-deployment-model"><strong>Deployment Model</strong></h3>
<p>Terraform follows a declarative model, where you define the desired state of your infrastructure and Terraform handles the details of how to achieve that state. Changes to infrastructure are managed by updating the Terraform configuration and applying the changes. AWS CDK, on the other hand, follows an imperative model, where you define the infrastructure using programming code and changes are made by updating the code and redeploying the CDK app. This means that with AWS CDK, you have more flexibility in terms of defining complex logic and dynamic behavior, but it may require additional coding and testing compared to Terraform.</p>
<h3 id="heading-learning-curve-and-familiarity"><strong>Learning Curve and Familiarity</strong></h3>
<p>Terraform’s HCL syntax is designed to be simple and easy to learn, with a configuration-based approach that is familiar to many operations and infrastructure teams. AWS CDK, being a programming-based approach, requires developers to have knowledge and experience with programming languages, which may be an advantage or disadvantage depending on your team’s skill set and preferences.</p>
<h2 id="heading-is-terraform-truly-declarative"><strong>Is Terraform truly declarative?</strong></h2>
<p>The <em>lifecycle</em> meta-argument in Terraform is considered imperative, as it allows you to specify certain lifecycle configuration settings for a resource, which affect how Terraform manages the resource during updates or deletes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683027692875/2631d443-a2c9-41c0-bc5e-bffee28d3a53.jpeg" alt class="image--center mx-auto" /></p>
<p>The <em>provisioner</em> meta-argument in Terraform is considered imperative, as it allows you to define actions that are performed on a resource after it has been created or updated, typically used for configuration management or bootstrapping tasks.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683027730875/4b365bcf-8135-415e-bbe5-a3940b9019e3.jpeg" alt class="image--center mx-auto" /></p>
<h2 id="heading-is-the-aws-cdk-truly-imperative"><strong>Is the AWS CDK truly imperative?</strong></h2>
<p>You can actually use the AWS CDK in such a way that the complete codebase will be declarative by avoiding imperative declarations.</p>
<p>Ini the following example, the definition of the S3 bucket can be considered declarative.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683027768133/5d14e967-9b98-4627-afb2-7c6f114b4fe9.jpeg" alt class="image--center mx-auto" /></p>
<h2 id="heading-terraform-vs-aws-cdk-again"><strong>Terraform VS AWS CDK (again)</strong></h2>
<p>All the above are just a matter of definitions. The choice between Terraform and AWS CDK depends on your specific requirements, preferences, and team’s skill set. Both tools are powerful and widely used in the industry, and they offer different approaches to defining and managing cloud infrastructure as code.</p>
<h1 id="heading-managing-k8s-infra-and-applications-on-aws-with-the-aws-cdk-and-cdk8s"><strong>Managing K8s infra and applications on AWS with the AWS CDK and cdk8s</strong></h1>
<p>You would typically deploy K8s in the following way: – Create infrastructure using IaC or in any other way. – Define your K8s workload (pods, deployments, statefulsets, etc) using Yaml. – Create your images using Docker. – Configure your cluster with kubectl and deploy.</p>
<blockquote>
<p>K8s configuration has always been a declarative paradigm, but then again so has been IaC in its early stages.</p>
</blockquote>
<p>Let’s consider the following challenge. We want to: – Deploy K8s infrastructure on AWS using AWS CDK. – Define K8s workload using cdk8s. – Use a single codebase – Use a single step deployment for the infrastructure and the K8s workload on AWS EKS for all the above.</p>
<p>The above use case does not describe a better or preferred way of working with IaC and K8s workload definitions, rather just showing an alternative way of approaching this topic.</p>
<h2 id="heading-target-infrastructure"><strong>Target infrastructure</strong></h2>
<p>The target infrastructure we will try to deploy can be seen in the following diagram:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683027809900/d6562c26-7e81-49db-8d69-5959093eb37b.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-create-you-aws-cdk-project"><strong>Create you AWS CDK project</strong></h2>
<p>We will be creating our AWS CDK project using python. The intention is to create a “template” project that can be reused when someone wants to get starts on AWS using K8s. The same approach can be taken to create similar “templates” in the other programming languages that are supported by the family of the CDK projects.</p>
<pre><code class="lang-plaintext">cdk init app --language=python
</code></pre>
<p>More information on getting started with the AWS CDK can be found <a target="_blank" href="https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html">here</a>.</p>
<h2 id="heading-define-your-aws-resources"><strong>Define your AWS resources</strong></h2>
<p>As per the design shown above, we need to create the following components in AWS:</p>
<ul>
<li><p>The network infrastructure</p>
</li>
<li><p>An EKS cluster</p>
</li>
</ul>
<h3 id="heading-network"><strong>Network</strong></h3>
<p>For the network, we will eb creating a VPC along with its surrounding resources. We will be using the <code>ec2.Vpc</code> level 2 construct.</p>
<p>Please find the implementation below.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> aws_cdk <span class="hljs-keyword">import</span> (
    NestedStack,
    aws_ec2 <span class="hljs-keyword">as</span> ec2,
)
<span class="hljs-keyword">from</span> constructs <span class="hljs-keyword">import</span> Construct
<span class="hljs-keyword">from</span> helper <span class="hljs-keyword">import</span> config

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NetworkingStack</span>(<span class="hljs-params">NestedStack</span>):</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, scope: Construct, construct_id: str, **kwargs</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        super().__init__(scope, construct_id, **kwargs)

        conf = config.Config(self.node.try_get_context(<span class="hljs-string">'environment'</span>))

        self.vpc = ec2.Vpc(self, <span class="hljs-string">"k8s-sample-vpc"</span>,
            ip_addresses=ec2.IpAddresses.cidr(conf.get(<span class="hljs-string">'cidr'</span>)),
            subnet_configuration=[
                ec2.SubnetConfiguration(
                    name = <span class="hljs-string">'public'</span>,
                    subnet_type = ec2.SubnetType.PUBLIC,
                    cidr_mask = <span class="hljs-number">28</span>
                ),
                ec2.SubnetConfiguration(
                    name = <span class="hljs-string">'eks'</span>,
                    subnet_type = ec2.SubnetType.PRIVATE_WITH_EGRESS,
                    cidr_mask = <span class="hljs-number">26</span>
                )
            ],
        )
</code></pre>
<h3 id="heading-eks-cluster"><strong>EKS cluster</strong></h3>
<p>For the EKS cluster, we will be using the <code>eks.Cluster</code> level 2 construct.</p>
<p>Please find the implementation below.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> aws_cdk <span class="hljs-keyword">import</span> (
    NestedStack,
    aws_eks <span class="hljs-keyword">as</span> eks,
    aws_ec2 <span class="hljs-keyword">as</span> ec2,
    aws_iam <span class="hljs-keyword">as</span> iam
)
<span class="hljs-keyword">from</span> constructs <span class="hljs-keyword">import</span> Construct
<span class="hljs-keyword">from</span> helper <span class="hljs-keyword">import</span> config
<span class="hljs-keyword">from</span> aws_cdk.lambda_layer_kubectl_v25 <span class="hljs-keyword">import</span> KubectlV25Layer

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EKSStack</span>(<span class="hljs-params">NestedStack</span>):</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, scope: Construct, construct_id: str, vpc: ec2.IVpc, **kwargs</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        super().__init__(scope, construct_id, **kwargs)

        conf = config.Config(self.node.try_get_context(<span class="hljs-string">'environment'</span>))

        self.cluster = eks.Cluster(
            self, <span class="hljs-string">'k8s-sample-cluster'</span>,
            version=eks.KubernetesVersion.V1_25,
            kubectl_layer=KubectlV25Layer(self, <span class="hljs-string">"kubectl"</span>),
            alb_controller=eks.AlbControllerOptions(
                version=eks.AlbControllerVersion.V2_4_1
            ),
            default_capacity=<span class="hljs-number">0</span>,
            vpc=vpc,
            vpc_subnets=[
                ec2.SubnetSelection(
                    subnet_group_name=<span class="hljs-string">'eks'</span>
                )
            ]
        )

        self.cluster.add_nodegroup_capacity(
            <span class="hljs-string">'eks-nodegroup'</span>,
            instance_types=[ec2.InstanceType(<span class="hljs-string">'t3.large'</span>)]
        )

        <span class="hljs-comment"># importing an existing user</span>
        admin_user = iam.User.from_user_arn(
            self, <span class="hljs-string">'imported_user'</span>,
            user_arn=<span class="hljs-string">'arn:aws:iam::970059968789:user/iam_user'</span> <span class="hljs-comment"># change me</span>
        )
        self.cluster.aws_auth.add_user_mapping(admin_user, groups=[<span class="hljs-string">"system:masters"</span>])
</code></pre>
<p>The level 2 construct for creating an EKS cluster creates a few important resources for the integration with cdk8s. Namely, 2 lambda functions are deployed together with the cluster:</p>
<ul>
<li><p>KubectlHandler is a Lambda function for invoking kubectl commands on the cluster.</p>
</li>
<li><p>ClusterHandler is a Lambda function for interacting with EKS API to manage the cluster lifecycle.</p>
</li>
</ul>
<p>See below for the architectural design of the <code>eks.Cluster</code> level 2 construct.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1683027921242/6c5f86c4-e3f4-442a-8059-1c679ddcf4f6.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-integrating-cdk8s-into-the-aws-cdk-project"><strong>Integrating cdk8s into the AWS CDK project</strong></h2>
<p>In order to start using cdk8s, we need to perform the following changes in the AWS CDK project.</p>
<ul>
<li><p>In the <code>requirements.txt</code>, we need to configure the following 2 libraries:</p>
<ul>
<li><p><code>cdk8s</code></p>
</li>
<li><p><code>cdk8s-plus-25</code> <sup> 1</sup></p>
</li>
</ul>
</li>
<li><p>Create a folder (e.g. <code>k8s_full_stack_charts</code>) on the root level of the project that will hold you cdk8s charts. Create your chars within that folder as classes that inherit from the <code>cdk8s.Chart</code> class.</p>
</li>
</ul>
<p>Example chart used in this project:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> cdk8s <span class="hljs-keyword">as</span> cdk8s
<span class="hljs-keyword">import</span> cdk8s_plus_25 <span class="hljs-keyword">as</span> kplus

<span class="hljs-keyword">from</span> constructs <span class="hljs-keyword">import</span> Construct

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SampleChart</span>(<span class="hljs-params">cdk8s.Chart</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, scope: Construct, id: str</span>):</span>
        super().__init__(scope, id)

        nginx_deployment = kplus.Deployment(
            self, <span class="hljs-string">'sampleDeployment'</span>,
            replicas=<span class="hljs-number">1</span>,
            containers=[
                kplus.ContainerProps(
                    image=<span class="hljs-string">'nginx:mainline-alpine'</span>,
                    port=<span class="hljs-number">80</span>,
                    security_context=kplus.ContainerSecurityContextProps(
                        ensure_non_root=<span class="hljs-literal">False</span>,
                        read_only_root_filesystem=<span class="hljs-literal">False</span>
                    )
                )
            ],
            security_context=kplus.PodSecurityContextProps(
                ensure_non_root=<span class="hljs-literal">False</span>
            )
        )

        nginx_deployment.expose_via_service(
            service_type=kplus.ServiceType.LOAD_BALANCER
        )
</code></pre>
<ul>
<li>Use the <code>add_cdk8s_chart</code> of the <code>eks.Cluster</code> class to deploy the chart on the EKS Cluster. The deployment will use the <code>KubectlHandler</code> lambda function for executing the relevant kubectl commands.</li>
</ul>
<p>Example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> aws_cdk <span class="hljs-keyword">import</span> (
    NestedStack,
    aws_eks <span class="hljs-keyword">as</span> eks
)
<span class="hljs-keyword">import</span> cdk8s <span class="hljs-keyword">as</span> cdk8s
<span class="hljs-keyword">from</span> constructs <span class="hljs-keyword">import</span> Construct

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EKSApplicationStack</span>(<span class="hljs-params">NestedStack</span>):</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, scope: Construct, construct_id: str, cluster: eks.ICluster, chart: cdk8s.Chart, **kwargs</span>) -&gt; <span class="hljs-keyword">None</span>:</span>
        super().__init__(scope, construct_id, **kwargs)

        cluster.add_cdk8s_chart(
            <span class="hljs-string">'sample-chart'</span>,
            chart,
            ingress_alb=<span class="hljs-literal">True</span>,
            ingress_alb_scheme=eks.AlbScheme.INTERNET_FACING,
            prune=<span class="hljs-literal">True</span>
        )
</code></pre>
<h1 id="heading-final-thoughts"><strong>Final thoughts</strong></h1>
<p>This way of deploying K8s clusters together with the workload can be really useful in ephemeral clusters. It could also be useful for teams that are proficient with high level programming languages to bundle infrastructure and workloads together using the same high level programming language of their choice.</p>
<p>You can find the complete solution for everything discussed above in <a target="_blank" href="https://github.com/kbessas/aws-cdk-and-cdk8s-example-project">GitHub</a>. You can use it as a started template for deploying K8s clusters on AWS together with managing the application in one repository. Next steps would include adding extra templates in the aforementioned repository in the other languages supported by the CDK frameworks family.</p>
<p><a target="_blank" href="https://www.freepik.com/free-photo/digital-cloud-data-storage-digital-concept-cloudscape-digital-online-service-global-network-database-backup-computer-infrastructure-technology-solution_37828059.htm">Main image by svstudioart on Freepik</a></p>
<p>[1]: The name/version of this library depends on the K8s version used for the EKS Cluster. In this case we are using K8s version <code>1.25</code>.</p>
<p>*This article was originally posted <a target="_blank" href="https://xebia.com/blog/managing-k8s-infrastructure-and-applications-on-aws/"><strong>here</strong></a>.</p>
]]></content:encoded></item><item><title><![CDATA[Benchmark series: Amazon MemoryDB and how it stands compared to Amazon ElastiCache for Redis]]></title><description><![CDATA[Until recently, Amazon Web Services (AWS) offered a collection of 10 Database Services. With the addition of Amazon MemoryDB, it now offers 11, resulting in more than 15 Database Engines that users can choose from. Amazon MemoryDB for Redis is a Redi...]]></description><link>https://blog.techinthe.cloud/benchmark-series-amazon-memorydb-and-how-it-stands-compared-to-amazon-elasticache-for-redis</link><guid isPermaLink="true">https://blog.techinthe.cloud/benchmark-series-amazon-memorydb-and-how-it-stands-compared-to-amazon-elasticache-for-redis</guid><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Thu, 02 Sep 2021 13:39:16 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1681306322298/dd458f46-f23c-45ee-b079-88b632b1f360.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Until recently, Amazon Web Services (AWS) offered a collection of 10 Database Services. With the addition of Amazon MemoryDB, it now offers 11, resulting in more than 15 Database Engines that users can choose from. Amazon MemoryDB for Redis is a Redis-compatible, durable, in-memory database service that delivers ultra-fast performance for modern, microservices applications. It is based in part on the open source Redis platform, but adds durability and persistence. AWS positions this as targeted for customers who require a full-blown database service rather than a cache for Redis, based on the assumption that the use cases will be quite different. It allows developers to build applications using the same Redis data structures, APIs, and commands they are familiar with. Furthermore, they get access to advanced features such as built-in replication, the least recently used (LRU) eviction, transactions, and automatic partitioning.</p>
<p>On the other hand, AWS ElastiCache for Redis offers a fully managed platform that makes it easy to deploy, manage, and scale a high performance distributed in-memory data store cluster. It is fully compatible with the usual Redis data structures, APIs, and clients, allowing your existing applications that already use Redis to start using ElastiCache without any code changes. It supports both Redis cluster and non-cluster modes, providing enhanced high availability and reliability, with automatic failover scenarios across availability zones.</p>
<h1 id="heading-getting-started">Getting Started</h1>
<p>Upon release, MemoryDB became available in US East (N. Virginia), EU (Ireland), Asia Pacific (Mumbai) and South America (Sao Paulo). MemoryDB clusters can be created using the AWS Management Console, AWS Command Line Interface (CLI), or AWS SDKs. CloudFormation support did not come out of the box with MemoryDB unlike other recent service releases from AWS. This means that we will have to wait before we can deploy MemoryDB clusters with CloudFormation and the AWS CDK.</p>
<p>There are several screenshot walkthrough guides out there to get you through setting up a MemoryDB cluster in the console. Below you can find a CLI command for getting you up and running quickly with a Cluster.</p>
<pre><code class="lang-plaintext">aws memorydb create-cluster \
  --cluster-name memorydb-test \
  --node-type db.r6g.large \
  --acl-name open-access \
  --subnet-group-name memorydb-test-subnet-group \
  --security-group-ids &lt;memorydb-test-security-group-id&gt;
</code></pre>
<p>A few assumptions:</p>
<ul>
<li><p>memorydb-test-subnet-group refers to a MemoryDB subnet group created with the <code>aws memorydb create-subnet-group</code> command.</p>
</li>
<li><p>memorydb-test-security-group-id refers to a pre-existing Security Group ID.</p>
</li>
</ul>
<h1 id="heading-performance">Performance</h1>
<p>The first questions that popped in my mind when Amazon MemoryDB was released was related to performance. More specifically, how does Amazon MemoryDB for Redis compare with Amazon ElastiCache for Redis. Can you get the same performance out of the more robust implementation of Redis that was encapsulated around MemoryDB?</p>
<p>In order to give an answer to the above question, the following experiment came to life:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681306420560/22611096-9f60-44e2-abdc-52d40120aa31.png" alt class="image--center mx-auto" /></p>
<p>The <a target="_blank" href="https://github.com/RedisLabs/memtier_benchmark">memtier benchmark</a> tool was used within EC2 to test the performance of both ElastiCache and MemoryDB. For reference, version 1.3.0 was used.</p>
<p>In the table below you can find the various configurations that were used for the experiment.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>EC2 instance</td><td>ElastiCache</td><td>MemoryDB</td></tr>
</thead>
<tbody>
<tr>
<td>m5.xlarge</td><td>r6g.large</td><td>r6g.large</td></tr>
<tr>
<td>m5.xlarge</td><td>r6g.2xlarge</td><td>r6g.2xlarge</td></tr>
<tr>
<td>m5.xlarge</td><td>r6g.8xlarge</td><td>r6g.8xlarge</td></tr>
</tbody>
</table>
</div><p>memtier benchmark was configured as follows:</p>
<ul>
<li><p>A 50/50 Set to Get ratio</p>
</li>
<li><p>Each object has random data in the value</p>
</li>
</ul>
<p>For comparison purposes exactly the same configuration was used for ElastiCache and for MemoryDB.</p>
<p>You can find the raw data from the test <a target="_blank" href="https://github.com/kbessas/elasticache_memorydb_benchmark/blob/main/benchmark_data.csv">here</a>.</p>
<h2 id="heading-throughput">Throughput</h2>
<p>In the next plot you can see the throughput performance of the combined Sets and Gets, also refered to as Total Throughput. You can see the results across the 3 different instance types that were used for ElastiCache and for MemoryDB.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681306527106/b91f4533-bc6f-4b2d-b903-6f054819e86b.png" alt class="image--center mx-auto" /></p>
<p>From the results it is quite obvious that MemoryDB can deliver less total throughput than ElastiCache across the same instance types. We can also see that when replication is enabled across multiple Availability Zones (AZs) the performance drops even within the same service type. Final remark for this graph is that, taking into consideration the configuration used for the memtier benchmark, performance seems to flatline after the r6g.2xlarge for ElastiCache, comethign that cannot be said for MemoryDB that seems to have increasing performance as we move to the r6g.8xlarge.</p>
<p>Looking at the performance of Sets and Gets separetely, we end up with the followin plots for the throughput, one for the 1 node situation and one with a replication set with 3 nodes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681306554763/e060b614-b4a3-4855-ad5e-cf1c7d2b3f00.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681306573581/aca0fbd8-26f4-40a4-af8f-fb0c8e3f57f1.png" alt class="image--center mx-auto" /></p>
<p>Without surprise, looking deeper into the Sets and Gets, we get the same remarks as for the Total Throughput. MemoryDB, in that regard, delivers less performance compared to ElasticSearch. The gap seems to be even greater when multiple replicas are used for the shards.</p>
<h2 id="heading-latency">Latency</h2>
<p>In the following plot you can see the latency performance of the combined Sets and Gets, also refered to as Total Latency.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681306634998/410889f9-a1ed-4159-be04-844ca0fe5188.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681306655688/d427c613-34f0-4d65-bb93-6c7ea5f9b6cc.png" alt class="image--center mx-auto" /></p>
<p>MemoryDB is exhibiting considerable latency, at least when it comes to the benchmarking execution set. Only when we are increasing the underlying computing capcity considerably we get results equivalent to ElastiCache. On the hand, ElastiCache seems to be consistent as we go through the different instance types when it comes to latency. Increasing the number of replicas from 0 to 2, the performance increase is less when switching to the r6g.2xlarge from the r6g.large. The above statement is true only for the 99 and 99.9 percentiles.</p>
<p>Below you can see the results for the 1 node scenario split over the Sets and Gets.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681306679787/cc884670-d2f4-420e-8061-716e2994f37e.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>It is quite evident that the extra durability of the implementation of Amazon MemoryDB comes at cost of performance that is available with Amazon ElastiCache. Although the results are affected by the configuration that was selected for the benchmarking tool, I believe that they are a good indicator for the expectations we can have in terms of performance from the two services. This means that the two services are different in their offerings and will remain available in the long run and they have distinct use cases.</p>
]]></content:encoded></item><item><title><![CDATA[Bring your own IPs to the AWS Cloud - Design Considerations]]></title><description><![CDATA[Most customers do not care about the public IPs that are used to expose their solutions to the internet. There are cases where static IPs (Elastic IPs or EIPs) are important, for example when whitelisting IPs to third parties, but not the IP itself. ...]]></description><link>https://blog.techinthe.cloud/bring-your-own-ips-to-the-aws-cloud-design-considerations</link><guid isPermaLink="true">https://blog.techinthe.cloud/bring-your-own-ips-to-the-aws-cloud-design-considerations</guid><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Thu, 18 Mar 2021 14:28:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1681305893172/14018e69-8479-4e8f-be2d-efd0eb30c158.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most customers do not care about the public IPs that are used to expose their solutions to the internet. There are cases where static IPs (Elastic IPs or EIPs) are important, for example when whitelisting IPs to third parties, but not the IP itself. There are some cases nevertheless, that the range of IPs is important.</p>
<p>IP reputation and whitelisting for large scale solutions that have been live for a long time could be a challenge to move away from when considering migrating the underlying infrastructure on AWS.</p>
<p>In this blog, we are not going to discuss the technical process of preparing, provisioning and advertizing IP ranges in AWS. Rather, I want to focus on important design considerations that one needs to make.</p>
<h1 id="heading-limitations">Limitations</h1>
<p>Before we move on, I would like to consider some important limitations that we need to be aware of.</p>
<ol>
<li><p>The most specific prefix ones can bring via Bring Your Own IP (BYOIP) is /24.</p>
</li>
<li><p>You can’t use the IP addresses that you bring to AWS for one AWS service with another service.</p>
</li>
<li><p>You cannot share your IP address range with other accounts using AWS Resource Access Manager (AWS RAM).</p>
</li>
</ol>
<p>Looking at the above, and relating the limitations to actual solutions on AWS, the most specific prefix limitations mean that even if you only need a few EIPs for NAT Gateways, you still need to bring a complete /24.</p>
<p>Furthermore, if you need to use BYOIP with Amazon EC2 as well as with the AWS Global Accelerator, you need to bring a minimum of two /24 blocks, one for each service. After you bring an address range to AWS, it appears in the AWS account as an address pool. When you create an accelerator, you can assign one IP address from your range to it. Global Accelerator assigns a second static IP address from an Amazon IP address range. You need to bring two IP address ranges to AWS if you want both IPs to come from your ranges for your accelerator. This requirement is in place because Global Accelerator assigns each address range to a different network zone, for high availability. This means two /24 blocks are needed just for the AWS Global Accelerator for assigning 2 IPs from your range to it.</p>
<p>Last but not least, the limitation of sharing IP ranges with no other AWS accounts leads to some interesting design patterns for your multi-account AWS solution.</p>
<h1 id="heading-design-considerations">Design Considerations</h1>
<p>As per the AWS Well-Architected Framework, account-level separation is strongly recommended for isolating production workloads from development or test workloads. The isolation could go one step forward, with requirements to isolate production workloads, for example due to compliance requirements. It is a good practice to set up multiple accounts as your workloads grow in size and complexity. For reference, a few of the benefits are:</p>
<ul>
<li><p>Opportunity for rapid innovation;</p>
</li>
<li><p>Better insights on billing;</p>
</li>
<li><p>Flexibility defining your security controls;</p>
</li>
<li><p>Convenient adaptation to business processes and requirements.</p>
</li>
</ul>
<p>Bellow, we are proposing a pattern that will help you design your solution around the aformentioned limitations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681306062535/fa7264da-49b2-499b-83a3-9f2002e7ee52.png" alt class="image--center mx-auto" /></p>
<p>In the above design you can see how you can deploy isolated VPCs in various accounts, with all internet traffic routed through a Transit Gateway in a centralized network account. The network account would be the account that holds all the provisioned BYOIP address ranges, with all the NAT gateways having EIPs from that pool.</p>
<p>Moreover, you can see how you can provision Application Load Balancers (ALBs) that leverage the AWS Global Accelerator. As you can see, two more BYOIP address ranges are needed for the Global Accelerator, reaching a total of three ranges required in this simplified example.</p>
<p>By sharing the private subnets using AWS RAM with the network account, it is then possible to create target groups for the ALBs that can have static routes to instances that live within the other accounts. Unfortunately this will not work for Auto Scaling Groups (ASGs) as instance registration to target groups across accounts is not possible. A custom solution using AWS Lambda could solve this limitation.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>BYOIP would fit under more advanced network topics and is only part of a handful (relatively) of implementations on AWS. Scarcity of information on this topic requires that best practices are leveraged by implementations that require similar design choices. I hope the above will give you a head start when tackling the BYOIP topic for your projects for the first time.</p>
]]></content:encoded></item><item><title><![CDATA[Deploying a Transit Gateway that integrates with a DX connection on AWS with the CDK]]></title><description><![CDATA[AWS released the Transit Gateway (TGW) back in 2018. It provided a breakthrough in enabling customers to connect Amazon Virtual Private Clouds (VPCs) and their on-premises networks using a single gateway. On its own, the TGW is a really powerful serv...]]></description><link>https://blog.techinthe.cloud/deploying-a-transit-gateway-that-integrates-with-a-dx-connection-on-aws-with-the-cdk</link><guid isPermaLink="true">https://blog.techinthe.cloud/deploying-a-transit-gateway-that-integrates-with-a-dx-connection-on-aws-with-the-cdk</guid><category><![CDATA[AWS]]></category><category><![CDATA[aws-cdk]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Mon, 18 Jan 2021 14:18:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1681305550364/a0a819eb-e910-4f8f-9415-439ce5505c3c.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AWS released the Transit Gateway (TGW) back in 2018. It provided a breakthrough in enabling customers to connect Amazon Virtual Private Clouds (VPCs) and their on-premises networks using a single gateway. On its own, the TGW is a really powerful service but when paired with other resources like the Direct Connect (DX), some limitations start to appear.</p>
<p>Those limitations were discussed extensively in the article with title <a target="_blank" href="https://blog.techinthe.cloud/aws-transit-gateway-for-connecting-to-on-premise-a-thorough-study">AWS Transit Gateway for connecting to on-premise: A thorough study</a>. In this extension to the original article, we will focus on all the limitations currently in place when trying to deploy a fully backed Infrastructure as Code (IaC) solution leveraging CloudFormation, developed in this particular case with the AWS Cloud Development Kit (CDK).</p>
<p>The main driver of this article is the fact that CloudFormation has limited support in resources specific to the DX and the TGW services, and most importantly the integration between the two. Furthermore, we will not focus on all the potential ways to integrate the solution, rather we will on resources required in order to deploy the solution as it was discussed in the article that was mentioned earlier.</p>
<p>With all this in mind, we will focus on the following three topics:</p>
<ul>
<li><p>Required resources</p>
</li>
<li><p>Custom CloudFormation resources with the AWS CDK</p>
</li>
<li><p>Code Reference for the Custom Resources</p>
</li>
<li><p>Extra pointers</p>
</li>
</ul>
<h1 id="heading-required-resources">Required resources</h1>
<p>In principle, some parts of the solution are not deployed with IaC. A good reason for this is resources that require external verification from 3rd parties, or even resources that appear in the destination account as a result of an external process. One such example are estabilishing Hosted DX Connection with networking partners of AWS.</p>
<p>With the assumption that a DX connection has already been establised and is available in the AWS account, the following resources need to be created for a complete solution.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Resource Name</td><td>CloudFormation Resource Type</td></tr>
</thead>
<tbody>
<tr>
<td>directconnect-gateway</td><td>Custom</td></tr>
<tr>
<td>directconnect-gateway-association</td><td>Custom</td></tr>
<tr>
<td>customer-gateway</td><td>Native</td></tr>
<tr>
<td>transit-gateway</td><td>Native</td></tr>
<tr>
<td>resource-share</td><td>Native</td></tr>
<tr>
<td>vpn-connection</td><td>Native</td></tr>
<tr>
<td>transit-gateway-route</td><td>Native</td></tr>
<tr>
<td>transit-virtual-interface</td><td>Custom</td></tr>
<tr>
<td>cloudwatch-alarm</td><td>Native</td></tr>
</tbody>
</table>
</div><h1 id="heading-custom-cloudformation-resources-with-the-aws-cdk">Custom CloudFormation resources with the AWS CDK</h1>
<p>There are several ways to deploy Custom Resouces with the AWS CDK. The CDK itself has a mini-framework for developing custom resources. For more information, you can look in the documentation of the CDK <a target="_blank" href="https://docs.aws.amazon.com/cdk/api/latest/docs/custom-resources-readme.html">here</a>.</p>
<p>The alternative is to define lambda functions for your custom resources and interact with CloudFormation either complete manually, or by leveraging a library that abstracts the calls to CloudFormation. One example is the crhelper library for Python. You can find more information on this <a target="_blank" href="https://aws.amazon.com/blogs/infrastructure-and-automation/aws-cloudformation-custom-resource-creation-with-python-aws-lambda-and-crhelper/">here</a>.</p>
<p>In order to define your custom resources using lambda, you need to perform two actions:</p>
<ol>
<li><p>You need to define and deploy the lambda function that holds the logic for the custom resource.</p>
</li>
<li><p>You need to define the custom resource that will leverage the lambda function that was defined above.</p>
</li>
</ol>
<p>A boilerplate of how you can achieve this with the CDK can be found below.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> aws_cdk <span class="hljs-keyword">import</span> (
    aws_iam <span class="hljs-keyword">as</span> iam,
    aws_lambda <span class="hljs-keyword">as</span> lambda_,
    aws_logs <span class="hljs-keyword">as</span> logs,
    core
)

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DirectConnectTGW</span>():</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, scope</span>)
        <span class="hljs-title">custom_resource_lambda</span> = <span class="hljs-title">lambda_</span>.<span class="hljs-title">Function</span>(<span class="hljs-params">
            scope,
            <span class="hljs-string">'&lt;custom_resource&gt;'</span>,
            code=(<span class="hljs-params">
                lambda_.AssetCode(<span class="hljs-params">
                    os.path.join(<span class="hljs-params">
                        os.path.dirname(<span class="hljs-params">__file__</span>),
                        <span class="hljs-string">'&lt;path_to_source&gt;'</span>
                    </span>)
                </span>)
            </span>),
            handler=<span class="hljs-string">'main.lambda_handler'</span>,
            runtime=lambda_.Runtime.PYTHON_3_7,
            timeout=core.Duration.minutes(<span class="hljs-params"><span class="hljs-number">5</span></span>),
            initial_policy=[
                iam.PolicyStatement(<span class="hljs-params">
                    actions=[
                        <span class="hljs-string">'lambda:AddPermission'</span>,
                        <span class="hljs-string">'lambda:RemovePermission'</span>,
                        <span class="hljs-string">'events:PutRule'</span>,
                        <span class="hljs-string">'events:DeleteRule'</span>,
                        <span class="hljs-string">'events:PutTargets'</span>,
                        <span class="hljs-string">'events:RemoveTargets'</span>
                    ],
                    resources=[
                        <span class="hljs-string">'*'</span>
                    ]
                </span>),
                iam.PolicyStatement(<span class="hljs-params">
                    actions=[
                        <span class="hljs-string">'&lt;policies_specific_to_the_lambda_code&gt;'</span>
                    ],
                    resources=[
                        <span class="hljs-string">'*'</span>
                    ]
                </span>)
            ],
            log_retention=logs.RetentionDays.ONE_YEAR
        </span>)

        <span class="hljs-title">dc_gateway_custom_resource</span> = <span class="hljs-title">core</span>.<span class="hljs-title">CustomResource</span>(<span class="hljs-params">
            scope, <span class="hljs-string">'&lt;custom_resource_id&gt;'</span>,
            service_token=custom_resource_lambda.function_arn,
            properties={
                <span class="hljs-string">'&lt;env_var_name1&gt;'</span>: <span class="hljs-string">'&lt;env_var_value1&gt;'</span>,
                <span class="hljs-string">'&lt;env_var_name2&gt;'</span>: <span class="hljs-string">'&lt;env_var_value2&gt;'</span>
            }
        </span>)</span>
</code></pre>
<h1 id="heading-code-reference-for-the-custom-resources">Code Reference for the Custom Resources</h1>
<p>For the context of this article, the custom resources have been developed using Lambda and the code is utilizing the crhelper library from AWS. As part of this blog, reference lambda functions written in Python are available <a target="_blank" href="https://github.com/kbessas/tgw-reference-custom-resources">here</a>.</p>
<h1 id="heading-extra-pointers">Extra pointers</h1>
<h2 id="heading-custom-metric-for-the-bgp-session-of-the-tvi">Custom Metric for the BGP session of the TVI</h2>
<p>I would like to make a special note in regard to the transit virtual interface and monitoring the BGP session status. Currently, there is no metric available for this. This can be easily achieved by creating a lambda function that will generate a custom metric for you. The following Python snippet showcases a potential way to achieve this.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> boto3
<span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">import</span> dateutil
<span class="hljs-keyword">import</span> os

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">lambda_handler</span>(<span class="hljs-params">event, context</span>):</span>
    region_name = os.environ[<span class="hljs-string">'AWS_REGION'</span>]

    dc = boto3.client(<span class="hljs-string">'directconnect'</span>, region_name=region_name)
    cw = boto3.client(<span class="hljs-string">'cloudwatch'</span>, region_name=region_name)

    virtualInterfaces = dc.describe_virtual_interfaces(
        connectionId=event[<span class="hljs-string">'connectionId'</span>]
    )[<span class="hljs-string">'virtualInterfaces'</span>]

    <span class="hljs-keyword">for</span> vi <span class="hljs-keyword">in</span> virtualInterfaces:
        state = <span class="hljs-literal">None</span>
        <span class="hljs-keyword">if</span> vi[<span class="hljs-string">'virtualInterfaceState'</span>] == <span class="hljs-string">'available'</span>:
            state = <span class="hljs-number">1</span>
        <span class="hljs-keyword">else</span>:
            state = <span class="hljs-number">0</span>

        cw.put_metric_data(
            Namespace=<span class="hljs-string">'AWS/DX'</span>,
            MetricData=[
                {
                    <span class="hljs-string">'MetricName'</span>: <span class="hljs-string">'BGPStatus'</span>,
                    <span class="hljs-string">'Dimensions'</span>: [{
                        <span class="hljs-string">'Name'</span>: <span class="hljs-string">'VirtualInterfaceId'</span>,
                        <span class="hljs-string">'Value'</span>: vi[<span class="hljs-string">'virtualInterfaceId'</span>]
                    }],
                    <span class="hljs-string">'Timestamp'</span>: datetime.datetime.now(dateutil.tz.tzlocal()),
                    <span class="hljs-string">'Value'</span>: state
                }
            ]
        )

    <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span>
Integrating the above <span class="hljs-keyword">in</span> your CDK solution could achieved <span class="hljs-keyword">with</span> something like this:

        <span class="hljs-comment"># Custom Metric for Transit Virtual Interface connection status</span>
        transit_vi_custom_metric_function = lambda_.Function(
            scope,
            <span class="hljs-string">'TransitVirtualInterfaceCustomMetric'</span>,
            code=(
                lambda_.AssetCode(
                    os.path.join(
                        os.path.dirname(__file__),
                        <span class="hljs-string">'transit-virtual-interface-custom-metric'</span>
                    )
                )
            ),
            handler=<span class="hljs-string">'main.lambda_handler'</span>,
            runtime=lambda_.Runtime.PYTHON_3_7,
            timeout=core.Duration.minutes(<span class="hljs-number">1</span>),
            initial_policy=[
                iam.PolicyStatement(
                    actions=[
                        <span class="hljs-string">'cloudwatch:PutMetricData'</span>,
                        <span class="hljs-string">'directconnect:DescribeVirtualInterfaces'</span>
                    ],
                    resources=[
                        <span class="hljs-string">'*'</span>
                    ]
                )
            ],
            log_retention=logs.RetentionDays.ONE_YEAR
        )

        <span class="hljs-comment"># the trigger (event) for the Lambda function</span>
        transit_vi_custom_metric_rule = events.Rule(
            scope, <span class="hljs-string">'TransitVirtualInterfaceCustomMetricRule'</span>,
            schedule=events.Schedule.rate(core.Duration.minutes(<span class="hljs-number">1</span>))
        )
        transit_vi_custom_metric_rule.add_target(
            targets.LambdaFunction(
                handler=transit_vi_custom_metric_function,
                event=events.RuleTargetInput.from_object(
                    {
                        <span class="hljs-string">'connectionId'</span>: &lt;dx_connection_id&gt;
                    }
                )
            )
        )

        bgp_status_state = cloudwatch.Alarm(
            scope,
            <span class="hljs-string">'BGPStatusAlarm'</span>,
            metric=cloudwatch.Metric(
                metric_name=<span class="hljs-string">'BGPStatus'</span>,
                namespace=<span class="hljs-string">'AWS/DX'</span>,
                dimensions={
                    <span class="hljs-string">'VirtualInterfaceId'</span>: &lt;tvi&gt;.get_att_string(
                        <span class="hljs-string">'TransitVirtualInterfaceId'</span>
                    )
                },
                period=core.Duration.minutes(<span class="hljs-number">1</span>),
                statistic=<span class="hljs-string">'Maximum'</span>
            ),
            evaluation_periods=<span class="hljs-number">5</span>,
            threshold=<span class="hljs-number">1</span>,
            alarm_description=(
                <span class="hljs-string">f'Alarm for TVI Connection State'</span>
            ),
            comparison_operator=(
                cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD
            )
        )
</code></pre>
<h2 id="heading-static-routes-for-the-tgw">Static Routes for the TGW</h2>
<p>Deploying static routes within your TGW route table in code can prove benneficial. If you remember from the original article, there is currently a limitation on the number of routes that can be advertised on premise from a DX connection. <strong>As an amendment to the original article</strong>, I should mention here that it is possible to advertize a superset of the actual CIDR blocks behind the TGW over the DX connection. This can be used to tackle in a way the above limitation by creating supersets instead of advertizing the CIDR bock of each VPC.</p>
<p>The problem that arises when you start using supersets of the CIDR blocks, is that if you are using in conjuction with the DX a VPN connection as a failover, the VPN will advertize via automatic propagation the CIDR blocks of all the VPCs behind the TGW. That will result in a deviation in the CIDR blocks advertized on premise via the DX and the VPN. In order to tackle the above issue, one can inject the TGW route table with superset static routes, exatly as they are advertized via the DX connection.</p>
<p>The following lambda function can help you pick up from tour configuration the manually advertized supersets and inject them in your TGW route table.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> boto3
<span class="hljs-keyword">import</span> logging
<span class="hljs-keyword">import</span> os

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">lambda_handler</span>(<span class="hljs-params">event, context</span>):</span>
    logger = logging.getLogger()
    logger.setLevel(logging.INFO)

    region = os.environ[<span class="hljs-string">'AWS_REGION'</span>]

    ec2 = boto3.client(<span class="hljs-string">'ec2'</span>, region_name=region)

    cidr_blocks = event[<span class="hljs-string">'cidr_blocks'</span>]
    tgw_route_table_id = event[<span class="hljs-string">'tgw_route_table_id'</span>]

    <span class="hljs-keyword">for</span> cidr_block <span class="hljs-keyword">in</span> cidr_blocks:
        <span class="hljs-comment"># find all routes that belong in a specific CIDR block or its subnets</span>
        routes = ec2.search_transit_gateway_routes(
            TransitGatewayRouteTableId=tgw_route_table_id,
            Filters=[
                {
                    <span class="hljs-string">'Name'</span>: <span class="hljs-string">'route-search.subnet-of-match'</span>,
                    <span class="hljs-string">'Values'</span>: [
                        cidr_block,
                    ]
                },
                {
                    <span class="hljs-string">'Name'</span>: <span class="hljs-string">'attachment.resource-type'</span>,
                    <span class="hljs-string">'Values'</span>: [
                        <span class="hljs-string">'vpc'</span>,
                    ]
                }
            ]
        )

        <span class="hljs-comment"># array with the CIDR blocks that were identified</span>
        cidr_blocks_for_routes = (
            [d[<span class="hljs-string">'DestinationCidrBlock'</span>] <span class="hljs-keyword">for</span> d <span class="hljs-keyword">in</span> routes[<span class="hljs-string">'Routes'</span>]]
        )

        <span class="hljs-comment"># if a static route does not already exis</span>
        <span class="hljs-keyword">if</span> len(cidr_blocks_for_routes) &gt; <span class="hljs-number">0</span>:
            <span class="hljs-keyword">if</span> cidr_block <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> cidr_blocks_for_routes:
                tgw_attachements = (
                    [d[<span class="hljs-string">'TransitGatewayAttachments'</span>] <span class="hljs-keyword">for</span> d <span class="hljs-keyword">in</span> routes[<span class="hljs-string">'Routes'</span>]]
                )
                tgw_vpc_attachements = (
                    [d <span class="hljs-keyword">for</span> d <span class="hljs-keyword">in</span> tgw_attachements <span class="hljs-keyword">if</span> d[<span class="hljs-number">0</span>][<span class="hljs-string">'ResourceType'</span>] <span class="hljs-keyword">in</span> [<span class="hljs-string">'vpc'</span>]]  <span class="hljs-comment"># noqa: E501</span>
                )
                <span class="hljs-comment"># identify attachment id for VPC</span>
                tgw_attach_id = tgw_vpc_attachements[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>][<span class="hljs-string">'TransitGatewayAttachmentId'</span>]  <span class="hljs-comment"># noqa: E501</span>

                logger.info(<span class="hljs-string">'Creating route for: %s'</span> % str(cidr_block))

                ec2.create_transit_gateway_route(
                    DestinationCidrBlock=cidr_block,
                    TransitGatewayRouteTableId=tgw_route_table_id,
                    TransitGatewayAttachmentId=tgw_attach_id
                )

    <span class="hljs-comment">####################</span>
    <span class="hljs-comment"># start - cleanup</span>
    <span class="hljs-comment"># find all static routes to vpcs</span>
    all_static_routes = ec2.search_transit_gateway_routes(
        TransitGatewayRouteTableId=tgw_route_table_id,
        Filters=[
            {
                <span class="hljs-string">'Name'</span>: <span class="hljs-string">'type'</span>,
                <span class="hljs-string">'Values'</span>: [
                    <span class="hljs-string">'static'</span>,
                ]
            },
            {
                <span class="hljs-string">'Name'</span>: <span class="hljs-string">'attachment.resource-type'</span>,
                <span class="hljs-string">'Values'</span>: [
                    <span class="hljs-string">'vpc'</span>,
                ]
            }
        ]
    )

    <span class="hljs-comment"># array with the CIDR blocks that were identified</span>
    all_cidr_blocks_for_static_routes = (
        [d[<span class="hljs-string">'DestinationCidrBlock'</span>] <span class="hljs-keyword">for</span> d <span class="hljs-keyword">in</span> all_static_routes[<span class="hljs-string">'Routes'</span>]]
    )

    <span class="hljs-keyword">for</span> cidr_block <span class="hljs-keyword">in</span> all_cidr_blocks_for_static_routes:
        <span class="hljs-keyword">if</span> cidr_block <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> cidr_blocks:
            logger.info(<span class="hljs-string">'Deleting route for: %s'</span> % str(cidr_block))
            ec2.delete_transit_gateway_route(
                DestinationCidrBlock=cidr_block,
                TransitGatewayRouteTableId=tgw_route_table_id
            )
    <span class="hljs-comment">####################</span>
    <span class="hljs-comment"># end - cleanup</span>
    <span class="hljs-comment">####################</span>
</code></pre>
<p>All the above can be found <a target="_blank" href="https://github.com/kbessas/tgw-reference-custom-resources">here</a> together with the CloudFormation custom resources.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Using the TGW to connect the on-premise environment to VPCs on AWS could simplify things a lot. Limitations from CloudFormation could complicate the solution as explained above. I do hope the information provided here and the custom resources that have been shared will help you get going. Knowing AWS, these limitations of CloudFormation should one by one be tackled in future announcements, but for now, this is the state of things.</p>
]]></content:encoded></item><item><title><![CDATA[AWS Transit Gateway for connecting to on-premise: A thorough study]]></title><description><![CDATA[AWS released the Transit Gateway (TGW) back in 2018. It provided a breakthrough in enabling customers to connect Amazon Virtual Private Clouds (VPCs) and their on-premises networks using a single gateway. On its own, the TGW is a really powerful serv...]]></description><link>https://blog.techinthe.cloud/aws-transit-gateway-for-connecting-to-on-premise-a-thorough-study</link><guid isPermaLink="true">https://blog.techinthe.cloud/aws-transit-gateway-for-connecting-to-on-premise-a-thorough-study</guid><category><![CDATA[AWS]]></category><dc:creator><![CDATA[Konstantinos Bessas]]></dc:creator><pubDate>Fri, 21 Aug 2020 13:20:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1681299303184/1e825f8f-d3bd-4a81-a52f-eef6e9e59f94.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AWS released the Transit Gateway (TGW) back in 2018. It provided a breakthrough in enabling customers to connect Amazon Virtual Private Clouds (VPCs) and their on-premises networks using a single gateway. On its own, the TGW is a really powerful service but when paired with other resources like the Direct Connect (DX), some limitations start to appear.</p>
<h1 id="heading-example-architecture">Example Architecture</h1>
<p>To simplify things, I provide below a visual representation of an architecture that we will study for its power as well as the limitations that come from it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681299333156/d0b190fc-4100-4df8-bb97-7065803646a0.png" alt class="image--center mx-auto" /></p>
<p>In this example architecture, you see the usage of a TGW to connect the on-premise environment with VPCs that live within different AWS accounts. It also enables those VPCs to talk to each other. The connectivity between on-premise and AWS is facilitated by a DX connection, with a Site-to-Site VPN as a failover.</p>
<h1 id="heading-associated-resources">Associated Resources</h1>
<p>In order to achieve the infrastructural setup that is visualized above, one needs to follow the following steps:</p>
<ol>
<li><p>Request a DX connection of at least 1 Gbps to the relevant AWS Region within the TGW account.</p>
</li>
<li><p>Create a DX Gateway.</p>
</li>
<li><p>Create a TGW.</p>
</li>
<li><p>Create a VPN Customer Gateway and VPN Connections directly to the TGW.</p>
</li>
<li><p>Associate the TGW with the DX Gateway. At this point, the allowed prefixes also need to be advertised to the on-premise network.</p>
</li>
<li><p>Create a Transit Virtual Interface for the DX Connection-Gateway pair.</p>
</li>
<li><p>Share the TGW resource with the relevant AWS Accounts using the AWS Resource Access Manager (RAM) service.</p>
</li>
</ol>
<h1 id="heading-dx-connection-vpn-failover">DX Connection – VPN Failover</h1>
<p>Once you have everything deployed and working, it is easy to test the failover of the DX Connection over to the VPN. At this point, the TGW Route Table should have at least a DX Gateway and a VPN associated with it. In the AWS Console, you can trigger a Failover test under the Transit Virtual Interface by selecting “Bring down BGP”.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681299362730/94bc0f13-dccc-473f-9f6c-fb297505029d.png" alt class="image--center mx-auto" /></p>
<p>By inspecting closely the TGW Route Table, one can then see the preferred route over the DX Gateway switched to the one that targets the VPN connection.</p>
<h1 id="heading-limitations-of-the-described-solution">Limitations of the described solution</h1>
<h2 id="heading-dx-connections">DX Connections</h2>
<p>Transit virtual interfaces are only available over dedicated connections or hosted connections with speeds of 1 Gbps or greater. Transit virtual interfaces are not available for hosted AWS Direct Connect connections with speeds of 500 Mbps and below, also known as a sub-1 Gbps hosted AWS Direct Connect connection.</p>
<h2 id="heading-propagation-of-vpc-cidr-blocks-to-on-premise">Propagation of VPC CIDR blocks to on-premise</h2>
<p>When a new VPC is associated with the TGW, the route table of the TGW is automatically updated. In order to advertise the CIDR block of each VPC to the on-premise network though, that requires a manual action. This is related to the allowed prefixes that were mentioned earlier in around the association of the TGW with the DX Gateway. One needs to explicitly update that list to include the new CIDR block. Furthermore, the exact CIDR block needs to be advertised and not a superset of it. For more information you can check <a target="_blank" href="https://docs.aws.amazon.com/directconnect/latest/UserGuide/allowed-to-prefixes.html">here</a>.</p>
<p>Another limitation related to the propagation of CIDR block to on-premise is the fact that the maximum number of allowed prefixes is capped at 20. This means that you can connect to on-premise a maximum of 20 VPCs. This is a major limitation considering the recommendation from AWS to isolate workloads into different accounts and VPCs as much as possible. It becomes an even bigger problem when DTAP comes in the picture.</p>
<p>The last point can be tackled in 2 ways:</p>
<ol>
<li><p>Follow the DTAP approach also for the TGW implementation and have a Production and a non-Production TGW.<br /> An example architecture of this is shown below.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681299514745/345be3f0-b673-4da3-bd70-98122ef5bb9b.png" alt class="image--center mx-auto" /></p>
</li>
<li><p>Connect up to 3 TGWs to the same DX Gateway.<br /> An example abstracted architecture of this is shown below.</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1681299568908/a23dd79b-54f1-4c94-9370-47e55ccb69fd.png" alt class="image--center mx-auto" /></p>
</li>
</ol>
<p>Both of these solutions are suffering from the same problem; you cannot peer, as of the time of writing this article (August, 2020), TGWs in the same region. The fact that all these TGWs are connected to the same DX Gateway does not create the magic bridge one would hope for. This automatically means that some of your VPCs won’t be able to talk to other VPCs, unless they are associated with the same TGW.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Using the TGW to connect the on-premise environment to VPCs on AWS could simplify things a lot. On the other hand, one needs to carefully plan and execute this solution taking into consideration the growth that is expected for the solution on AWS, in order to avoid hiccups down the road. Knowing AWS, these limitations should one by one be tackled in future announcements, but for now, this is the state of things.</p>
]]></content:encoded></item></channel></rss>