<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>AI Apps and Agents - Microsoft Azure Blog</title>
        <link>https://azure.github.io/Cloud-Native/cnny-2023</link>
        <description>AI Apps and Agents - Microsoft Azure Blog</description>
        <lastBuildDate>Sun, 22 Jan 2023 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Kicking Off 30DaysOfCloudNative!]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/cnny-kickoff</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/cnny-kickoff</guid>
            <pubDate>Sun, 22 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Let's  kick-off Cloud Native New Year with #30DaysOfCloudNative]]></description>
            <content:encoded><![CDATA[
<p>Welcome to the <code>Kick-off Post</code> for #30DaysOfCloudNative - one of the core initiatives within #CloudNativeNewYear! Over the next four weeks, join us as we take you from fundamentals to functional usage of Cloud-native technologies, one blog post at a time! Read on to learn a little bit about this initiative and what you can expect to learn from this journey!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/cnny-kickoff#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>What is Cloud-native New Year? (3 initiatives)</li>
<li>How can I <em>skill up</em> (30 days)</li>
<li>Who is behind this? (Team Contributors)</li>
<li><strong>Exercise</strong>: Take the <a href="https://aka.ms/CNNY/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a>!</li>
<li><strong>Resources</strong>: <a href="https://aka.ms/CNNY/collection" target="_blank" rel="noopener noreferrer">#30DaysOfCloudNative Collection</a>.</li>
</ul>
<hr>
<p><img loading="lazy" alt="Cloud-native New Year" src="https://azure.github.io/Cloud-Native/assets/images/cnny-event-card-df287cbd24f042a3ac51e30b416f458d.png" width="1920" height="1080" class="img_ev3q"></p>
<p>Welcome to <code>Week 01</code> of <a href="https://aka.ms/CNNY" target="_blank" rel="noopener noreferrer"> 🥳 #CloudNativeNewYear </a>! Today, we kick off a full month of content and activities to skill you up on all things Cloud-native on Azure with content, events, and community interactions! Read on to learn about what we have planned!</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="explore-our-initiatives">Explore our initiatives<a href="https://azure.github.io/Cloud-Native/cnny-2023/cnny-kickoff#explore-our-initiatives" class="hash-link" aria-label="Direct link to Explore our initiatives" title="Direct link to Explore our initiatives">​</a></h2>
<p>We have a number of initiatives planned for the month to help you learn and skill up on relevant technologies. Click on the links to visit the relevant pages for each.</p>
<ul>
<li><a href="https://azure.github.io/Cloud-Native/cnny-2023/">#30DaysOfCloudNative</a> - 4 themed weeks of daily articles in a structured roadmap</li>
<li><a href="https://aka.ms/CNNY/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a> - skill up by competing with peers to complete modules</li>
<li><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Ask The Expert</a> - watch the recorded Q&amp;A sessions with Product Engineering teams</li>
</ul>
<p>We'll go into more details about <strong>#30DaysOfCloudNative</strong> in this post - don't forget to <a href="https://azure.github.io/Cloud-Native/cnny-2023/rss.xml" target="_blank" rel="noopener noreferrer">subscribe</a> to the blog to get daily posts delivered directly to your preferred feed reader!</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="register-for-events">Register for events!<a href="https://azure.github.io/Cloud-Native/cnny-2023/cnny-kickoff#register-for-events" class="hash-link" aria-label="Direct link to Register for events!" title="Direct link to Register for events!">​</a></h2>
<p>What are 3 things you can do today, to jumpstart your learning journey?</p>
<ul>
<li><strong>Register</strong> for live Q&amp;A sessions (free, online)<!-- -->
<ul>
<li>Feb 9 - <a href="https://aka.ms/ATE0209/RSVP" target="_blank" rel="noopener noreferrer">Ask The Expert: Azure Kubernetes Service (PDT)</a></li>
<li>Feb 10 - <a href="https://aka.ms/ATE0209/APAC-RSVP" target="_blank" rel="noopener noreferrer">Ask the Expert: Azure Kubernetes Service (SGT)</a></li>
</ul>
</li>
<li><strong>Register</strong> for the <a href="https://aka.ms/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a> - 30 days to complete it!</li>
</ul>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="30daysofcloudnative">#30DaysOfCloudNative<a href="https://azure.github.io/Cloud-Native/cnny-2023/cnny-kickoff#30daysofcloudnative" class="hash-link" aria-label="Direct link to #30DaysOfCloudNative" title="Direct link to #30DaysOfCloudNative">​</a></h2>
<p><a href="https://azure.github.io/Cloud-Native/New-Year/" target="_blank" rel="noopener noreferrer">#30DaysOfCloudNative</a> is a month-long series of daily blog posts grouped into 4 themed weeks - taking you from core concepts to end-to-end solution examples in 30 days. Each article will be short (5-8 mins reading time) and provide exercises and resources to help you reinforce learnings and take next steps.</p>
<p>This series focuses on the <a href="https://azure.microsoft.com/solutions/cloud-native-apps/?WT.mc_id=javascript-99907-ninarasi" target="_blank" rel="noopener noreferrer">Cloud-native On Azure</a> learning journey in <strong>four stages</strong>, each building on the previous week to help you skill up in a beginner-friendly way:</p>
<ul>
<li><strong>Week 1:</strong> Get started with <a href="https://azure.microsoft.com/solutions/cloud-native-apps/?WT.mc_id=javascript-99907-ninarasi" target="_blank" rel="noopener noreferrer">Cloud-native Concepts</a></li>
<li><strong>Week 2:</strong> Build &amp; deploy <a href="https://azure.microsoft.com/solutions/kubernetes-on-azure/?WT.mc_id=javascript-99907-ninarasi" target="_blank" rel="noopener noreferrer">Kubernetes Apps on cloud</a>.</li>
<li><strong>Week 3:</strong> Migrate your applications to <a href="https://azure.microsoft.com/products/kubernetes-service/?WT.mc_id=javascript-99907-ninarasi" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a>.</li>
<li><strong>Week 4:</strong> Go from Code to Containers to Cloud with <a href="https://azure.microsoft.com/solutions/cloud-native-apps/?WT.mc_id=javascript-99907-ninarasi" target="_blank" rel="noopener noreferrer">Cloud-native solutions</a></li>
</ul>
<p><img loading="lazy" alt="Event kickoff slide for #CloudNativeNewYear with speaker profiles and a sketch promoting Kubernetes as the de facto container orchestrator." src="https://azure.github.io/Cloud-Native/assets/images/banner-a11b83bfb13e4ec7dfad48c200c24cf1.png" width="1600" height="672" class="img_ev3q"></p>
<p>We have a tentative weekly-themed roadmap for the topics we hope to cover and will keep this updated as we go with links to actual articles as they get published.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Week 1: FOCUS ON CLOUD-NATIVE FUNDAMENTALS</div><div class="admonitionContent_BuS1"><p>Here's a sneak peek at the week 1 schedule. We'll start with a broad review of cloud-native fundamentals and walkthrough the core concepts of microservices, containers and Kubernetes.</p><ul>
<li><strong>Jan 23</strong>: Learn Core Concepts for Cloud-native</li>
<li><strong>Jan 24</strong>: Container 101</li>
<li><strong>Jan 25</strong>: Adopting Microservices with Kubernetes</li>
<li><strong>Jan 26</strong>: Kubernetes 101</li>
<li><strong>Jan 27</strong>: Exploring your Cloud Native Options</li>
</ul></div></div>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="lets-get-started">Let's Get Started!<a href="https://azure.github.io/Cloud-Native/cnny-2023/cnny-kickoff#lets-get-started" class="hash-link" aria-label="Direct link to Let's Get Started!" title="Direct link to Let's Get Started!">​</a></h2>
<p>Now you know everything! We hope you are as excited as we are to dive into a full month of active learning and doing! Don't forget to <a href="https://azure.github.io/Cloud-Native/cnny-2023/rss.xml?WT.mc_id=javascript-99907-ninarasi" target="_blank" rel="noopener noreferrer">subscribe</a> for updates in your favorite feed reader! <strong>And look out for our first Cloud-native Fundamentals post on January 23rd!</strong></p>
<hr>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[1-1. Cloud-native Fundamentals]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/cloud-native-fundamentals</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/cloud-native-fundamentals</guid>
            <pubDate>Mon, 23 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[The fundamentals of Cloud-native!]]></description>
            <content:encoded><![CDATA[<p>Welcome to <code>Week 1</code> of #CloudNativeNewYear!</p>
<p><img loading="lazy" alt="Cloud-native New Year" src="https://azure.github.io/Cloud-Native/assets/images/cnny-event-card-df287cbd24f042a3ac51e30b416f458d.png" width="1920" height="1080" class="img_ev3q"></p>
<p>You will often hear the term "cloud-native" when discussing modern application development, but even a quick online search will return a huge number of articles, tweets, and web pages with a variety of definitions. So, what does cloud-native actually mean? Also, what makes an application a <em>cloud-native application</em> versus a "regular" application?</p>
<p>Today, we will address these questions and more as we kickstart our learning journey (and our new year!) with an introductory dive into the wonderful world of cloud-native.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/cloud-native-fundamentals#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>What is cloud-native?</li>
<li>What is a cloud-native application?</li>
<li>The benefits of cloud-native</li>
<li>The five pillars of cloud-native</li>
<li><strong>Exercise</strong>: Take the <a href="https://aka.ms/CNNY/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a>!</li>
</ul>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="1-what-is-cloud-native">1. What is cloud-native?<a href="https://azure.github.io/Cloud-Native/cnny-2023/cloud-native-fundamentals#1-what-is-cloud-native" class="hash-link" aria-label="Direct link to 1. What is cloud-native?" title="Direct link to 1. What is cloud-native?">​</a></h2>
<p>The term "cloud-native" can seem pretty self-evident (yes, hello, native to the cloud?), and in a way, it is.
While there are lots of definitions of cloud-native floating around, at it's core, cloud-native simply refers to a modern approach to building software that takes advantage of cloud services and environments. This includes using cloud-native technologies, such as containers, microservices, and serverless, and following best practices for deploying, scaling, and managing applications in a cloud environment.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span><strong>Official definition</strong> from the <a href="https://www.cncf.io/" target="_blank" rel="noopener noreferrer">Cloud Native Computing Foundation</a>:</div><div class="admonitionContent_BuS1"><p><em>Cloud-native technologies empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds. Containers, service meshes, microservices, immutable infrastructure, and declarative APIs exemplify this approach.</em></p><p><em>These techniques enable loosely coupled systems that are resilient, manageable, and observable. Combined with robust automation, they allow engineers to make high-impact changes frequently and predictably with minimal toil.</em> <a href="https://github.com/cncf/foundation/blob/main/charter.md" target="_blank" rel="noopener noreferrer">Source</a></p></div></div>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="2-so-what-exactly-is-a-cloud-native-application">2. So, what exactly is a cloud-native application?<a href="https://azure.github.io/Cloud-Native/cnny-2023/cloud-native-fundamentals#2-so-what-exactly-is-a-cloud-native-application" class="hash-link" aria-label="Direct link to 2. So, what exactly is a cloud-native application?" title="Direct link to 2. So, what exactly is a cloud-native application?">​</a></h2>
<p>Cloud-native applications are <em>specifically</em> designed to take advantage of the scalability, resiliency, and distributed nature of modern cloud infrastructure.  But how does this differ from a "traditional" application?</p>
<p>Traditional applications are generally been built, tested, and deployed as a single, monolithic unit.  The monolithic nature of this type of architecture creates close dependencies between components.  This complexity and interweaving only increases as an application grows and can make it difficult to evolve (not to mention troubleshoot) and challenging to operate over time.</p>
<p>To contrast, in cloud-native architectures the application components are decomposed into loosely coupled services, rather than built and deployed as one block of code. This decomposition into multiple self-contained services enables teams to manage complexity and improve the speed, agility, and scale of software delivery. Many small parts enables teams to make targeted updates, deliver new features, and fix any issues without leading to broader service disruption.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="3-the-benefits-of-cloud-native">3. The benefits of cloud-native<a href="https://azure.github.io/Cloud-Native/cnny-2023/cloud-native-fundamentals#3-the-benefits-of-cloud-native" class="hash-link" aria-label="Direct link to 3. The benefits of cloud-native" title="Direct link to 3. The benefits of cloud-native">​</a></h2>
<p>Cloud-native architectures can bring many benefits to an organization, including:</p>
<ol>
<li><strong>Scalability:</strong> easily scale up or down based on demand, allowing organizations to adjust their resource usage and costs as needed.</li>
<li><strong>Flexibility:</strong> deploy and run on any cloud platform, and easily move between clouds and on-premises environments.</li>
<li><strong>High-availability:</strong> techniques such as redundancy, self-healing, and automatic failover help ensure that cloud-native applications are designed to be highly-available and fault tolerant.</li>
<li><strong>Reduced costs:</strong> take advantage of the pay-as-you-go model of cloud computing, reducing the need for expensive infrastructure investments.</li>
<li><strong>Improved security:</strong> tap in to cloud security features, such as encryption and identity management, to improve the security of the application.</li>
<li><strong>Increased agility:</strong> easily add new features or services to your applications to meet changing business needs and market demand.</li>
</ol>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="4-the-pillars-of-cloud-native">4. The pillars of cloud-native<a href="https://azure.github.io/Cloud-Native/cnny-2023/cloud-native-fundamentals#4-the-pillars-of-cloud-native" class="hash-link" aria-label="Direct link to 4. The pillars of cloud-native" title="Direct link to 4. The pillars of cloud-native">​</a></h2>
<p>There are five areas that are generally cited as the core building blocks of cloud-native architecture:</p>
<ol>
<li><a href="https://learn.microsoft.com/devops/deliver/what-are-microservices" target="_blank" rel="noopener noreferrer">Microservices</a>: Breaking down monolithic applications into smaller, independent, and loosely-coupled services that can be developed, deployed, and scaled independently.</li>
<li>Containers: Packaging software in lightweight, portable, and self-sufficient containers that can run consistently across different environments.</li>
<li>Automation: Using automation tools and DevOps processes to manage and operate the cloud-native infrastructure and applications, including deployment, scaling, monitoring, and self-healing.</li>
<li>Service discovery: Using service discovery mechanisms, such as APIs &amp; service meshes, to enable services to discover and communicate with each other.</li>
<li>Observability: Collecting and analyzing data from the infrastructure and applications to understand and optimize the performance, behavior, and health of the system.</li>
</ol>
<p>These can (and should!) be used in combination to deliver cloud-native solutions that are highly scalable, flexible, and available.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>WHAT'S NEXT</div><div class="admonitionContent_BuS1"><p>Stay tuned, as we will be diving deeper into these topics in the coming weeks:</p><ul>
<li><strong>Jan 24</strong>: Containers 101</li>
<li><strong>Jan 25</strong>: Adopting Microservices with Kubernetes</li>
<li><strong>Jan 26</strong>: Kubernetes 101</li>
<li><strong>Jan 27</strong>: Exploring your Cloud-native Options</li>
</ul></div></div>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/cloud-native-fundamentals#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<ul>
<li><strong>Register</strong> for the <a href="https://aka.ms/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a> - 30 days to complete it!</li>
<li><strong>Resources</strong>: <a href="https://aka.ms/CNNY/collection" target="_blank" rel="noopener noreferrer">#30DaysOfCloudNative Collection</a></li>
<li><strong>eBook:</strong> <a href="https://azure.microsoft.com/resources/cloud-native-infrastructure-with-microsoft-azure/" target="_blank" rel="noopener noreferrer">Cloud Native Infrastructure with Azure</a></li>
</ul>
<hr>
<p>Don't forget to <a href="https://azure.github.io/Cloud-Native/cnny-2023/rss.xml?WT.mc_id=javascript-99907-ninarasi" target="_blank" rel="noopener noreferrer">subscribe</a> to the blog to get daily posts delivered directly to your favorite feed reader!</p>
<hr>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[1-2. Containers 101]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/containers-101</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/containers-101</guid>
            <pubDate>Tue, 24 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Let's dive into the various technologies behind Cloud Native development, starting with Containers.]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 2 of Week 1</code> of #CloudNativeNewYear!</p>
<p>Today, we'll focus on building an understanding of containers.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Introduction</li>
<li>How do Containers Work?</li>
<li>Why are Containers Becoming so Popular?</li>
<li>Conclusion</li>
<li>Resources</li>
<li>Learning Path</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="promotional-banner-for-cloud-native-new-year-featuring-colorful-3d-icons-representing-security-containers-and-cloud-technology"><img loading="lazy" alt="Promotional banner for Cloud Native New Year featuring colorful 3D icons representing security, containers, and cloud technology." src="https://azure.github.io/Cloud-Native/assets/images/hero-banner-991129dffd470b38678db8972274c09a.png" width="3840" height="654" class="img_ev3q"><a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101#promotional-banner-for-cloud-native-new-year-featuring-colorful-3d-icons-representing-security-containers-and-cloud-technology" class="hash-link" aria-label="Direct link to promotional-banner-for-cloud-native-new-year-featuring-colorful-3d-icons-representing-security-containers-and-cloud-technology" title="Direct link to promotional-banner-for-cloud-native-new-year-featuring-colorful-3d-icons-representing-security-containers-and-cloud-technology">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>REGISTER &amp; LEARN: KUBERNETES 101</div><div class="admonitionContent_BuS1"><p>Interested in a dive into Kubernetes and a chance to talk to experts?</p><p>🎙: Join us <strong>Jan 26 @1pm PST</strong>
<a href="https://info.microsoft.com/ww-landing-a-quickstart-guide-to-kubernetes-concepts.html?lcid=en-us" target="_blank" rel="noopener noreferrer">by registering here</a></p><p>Here's what you will learn:</p><ul>
<li>Key concepts and core principles of Kubernetes.</li>
<li>How to deploy, scale and manage containerized workloads.</li>
<li>Live Demo of the concepts explained</li>
<li>How to get started with Azure Kubernetes Service for free.</li>
</ul><p><strong>Start your free Azure Kubernetes Trial Today!!</strong>: <a href="https://aka.ms/TryAKS" target="_blank" rel="noopener noreferrer">aka.ms/TryAKS</a></p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction">​</a></h2>
<p>In the beginning, we deployed our applications onto physical servers.  We only had a certain number of those servers, so often they hosted multiple applications.  This led to some problems when those applications shared dependencies.  Upgrading one application could break another application on the same server.</p>
<p>Enter virtualization.  Virtualization allowed us to run our applications in an isolated operating system instance.  This removed much of the risk of updating shared dependencies.  However, it increased our overhead since we had to run a full operating system for each application environment.</p>
<p>To address the challenges created by virtualization, containerization was created to improve isolation without duplicating kernel level resources. Containers provide efficient and consistent deployment and runtime experiences for our applications and have become very popular as a way of packaging and distributing applications.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-containers-work">How do Containers Work?<a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101#how-do-containers-work" class="hash-link" aria-label="Direct link to How do Containers Work?" title="Direct link to How do Containers Work?">​</a></h2>
<p>Containers build on two capabilities in the Linux operating system, namespaces and cgroups.  These constructs allow the operating system to provide isolation to a process or group of processes, keeping their access to filesystem resources separate and providing controls on resource utilization.  This, combined with tooling to help package, deploy, and run container images has led to their popularity in today’s operating environment.  This provides us our isolation without the overhead of additional operating system resources.</p>
<p>When a container host is deployed on an operating system, it works at scheduling the access to the OS (operating systems) components. This is done by providing a logical isolated group that can contain processes for a given application, called a namespace. The container host then manages /schedules access from the namespace to the host OS.  The container host then uses cgroups to allocate compute resources. Together, the container host with the help of cgroups and namespaces can schedule multiple applications to access host OS resources.</p>
<p>Overall, this gives the illusion of virtualizing the host OS, where each application gets its own OS. In actuality, all the applications are running on the same operating system and sharing the same kernel as the container host.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="why-is-containerization-so-popular">Why is Containerization so Popular?<a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101#why-is-containerization-so-popular" class="hash-link" aria-label="Direct link to Why is Containerization so Popular?" title="Direct link to Why is Containerization so Popular?">​</a></h2>
<p>Containers are popular in the software development industry because they provide several benefits over traditional virtualization methods. Some of these benefits include:</p>
<ul>
<li><strong>Portability</strong>: Containers make it easy to move an application from one environment to another without having to worry about compatibility issues or missing dependencies.</li>
<li><strong>Isolation</strong>: Containers provide a level of isolation between the application and the host system, which means that the application running in the container cannot access the host system's resources.</li>
<li><strong>Scalability</strong>: Containers make it easy to scale an application up or down as needed, which is useful for applications that experience a lot of traffic or need to handle a lot of data.</li>
<li><strong>Resource Efficiency</strong>: Containers are more resource-efficient than traditional virtualization methods because they don't require a full operating system to be running on each virtual machine.</li>
<li><strong>Cost-Effective</strong>: Containers are more cost-effective than traditional virtualization methods because they don't require expensive hardware or licensing fees.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>Containers are a powerful technology that allows developers to package and deploy applications in a portable and isolated environment. This technology is becoming increasingly popular in the world of software development and is being used by many companies and organizations to improve their application deployment and management processes. With the benefits of portability, isolation, scalability, resource efficiency, and cost-effectiveness, containers are definitely worth considering for your next application development project.</p>
<p>Containerizing applications is a key step in modernizing them, and there are many other patterns that can be adopted to achieve cloud-native architectures, including using serverless platforms, Kubernetes, and implementing DevOps practices.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<ul>
<li>
<p><a href="https://azure.microsoft.com/resources/cloud-computing-dictionary/what-is-a-container/?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">What are Containers</a></p>
</li>
<li>
<p><a href="https://learn.microsoft.com/dotnet/architecture/microservices/container-docker-introduction/?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Containerizing .NET Applications</a></p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="learning-path">Learning Path<a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101#learning-path" class="hash-link" aria-label="Direct link to Learning Path" title="Direct link to Learning Path">​</a></h2>
<ul>
<li><a href="https://learn.microsoft.com/training/modules/intro-to-docker-containers/?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Introduction to Docker Containers</a></li>
</ul>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
            <category>containers</category>
        </item>
        <item>
            <title><![CDATA[1-3. Kubernetes 101]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/Kubernetes-101</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/Kubernetes-101</guid>
            <pubDate>Wed, 25 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[What is Kubernetes? And why is it so ubiquitous in Cloud-native solutions?]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 3 of Week 1</code> of #CloudNativeNewYear!</p>
<p>This week we'll focus on what Kubernetes is.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/Kubernetes-101#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Introduction</li>
<li>What is Kubernetes? (Video)</li>
<li>How does Kubernetes Work? (Video)</li>
<li>Conclusion</li>
</ul>
<p><img loading="lazy" alt="Promotional banner for Cloud Native New Year featuring colorful 3D icons representing security, containers, and cloud technology." src="https://azure.github.io/Cloud-Native/assets/images/hero-banner-991129dffd470b38678db8972274c09a.png" width="3840" height="654" class="img_ev3q"></p>
<hr>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>REGISTER &amp; LEARN: KUBERNETES 101</div><div class="admonitionContent_BuS1"><p>Interested in a dive into Kubernetes and a chance to talk to experts?</p><p>🎙: Join us <strong>Jan 26 @1pm PST</strong>
<a href="https://info.microsoft.com/ww-landing-a-quickstart-guide-to-kubernetes-concepts.html?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">by registering here</a></p><p>Here's what you will learn:</p><ul>
<li>Key concepts and core principles of Kubernetes.</li>
<li>How to deploy, scale and manage containerized workloads.</li>
<li>Live Demo of the concepts explained</li>
<li>How to get started with Azure Kubernetes Service for free.</li>
</ul><p><strong>Start your free Azure Kubernetes Trial Today!!</strong>: <a href="https://aka.ms/TryAKS" target="_blank" rel="noopener noreferrer">aka.ms/TryAKS</a></p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a href="https://azure.github.io/Cloud-Native/cnny-2023/Kubernetes-101#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction">​</a></h2>
<p>Kubernetes is an open source container orchestration engine that can help with automated deployment, scaling, and management of our applications.</p>
<p>Kubernetes takes physical (or virtual) resources and provides a consistent API over them, bringing a consistency to the management and runtime experience for our applications.  Kubernetes provides us with a number of capabilities such as:</p>
<ul>
<li>Container scheduling</li>
<li>Service discovery and load balancing</li>
<li>Storage orchestration</li>
<li>Automated rollouts and rollbacks</li>
<li>Automatic bin packing</li>
<li>Self-healing</li>
<li>Secret and configuration management</li>
</ul>
<p>We'll learn more about most of these topics as we progress through Cloud Native New Year.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-kubernetes">What is Kubernetes?<a href="https://azure.github.io/Cloud-Native/cnny-2023/Kubernetes-101#what-is-kubernetes" class="hash-link" aria-label="Direct link to What is Kubernetes?" title="Direct link to What is Kubernetes?">​</a></h2>
<p>Let's hear from Brendan Burns, one of the founders of Kubernetes as to what Kubernetes actually is.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/q1PcAawa4Bg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"></iframe>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-does-kubernetes-work">How does Kubernetes Work?<a href="https://azure.github.io/Cloud-Native/cnny-2023/Kubernetes-101#how-does-kubernetes-work" class="hash-link" aria-label="Direct link to How does Kubernetes Work?" title="Direct link to How does Kubernetes Work?">​</a></h2>
<p>And Brendan shares a bit more with us about how Kubernetes works.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/daVUONZqn88" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"></iframe>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/cnny-2023/Kubernetes-101#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>Kubernetes allows us to deploy and manage our applications effectively and consistently.</p>
<p>By providing a consistent API across many of the concerns our applications have, like load balancing, networking, storage, and compute, Kubernetes improves both our ability to build and ship new software.</p>
<p>There are standards for the applications to depend on for resources needed. Deployments, metrics, and logs are provided in a standardized fashion allowing more effecient operations across our application environments.</p>
<p>And since Kubernetes is an open source platform, it can be found in just about every type of operating environment - cloud, virtual machines, physical hardware, shared data centers, even small devices like Rasberry Pi's!</p>
<p>Want to learn more?  <a href="https://info.microsoft.com/ww-landing-a-quickstart-guide-to-kubernetes-concepts.html?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Join us for a webinar on Kubernetes Concepts (or catch the playback) on Thursday, January 26th at 1 PM PST</a> and watch for the rest of this series right here!</p>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[1-4. Microservices 101]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/microservices-101</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/microservices-101</guid>
            <pubDate>Thu, 26 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[What are Microservices? Why are they a core pillar for Cloud-native and how does Kubernetes help in their deployment?]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 4 of Week 1</code> of #CloudNativeNewYear!</p>
<p>This week we'll focus on advanced topics and best practices for Cloud-Native practitioners, kicking off with this post on <em>Serverless Container Options</em> with Azure. We'll look at technologies, tools and best practices that range from managed services like Azure Kubernetes Service, to options allowing finer granularity of control and oversight.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/microservices-101#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>What is Microservice Architecture?</li>
<li>How do you design a Microservice?</li>
<li>What challenges do Microservices introduce?</li>
<li>Conclusion</li>
<li>Resources</li>
</ul>
<p><img loading="lazy" alt="Promotional banner for Cloud Native New Year featuring colorful 3D icons representing security, containers, and cloud technology." src="https://azure.github.io/Cloud-Native/assets/images/hero-banner-991129dffd470b38678db8972274c09a.png" width="3840" height="654" class="img_ev3q"></p>
<hr>
<p>Microservices are a modern way of designing and building software that increases deployment velocity by decomposing an application into small autonomous services that can be deployed independently.</p>
<p>By deploying loosely coupled microservices your applications can be developed, deployed, and scaled independently. Because each service is independent, it can be updated or replaced without having to worry about the impact on the rest of the application. This means that if a bug is found in one service, it can be fixed without having to redeploy the entire application. All of which gives an organization the ability to deliver value to their customers faster.</p>
<p>In this article, we will explore the basics of microservices architecture, its benefits and challenges, and how it can help improve the development, deployment, and maintenance of software applications.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-microservice-architecture">What is Microservice Architecture?<a href="https://azure.github.io/Cloud-Native/cnny-2023/microservices-101#what-is-microservice-architecture" class="hash-link" aria-label="Direct link to What is Microservice Architecture?" title="Direct link to What is Microservice Architecture?">​</a></h2>
<p>Before explaining what Microservice architecture is, it’s important to understand what problems microservices aim to address.</p>
<p>Traditional software development is centered around building monolithic applications. Monolithic applications are built as a single, large codebase. Meaning your code is tightly coupled causing the monolithic app to suffer from the following:</p>
<p><strong>Too much Complexity:</strong> Monolithic applications can become complex and difficult to understand and maintain as they grow. This can make it hard to identify and fix bugs and add new features.</p>
<p><strong>Difficult to Scale:</strong> Monolithic applications can be difficult to scale as they often have a single point of failure, which can cause the whole application to crash if a service fails.</p>
<p><strong>Slow Deployment:</strong> Deploying a monolithic application can be risky and time-consuming, as a small change in one part of the codebase can affect the entire application.</p>
<p>Microservice architecture (often called microservices) is an architecture style that addresses the challenges created by Monolithic applications. Microservices architecture is a way of designing and building software applications as a collection of small, independent services that communicate with each other through APIs. This allows for faster development and deployment cycles, as well as easier scaling and maintenance than is possible with a monolithic application.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="how-do-you-design-a-microservice">How do you design a Microservice?<a href="https://azure.github.io/Cloud-Native/cnny-2023/microservices-101#how-do-you-design-a-microservice" class="hash-link" aria-label="Direct link to How do you design a Microservice?" title="Direct link to How do you design a Microservice?">​</a></h2>
<p>Building applications with Microservices architecture requires a different approach. Microservices architecture focuses on business capabilities rather than technical layers, such as data access or messaging. Doing so requires that you shift your focus away from the technical stack and model your applications based upon the various domains that exist within the business.</p>
<p>Domain-driven design (DDD) is a way to design software by focusing on the business needs. You can use Domain-driven design as a framework that guides the development of well-designed microservices by building services that encapsulate knowledge in each domain and abstract that knowledge from clients.</p>
<p>In Domain-driven design you start by modeling the business domain and creating a domain model. A domain model is an abstract model of the business model that distills and organizes a domain of knowledge and provides a common language for developers and domain experts. It’s the resulting domain model that microservices a best suited to be built around because it helps establish a well-defined boundary between external systems and other internal applications.</p>
<p>In short, before you begin designing microservices, start by mapping the functions of the business and their connections to create a domain model for the microservice(s) to be built around.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-challenges-do-microservices-introduce">What challenges do Microservices introduce?<a href="https://azure.github.io/Cloud-Native/cnny-2023/microservices-101#what-challenges-do-microservices-introduce" class="hash-link" aria-label="Direct link to What challenges do Microservices introduce?" title="Direct link to What challenges do Microservices introduce?">​</a></h2>
<p>Microservices solve a lot of problems and have several advantages, but the grass isn’t always greener on the other side.</p>
<p>One of the key challenges of microservices is managing communication between services. Because services are independent, they need to communicate with each other through APIs. This can be complex and difficult to manage, especially as the number of services grows. To address this challenge, it is important to have a clear API design, with well-defined inputs and outputs for each service. It is also important to have a system for managing and monitoring communication between services, to ensure that everything is running smoothly.</p>
<p>Another challenge of microservices is managing the deployment and scaling of services. Because each service is independent, it needs to be deployed and scaled separately from the rest of the application. This can be complex and difficult to manage, especially as the number of services grows. To address this challenge, it is important to have a clear and consistent deployment process, with well-defined steps for deploying and scaling each service. Furthermore, it is advisable to host them on a system with self-healing capabilities to reduce operational burden.</p>
<p>It is also important to have a system for monitoring and managing the deployment and scaling of services, to ensure optimal performance.</p>
<p>Each of these challenges has created fertile ground for tooling and process that exists in the cloud-native ecosystem. Kubernetes, CI CD, and other DevOps practices are part of the package of adopting the microservices architecture.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/cnny-2023/microservices-101#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>In summary, microservices architecture focuses on software applications as a collection of small, independent services that communicate with each other over well-defined APIs.</p>
<p>The main advantages of microservices include:</p>
<ul>
<li>increased flexibility and scalability per microservice,</li>
<li>efficient resource utilization (with help from a container orchestrator like Kubernetes),</li>
<li>and faster development cycles.</li>
</ul>
<p>Continue following along with this series to see how you can use Kubernetes to help adopt microservices patterns in your own environments!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/microservices-101#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<ul>
<li><a href="https://azure.microsoft.com/solutions/microservice-applications?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Microservice Applications</a></li>
<li><a href="https://learn.microsoft.com/azure/architecture/microservices?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Microservices architecture design - Azure Architecture Center | Microsoft Learn</a></li>
<li><a href="https://learn.microsoft.com/azure/architecture/microservices/design?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Design a microservices architecture - Azure Architecture Center | Microsoft Learn</a></li>
<li><a href="https://learn.microsoft.com/azure/architecture/microservices/model/domain-analysis?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Domain analysis for microservices - Azure Architecture Center | Microsoft Learn</a></li>
</ul>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
            <category>microservices</category>
        </item>
        <item>
            <title><![CDATA[1-5. Exploring Cloud-Native Options]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/explore-options</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/explore-options</guid>
            <pubDate>Fri, 27 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[There are many cloud-native technologies - but which are the best fit for your projects?]]></description>
            <content:encoded><![CDATA[
<p>We are excited to be wrapping up our first week of #CloudNativeNewYear! This week, we have tried to set the stage by covering the fundamentals of cloud-native practices and technologies, including primers on <a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101/" target="_blank" rel="noopener noreferrer">containerization</a>, <a href="https://azure.github.io/Cloud-Native/cnny-2023/microservices-101" target="_blank" rel="noopener noreferrer">microservices</a>, and <a href="https://azure.github.io/Cloud-Native/cnny-2023/Kubernetes-101" target="_blank" rel="noopener noreferrer">Kubernetes</a>.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Don't forget to sign up for the the <a href="https://aka.ms/CNNY/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a>!</div></div>
<p>Today, we will do a brief recap of some of these technologies and provide some basic guidelines for when it is optimal to use each.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/explore-options#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>To Containerize or not to Containerize?</li>
<li>The power of Kubernetes</li>
<li>Where does Serverless fit?</li>
<li>Resources</li>
<li>What's coming next!</li>
</ul>
<p><img loading="lazy" alt="Promotional banner for Cloud Native New Year featuring colorful 3D icons representing security, containers, and cloud technology." src="https://azure.github.io/Cloud-Native/assets/images/hero-banner-991129dffd470b38678db8972274c09a.png" width="3840" height="654" class="img_ev3q"></p>
<hr>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>Just joining us now? Check out these other Week 1 posts:</div><div class="admonitionContent_BuS1"><ul>
<li><a href="https://azure.github.io/Cloud-Native/cnny-2023/cloud-native-fundamentals" target="_blank" rel="noopener noreferrer">Cloud-native fundamentals</a></li>
<li><a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101" target="_blank" rel="noopener noreferrer">Containers 101</a></li>
<li><a href="https://azure.github.io/Cloud-Native/cnny-2023/microservices-101" target="_blank" rel="noopener noreferrer">Microservices 101</a></li>
<li><a href="https://azure.github.io/Cloud-Native/cnny-2023/Kubernetes-101" target="_blank" rel="noopener noreferrer">Kubernetes 101</a></li>
</ul></div></div>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="to-containerize-or-not-to-containerize">To Containerize or not to Containerize?<a href="https://azure.github.io/Cloud-Native/cnny-2023/explore-options#to-containerize-or-not-to-containerize" class="hash-link" aria-label="Direct link to To Containerize or not to Containerize?" title="Direct link to To Containerize or not to Containerize?">​</a></h2>
<p>As mentioned in our Containers 101 post earlier this week, containers can provide several benefits over traditional virtualization methods, which has made them popular within the software development community. Containers provide a consistent and predictable runtime environment, which can help reduce the risk of compatibility issues and simplify the deployment process. Additionally, containers can improve resource efficiency by allowing multiple applications to run on the same host while isolating their dependencies.</p>
<p>Some types of apps that are a particularly good fit for containerization include:</p>
<ol>
<li><strong>Microservices:</strong> Containers are particularly well-suited for microservices-based applications, as they can be used to isolate and deploy individual components of the system. This allows for more flexibility and scalability in the deployment process.</li>
<li><strong>Stateless applications:</strong> Applications that do not maintain state across multiple sessions, such as web applications, are well-suited for containers. Containers can be easily scaled up or down as needed and replaced with new instances, without losing data.</li>
<li><strong>Portable applications:</strong> Applications that need to be deployed in different environments, such as on-premises, in the cloud, or on edge devices, can benefit from containerization. The consistent and portable runtime environment of containers can make it easier to move the application between different environments.</li>
<li><strong>Legacy applications:</strong> Applications that are built using older technologies or that have compatibility issues can be containerized to run in an isolated environment, without impacting other applications or the host system.</li>
<li><strong>Dev and testing environments:</strong> Containerization can be used to create isolated development and testing environments, which can be easily created and destroyed as needed.</li>
</ol>
<p>While there are many types of applications that can benefit from a containerized approach, it's worth noting that containerization is not <strong>always</strong> the best option, and it's important to weigh the benefits and trade-offs before deciding to containerize an application. Additionally, some types of applications may not be a good fit for containers including:</p>
<ul>
<li>Apps that require full access to host resources: Containers are isolated from the host system, so if an application needs direct access to hardware resources such as GPUs or specialized devices, it might not work well in a containerized environment.</li>
<li>Apps that require low-level system access: If an application requires deep access to the underlying operating system, it may not be suitable for running in a container.</li>
<li>Applications that have specific OS dependencies: Apps that have specific dependencies on a certain version of an operating system or libraries may not be able to run in a container.</li>
<li>Stateful applications: Apps that maintain state across multiple sessions, such as databases, may not be well suited for containers. Containers are ephemeral by design, so the data stored inside a container may not persist between restarts.</li>
</ul>
<p>The good news is that some of these limitations can be overcome with the use of specialized containerization technologies such as Kubernetes, and by carefully designing the architecture of the application.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="the-power-of-kubernetes">The power of Kubernetes<a href="https://azure.github.io/Cloud-Native/cnny-2023/explore-options#the-power-of-kubernetes" class="hash-link" aria-label="Direct link to The power of Kubernetes" title="Direct link to The power of Kubernetes">​</a></h2>
<p>Speaking of Kubernetes...</p>
<p>Kubernetes is a powerful tool for managing and deploying containerized applications in production environments, particularly for applications that need to scale, handle large numbers of requests, or run in multi-cloud or hybrid environments.</p>
<p>Kubernetes is well-suited for a wide variety of applications, but it is particularly well-suited for the following types of applications:</p>
<ol>
<li><strong>Microservices-based applications:</strong> Kubernetes provides a powerful set of tools for managing and deploying microservices-based applications, making it easy to scale, update, and manage the individual components of the application.</li>
<li><strong>Stateful applications:</strong> Kubernetes provides support for stateful applications through the use of Persistent Volumes and StatefulSets, allowing for applications that need to maintain state across multiple instances.</li>
<li><strong>Large-scale, highly-available systems:</strong> Kubernetes provides built-in support for scaling, self-healing, and rolling updates, making it an ideal choice for large-scale, highly-available systems that need to handle large numbers of users and requests.</li>
<li><strong>Multi-cloud and hybrid environments:</strong> Kubernetes can be used to deploy and manage applications across multiple cloud providers and on-premises environments, making it a good choice for organizations that want to take advantage of the benefits of multiple cloud providers or that need to deploy applications in a hybrid environment.</li>
</ol>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>New to Kubernetes?</div><div class="admonitionContent_BuS1"><p>Catch <a href="https://info.microsoft.com/ww-ondemand-a-quickstart-guide-to-kubernetes-concepts.html?lcid=en-us" target="_blank" rel="noopener noreferrer">A Quickstart Guide to Kubernetes Concepts</a> on demand, now!</p></div></div>
<hr>
<h1>Where does Serverless fit in?</h1>
<p>Serverless is a cloud computing model where the cloud provider (like Azure) is responsible for executing a piece of code by dynamically allocating the resources. With serverless, you only pay for the exact amount of compute time that you use, rather than paying for a fixed amount of resources. This can lead to significant cost savings, particularly for applications with variable or unpredictable workloads.</p>
<p>Serverless is commonly used for building applications like web or mobile apps, IoT, data processing, and real-time streaming - apps where the workloads are variable and high scalability is required.
It's important to note that serverless is not a replacement for all types of workloads - it's best suited for stateless, short-lived and small-scale workloads.</p>
<p>For a detailed look into the world of Serverless and lots of great learning content, revisit <a href="https://azure.github.io/Cloud-Native/serverless-september/30DaysOfServerless/" target="_blank" rel="noopener noreferrer">#30DaysofServerless</a>.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/explore-options#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<ul>
<li><strong>Register</strong> for the <a href="https://aka.ms/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a> - 30 days to complete it!</li>
<li><strong>Learning Resources</strong>: <a href="https://aka.ms/CNNY/collection" target="_blank" rel="noopener noreferrer">#30DaysOfCloudNative Collection</a></li>
<li><strong>eBook:</strong> <a href="https://azure.microsoft.com/resources/cloud-native-infrastructure-with-microsoft-azure/?WT.mc_id=javascript-99907-ninarasi" target="_blank" rel="noopener noreferrer">Cloud Native Infrastructure with Azure</a></li>
<li><strong>eBook:</strong> <a href="https://azure.microsoft.com/resources/azure-cloud-native-architecture-mapbook/?WT.mc_id=javascript-99907-ninarasi" target="_blank" rel="noopener noreferrer">Cloud-native Architecture Mapbook</a></li>
</ul>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="whats-up-next-in-cloudnativenewyear">What's up next in #CloudNativeNewYear?<a href="https://azure.github.io/Cloud-Native/cnny-2023/explore-options#whats-up-next-in-cloudnativenewyear" class="hash-link" aria-label="Direct link to What's up next in #CloudNativeNewYear?" title="Direct link to What's up next in #CloudNativeNewYear?">​</a></h2>
<p>Week 1 has been all about the fundamentals of cloud-native. Next week, the team will be diving in to application deployment with Azure Kubernetes Service. Don't forget to <a href="https://azure.github.io/Cloud-Native/cnny-2023/rss.xml?WT.mc_id=javascript-99907-ninarasi" target="_blank" rel="noopener noreferrer">subscribe</a> to the blog to get daily posts delivered directly to your favorite feed reader!</p>
<hr>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[2-1. Kubernetes Fundamentals - Pods and Deployments]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1</guid>
            <pubDate>Mon, 30 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[The theme for this week is Kubernetes fundamentals. Today we'll explore the topic of Pods and Deployments in Kubernetes.]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day #1 of Week 2</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is Kubernetes fundamentals. Last week we talked about Cloud Native architectures and the Cloud Native landscape. Today we'll explore the topic of Pods and Deployments in Kubernetes.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Ask the Experts Thursday, February 9th at 9 AM PST</div><div class="admonitionContent_BuS1"><p><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Watch our Q&amp;A with Experts from the Azure Kubernetes Service product team!</a></p></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Catch the Replay of the Live Demo</div><div class="admonitionContent_BuS1"><p>Watch the recorded demo and conversation about this week's topics.</p><p><a href="https://aka.ms/cnny/week2-demo" target="_blank" rel="noopener noreferrer">We were live on YouTube walking through today's (and the rest of this week's) demos</a>.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Setting Up A Kubernetes Environment in Azure</li>
<li>Running Containers in Kubernetes Pods</li>
<li>Making the Pods Resilient with Deployments</li>
<li>Exercise</li>
<li>Resources</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="setting-up-a-kubernetes-environment-in-azure">Setting Up A Kubernetes Environment in Azure<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#setting-up-a-kubernetes-environment-in-azure" class="hash-link" aria-label="Direct link to Setting Up A Kubernetes Environment in Azure" title="Direct link to Setting Up A Kubernetes Environment in Azure">​</a></h2>
<p>For this week, we'll be working with a simple app - <a href="https://aka.ms/azure-voting-app-rust" target="_blank" rel="noopener noreferrer">the Azure Voting App</a>. My teammate <a href="https://github.com/pauldotyu" target="_blank" rel="noopener noreferrer">Paul Yu</a> ported the app to Rust and we tweaked it a bit to let us highlight some of the basic features of Kubernetes.</p>
<p>You should be able to replicate this in just about any Kubernetes environment, but we'll use <a href="https://learn.microsoft.com/azure/aks/intro-kubernetes?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a> (AKS) as our working environment for this week.</p>
<p>To make it easier to get started, there's a <a href="https://learn.microsoft.com/azure/azure-resource-manager/bicep/overview?WT.mc_id=containers-84290-stmuraws&amp;tabs=bicep" target="_blank" rel="noopener noreferrer">Bicep</a> template to deploy an AKS cluster, an Azure Container Registry (ACR) (to host our container image), and connect the two so that we can easily deploy our application.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-0---prerequisites">Step 0 - Prerequisites<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#step-0---prerequisites" class="hash-link" aria-label="Direct link to Step 0 - Prerequisites" title="Direct link to Step 0 - Prerequisites">​</a></h3>
<p>There are a few things you'll need if you want to work through this and the following examples this week.</p>
<p>Required:</p>
<ul>
<li>Git (and probably a GitHub account if you want to persist your work outside of your computer)</li>
<li>Azure CLI</li>
<li>An Azure subscription (if you want to follow along with the Azure steps)</li>
<li>Kubectl (the command line tool for managing Kubernetes)</li>
</ul>
<p>Helpful:</p>
<ul>
<li>Visual Studio Code (or equivalent editor)</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-1---clone-the-application-repository">Step 1 - Clone the application repository<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#step-1---clone-the-application-repository" class="hash-link" aria-label="Direct link to Step 1 - Clone the application repository" title="Direct link to Step 1 - Clone the application repository">​</a></h3>
<p>First, I forked <a href="https://aka.ms/azure-voting-app-rust" target="_blank" rel="noopener noreferrer">the source repository</a> to my account.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$GitHubOrg = 'smurawski' # Replace this with your GitHub account name or org name</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">git clone "https://github.com/$GitHubOrg/azure-voting-app-rust"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cd azure-voting-app-rust</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Leave your shell opened with your current location inside the application repository.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-2---set-up-aks">Step 2 - Set up AKS<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#step-2---set-up-aks" class="hash-link" aria-label="Direct link to Step 2 - Set up AKS" title="Direct link to Step 2 - Set up AKS">​</a></h3>
<p>Running the template deployment from the demo script (I'm using the PowerShell example in <a href="https://aka.ms/azure-voting-app-rust/setup-powershell" target="_blank" rel="noopener noreferrer">cnny23-week2-day1.ps1</a>, but there's a Bash variant at <a href="https://aka.ms/azure-voting-app-rust/setup-bash" target="_blank" rel="noopener noreferrer">cnny23-week2-day1.sh</a>) stands up the environment.  The second, third, and fourth commands take some of the output from the Bicep deployment to set up for later commands, so don't close out your shell after you run these commands.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az deployment sub create --template-file ./deploy/main.bicep --location eastus --parameters 'resourceGroup=cnny-week2'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$AcrName = az deployment sub show --name main --query 'properties.outputs.acr_name.value' -o tsv</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$AksName = az deployment sub show --name main --query 'properties.outputs.aks_name.value' -o tsv</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$ResourceGroup = az deployment sub show --name main --query 'properties.outputs.resource_group_name.value' -o tsv</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az aks get-credentials --resource-group $ResourceGroup --name $AksName</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="step-3---build-our-application-container">Step 3 - Build our application container<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#step-3---build-our-application-container" class="hash-link" aria-label="Direct link to Step 3 - Build our application container" title="Direct link to Step 3 - Build our application container">​</a></h3>
<p>Since we have an Azure Container Registry set up, I'll use ACR Build Tasks to build and store my container image.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az acr build --registry $AcrName --% --image cnny2023/azure-voting-app-rust:{{.Run.ID}} .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$BuildTag = az acr repository show-tags `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                              --name $AcrName `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                              --repository cnny2023/azure-voting-app-rust `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                              --orderby time_desc `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                              --query '[0]' -o tsv</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p>Wondering what the <code>--%</code> is in the first command line?  That tells the PowerShell interpreter to pass the input after it "as is" to the command without parsing/evaluating it. Otherwise, PowerShell messes a bit with the templated <code>{{.Run.ID}}</code> bit.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="running-containers-in-kubernetes-pods">Running Containers in Kubernetes Pods<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#running-containers-in-kubernetes-pods" class="hash-link" aria-label="Direct link to Running Containers in Kubernetes Pods" title="Direct link to Running Containers in Kubernetes Pods">​</a></h2>
<p>Now that we have our AKS cluster and application image ready to go, let's look into how Kubernetes runs containers.</p>
<p>If you've been in tech for any length of time, you've seen that every framework, runtime, orchestrator, etc.. can have their own naming scheme for their concepts. So let's get into some of what Kubernetes calls things.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-pod">The Pod<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#the-pod" class="hash-link" aria-label="Direct link to The Pod" title="Direct link to The Pod">​</a></h3>
<p>A container running in Kubernetes is called a <a href="https://learn.microsoft.com/azure/aks/concepts-clusters-workloads?WT.mc_id=containers-84290-stmuraws#pods" target="_blank" rel="noopener noreferrer">Pod</a>. A Pod is basically a running container on a <a href="https://learn.microsoft.com/azure/aks/concepts-clusters-workloads?WT.mc_id=containers-84290-stmuraws#nodes-and-node-pools" target="_blank" rel="noopener noreferrer">Node</a> or VM. It can be more. For example you can run multiple containers and specify some funky configuration, but we'll keep it simple for now - add the complexity when you need it.</p>
<p>Our Pod definition can be created via the <code>kubectl</code> command imperatively from arguments or declaratively from a configuration file.  We'll do a little of both.  We'll use the <code>kubectl</code> command to help us write our configuration files.  Kubernetes configuration files are YAML, so having an editor that supports and can help you syntax check YAML is really helpful.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="creating-a-pod-definition">Creating a Pod Definition<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#creating-a-pod-definition" class="hash-link" aria-label="Direct link to Creating a Pod Definition" title="Direct link to Creating a Pod Definition">​</a></h3>
<p>Let's create a few Pod definitions.  Our application requires two containers to get working - the application and a database.</p>
<p>Let's create the database Pod first.  And before you comment, the configuration isn't secure nor best practice.  We'll fix that later this week.  For now, let's focus on getting up and running.</p>
<p>This is a trick I learned from one of my teammates - Paul.  By using the <code>--output yaml</code> and <code>--dry-run=client</code> options, we can have the command help us write our YAML.  And with a bit of output redirection, we can stash it safely in a file for later use.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl run azure-voting-db `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            --image "postgres:15.0-alpine" `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            --env "POSTGRES_PASSWORD=mypassword" `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            --output yaml `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            --dry-run=client &gt; manifests/pod-db.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This creates a file that looks like:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Pod</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">containers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> POSTGRES_PASSWORD</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mypassword</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> postgres</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">15.0</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">alpine</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">resources</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">dnsPolicy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ClusterFirst</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">restartPolicy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Always</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The file, when supplied to the Kubernetes API, will identify what kind of resource to create, the API version to use, and the details of the container (as well as an environment variable to be supplied).</p>
<p>We'll get that container image started with the <code>kubectl</code> command.  Because the details of what to create are in the file, we don't need to specify much else to the <code>kubectl</code> command but the path to the file.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/pod-db.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>I'm going to need the IP address of the Pod, so that my application can connect to it, so we can use <code>kubectl</code> to get some information about our pod.  By default, <code>kubectl get pod</code> only displays certain information but it retrieves a lot more.  We can use the <a href="https://kubernetes.io/docs/reference/kubectl/jsonpath/" target="_blank" rel="noopener noreferrer">JSONPath syntax</a> to index into the response and get the information you want.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p>To see what you can get, I usually run the <code>kubectl</code> command with the output type (<code>-o JSON</code>) of JSON and then I can find where the data I want is and create my JSONPath query to get it.</p></div></div>
<div class="language-powershell, codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell, codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$DB_IP = kubectl get pod azure-voting-db -o jsonpath='{.status.podIP}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now, let's create our Pod definition for our application.  We'll use the same technique as before.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl run azure-voting-app `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            --image "$AcrName.azurecr.io/cnny2023/azure-voting-app-rust:$BuildTag" `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            --env "DATABASE_SERVER=$DB_IP" `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            --env "DATABASE_PASSWORD=mypassword`</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            --output yaml `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            --dry-run=client &gt; manifests/pod-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That command gets us a similar YAML file to the database container - you can see <a href="https://github.com/azure-samples/azure-voting-app-rust/blob/week2/day1/manifests/pod-app.yaml" target="_blank" rel="noopener noreferrer">the full file here</a></p>
<p>Let's get our application container running.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/pod-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="now-that-the-application-is-running">Now that the Application is Running<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#now-that-the-application-is-running" class="hash-link" aria-label="Direct link to Now that the Application is Running" title="Direct link to Now that the Application is Running">​</a></h3>
<p>We can check the status of our Pods with:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pods</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And we should see something like:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-app-rust ❯  kubectl get pods</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME               READY   STATUS    RESTARTS   AGE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-app   1/1     Running   0          36s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-db    1/1     Running   0          84s</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Once our pod is running, we can check to make sure everything is working by letting <code>kubectl</code> proxy network connections to our Pod running the application. If we get the voting web page, we'll know the application found the database and we can start voting!</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl port-forward pod/azure-voting-app 8080:8080</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><img loading="lazy" alt="Azure voting website in a browser with three buttons, one for Dogs, one for Cats, and one for Reset.  The counter is Dogs - 0 and Cats - 0." src="https://azure.github.io/Cloud-Native/assets/images/azure_voting_app-f23e02d61834bad88440b2aab40012fb.png" width="1590" height="1137" class="img_ev3q"></p>
<p>When you are done voting, you can stop the port forwarding by using Control-C to break the command.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="clean-up">Clean Up<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#clean-up" class="hash-link" aria-label="Direct link to Clean Up" title="Direct link to Clean Up">​</a></h3>
<p>Let's clean up after ourselves and see if we can't get Kubernetes to help us keep our application running.  We can use the same configuration files to ensure that Kubernetes only removes what we want removed.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete -f ./manifests/pod-app.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete -f ./manifests/pod-db.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="summary---pods">Summary - Pods<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#summary---pods" class="hash-link" aria-label="Direct link to Summary - Pods" title="Direct link to Summary - Pods">​</a></h3>
<p>A Pod is the most basic unit of work inside Kubernetes. Once the Pod is deleted, it's gone.  That leads us to our next topic (and final topic for today.)</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="making-the-pods-resilient-with-deployments">Making the Pods Resilient with Deployments<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#making-the-pods-resilient-with-deployments" class="hash-link" aria-label="Direct link to Making the Pods Resilient with Deployments" title="Direct link to Making the Pods Resilient with Deployments">​</a></h2>
<p>We've seen how easy it is to deploy a Pod and get our containers running on Nodes in our Kubernetes cluster.  But there's a problem with that.  Let's illustrate it.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="breaking-stuff">Breaking Stuff<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#breaking-stuff" class="hash-link" aria-label="Direct link to Breaking Stuff" title="Direct link to Breaking Stuff">​</a></h3>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="setting-back-up">Setting Back Up<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#setting-back-up" class="hash-link" aria-label="Direct link to Setting Back Up" title="Direct link to Setting Back Up">​</a></h4>
<p>First, let's redeploy our application environment.  We'll start with our application container.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/pod-db.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pod azure-voting-db -o jsonpath='{.status.podIP}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The second command will report out the new IP Address for our database container.  Let's open <code>./manifests/pod-app.yaml</code> and update the container IP to our new one.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DATABASE_SERVER</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> YOUR_NEW_IP_HERE</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Then we can deploy the application with the information it needs to find its database.  We'll also list out our pods to see what is running.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/pod-app.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pods</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Feel free to look back and use the port forwarding trick to make sure your app is running if you'd like.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="knocking-it-down">Knocking It Down<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#knocking-it-down" class="hash-link" aria-label="Direct link to Knocking It Down" title="Direct link to Knocking It Down">​</a></h4>
<p>The first thing we'll try to break is our application pod.  Let's delete it.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete pod azure-voting-app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Then, we'll check our pod's status:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pods</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Which should show something like:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-app-rust ❯  kubectl get pods</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME              READY   STATUS    RESTARTS   AGE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-db   1/1     Running   0          50s</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We should be able to recreate our application pod deployment with no problem, since it has the current database IP address and nothing else depends on it.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/pod-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Again, feel free to do some fun port forwarding and check your site is running.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="uncomfortable-truths">Uncomfortable Truths<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#uncomfortable-truths" class="hash-link" aria-label="Direct link to Uncomfortable Truths" title="Direct link to Uncomfortable Truths">​</a></h4>
<p>Here's where it gets a bit stickier, what if we delete the database container?</p>
<p>If we delete our database container and recreate it, it'll likely have a new IP address, which would force us to update our application configuration.  We'll look at some solutions for these problems in the next three posts this week.</p>
<p>Because our database problem is a bit tricky, we'll primarily focus on making our application layer more resilient and prepare our database layer for those other techniques over the next few days.</p>
<p>Let's clean back up and look into making things more resilient.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete -f ./manifests/pod-app.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete -f ./manifests/pod-db.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="the-deployment">The Deployment<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#the-deployment" class="hash-link" aria-label="Direct link to The Deployment" title="Direct link to The Deployment">​</a></h3>
<p>One of the reasons you may want to use Kubernetes is it's ability to orchestrate workloads.  Part of that orchestration includes being able to ensure that certain workloads are running (regardless of what Node they might be on).</p>
<p>We saw that we could delete our application pod and then restart it from the manifest with little problem.  It just meant that we had to run a command to restart it.  We can use the <a href="https://learn.microsoft.com/azure/aks/concepts-clusters-workloads?WT.mc_id=containers-84290-stmuraws#deployments-and-yaml-manifests" target="_blank" rel="noopener noreferrer">Deployment</a> in Kubernetes to tell the orchestrator to ensure we have our application pod running.</p>
<p>The Deployment also can encompass a lot of extra configuration - controlling how many containers of a particular type should be running, how upgrades of container images should proceed, and more.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="creating-the-deployment">Creating the Deployment<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#creating-the-deployment" class="hash-link" aria-label="Direct link to Creating the Deployment" title="Direct link to Creating the Deployment">​</a></h4>
<p>First, we'll create a Deployment for our database. We'll use a technique similar to what we did for the Pod, with just a bit of difference.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create deployment azure-voting-db `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            --image "postgres:15.0-alpine" `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            --port 5432 `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            --output yaml `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                            --dry-run=client &gt; manifests/deployment-db.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Unlike our Pod definition creation, we can't pass in environment variable configuration from the command line.  We'll have to edit the YAML file to add that.</p>
<p>So, let's open <code>./manifests/deployment-db.yaml</code> in our editor and add the following in the <code>spec/containers</code> configuration.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> POSTGRES_PASSWORD</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"mypassword"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Your file should look like this <a href="https://github.com/azure-samples/azure-voting-app-rust/blob/week2/day1/manifests/deployment-db.yaml" target="_blank" rel="noopener noreferrer">deployment-db.yaml</a>.</p>
<p>Once we have our configuration file updated, we can deploy our database container image.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/deployment-db.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>For our application, we'll use the same technique.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create deployment azure-voting-app `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        --image "$AcrName.azurecr.io/cnny2023/azure-voting-app-rust:$BuildTag" `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        --port 8080 `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        --output yaml `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        --dry-run=client &gt; manifests/deployment-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, we'll need to add an environment variable to the generated configuration.  We'll also need the new IP address for the database deployment.</p>
<p>Previously, we named the pod and were able to ask for the IP address with <code>kubectl</code> and a bit of JSONPath. Now, the deployment created the pod for us, so there's a bit of random in the naming.  Check out:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pods</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Should return something like:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-app-rust ❯  kubectl get pods</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME                               READY   STATUS    RESTARTS   AGE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-db-686d758fbf-8jnq8   1/1     Running   0          7s</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We can either ask for the IP with the new pod name, or we can use a <a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors" target="_blank" rel="noopener noreferrer">selector</a> to find our desired pod.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pod --selector app=azure-voting-db -o jsonpath='{.items[0].status.podIP}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now, we can update our application deployment configuration file with:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DATABASE_SERVER</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> YOUR_NEW_IP_HERE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DATABASE_PASSWORD</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mypassword</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Your file should look like this <a href="https://github.com/azure-samples/azure-voting-app-rust/blob/week2/day1/manifests/deployment-app.yaml" target="_blank" rel="noopener noreferrer">deployment-app.yaml</a> (but with IPs and image names matching your environment).</p>
<p>After we save those changes, we can deploy our application.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/deployment-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Let's test the resilience of our app now. First, we'll delete the pod running our application, then we'll check to make sure Kubernetes restarted our application pod.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pods</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-app-rust ❯  kubectl get pods</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME                                READY   STATUS    RESTARTS   AGE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-app-56c9ccc89d-skv7x   1/1     Running   0          71s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-db-686d758fbf-8jnq8    1/1     Running   0          12m</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete pod azure-voting-app-56c9ccc89d-skv7x</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pods</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-app-rust ❯  kubectl delete pod azure-voting-app-56c9ccc89d-skv7x</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">&gt;&gt; kubectl get pods</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pod "azure-voting-app-56c9ccc89d-skv7x" deleted</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME                                READY   STATUS    RESTARTS   AGE</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-app-56c9ccc89d-2b5mx   1/1     Running   0          2s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-db-686d758fbf-8jnq8    1/1     Running   0          14m</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Your Pods will likely have different identifiers at the end, so adjust your commands to match the names in your environment.</p></div></div>
<p>As you can see, by the time the <code>kubectl get pods</code> command was run, Kubernetes had already spun up a new pod for the application container image.  Thanks Kubernetes!</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="clean-up-1">Clean up<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#clean-up-1" class="hash-link" aria-label="Direct link to Clean up" title="Direct link to Clean up">​</a></h3>
<p>Since we can't just delete the pods, we have to delete the deployments.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete -f ./manifests/deployment-app.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete -f ./manifests/deployment-db.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="summary---deployments">Summary - Deployments<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#summary---deployments" class="hash-link" aria-label="Direct link to Summary - Deployments" title="Direct link to Summary - Deployments">​</a></h3>
<p>Deployments allow us to create more durable configuration for the workloads we deploy into Kubernetes. As we dig deeper, we'll discover more capabilities the deployments offer. Check out the Resources below for more.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="exercise">Exercise<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#exercise" class="hash-link" aria-label="Direct link to Exercise" title="Direct link to Exercise">​</a></h2>
<p>If you want to try these steps, head over to <a href="https://aka.ms/azure-voting-app-rust" target="_blank" rel="noopener noreferrer">the source repository</a>, fork it, clone it locally, and give it a spin!</p>
<p>You can check your manifests against the manifests in the <code>week2/day1</code> <a href="https://github.com/azure-samples/azure-voting-app-rust/tree/week2/day1/manifests" target="_blank" rel="noopener noreferrer">branch of the source repository</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Take the Cloud Skills Challenge!</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356" target="_blank" rel="noopener noreferrer">Enroll</a> in the Cloud Skills Challenge!</p><p>Don't miss out on this opportunity to level up your skills and stay ahead of the curve in the world of cloud native.</p></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="documentation">Documentation<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation">​</a></h3>
<ul>
<li><a href="https://learn.microsoft.com/azure/aks/intro-kubernetes?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a></li>
<li><a href="https://learn.microsoft.com/azure/azure-resource-manager/bicep/overview?WT.mc_id=containers-84290-stmuraws&amp;tabs=bicep" target="_blank" rel="noopener noreferrer">Bicep</a></li>
<li><a href="https://aka.ms/azure-voting-app-rust" target="_blank" rel="noopener noreferrer">Azure Voting App in Rust</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/concepts-clusters-workloads?WT.mc_id=containers-84290-stmuraws#pods" target="_blank" rel="noopener noreferrer">Pods</a>.</li>
<li><a href="https://learn.microsoft.com/azure/aks/concepts-clusters-workloads?WT.mc_id=containers-84290-stmuraws#nodes-and-node-pools" target="_blank" rel="noopener noreferrer">Nodes</a></li>
<li><a href="https://kubernetes.io/docs/reference/kubectl/kubectl/" target="_blank" rel="noopener noreferrer">kubectl</a></li>
<li><a href="https://kubernetes.io/docs/reference/kubectl/jsonpath/" target="_blank" rel="noopener noreferrer">JSONPath syntax</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/concepts-clusters-workloads?WT.mc_id=containers-84290-stmuraws#deployments-and-yaml-manifests" target="_blank" rel="noopener noreferrer">Deployment</a></li>
<li><a href="https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors" target="_blank" rel="noopener noreferrer">Labels and Selectors</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="training">Training<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#training" class="hash-link" aria-label="Direct link to Training" title="Direct link to Training">​</a></h3>
<ul>
<li><a href="https://learn.microsoft.com/training/paths/intro-to-kubernetes-on-azure/?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Learning Path - Introduction to Kubernetes on Azure</a></li>
</ul>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[2-2. Kubernetes Fundamentals - Services and Ingress]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-2</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-2</guid>
            <pubDate>Tue, 31 Jan 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[A Step-by-Step Guide using Kubernetes Service and Ingress Resources on AKS]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 2 of Week 2</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is #Kubernetes fundamentals. Yesterday we talked about how to deploy a containerized web app workload to Azure Kubernetes Service (AKS). Today we'll explore the topic of services and ingress and walk through the steps of making our containers accessible both internally as well as over the internet so that you can share it with the world 😊</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Ask the Experts Thursday, February 9th at 9 AM PST</div><div class="admonitionContent_BuS1"><p><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Watch our Q&amp;A with Experts from the Azure Kubernetes Service product team!</a></p></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Catch the Replay of the Live Demo</div><div class="admonitionContent_BuS1"><p>Watch the recorded demo and conversation about this week's topics.</p><p><a href="https://aka.ms/cnny/week2-demo" target="_blank" rel="noopener noreferrer">We were live on YouTube walking through today's (and the rest of this week's) demos</a>.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-2#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Exposing Pods via Service</li>
<li>Exposing Services via Ingress</li>
<li>Takeaways</li>
<li>Resources</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="exposing-pods-via-service">Exposing Pods via Service<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-2#exposing-pods-via-service" class="hash-link" aria-label="Direct link to Exposing Pods via Service" title="Direct link to Exposing Pods via Service">​</a></h2>
<p>There are a few ways to expose your pod in Kubernetes. One way is to take an imperative approach and use the <code>kubectl expose</code> command. This is probably the quickest way to achieve your goal but it isn't the best way. A better way to expose your pod by taking a declarative approach by creating a <a href="https://learn.microsoft.com/azure/aks/concepts-network?WT.mc_id=containers-84290-pauyu#services" target="_blank" rel="noopener noreferrer">services</a> manifest file and deploying it using the <code>kubectl apply</code> command.</p>
<p>Don't worry if you are unsure of how to make this manifest, we'll use <code>kubectl</code> to help generate it.</p>
<p>First, let's ensure we have the database deployed on our AKS cluster.</p>
<blockquote>
<p>📝 NOTE: If you don't have an AKS cluster deployed, please head over to <a href="https://github.com/Azure-Samples/azure-voting-app-rust/tree/main" target="_blank" rel="noopener noreferrer">Azure-Samples/azure-voting-app-rust</a>, clone the repo, and follow the instructions in the <a href="https://github.com/Azure-Samples/azure-voting-app-rust/blob/main/README.md" target="_blank" rel="noopener noreferrer">README.md</a> to execute the Azure deployment and setup your <code>kubectl</code> context.  Check out <a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#setting-up-a-kubernetes-environment-in-azure">the first post this week for more on the environment setup</a>.</p>
</blockquote>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/deployment-db.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, let's deploy the application. If you are following along from yesterday's content, there isn't anything you need to change; however, if you are deploy the app from scratch, you'll need to modify the <code>deployment-app.yaml</code> manifest and update it with your image tag and database pod's IP address.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/deployment-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now, let's expose the database using a service so that we can leverage Kubernetes' built-in service discovery to be able to reference it by name; not pod IP. Run the following command.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl expose deployment azure-voting-db \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --port=5432 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --target-port=5432</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>With the database exposed using service, we can update the app deployment manifest to use the service name instead of pod IP. This way, if the pod ever gets assigned a new IP, we don't have to worry about updating the IP each time and redeploying our web application. Kubernetes has internal service discovery mechanism in place that allows us to reference a service by its name.</p>
<p>Let's make an update to the manifest. Replace the environment variable for <code>DATABASE_SERVER</code> with the following:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DATABASE_SERVER</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Re-deploy the app with the updated configuration.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/deployment-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>One service down, one to go. Run the following command to expose the web application.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl expose deployment azure-voting-app \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --type=LoadBalancer \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --port=80 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --target-port=8080</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Notice the <code>--type</code> argument has a value of <code>LoadBalancer</code>. This service type is implemented by the <code>cloud-controller-manager</code> which is part of the Kubernetes control plane. When using a managed Kubernetes cluster such as Azure Kubernetes Service, a <a href="https://learn.microsoft.com/azure/aks/load-balancer-standard?WT.mc_id=containers-84290-pauyu#use-the-public-standard-load-balancer" target="_blank" rel="noopener noreferrer">public standard load balancer</a> will be able to provisioned when the service type is set to <code>LoadBalancer</code>. The load balancer will also have a public IP assigned which will make your deployment publicly available.</p>
<p>Kubernetes supports four <a href="https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types" target="_blank" rel="noopener noreferrer">service types</a>:</p>
<ul>
<li><strong>ClusterIP</strong>: this is the default and limits service access to internal traffic within the cluster</li>
<li><strong>NodePort</strong>: this assigns a port mapping on the node's IP address and allows traffic from the virtual network (outside the cluster)</li>
<li><strong>LoadBalancer</strong>: as mentioned above, this creates a cloud-based load balancer</li>
<li><strong>ExternalName</strong>: this is used in special case scenarios where you want to map a service to an external DNS name</li>
</ul>
<blockquote>
<p>📝 NOTE: When exposing a web application to the internet, allowing external users to connect to your <strong>Service</strong> directly is not the best approach. Instead, you should use an <strong>Ingress</strong>, which we'll cover in the next section.</p>
</blockquote>
<p>Now, let's confirm you can reach the web app from the internet. You can use the following command to print the URL to your terminal.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">echo "http://$(kubectl get service azure-voting-app -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Great! The <code>kubectl expose</code> command gets the job done, but as mentioned above, it is not the best method of exposing deployments. It is better to expose deployments declaratively using a <a href="https://kubernetes.io/docs/concepts/services-networking/service/" target="_blank" rel="noopener noreferrer">service</a> manifest, so let's delete the services and redeploy using manifests.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete service azure-voting-db azure-voting-app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To use <code>kubectl</code> to generate our manifest file, we can use the same <code>kubectl expose</code> command that we ran earlier but this time, we'll include  <code>--output=yaml</code> and <code>--dry-run=client</code>. This will instruct the command to output the manifest that would be sent to the <code>kube-api</code> server in YAML format to the terminal.</p>
<p>Generate the manifest for the database service.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl expose deployment azure-voting-db \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --type=ClusterIP \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --port=5432 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --target-port=5432 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --output=yaml \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --dry-run=client &gt; ./manifests/service-db.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Generate the manifest for the application service.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl expose deployment azure-voting-app \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --type=LoadBalancer \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --port=80 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --target-port=8080 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --output=yaml \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --dry-run=client &gt; ./manifests/service-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The command above redirected the YAML output to your manifests directory. Here is what the web application service looks like.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TCP</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> LoadBalancer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">loadBalancer</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>💡 TIP: To view the schema of any <code>api-resource</code> in Kubernetes, you can use the <code>kubectl explain</code> command. In this case the <code>kubectl explain service</code> command will tell us exactly what each of these fields do.</p>
</blockquote>
<p>Re-deploy the services using the new service manifests.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/service-db.yaml -f ./manifests/service-app.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># You should see TYPE is set to LoadBalancer and the EXTERNAL-IP is set</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get service azure-voting-db azure-voting-app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Confirm again that our application is accessible again. Run the following command to print the URL to the terminal.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">echo "http://$(kubectl get service azure-voting-app -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>That was easy, right? We just exposed both of our pods using Kubernetes services. The database only needs to be accessible from within the cluster so <code>ClusterIP</code> is perfect for that. For the web application, we specified the type to be <code>LoadBalancer</code> so that we can access the application over the public internet.</p>
<p>But wait... remember that if you want to expose web applications over the public internet, a Service with a public IP is not the best way; the better approach is to use an Ingress resource.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="exposing-services-via-ingress">Exposing Services via Ingress<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-2#exposing-services-via-ingress" class="hash-link" aria-label="Direct link to Exposing Services via Ingress" title="Direct link to Exposing Services via Ingress">​</a></h2>
<p>If you read through the Kubernetes documentation on <a href="https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress" target="_blank" rel="noopener noreferrer">Ingress</a> you will see a diagram that depicts the Ingress sitting in front of the Service resource with a routing rule between it. In order to use Ingress, you need to deploy an Ingress Controller and it can be configured with many routing rules to forward traffic to one or many backend services. So effectively, an Ingress is a load balancer for your Services.</p>
<p>With that said, we no longer need a service type of <code>LoadBalancer</code> since the service does not need to be accessible from the internet. It only needs to be accessible from the Ingress Controller (internal to the cluster) so we can change the service type to <code>ClusterIP</code>.</p>
<p>Update your <code>service.yaml</code> file to look like this:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TCP</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">targetPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>📝 NOTE: The default service type is ClusterIP so we can omit the <code>type</code> altogether.</p>
</blockquote>
<p>Re-apply the app service manifest.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/service-app.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># You should see TYPE set to ClusterIP and EXTERNAL-IP set to &lt;none&gt;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get service azure-voting-app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, we need to install an <a href="https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/" target="_blank" rel="noopener noreferrer">Ingress Controller</a>. There are quite a few options, and the Kubernetes-maintained <a href="https://github.com/kubernetes/ingress-nginx" target="_blank" rel="noopener noreferrer">NGINX Ingress Controller</a> is commonly deployed.</p>
<p>You could install this manually by following <a href="https://kubernetes.github.io/ingress-nginx/deploy/#azure" target="_blank" rel="noopener noreferrer">these instructions</a>, but if you do that you'll be responsible for maintaining and supporting the resource.</p>
<p>I like to take advantage of free maintenance and support when I can get it, so I'll opt to use the <a href="https://learn.microsoft.com/azure/aks/web-app-routing?WT.mc_id=containers-84290-pauyu&amp;tabs=without-osm" target="_blank" rel="noopener noreferrer">Web Application Routing add-on for AKS</a>.</p>
<blockquote>
<p>💡 TIP: Whenever you install an AKS add-on, it will be maintained and fully supported by Azure Support.</p>
</blockquote>
<p>Enable the web application routing add-on in our AKS cluster with the following command.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks addon enable \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name &lt;YOUR_AKS_NAME&gt; \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group &lt;YOUR_AKS_RESOURCE_GROUP&gt;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --addon web_application_routing</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<blockquote>
<p>⚠️ WARNING: This command can take a few minutes to complete</p>
</blockquote>
<p>Now, let's use the same approach we took in creating our service to create our Ingress resource. Run the following command to generate the Ingress manifest.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create ingress azure-voting-app \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --class=webapprouting.kubernetes.azure.com \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --rule="/*=azure-voting-app:80" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --output yaml \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --dry-run=client &gt; ./manifests/ingress.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <code>--class=webapprouting.kubernetes.azure.com</code> option activates the AKS web application routing add-on. This AKS add-on can also integrate with other Azure services such as <a href="https://learn.microsoft.com/azure/dns/dns-overview?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure DNS</a> and <a href="https://learn.microsoft.com/azure/key-vault/general/overview?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure Key Vault</a> for TLS certificate management and this special class makes it all work.</p>
<p>The <code>--rule="/*=azure-voting-app:80"</code> option looks confusing but we can use <code>kubectl</code> again to help us understand how to format the value for the option.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create ingress --help</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In the output you will see the following:</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">--rule=[]:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    Rule in format host/path=service:port[,tls=secretname]. Paths containing the leading character '*' are</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    considered pathType=Prefix. tls argument is optional.</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>It expects a <code>host</code> and <code>path</code> separated by a forward-slash, then expects the backend <code>service</code> name and <code>port</code> separated by a colon. We're not using a hostname for this demo so we can omit it. For the path, an asterisk is used to specify a wildcard path prefix.</p>
<p>So, the value of <code>/*=azure-voting-app:80</code> creates a routing rule for all paths following the domain (or in our case since we don't have a hostname specified, the IP) to route traffic to our <code>azure-voting-app</code> backend service on port <code>80</code>.</p>
<blockquote>
<p>📝 NOTE: Configuring the hostname and TLS is outside the scope of this demo but please visit this URL <a href="https://bit.ly/aks-webapp-routing" target="_blank" rel="noopener noreferrer">https://bit.ly/aks-webapp-routing</a> for an in-depth hands-on lab centered around Web Application Routing on AKS.</p>
</blockquote>
<p>Your <code>ingress.yaml</code> file should look like this:</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> networking.k8s.io/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Ingress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">ingressClassName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> webapprouting.kubernetes.azure.com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">rules</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">paths</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">backend</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">service</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              </span><span class="token key atrule" style="color:#00a4db">number</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">path</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> /</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">pathType</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Prefix</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">loadBalancer</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Apply the app ingress manifest.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/ingress.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Validate the web application is available from the internet again. You can run the following command to print the URL to the terminal.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">echo "http://$(kubectl get ingress azure-voting-app -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="takeaways">Takeaways<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-2#takeaways" class="hash-link" aria-label="Direct link to Takeaways" title="Direct link to Takeaways">​</a></h2>
<p>Exposing your applications both internally and externally can be easily achieved using Service and Ingress resources respectively. If your service is HTTP or HTTPS based and needs to be accessible from outsie the cluster, use Ingress with an internal Service (i.e., ClusterIP or NodePort); otherwise, use the Service resource.  If your TCP-based Service needs to be publicly accessible, you set the type to LoadBalancer to expose a public IP for it. To learn more about these resources, please visit the links listed below.</p>
<p>Lastly, if you are unsure how to begin writing your service manifest, you can use <code>kubectl</code> and have it do most of the work for you 🥳</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-2#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Take the Cloud Skills Challenge!</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356" target="_blank" rel="noopener noreferrer">Enroll</a> in the Cloud Skills Challenge!</p><p>Don't miss out on this opportunity to level up your skills and stay ahead of the curve in the world of cloud native.</p></div></div>
<ul>
<li><a href="https://learn.microsoft.com/azure/aks/concepts-network?WT.mc_id=containers-84290-pauyu#services" target="_blank" rel="noopener noreferrer">Services</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/concepts-network?WT.mc_id=containers-84290-pauyu#ingress-controllers" target="_blank" rel="noopener noreferrer">Ingress Controllers</a></li>
<li><a href="https://aka.ms/aks-webapp-routing-lab" target="_blank" rel="noopener noreferrer">Hands-on Lab: Web Application Routing on AKS</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/ingress-basic??WT.mc_id=containers-84290-pauyu&amp;tabs=azure-cli" target="_blank" rel="noopener noreferrer">How-to Guide: Ingress Controller in AKS</a></li>
</ul>]]></content:encoded>
            <category>cloud-native-new-year</category>
            <category>azure-kubernetes-service</category>
            <category>aks</category>
            <category>kubernetes</category>
            <category>service</category>
            <category>ingress</category>
        </item>
        <item>
            <title><![CDATA[2-3. Kubernetes Fundamentals - ConfigMaps and Secrets]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3</guid>
            <pubDate>Wed, 01 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Working with ConfigMaps and Secrets in Kubernetes]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 3 of Week 2</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is Kubernetes fundamentals. Yesterday we talked about Services and Ingress. Today we'll explore the topic of passing configuration and secrets to our applications in Kubernetes with ConfigMaps and Secrets.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Ask the Experts Thursday, February 9th at 9 AM PST</div><div class="admonitionContent_BuS1"><p><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Watch our Q&amp;A with Experts from the Azure Kubernetes Service product team!</a></p></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Catch the Replay of the Live Demo</div><div class="admonitionContent_BuS1"><p>Watch the recorded demo and conversation about this week's topics.</p><p><a href="https://aka.ms/cnny/week2-demo" target="_blank" rel="noopener noreferrer">We were live on YouTube walking through today's (and the rest of this week's) demos</a>.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Decouple configurations with ConfigMaps and Secerts</li>
<li>Passing Environment Data with ConfigMaps and Secrets</li>
<li>Conclusion</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="decouple-configurations-with-configmaps-and-secerts">Decouple configurations with ConfigMaps and Secerts<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3#decouple-configurations-with-configmaps-and-secerts" class="hash-link" aria-label="Direct link to Decouple configurations with ConfigMaps and Secerts" title="Direct link to Decouple configurations with ConfigMaps and Secerts">​</a></h2>
<p>A ConfigMap is a Kubernetes object that decouples configuration data from pod definitions. Kubernetes secerts are similar, but were designed to decouple senstive information.</p>
<p>Separating the configuration and secerts from your application promotes better organization and security of your Kubernetes environment. It also enables you to share the same configuration and different secerts across multiple pods and deployments which can simplify scaling and management. Using ConfigMaps and Secerts in Kubernetes is a best practice that can help to improve the scalability, security, and maintainability of your cluster.</p>
<p>By the end of this tutorial, you'll have added a Kubernetes ConfigMap and Secret to the Azure Voting deployment.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="passing-environment-data-with-configmaps-and-secrets">Passing Environment Data with ConfigMaps and Secrets<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3#passing-environment-data-with-configmaps-and-secrets" class="hash-link" aria-label="Direct link to Passing Environment Data with ConfigMaps and Secrets" title="Direct link to Passing Environment Data with ConfigMaps and Secrets">​</a></h2>
<blockquote>
<p>📝 NOTE: If you don't have an AKS cluster deployed, please head over to <a href="https://github.com/Azure-Samples/azure-voting-app-rust/tree/week2/day2" target="_blank" rel="noopener noreferrer">Azure-Samples/azure-voting-app-rust</a>, clone the repo, and follow the instructions in the <a href="https://github.com/Azure-Samples/azure-voting-app-rust/blob/main/README.md" target="_blank" rel="noopener noreferrer">README.md</a> to execute the Azure deployment and setup your <code>kubectl</code> context. Check out <a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#setting-up-a-kubernetes-environment-in-azure">the first post this week for more on the environment setup</a>.</p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="create-the-configmap">Create the ConfigMap<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3#create-the-configmap" class="hash-link" aria-label="Direct link to Create the ConfigMap" title="Direct link to Create the ConfigMap">​</a></h3>
<p>ConfigMaps can be used in one of two ways; as environment variables or volumes.</p>
<p>For this tutorial you'll use a ConfigMap to create three environment variables inside the pod; DATABASE_SERVER, FISRT_VALUE, and SECOND_VALUE. The DATABASE_SERVER provides part of connection string to a Postgres. FIRST_VALUE and SECOND_VALUE are configuration options that change what voting options the application presents to the users.</p>
<p>Follow the below steps to create a new ConfigMap:</p>
<ol>
<li>
<p>Create a YAML file named 'config-map.yaml'. In this file, specify the environment variables for the application.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ConfigMap</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">config</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">DATABASE_SERVER</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">FIRST_VALUE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Go"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">SECOND_VALUE</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Rust"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Create the config map in your Kubernetes cluster by running the following command:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create -f config-map.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
</ol>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="create-the-secret">Create the Secret<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3#create-the-secret" class="hash-link" aria-label="Direct link to Create the Secret" title="Direct link to Create the Secret">​</a></h3>
<p>The <code>deployment-db.yaml</code> and <code>deployment-app.yaml</code> are Kubernetes manifests that deploy the Azure Voting App. Currently, those deployment manifests contain the environment variables <code>POSTGRES_PASSWORD</code> and <code>DATABASE_PASSWORD</code> with the value stored as plain text. Your task is to replace that environment variable with a Kubernetes Secret.</p>
<p>Create a Secret running the following commands:</p>
<ol>
<li>
<p>Encode <code>mypassword</code>.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">echo -n "mypassword" | base64</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Create a YAML file named <code>secret.yaml</code>. In this file, add <code>POSTGRES_PASSWORD</code> as the key and the encoded value returned above under as the value in the data section.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Opaque</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">data</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">POSTGRES_PASSWORD</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> bXlwYXNzd29yZA==</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Create the Secret in your Kubernetes cluster by running the following command:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl create -f secret.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
</ol>
<blockquote>
<p>[!WARNING]
base64 encoding is a simple and widely supported way to obscure plaintext data, it is not secure, as it can easily be decoded. If you want to store sensitive data like password, you should use a more secure method like encrypting with a Key Management Service (KMS) before storing it in the Secret.</p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="modify-the-app-deployment-manifest">Modify the app deployment manifest<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3#modify-the-app-deployment-manifest" class="hash-link" aria-label="Direct link to Modify the app deployment manifest" title="Direct link to Modify the app deployment manifest">​</a></h3>
<p>With the ConfigMap and Secert both created the next step is to replace the environment variables provided in the application deployment manuscript with the values stored in the ConfigMap and the Secert.</p>
<p>Complete the following steps to add the ConfigMap and Secert to the deployment mainifest:</p>
<ol>
<li>
<p>Open the Kubernetes manifest file <code>deployment-app.yaml</code>.</p>
</li>
<li>
<p>In the containers section, add an <code>envFrom</code> section and upate the <code>env</code> section.</p>
<div class="language-yaml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yaml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">envFrom</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">configMapRef</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">config</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DATABASE_PASSWORD</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">valueFrom</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">secretKeyRef</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> POSTGRES_PASSWORD</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Using <code>envFrom</code> exposes all the values witin the ConfigMap as environment variables. Making it so you don't have to list them individually.</p>
</li>
<li>
<p>Save the changes to the deployment manifest file.</p>
</li>
<li>
<p>Apply the changes to the deployment by running the following command:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f deployment-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
</ol>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="modify-the-database-deployment-manifest">Modify the database deployment manifest<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3#modify-the-database-deployment-manifest" class="hash-link" aria-label="Direct link to Modify the database deployment manifest" title="Direct link to Modify the database deployment manifest">​</a></h3>
<p>Next, update the database deployment manifest and replace the plain text environment variable with the Kubernetes Secert.</p>
<ol>
<li>
<p>Open the <code>deployment-db.yaml</code>.</p>
</li>
<li>
<p>To add the secret to the deployment, replace the <em>env</em> section with the following code:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> POSTGRES_PASSWORD</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">valueFrom</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">secretKeyRef</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> POSTGRES_PASSWORD</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Apply the updated manifest.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f deployment-db.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
</ol>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="verify-the-configmap-and-output-environment-variables">Verify the ConfigMap and output environment variables<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3#verify-the-configmap-and-output-environment-variables" class="hash-link" aria-label="Direct link to Verify the ConfigMap and output environment variables" title="Direct link to Verify the ConfigMap and output environment variables">​</a></h3>
<p>Verify that the ConfigMap was added to your deploy by running the following command:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl describe deployment azure-voting-app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Browse the output until you find the <code>envFrom</code> section with the config map reference.</p>
<p>You can also verify that the environment variables from the config map are being passed to the container by running the command <code>kubectl exec -it &lt;pod-name&gt; -- printenv</code>. This command will show you all the environment variables passed to the pod including the one from configmap.</p>
<p>By following these steps, you will have successfully added a config map to the Azure Voting App Kubernetes deployment, and the environment variables defined in the config map will be passed to the container running in the pod.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="verify-the-secret-and-describe-the-deployment">Verify the Secret and describe the deployment<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3#verify-the-secret-and-describe-the-deployment" class="hash-link" aria-label="Direct link to Verify the Secret and describe the deployment" title="Direct link to Verify the Secret and describe the deployment">​</a></h3>
<p>Once the secret has been created you can verify it exists by running the following command:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get secrets</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You can view additional information, such as labels, annotations, type, and the Data by running kubectl describe:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl describe secret azure-voting-secret</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>By default, the describe command doesn't output the encoded value, but if you output the results as JSON or YAML you'll be able to see the secret's encoded value.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"> kubectl get secret azure-voting-secret -o json</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-3#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>In conclusion, using ConfigMaps and Secrets in Kubernetes can help to improve the scalability, security, and maintainability of your cluster. By decoupling configuration data and sensitive information from pod definitions, you can promote better organization and security in your Kubernetes environment. Additionally, separating these elements allows for sharing the same configuration and different secrets across multiple pods and deployments, simplifying scaling and management.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Take the Cloud Skills Challenge!</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356" target="_blank" rel="noopener noreferrer">Enroll</a> in the Cloud Skills Challenge!</p><p>Don't miss out on this opportunity to level up your skills and stay ahead of the curve in the world of cloud native.</p></div></div>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[2-4. Kubernetes Fundamentals - Volumes, Mounts, and Claims]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-4</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-4</guid>
            <pubDate>Thu, 02 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[A Step-by-Step Guide using Kubernetes Persistent Volumes, Persistent Volume Claims, and Storage Classes]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 4 of Week 2</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is Kubernetes fundamentals. Yesterday we talked about how to set app configurations and secrets at runtime using Kubernetes ConfigMaps and Secrets. Today we'll explore the topic of persistent storage on Kubernetes and show you can leverage Persistent Volumes and Persistent Volume Claims to ensure your PostgreSQL data can survive container restarts.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Ask the Experts Thursday, February 9th at 9 AM PST</div><div class="admonitionContent_BuS1"><p><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Watch our Q&amp;A with Experts from the Azure Kubernetes Service product team!</a></p></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Catch the Replay of the Live Demo</div><div class="admonitionContent_BuS1"><p>Watch the recorded demo and conversation about this week's topics.</p><p><a href="https://aka.ms/cnny/week2-demo" target="_blank" rel="noopener noreferrer">We were live on YouTube walking through today's (and the rest of this week's) demos</a>.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-4#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Containers are ephemeral</li>
<li>Persistent storage on Kubernetes</li>
<li>Persistent storage on AKS</li>
<li>Takeaways</li>
<li>Resources</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="containers-are-ephemeral">Containers are ephemeral<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-4#containers-are-ephemeral" class="hash-link" aria-label="Direct link to Containers are ephemeral" title="Direct link to Containers are ephemeral">​</a></h2>
<p>In our sample application, the frontend UI writes vote values to a backend PostgreSQL database. By default the database container stores its data on the container's local file system, so there will be data loss when the pod is re-deployed or crashes as containers are meant to start with a clean slate each time.</p>
<p>Let's re-deploy our sample app and experience the problem first hand.</p>
<blockquote>
<p>📝 NOTE: If you don't have an AKS cluster deployed, please head over to <a href="https://github.com/Azure-Samples/azure-voting-app-rust/tree/week2/day3" target="_blank" rel="noopener noreferrer">Azure-Samples/azure-voting-app-rust</a>, clone the repo, and follow the instructions in the <a href="https://github.com/Azure-Samples/azure-voting-app-rust/blob/main/README.md" target="_blank" rel="noopener noreferrer">README.md</a> to execute the Azure deployment and setup your <code>kubectl</code> context. Check out <a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#setting-up-a-kubernetes-environment-in-azure">the first post this week for more on the environment setup</a>.</p>
</blockquote>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Wait for the <code>azure-voting-app</code> service to be assigned a public IP then browse to the website and submit some votes. Use the command below to print the URL to the terminal.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">echo "http://$(kubectl get ingress azure-voting-app -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now, let's delete the pods and watch Kubernetes do what it does best... that is, re-schedule pods.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># wait for the pod to come up then ctrl+c to stop watching</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete --all pod --wait=false &amp;&amp; kubectl get po -w</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Once the pods have been recovered, reload the website and confirm the vote tally has been reset to zero.</p>
<p>We need to fix this so that the data outlives the container.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="persistent-storage-on-kubernetes">Persistent storage on Kubernetes<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-4#persistent-storage-on-kubernetes" class="hash-link" aria-label="Direct link to Persistent storage on Kubernetes" title="Direct link to Persistent storage on Kubernetes">​</a></h2>
<p>In order for application data to survive crashes and restarts, you must implement <a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/" target="_blank" rel="noopener noreferrer">Persistent Volumes and Persistent Volume Claims</a>.</p>
<p>A persistent volume represents storage that is available to the cluster. Storage volumes can be provisioned manually by an administrator or dynamically using <a href="https://kubernetes.io/docs/concepts/storage/volumes/#csi" target="_blank" rel="noopener noreferrer">Container Storage Interface (CSI)</a> and <a href="https://kubernetes.io/docs/concepts/storage/storage-classes/" target="_blank" rel="noopener noreferrer">storage classes</a>, which includes information on how to provision CSI volumes.</p>
<p>When a user needs to add persistent storage to their application, a persistent volume claim is made to allocate chunks of storage from the volume. This "claim" includes things like volume mode (e.g., file system or block storage), the amount of storage to allocate, the <a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes" target="_blank" rel="noopener noreferrer">access mode</a>, and optionally a storage class. Once a persistent volume claim has been deployed, users can add the volume to the pod and <a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#claims-as-volumes" target="_blank" rel="noopener noreferrer">mount it in a container</a>.</p>
<p>In the next section, we'll demonstrate how to enable persistent storage on AKS.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="persistent-storage-on-aks">Persistent storage on AKS<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-4#persistent-storage-on-aks" class="hash-link" aria-label="Direct link to Persistent storage on AKS" title="Direct link to Persistent storage on AKS">​</a></h2>
<p>With AKS, <a href="https://learn.microsoft.com/azure/aks/csi-storage-drivers?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">CSI drivers</a> and <a href="https://learn.microsoft.com/azure/aks/concepts-storage?WT.mc_id=containers-84290-pauyu#storage-classes" target="_blank" rel="noopener noreferrer">storage classes</a> are pre-deployed into your cluster. This allows you to natively use <a href="https://learn.microsoft.com/azure/aks/azure-disk-csi?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure Disks</a>, <a href="https://learn.microsoft.com/azure/aks/azure-files-csi?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure Files</a>, and <a href="https://learn.microsoft.com/azure/aks/azure-blob-csi?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure Blob Storage</a> as persistent volumes. You can either bring your own Azure storage account and use it with AKS or have AKS provision an Azure storage account for you.</p>
<p>To view the Storage CSI drivers that have been enabled in your AKS cluster, run the following command.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks show \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name &lt;YOUR_AKS_NAME&gt; \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group &lt;YOUR_AKS_RESOURCE_GROUP&gt; \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query storageProfile</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>You should see output that looks like this.</p>
<div class="language-json codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-json codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "blobCsiDriver": null,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "diskCsiDriver": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "enabled": true,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "version": "v1"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "fileCsiDriver": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "enabled": true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "snapshotController": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "enabled": true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To view the storage classes that have been installed in your cluster, run the following command.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get storageclass</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Workload requirements will dictate which CSI driver and storage class you will need to use.</p>
<p>If you need block storage, then you should use the <code>blobCsiDriver</code>. The driver may not be enabled by default but you can enable it by following instructions which can be found in the <a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-4#resources">Resources</a> section below.</p>
<p>If you need file storage you should leverage either <code>diskCsiDriver</code> or <code>fileCsiDriver</code>. The decision between these two boils down to whether or not you need to have the underlying storage accessible by one pod or multiple pods. It is important to note that <code>diskCsiDriver</code> currently supports access from a single pod only. Therefore, if you need data to be accessible by multiple pods at the same time, then you should opt for <code>fileCsiDriver</code>.</p>
<p>For our PostgreSQL deployment, we'll use the <code>diskCsiDriver</code> and have AKS create an Azure Disk resource for us. There is no need to create a PV resource, all we need to do to is create a PVC using the <code>managed-csi-premium</code> storage class.</p>
<p>Run the following command to create the PVC.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF            </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: PersistentVolumeClaim</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: pvc-azuredisk</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  accessModes:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    - ReadWriteOnce</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  resources:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    requests:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      storage: 10Gi</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  storageClassName: managed-csi-premium</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>When you check the PVC resource, you'll notice the <code>STATUS</code> is set to <code>Pending</code>. It will be set to <code>Bound</code> once the volume is mounted in the PostgreSQL container.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get persistentvolumeclaim</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Let's delete the <code>azure-voting-db</code> deployment.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete deploy azure-voting-db</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Next, we need to apply an updated deployment manifest which includes our PVC.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: apps/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: Deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  creationTimestamp: null</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  labels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    app: azure-voting-db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: azure-voting-db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  replicas: 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  selector:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    matchLabels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      app: azure-voting-db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  strategy: {}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  template:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      creationTimestamp: null</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      labels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        app: azure-voting-db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      containers:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      - image: postgres:15.0-alpine</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        name: postgres</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ports:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - containerPort: 5432</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        env:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: POSTGRES_PASSWORD</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          valueFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            secretKeyRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              name: azure-voting-secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              key: POSTGRES_PASSWORD</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        resources: {}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        volumeMounts:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: mypvc</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          mountPath: "/var/lib/postgresql/data"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          subPath: "data"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      volumes:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      - name: mypvc</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        persistentVolumeClaim:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          claimName: pvc-azuredisk</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In the manifest above, you'll see that we are mounting a new volume called <code>mypvc</code> (the name can be whatever you want) in the pod which points to a PVC named <code>pvc-azuredisk</code>. With the volume in place, we can mount it in the container by referencing the name of the volume  <code>mypvc</code> and setting the mount path to <code>/var/lib/postgresql/data</code> (which is the <a href="https://www.postgresql.org/docs/9.1/storage-file-layout.html" target="_blank" rel="noopener noreferrer">default path</a>).</p>
<blockquote>
<p>💡 IMPORTANT: When mounting a volume into a non-empty subdirectory, you must add <a href="https://kubernetes.io/docs/concepts/storage/volumes/#using-subpath" target="_blank" rel="noopener noreferrer"><code>subPath</code></a> to the volume mount and point it to a subdirectory in the volume rather than mounting at root. In our case, when Azure Disk is formatted, it leaves a <code>lost+found</code> directory as documented <a href="https://learn.microsoft.com/troubleshoot/azure/azure-kubernetes/could-not-change-permissions-azure-files?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">here</a>.</p>
</blockquote>
<p>Watch the pods and wait for the <code>STATUS</code> to show <code>Running</code> and the pod's <code>READY</code> status shows <code>1/1</code>.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># wait for the pod to come up then ctrl+c to stop watching</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get po -w</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Verify that the <code>STATUS</code> of the PVC is now set to <code>Bound</code></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get persistentvolumeclaim</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>With the new database container running, let's restart the application pod, wait for the pod's <code>READY</code> status to show <code>1/1</code>, then head back over to our web browser and submit a few votes.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete pod -lapp=azure-voting-app --wait=false &amp;&amp; kubectl get po -lapp=azure-voting-app -w</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now the moment of truth... let's rip out the pods again, wait for the pods to be re-scheduled, and confirm our vote counts remain in tact.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl delete --all pod --wait=false &amp;&amp; kubectl get po -w</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you navigate back to the website, you'll find the vote are still there 🎉</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="takeaways">Takeaways<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-4#takeaways" class="hash-link" aria-label="Direct link to Takeaways" title="Direct link to Takeaways">​</a></h2>
<p>By design, containers are meant to be ephemeral and stateless workloads are ideal on Kubernetes. However, there will come a time when your data needs to outlive the container. To persist data in your Kubernetes workloads, you need to leverage PV, PVC, and optionally storage classes. In our demo scenario, we leveraged CSI drivers built into AKS and created a PVC using pre-installed storage classes. From there, we updated the database deployment to mount the PVC in the container and AKS did the rest of the work in provisioning the underlying Azure Disk. If the built-in storage classes does not fit your needs; for example, you need to change the <code>ReclaimPolicy</code> or change the SKU for the Azure resource, then you can <a href="https://learn.microsoft.com/azure/aks/azure-disk-csi#create-a-custom-storage-class?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">create your own custom storage class</a> and configure it just the way you need it 😊</p>
<p>We'll revisit this topic again next week but in the meantime, check out some of the resources listed below to learn more.</p>
<p>See you in the next post!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-4#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Take the Cloud Skills Challenge!</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356" target="_blank" rel="noopener noreferrer">Enroll</a> in the Cloud Skills Challenge!</p><p>Don't miss out on this opportunity to level up your skills and stay ahead of the curve in the world of cloud native.</p></div></div>
<ul>
<li><a href="https://kubernetes.io/docs/concepts/storage/volumes/" target="_blank" rel="noopener noreferrer">Kubernetes: Volumes</a></li>
<li><a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/" target="_blank" rel="noopener noreferrer">Kubernetes: Persistent Volumes</a></li>
<li><a href="https://kubernetes.io/blog/2019/01/15/container-storage-interface-ga/" target="_blank" rel="noopener noreferrer">Container Storage Interface (CSI) for Kubernetes</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/csi-storage-drivers?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Container Storage Interface (CSI) drivers on Azure Kubernetes Service (AKS)</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/azure-blob-csi?WT.mc_id=containers-84290-pauyu&amp;tabs=NFS#enable-csi-driver-on-a-new-or-existing-aks-cluster" target="_blank" rel="noopener noreferrer">Enable CSI driver on a new or existing AKS cluster</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/concepts-storage?WT.mc_id=containers-84290-pauyu#volumes" target="_blank" rel="noopener noreferrer">AKS: Volumes</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/concepts-storage?WT.mc_id=containers-84290-pauyu#storage-classes" target="_blank" rel="noopener noreferrer">AKS: Storage Classes</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/azure-disks-dynamic-pv?WT.mc_id=containers-84290-pauyu#built-in-storage-classes" target="_blank" rel="noopener noreferrer">AKS: Built-in Storage Classes</a></li>
</ul>]]></content:encoded>
            <category>cloud-native-new-year</category>
            <category>azure-kubernetes-service</category>
            <category>aks</category>
            <category>kubernetes</category>
            <category>persistent-volumes</category>
            <category>persistent-volume-claims</category>
        </item>
        <item>
            <title><![CDATA[2-5. Kubernetes Fundamentals - Scaling Pods and Nodes]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5</guid>
            <pubDate>Fri, 03 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Learning to Scale Pods and Nodes in Kubernetes on Azure]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 5 of Week 2</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is Kubernetes fundamentals. Yesterday we talked about adding persistent storage to our deployment. Today we'll explore the topic of scaling pods and nodes in our Kubernetes cluster.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Ask the Experts Thursday, February 9th at 9 AM PST</div><div class="admonitionContent_BuS1"><p><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Watch our Q&amp;A with Experts from the Azure Kubernetes Service product team!</a></p></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Catch the Replay of the Live Demo</div><div class="admonitionContent_BuS1"><p>Watch the recorded demo and conversation about this week's topics.</p><p><a href="https://aka.ms/cnny/week2-demo" target="_blank" rel="noopener noreferrer">We were live on YouTube walking through today's (and the rest of this week's) demos</a>.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Scaling Our Application</li>
<li>Scaling Pods</li>
<li>Scaling Nodes</li>
<li>Exercise</li>
<li>Resources</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="scaling-our-application">Scaling Our Application<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#scaling-our-application" class="hash-link" aria-label="Direct link to Scaling Our Application" title="Direct link to Scaling Our Application">​</a></h2>
<p>One of our primary reasons to use a service like Kubernetes to orchestrate our workloads is the ability to scale.  We've approached scaling in a multitude of ways over the years, taking advantage of the ever-evolving levels of hardware and software. Kubernetes allows us to <a href="https://learn.microsoft.com/azure/aks/concepts-scale?WT.mc_id=containers-84290-stmuraws#manually-scale-pods-or-nodes" target="_blank" rel="noopener noreferrer">scale our units of work, Pods</a>, and <a href="https://learn.microsoft.com/azure/aks/concepts-scale?WT.mc_id=containers-84290-stmuraws#cluster-autoscaler" target="_blank" rel="noopener noreferrer">the Nodes they run on</a>.  This allows us to take advantage of both hardware and software scaling abilities.  Kubernetes can help improve the utilization of existing hardware (by scheduling Pods on Nodes that have resource capacity).  And, with the capabilities of virtualization and/or cloud hosting (or a bit more work, if you have a pool of physical machines), Kubernetes can expand (or contract) the number of Nodes capable of hosting Pods.  Scaling is primarily driven by resource utilization, but can be triggered by a variety of other sources thanks to projects like <a href="https://keda.sh/" target="_blank" rel="noopener noreferrer">Kubernetes Event-driven Autoscaling (KEDA)</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="scaling-pods">Scaling Pods<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#scaling-pods" class="hash-link" aria-label="Direct link to Scaling Pods" title="Direct link to Scaling Pods">​</a></h2>
<p>Our first level of scaling is with our Pods. Earlier, when we worked on our deployment, we talked about how the Kubernetes would use the deployment configuration to ensure that we had the desired workloads running.  One thing we didn't explore was running more than one instance of a pod. We can define a number of replicas of a pod in our <a href="https://learn.microsoft.com/azure/aks/concepts-clusters-workloads?WT.mc_id=containers-84290-stmuraws#deployments-and-yaml-manifests" target="_blank" rel="noopener noreferrer">Deployment</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="manually-scale-pods">Manually Scale Pods<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#manually-scale-pods" class="hash-link" aria-label="Direct link to Manually Scale Pods" title="Direct link to Manually Scale Pods">​</a></h3>
<p>So, if we wanted to define more pods right at the start (or at any point really), we could update our deployment configuration file with the number of replicas and apply that configuration file.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">replicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Or we could use the <code>kubectl scale</code> command to update the deployment with a number of pods to create.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl scale --replicas=5 deployment/azure-voting-app</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Both of these approaches modify the running configuration of our Kubernetes cluster and request that it ensure that we have that set number of replicas running.  Because this was a manual change, the Kubernetes cluster won't automatically increase or decrease the number of pods.  It'll just ensure that there are always the specified number of pods running.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="autoscale-pods-with-the-horizontal-pod-autoscaler">Autoscale Pods with the Horizontal Pod Autoscaler<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#autoscale-pods-with-the-horizontal-pod-autoscaler" class="hash-link" aria-label="Direct link to Autoscale Pods with the Horizontal Pod Autoscaler" title="Direct link to Autoscale Pods with the Horizontal Pod Autoscaler">​</a></h3>
<p>Another approach to scaling our pods is to allow the <a href="https://learn.microsoft.com/azure/aks/concepts-scale?WT.mc_id=containers-84290-stmuraws#horizontal-pod-autoscaler" target="_blank" rel="noopener noreferrer">Horizontal Pod Autoscaler</a> to help us scale in response to resources being used by the pod.  This requires a bit more configuration up front.  When we define our pod in our deployment, we need to include resource requests and limits.  The requests help Kubernetes determine what nodes may have capacity for a new instance of a pod.  The limit tells us where the node should cap utilization for a particular instance of a pod.  For example, we'll update our deployment to request 0.25 CPU and set a limit of 0.5 CPU.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> acrudavoz.azurecr.io/cnny2023/azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">rust</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">ca4</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">rust</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">containerPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">8080</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">env</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> DATABASE_URL</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> postgres</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//postgres</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">mypassword@10.244.0.29</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">resources</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">requests</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">cpu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 250m</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">limits</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">cpu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 500m</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Now that we've given Kubernetes an allowed range and an idea of what free resources a node should have to place new pods, we can set up autoscaling.  Because autoscaling is a persistent configuration, I like to define it in a configuration file that I'll be able to keep with the rest of my cluster configuration.  We'll use the <code>kubectl</code> command to help us write the configuration file.  We'll request that Kubernetes watch our pods and when the average CPU utilization if 50% of the requested usage (in our case if it's using more than 0.375 CPU across the current number of pods), it can grow the number of pods serving requests up to 10.  If the utilization drops, Kubernetes will have the permission to deprovision pods down to the minimum (three in our example).</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl autoscale deployment azure-voting-app --cpu-percent=50 --min=3 --max=10 -o YAML --dry-run=client</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Which would give us:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> autoscaling/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> HorizontalPodAutoscaler</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">creationTimestamp</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token null important">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">maxReplicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">10</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">minReplicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">3</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">scaleTargetRef</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> apps/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">voting</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">app</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">targetCPUUtilizationPercentage</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">50</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">status</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">currentReplicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">desiredReplicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>So, how often does the autoscaler check the metrics being monitored?  The autoscaler checks the Metrics API every 15 seconds, however the pods stats are only updated every 60 seconds.  This means that an autoscale event may be evaluated about once a minute.  Once an autoscale down event happens however, Kubernetes has a cooldown period to give the new pods a chance to distribute the workload and let the new metrics accumulate.  There is no delay on scale up events.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="application-architecture-considerations">Application Architecture Considerations<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#application-architecture-considerations" class="hash-link" aria-label="Direct link to Application Architecture Considerations" title="Direct link to Application Architecture Considerations">​</a></h3>
<p>We've focused in this example on our front end, which is an easier scaling story.  When we start talking about scaling our database layers or anything that deals with persistent storage or has primary/replica configuration requirements things get a bit more complicated. Some of these applications may have built-in leader election or <a href="https://kubernetes.io/blog/2016/01/simple-leader-election-with-kubernetes/" target="_blank" rel="noopener noreferrer">could use sidecars to help use existing features in Kubernetes to perform that function</a>.  For shared storage scenarios, <a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/" target="_blank" rel="noopener noreferrer">persistent volumes</a> (or <a href="https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/app-platform/aks/storage?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">persistent volumes with Azure</a>) can be of help, if the application knows how to play well with shared file access.</p>
<p>Ultimately, you know your application architecture and, while Kubernetes may not have an exact match to how you are doing things today, the underlying capability is probably there under a different name.  This abstraction allows you to more effectively use Kubernetes to operate a variety of workloads with the levels of controls you need.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="scaling-nodes">Scaling Nodes<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#scaling-nodes" class="hash-link" aria-label="Direct link to Scaling Nodes" title="Direct link to Scaling Nodes">​</a></h2>
<p>We've looked at how to scale our pods, but that assumes we have enough resources in our existing pool of nodes to accomodate those scaling requests.  Kubernetes can also help scale our available nodes to ensure that our applications have the necessary resources to meet their performance requirements.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="manually-scale-nodes">Manually Scale Nodes<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#manually-scale-nodes" class="hash-link" aria-label="Direct link to Manually Scale Nodes" title="Direct link to Manually Scale Nodes">​</a></h3>
<p>Manually scaling nodes isn't a direct function of Kubernetes, so your operating environment instructions may vary.  On Azure, it's pretty straight forward.  Using the Azure CLI (or other tools), we can tell our AKS cluster to scale up or scale down the number of nodes in our node pool.</p>
<p>First, we'll check out how many nodes we currently have in our working environment.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get nodes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>This will show us</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-app-rust ❯  kubectl get nodes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME                            STATUS   ROLES   AGE     VERSION</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">aks-pool0-37917684-vmss000000   Ready    agent   5d21h   v1.24.6</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Then, we'll scale it up to three nodes.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks scale --resource-group $ResourceGroup --name $AksName --node-count 3</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Then, we'll check out how many nodes we now have in our working environment.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get nodes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Which returns:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">azure-voting-app-rust ❯  kubectl get nodes</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NAME                            STATUS   ROLES   AGE     VERSION</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">aks-pool0-37917684-vmss000000   Ready    agent   5d21h   v1.24.6</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">aks-pool0-37917684-vmss000001   Ready    agent   5m27s   v1.24.6</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">aks-pool0-37917684-vmss000002   Ready    agent   5m10s   v1.24.6</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="autoscale-nodes-with-the-cluster-autoscaler">Autoscale Nodes with the Cluster Autoscaler<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#autoscale-nodes-with-the-cluster-autoscaler" class="hash-link" aria-label="Direct link to Autoscale Nodes with the Cluster Autoscaler" title="Direct link to Autoscale Nodes with the Cluster Autoscaler">​</a></h3>
<p>Things get more interesting when we start working with <a href="https://learn.microsoft.com/azure/aks/cluster-autoscaler?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">the Cluster Autoscaler</a>.  The Cluster Autoscaler watches for the inability of Kubernetes to schedule the required number of pods due to resource constraints (and a few other criteria like affinity/anti-affinity).  If there are insufficient resources available on the existing nodes, the autoscaler can provision new nodes into the nodepool.  Likewise, the autoscaler watches to see if the existing pods could be consolidated to a smaller set of nodes and can remove excess nodes.</p>
<p>Enabling the autoscaler is likewise an update that can be dependent on where and how your Kubernetes cluster is hosted. Azure makes it easy with a simple Azure CLI command.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks update `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $ResourceGroup `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AksName `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --update-cluster-autoscaler `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --min-count 1 `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --max-count 5</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>There are a <a href="https://learn.microsoft.com/azure/aks/cluster-autoscaler#using-the-autoscaler-profile?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">variety of settings</a> that can be configured to tune how the autoscaler works.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="scaling-on-different-events">Scaling on Different Events<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#scaling-on-different-events" class="hash-link" aria-label="Direct link to Scaling on Different Events" title="Direct link to Scaling on Different Events">​</a></h2>
<p>CPU and memory utilization are the primary drivers for the Horizontal Pod Autoscaler, but those might not be the best measures as to when you might want to scale workloads.  There are other options for scaling triggers and one of the more common plugins to help with that is the <a href="https://keda.sh/" target="_blank" rel="noopener noreferrer">Kubernetes Event-driven Autoscaling (KEDA) project</a>.  The KEDA project makes it easy to plug in different event sources to help drive scaling.  <a href="https://learn.microsoft.com/azure/aks/keda-about?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Find more information about using KEDA on AKS here.</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="exercise">Exercise<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#exercise" class="hash-link" aria-label="Direct link to Exercise" title="Direct link to Exercise">​</a></h2>
<p>Let's try out the scaling configurations that we just walked through using <a href="https://aka.ms/azure-voting-app-rust" target="_blank" rel="noopener noreferrer">our sample application</a>.  If you still have your environment from Day 1, you can use that.</p>
<blockquote>
<p>📝 NOTE: If you don't have an AKS cluster deployed, please head over to <a href="https://github.com/Azure-Samples/azure-voting-app-rust/tree/week2/day4" target="_blank" rel="noopener noreferrer">Azure-Samples/azure-voting-app-rust</a>, clone the repo, and follow the instructions in the <a href="https://github.com/Azure-Samples/azure-voting-app-rust/blob/main/README.md" target="_blank" rel="noopener noreferrer">README.md</a> to execute the Azure deployment and setup your <code>kubectl</code> context. Check out <a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#setting-up-a-kubernetes-environment-in-azure">the first post this week for more on the environment setup</a>.</p>
</blockquote>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="configure-horizontal-pod-autoscaler">Configure Horizontal Pod Autoscaler<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#configure-horizontal-pod-autoscaler" class="hash-link" aria-label="Direct link to Configure Horizontal Pod Autoscaler" title="Direct link to Configure Horizontal Pod Autoscaler">​</a></h3>
<ul>
<li>Edit <code>./manifests/deployment-app.yaml</code> to include resource requests and limits.</li>
</ul>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">resources</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">requests</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">cpu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 250m</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">limits</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">cpu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 500m</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>Apply the updated deployment configuration.</li>
</ul>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/deployment-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>Create the horizontal pod autoscaler configuration and apply it</li>
</ul>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl autoscale deployment azure-voting-app --cpu-percent=50 --min=3 --max=10 -o YAML --dry-run=client &gt; ./manifests/scaler-app.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f ./manifests/scaler-app.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>Check to see your pods scale out to the minimum.</li>
</ul>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pods</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="configure-cluster-autoscaler">Configure Cluster Autoscaler<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#configure-cluster-autoscaler" class="hash-link" aria-label="Direct link to Configure Cluster Autoscaler" title="Direct link to Configure Cluster Autoscaler">​</a></h3>
<p>Configuring the basic behavior of the Cluster Autoscaler is a bit simpler.  We just need to run the Azure CLI command to enable the autoscaler and define our lower and upper limits.</p>
<ul>
<li>Check the current nodes available (should be 1).</li>
</ul>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get nodes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>Update the cluster to enable the autoscaler</li>
</ul>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks update `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $ResourceGroup `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AksName `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --update-cluster-autoscaler `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --min-count 2 `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --max-count 5</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<ul>
<li>Check to see the current number of nodes (should be 2 now).</li>
</ul>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get nodes</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Take the Cloud Skills Challenge!</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356" target="_blank" rel="noopener noreferrer">Enroll</a> in the Cloud Skills Challenge!</p><p>Don't miss out on this opportunity to level up your skills and stay ahead of the curve in the world of cloud native.</p></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="documentation">Documentation<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#documentation" class="hash-link" aria-label="Direct link to Documentation" title="Direct link to Documentation">​</a></h3>
<ul>
<li><a href="https://learn.microsoft.com/azure/aks/concepts-scale?WT.mc_id=containers-84290-stmuraws#manually-scale-pods-or-nodes" target="_blank" rel="noopener noreferrer">Manually Scaling Pods and Nodes</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/concepts-clusters-workloads?WT.mc_id=containers-84290-stmuraws#deployments-and-yaml-manifests" target="_blank" rel="noopener noreferrer">Deployments</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/concepts-scale?WT.mc_id=containers-84290-stmuraws#horizontal-pod-autoscaler" target="_blank" rel="noopener noreferrer">Horizontal Pod Autoscaler</a></li>
<li><a href="https://kubernetes.io/blog/2016/01/simple-leader-election-with-kubernetes/" target="_blank" rel="noopener noreferrer">Leader Election in Kubernetes</a></li>
<li><a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/" target="_blank" rel="noopener noreferrer">Persistent Volumes</a></li>
<li><a href="https://learn.microsoft.com/azure/cloud-adoption-framework/scenarios/app-platform/aks/storage?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Persistent Volumes with Azure</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/cluster-autoscaler?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Cluster Autoscaler</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/cluster-autoscaler#using-the-autoscaler-profile?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Cluster Autoscaler Profile Settings</a></li>
<li><a href="https://keda.sh/" target="_blank" rel="noopener noreferrer">Kubernetes Event-driven Autoscaling (KEDA) project</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/keda-about?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">KEDA on AKS</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="training">Training<a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-5#training" class="hash-link" aria-label="Direct link to Training" title="Direct link to Training">​</a></h3>
<ul>
<li><a href="https://learn.microsoft.com/training/modules/aks-application-autoscaling-native?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Application scalability on AKS with HorizontalPodAutoscalers</a></li>
<li><a href="https://learn.microsoft.com/training/modules/aks-cluster-autoscaling?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Cluster Autoscaling with AKS</a></li>
<li><a href="https://learn.microsoft.com/training/modules/aks-app-scale-keda?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Scale container applications in Azure Kubernetes Services using KEDA</a></li>
</ul>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[3-1. Bringing Your Application to Kubernetes - CI/CD]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1</guid>
            <pubDate>Mon, 06 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Taking a existing application, containerizing it, and publishing to Kubernetes in GitHub Actions.]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 1 of Week 3</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is Bringing Your Application to Kubernetes. Last we talked about Kubernetes Fundamentals. Today we'll explore getting an existing application running in Kubernetes with a full pipeline in GitHub Actions.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Ask the Experts Thursday, February 9th at 9 AM PST</div><div class="admonitionContent_BuS1"><p><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Watch our Q&amp;A with Experts from the Azure Kubernetes Service product team!</a></p></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Friday, February 10th at 11 AM PST</div><div class="admonitionContent_BuS1"><p>Watch the recorded demo and conversation about this week's topics.</p><p><a href="https://aka.ms/cnny/week3-demo" target="_blank" rel="noopener noreferrer">We were live on YouTube walking through today's (and the rest of this week's) demos</a>.  Join us Friday, February 10th and bring your questions!</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Our Application</li>
<li>Adding Some Infrastructure as Code</li>
<li>Building and Publishing a Container Image</li>
<li>Deploying to Kubernetes</li>
<li>Summary</li>
<li>Resources</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="our-application">Our Application<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#our-application" class="hash-link" aria-label="Direct link to Our Application" title="Direct link to Our Application">​</a></h2>
<p>This week we'll be taking an exisiting application - something similar to a typical line of business application - and setting it up to run in Kubernetes.  Over the course of the week, we'll address different concerns.  Today we'll focus on updating our CI/CD process to handle standing up (or validating that we have) an <a href="https://learn.microsoft.com/azure/aks/intro-kubernetes?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service (AKS)</a> environment, building and publishing container images for our web site and API server, and getting those services running in Kubernetes.</p>
<p>The application we'll be starting with is <a href="https://github.com/Azure-Samples/eShopOnAKS" target="_blank" rel="noopener noreferrer">eShopOnWeb</a>.  This application has a web site and API which are backed by a SQL Server instance.  It's built in .NET 7, so it's cross-platform.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>For the enterprising among you, you may notice that there are a number of different eShopOn* variants on GitHub, including <a href="https://github.com/dotnet-architecture/eShopOnContainers" target="_blank" rel="noopener noreferrer">eShopOnContainers</a>.  We aren't using that example as it's more of an end state than a starting place. Afterwards, feel free to check out that example as what this solution could look like as a series of microservices.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="adding-some-infrastructure-as-code">Adding Some Infrastructure as Code<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#adding-some-infrastructure-as-code" class="hash-link" aria-label="Direct link to Adding Some Infrastructure as Code" title="Direct link to Adding Some Infrastructure as Code">​</a></h2>
<p><a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#setting-up-a-kubernetes-environment-in-azure">Just like last week</a>, we need to stand up an AKS environment.  This week, however, rather than running commands in our own shell, we'll set up GitHub Actions to do that for us.</p>
<p>There is a <strong>LOT</strong> of plumbing in this section, <strong>but</strong> once it's set up, it'll make our lives a lot easier.  This section ensures that we have an environment to deploy our application into configured the way we want.  We can easily extend this to accomodate multiple environments or add additional microservices with minimal new effort.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="federated-identity">Federated Identity<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#federated-identity" class="hash-link" aria-label="Direct link to Federated Identity" title="Direct link to Federated Identity">​</a></h3>
<p>Setting up a federated identity will allow us a more securable and auditable way of accessing Azure from GitHub Actions.  For more about setting up a federated identity, Microsoft Learn has the details on <a href="https://learn.microsoft.com/azure/developer/github/connect-from-azure?tabs=azure-portal%2Cwindows&amp;WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">connecting GitHub Actions to Azure</a>.</p>
<p>Here, we'll just walk through the setup of the identity and configure GitHub to use that idenity to deploy our AKS environment and interact with our Azure Container Registry.</p>
<p>The examples will use PowerShell, but a Bash version of the setup commands is available in the <a href="https://github.com/Azure-Samples/eShopOnAKS/tree/week3/day1" target="_blank" rel="noopener noreferrer">week3/day1 branch</a>.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites">​</a></h4>
<p>To follow along, you'll need:</p>
<ul>
<li>a GitHub account</li>
<li>an Azure Subscription</li>
<li>the Azure CLI</li>
<li>and the Git CLI.</li>
</ul>
<p>You'll need to fork the <a href="https://github.com/Azure-Samples/eShopOnAKS" target="_blank" rel="noopener noreferrer">source repository</a> under your GitHub user or organization where you can manage secrets and GitHub Actions.</p>
<p>It would be helpful to have the <a href="https://cli.github.com/" target="_blank" rel="noopener noreferrer">GitHub CLI</a>, but it's not required.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="set-up-some-defaults">Set Up Some Defaults<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#set-up-some-defaults" class="hash-link" aria-label="Direct link to Set Up Some Defaults" title="Direct link to Set Up Some Defaults">​</a></h4>
<p>You will need to update one or more of the variables (your user or organization, what branch you want to work off of, and possibly the Azure AD application name if there is a conflict).</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Replace the gitHubOrganizationName value</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># with the user or organization you forked</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># the repository under.</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$githubOrganizationName = 'Azure-Samples'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$githubRepositoryName  = 'eShopOnAKS'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$branchName = 'week3/day1'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$applicationName = 'cnny-week3-day1'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="create-an-azure-ad-application">Create an Azure AD Application<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#create-an-azure-ad-application" class="hash-link" aria-label="Direct link to Create an Azure AD Application" title="Direct link to Create an Azure AD Application">​</a></h4>
<p>Next, we need to create an Azure AD application.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Create an Azure AD application</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">$aksDeploymentApplication = New-AzADApplication -DisplayName $applicationName</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="set-up-federation-for-that-azure-ad-application">Set Up Federation for that Azure AD Application<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#set-up-federation-for-that-azure-ad-application" class="hash-link" aria-label="Direct link to Set Up Federation for that Azure AD Application" title="Direct link to Set Up Federation for that Azure AD Application">​</a></h4>
<p>And configure that application to allow federated credential requests from our GitHub repository for a particular branch.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Create a federated identity credential for the application</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">New-AzADAppFederatedCredential `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   -Name $applicationName `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   -ApplicationObjectId $aksDeploymentApplication.Id `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   -Issuer 'https://token.actions.githubusercontent.com' `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   -Audience 'api://AzureADTokenExchange' `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   -Subject "repo:$($githubOrganizationName)/$($githubRepositoryName):ref:refs/heads/$branchName"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="create-a-service-principal-for-the-azure-ad-application">Create a Service Principal for the Azure AD Application<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#create-a-service-principal-for-the-azure-ad-application" class="hash-link" aria-label="Direct link to Create a Service Principal for the Azure AD Application" title="Direct link to Create a Service Principal for the Azure AD Application">​</a></h4>
<p>Once the application has been created, we need a service principal tied to that application.  The service principal can be granted rights in Azure.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Create a service principal for the application</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">New-AzADServicePrincipal -AppId $($aksDeploymentApplication.AppId)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="give-that-service-principal-rights-to-azure-resources">Give that Service Principal Rights to Azure Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#give-that-service-principal-rights-to-azure-resources" class="hash-link" aria-label="Direct link to Give that Service Principal Rights to Azure Resources" title="Direct link to Give that Service Principal Rights to Azure Resources">​</a></h3>
<p>Because our Bicep deployment exists at the subscription level and we are creating role assignments, we need to give it Owner rights. If we changed the scope of the deployment to just a resource group, we could apply more scoped permissions.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">$azureContext = Get-AzContext</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">New-AzRoleAssignment `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   -ApplicationId $($aksDeploymentApplication.AppId) `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   -RoleDefinitionName Owner `</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">   -Scope $azureContext.Subscription.Id</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="add-secrets-to-github-repository">Add Secrets to GitHub Repository<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#add-secrets-to-github-repository" class="hash-link" aria-label="Direct link to Add Secrets to GitHub Repository" title="Direct link to Add Secrets to GitHub Repository">​</a></h4>
<p>If you have the GitHub CLI, you can use that right from your shell to set the secrets needed.</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">gh secret set AZURE_CLIENT_ID --body $aksDeploymentApplication.AppId</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">gh secret set AZURE_TENANT_ID --body $azureContext.Tenant.Id</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">gh secret set AZURE_SUBSCRIPTION_ID --body $azureContext.Subscription.Id</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Otherwise, you can create them through the web interface like I did in the Learn Live event below.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>It may look like the whole video will play, but it'll stop after configuring the secrets in GitHub (after about 9 minutes)</p><p>The video shows creating the Azure AD application, service principals, and configuring the federated identity in Azure AD and GitHub.</p></div></div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/sZ0Z-4r08so?start=1613&amp;end=2124" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"></iframe>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="creating-a-bicep-deployment">Creating a Bicep Deployment<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#creating-a-bicep-deployment" class="hash-link" aria-label="Direct link to Creating a Bicep Deployment" title="Direct link to Creating a Bicep Deployment">​</a></h3>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="resuable-workflows">Resuable Workflows<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#resuable-workflows" class="hash-link" aria-label="Direct link to Resuable Workflows" title="Direct link to Resuable Workflows">​</a></h4>
<p>We'll create our Bicep deployment in a <a href="https://docs.github.com/actions/using-workflows/reusing-workflows" target="_blank" rel="noopener noreferrer">reusable workflows</a>.  What are they?  The previous link has the documentation or the video below has <a href="https://twitter.com/brandonmartinez" target="_blank" rel="noopener noreferrer">my colleague Brandon Martinez</a> and I talking about them.</p>
<iframe width="560" height="315" src="https://www.youtube.com/embed/sZ0Z-4r08so?start=1065&amp;end=1524" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"></iframe>
<p>This workflow is basically <a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#setting-up-a-kubernetes-environment-in-azure">the same deployment</a> we did in last week's series, just in GitHub Actions.</p>
<p>Start by creating a file called <code>deploy_aks.yml</code> in the <code>.github/workflows</code> directory with the below contents.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> deploy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">workflow_call</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">inputs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">resourceGroupName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">secrets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_CLIENT_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_TENANT_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_SUBSCRIPTION_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">outputs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containerRegistryName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">description</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Container Registry Name</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> jobs.deploy.outputs.containerRegistryName </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containerRegistryUrl</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">description</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Container Registry Login Url</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> jobs.deploy.outputs.containerRegistryUrl </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">resourceGroupName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">description</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Resource Group Name</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> jobs.deploy.outputs.resourceGroupName </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">aksName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">description</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Azure Kubernetes Service Cluster Name</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">value</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> jobs.deploy.outputs.aksName </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">permissions</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">id-token</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> write</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">contents</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> read</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">jobs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">validate</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">runs-on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">steps</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/checkout@v2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure/login@v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Sign in to Azure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">client-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_CLIENT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">tenant-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_TENANT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">subscription-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_SUBSCRIPTION_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure/arm</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">deploy@v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Run preflight validation</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">deploymentName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> github.run_number </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">scope</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> subscription</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">region</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> eastus</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">template</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./deploy/main.bicep</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">parameters</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          resourceGroup=${{ inputs.resourceGroupName }}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">deploymentMode</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Validate</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">deploy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">needs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> validate</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">runs-on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">outputs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containerRegistryName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> steps.deploy.outputs.acr_name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containerRegistryUrl</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> steps.deploy.outputs.acr_login_server_url </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">resourceGroupName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> steps.deploy.outputs.resource_group_name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">aksName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> steps.deploy.outputs.aks_name </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">steps</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/checkout@v2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure/login@v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Sign in to Azure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">client-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_CLIENT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">tenant-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_TENANT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">subscription-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_SUBSCRIPTION_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure/arm</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">deploy@v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> deploy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Deploy Bicep file</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">failOnStdErr</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">deploymentName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> github.run_number </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">scope</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> subscription</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">region</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> eastus</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">template</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./deploy/main.bicep</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">parameters</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          resourceGroup=${{ inputs.resourceGroupName }}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="adding-the-bicep-deployment">Adding the Bicep Deployment<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#adding-the-bicep-deployment" class="hash-link" aria-label="Direct link to Adding the Bicep Deployment" title="Direct link to Adding the Bicep Deployment">​</a></h3>
<p>Once we have the Bicep deployment workflow, we can add it to the primary build definition in <code>.github/workflows/dotnetcore.yml</code></p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="permissions">Permissions<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#permissions" class="hash-link" aria-label="Direct link to Permissions" title="Direct link to Permissions">​</a></h4>
<p>First, we need to add a permissions block to let the workflow request our Azure AD token.  This can go towards the top of the YAML file (I started it on line 5).</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">permissions</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">id-token</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> write</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">contents</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> read</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="deploy-aks-job">Deploy AKS Job<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#deploy-aks-job" class="hash-link" aria-label="Direct link to Deploy AKS Job" title="Direct link to Deploy AKS Job">​</a></h4>
<p>Next, we'll add a reference to our reusable workflow.  This will go after the <code>build</code> job.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">deploy_aks</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">needs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">build</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./.github/workflows/deploy_aks.yml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">resourceGroupName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'cnny-week3'</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">secrets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_CLIENT_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_CLIENT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_TENANT_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_TENANT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_SUBSCRIPTION_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_SUBSCRIPTION_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="building-and-publishing-a-container-image">Building and Publishing a Container Image<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#building-and-publishing-a-container-image" class="hash-link" aria-label="Direct link to Building and Publishing a Container Image" title="Direct link to Building and Publishing a Container Image">​</a></h2>
<p>Now that we have our target environment in place and an Azure Container Registry, we can build and publish our container images.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="add-a-reusable-workflow">Add a Reusable Workflow<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#add-a-reusable-workflow" class="hash-link" aria-label="Direct link to Add a Reusable Workflow" title="Direct link to Add a Reusable Workflow">​</a></h3>
<p>First, we'll create a new file for our reusable workflow at <code>.github/workflows/publish_container_image.yml</code>.</p>
<p>We'll start the file with a name, the parameters it needs to run, and the permissions requirements for the federated identity request.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Publish Container Images</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">workflow_call</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">inputs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containerRegistryName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containerRegistryUrl</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">githubSha</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">secrets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_CLIENT_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_TENANT_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_SUBSCRIPTION_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">permissions</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">id-token</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> write</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">contents</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> read</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="build-the-container-images">Build the Container Images<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#build-the-container-images" class="hash-link" aria-label="Direct link to Build the Container Images" title="Direct link to Build the Container Images">​</a></h4>
<p>Our next step is to build the two container images we'll need for the application, the website and the API.  We'll build the container images on our build worker and tag it with the git SHA, so there'll be a direct tie between the point in time in our codebase and the container images that represent it.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">jobs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">publish_container_image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">runs-on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">steps</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/checkout@v2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> docker build</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        docker build . -f src/Web/Dockerfile -t ${{ inputs.containerRegistryUrl }}/web:${{ inputs.githubSha }}</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        docker build . -f src/PublicApi/Dockerfile -t ${{ inputs.containerRegistryUrl }}/api:${{ inputs.githubSha}}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="scan-the-container-images">Scan the Container Images<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#scan-the-container-images" class="hash-link" aria-label="Direct link to Scan the Container Images" title="Direct link to Scan the Container Images">​</a></h4>
<p>Before we publish those container images, we'll scan them for vulnerabilities and best practice violations.  We can add these two steps (one scan for each image).</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> scan web container image</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Azure/container</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">scan@v0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">image-name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> inputs.containerRegistryUrl </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">/web</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> inputs.githubSha</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> scan api container image</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Azure/container</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">scan@v0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">image-name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> inputs.containerRegistryUrl </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">/web</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">$</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> inputs.githubSha</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The container images provided have a few items that'll be found. We can create an allowed list at <code>.github/containerscan/allowedlist.yaml</code> to define vulnerabilities or best practice violations that we'll explictly allow to <strong>not</strong> fail our build.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">general</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">vulnerabilities</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CVE</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">2022</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">29458</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CVE</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">2022</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">3715</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CVE</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">2022</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">1304</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CVE</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">2021</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">33560</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CVE</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">2020</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">16156</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CVE</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">2019</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">8457</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CVE</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">2018</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">8292</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">bestPracticeViolations</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CIS</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">DI</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">0001</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CIS</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">DI</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">0005</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CIS</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">DI</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">0006</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> CIS</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">DI</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">0008</span><span class="token plain">  </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="publish-the-container-images">Publish the Container Images<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#publish-the-container-images" class="hash-link" aria-label="Direct link to Publish the Container Images" title="Direct link to Publish the Container Images">​</a></h4>
<p>Finally, we'll log in to Azure, then log in to our Azure Container Registry, and push our images.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure/login@v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Sign in to Azure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">client-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_CLIENT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">tenant-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_TENANT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">subscription-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_SUBSCRIPTION_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> acr login </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> az acr login </span><span class="token punctuation" style="color:#393A34">-</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">name $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> inputs.containerRegistryName  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> docker push</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        docker push ${{ inputs.containerRegistryUrl }}/web:${{ inputs.githubSha}}</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">        docker push ${{ inputs.containerRegistryUrl }}/api:${{ inputs.githubSha}}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="update-the-build-with-the-image-build-and-publish">Update the Build With the Image Build and Publish<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#update-the-build-with-the-image-build-and-publish" class="hash-link" aria-label="Direct link to Update the Build With the Image Build and Publish" title="Direct link to Update the Build With the Image Build and Publish">​</a></h3>
<p>Now that we have our reusable workflow to create and publish our container images, we can include that in our primary build defnition at <code>.github/workflows/dotnetcore.yml</code>.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">publish_container_image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">needs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">deploy_aks</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ./.github/workflows/publish_container_image.yml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containerRegistryName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> needs.deploy_aks.outputs.containerRegistryName </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containerRegistryUrl</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> needs.deploy_aks.outputs.containerRegistryUrl </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">githubSha</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> github.sha </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">secrets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_CLIENT_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_CLIENT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_TENANT_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_TENANT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_SUBSCRIPTION_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_SUBSCRIPTION_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="deploying-to-kubernetes">Deploying to Kubernetes<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#deploying-to-kubernetes" class="hash-link" aria-label="Direct link to Deploying to Kubernetes" title="Direct link to Deploying to Kubernetes">​</a></h2>
<p>Finally, we've gotten enough set up that a commit to the target branch will:</p>
<ul>
<li>build and test our application code</li>
<li>set up (or validate) our AKS and ACR environment</li>
<li>and create, scan, and publish our container images to ACR</li>
</ul>
<p>Our last step will be to deploy our application to Kubernetes.  We'll use the basic building blocks we worked with last week, <a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-1#creating-the-deployment">deployments</a> and <a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-2#exposing-pods-via-service">services</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="starting-the-reusable-workflow-to-deploy-to-aks">Starting the Reusable Workflow to Deploy to AKS<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#starting-the-reusable-workflow-to-deploy-to-aks" class="hash-link" aria-label="Direct link to Starting the Reusable Workflow to Deploy to AKS" title="Direct link to Starting the Reusable Workflow to Deploy to AKS">​</a></h3>
<p>We'll start our workflow with our parameters that we need, as well as the permissions to access the token to log in to Azure.</p>
<p>We'll check out our code, then log in to Azure, and use the <code>az</code> CLI to get credentials for our AKS cluster.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> deploy_to_aks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">workflow_call</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">inputs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">aksName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">resourceGroupName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containerRegistryUrl</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">githubSha</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">secrets</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_CLIENT_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_TENANT_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">AZURE_SUBSCRIPTION_ID</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">required</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">true</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">permissions</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">id-token</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> write</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">contents</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> read</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">jobs</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">deploy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">runs-on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ubuntu</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">steps</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> actions/checkout@v2</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">uses</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> azure/login@v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Sign in to Azure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">with</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">client-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_CLIENT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">tenant-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_TENANT_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">subscription-id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> $</span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> secrets.AZURE_SUBSCRIPTION_ID </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Get AKS Credentials</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          az aks get-credentials --resource-group ${{ inputs.resourceGroupName }} --name ${{ inputs.aksName }}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="edit-the-deployment-for-our-current-image-tag">Edit the Deployment For Our Current Image Tag<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#edit-the-deployment-for-our-current-image-tag" class="hash-link" aria-label="Direct link to Edit the Deployment For Our Current Image Tag" title="Direct link to Edit the Deployment For Our Current Image Tag">​</a></h3>
<p>Let's add the Kubernetes manifests to our repo.  This post is long enough, so you can find the content for the manifests folder <a href="https://github.com/Azure-Samples/eShopOnAKS/tree/week3/day1/manifests" target="_blank" rel="noopener noreferrer">in the manifests folder in the source repo under the <code>week3/day1</code> branch</a>.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p>If you only forked the main branch of the source repo, you can easily get the updated manifests by using the following <code>git</code> commands:</p><div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">git remote add upstream https://github.com/Azure-Samples/eShopOnAks</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">git fetch upstream week3/day1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">git checkout upstream/week3/day1 manifests</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>This will make the <code>week3/day1</code> branch available locally and then we can update the manifests directory to match the state of that branch.</p></div></div>
<p>The deployments and the service defintions should be familiar from last week's content (but not the same).  This week, however, there's a new file in the manifests - <code>./manifests/kustomization.yaml</code></p>
<p>This file helps us more dynamically edit our kubernetes manifests and support is baked right in to the <code>kubectl</code> command.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="kustomize-definition">Kustomize Definition<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#kustomize-definition" class="hash-link" aria-label="Direct link to Kustomize Definition" title="Direct link to Kustomize Definition">​</a></h4>
<p><a href="https://kustomize.io/" target="_blank" rel="noopener noreferrer">Kustomize</a> allows us to specify specific resource manifests and areas of that manifest to replace.  We've put some placeholders in our file as well, so we can replace those for each run of our CI/CD system.</p>
<p>In <code>./manifests/kustomization.yaml</code> you will see:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">resources</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> deployment</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">api.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> deployment</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">web.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Change the image name and version</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">images</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> notavalidregistry.azurecr.io/api</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">v0.1.0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">newName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;YOUR_ACR_SERVER</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain">/api</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">newTag</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;YOUR_IMAGE_TAG</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> notavalidregistry.azurecr.io/web</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">v0.1.0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">newName</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;YOUR_ACR_SERVER</span><span class="token punctuation" style="color:#393A34">&gt;</span><span class="token plain">/web</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">newTag</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> &lt;YOUR_IMAGE_TAG</span><span class="token punctuation" style="color:#393A34">&gt;</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="replacing-values-in-our-build">Replacing Values in our Build<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#replacing-values-in-our-build" class="hash-link" aria-label="Direct link to Replacing Values in our Build" title="Direct link to Replacing Values in our Build">​</a></h4>
<p>Now, we encounter a little problem - our deployment files need to know the tag and ACR server.  We can do a bit of <code>sed</code> magic to edit the file on the fly.</p>
<p>In <code>.github/workflows/deploy_to_aks.yml</code>, we'll add:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> replace_placeholders_with_current_run</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          sed -i "s/&lt;YOUR_ACR_SERVER&gt;/${{ inputs.containerRegistryUrl }}/g" ./manifests/kustomization.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          sed -i "s/&lt;YOUR_IMAGE_TAG&gt;/${{ inputs.githubSha }}/g" ./manifests/kustomization.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="deploying-the-manifests">Deploying the Manifests<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#deploying-the-manifests" class="hash-link" aria-label="Direct link to Deploying the Manifests" title="Direct link to Deploying the Manifests">​</a></h3>
<p>We have our manifests in place and our <code>kustomization.yaml</code> file (with commands to update it at runtime) ready to go, we can deploy our manifests.</p>
<p>First, we'll deploy our database (deployment and service).
Next, we'll use the <code>-k</code> parameter on <code>kubectl</code> to tell it to look for a <code>kustomize</code> configuration, transform the requested manifests and apply those.
Finally, we apply the service defintions for the web and API deployments.</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">run</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">|</span><span class="token scalar string" style="color:#e3116c"></span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          kubectl apply -f ./manifests/deployment-db.yaml \</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">                        -f ./manifests/service-db.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          kubectl apply -k ./manifests</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">          kubectl apply -f ./manifests/service-api.yaml \</span><br></span><span class="token-line" style="color:#393A34"><span class="token scalar string" style="color:#e3116c">                        -f ./manifests/service-web.yaml</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="summary">Summary<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#summary" class="hash-link" aria-label="Direct link to Summary" title="Direct link to Summary">​</a></h2>
<p>We've covered a lot of ground in today's post.  We set up federated credentials with GitHub.  Then we added reusable workflows to deploy an AKS environment and build/scan/publish our container images, and then to deploy them into our AKS environment.</p>
<p>This sets us up to start making changes to our application and Kubernetes configuration and have those changes automatically validated and deployed by our CI/CD system.  Tomorrow, we'll look at updating our application environment with runtime configuration, persistent storage, and more.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Take the Cloud Skills Challenge!</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356" target="_blank" rel="noopener noreferrer">Enroll</a> in the Cloud Skills Challenge!</p><p>Don't miss out on this opportunity to level up your skills and stay ahead of the curve in the world of cloud native.</p></div></div>
<ul>
<li><a href="https://learn.microsoft.com/azure/aks/intro-kubernetes?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service (AKS)</a></li>
<li><a href="https://docs.github.com/actions/using-workflows/reusing-workflows" target="_blank" rel="noopener noreferrer">Reusable workflows in GitHub Actions</a></li>
<li><a href="https://learn.microsoft.com/azure/developer/github/connect-from-azure?tabs=azure-portal%2Cwindows&amp;WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Connecting GitHub Actions to Azure</a></li>
<li><a href="https://kustomize.io/" target="_blank" rel="noopener noreferrer">Kustomize</a></li>
<li><a href="https://cli.github.com/" target="_blank" rel="noopener noreferrer">GitHub CLI</a></li>
<li><a href="https://github.com/Azure-Samples/eShopOnAKS" target="_blank" rel="noopener noreferrer">eShopOnAKS</a></li>
</ul>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[3-2. Bringing Your Application to Kubernetes - Adapting Storage, Secrets, and Configuration]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2</guid>
            <pubDate>Tue, 07 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Learn how to optimize your Kubernetes environment by implementing ConfigMaps for environment variable management, Azure Files for persistent storage, and Azure Workload Identity plus Azure Key Vault for secure secret management.]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 2 of Week 3</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is Bringing Your Application to Kubernetes. Yesterday we talked about getting an existing application running in Kubernetes with a full pipeline in GitHub Actions. Today we'll evaluate our sample application's configuration, storage, and networking requirements and implement using Kubernetes and Azure resources.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Ask the Experts Thursday, February 9th at 9 AM PST</div><div class="admonitionContent_BuS1"><p><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Watch our Q&amp;A with Experts from the Azure Kubernetes Service product team!</a></p></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Friday, February 10th at 11 AM PST</div><div class="admonitionContent_BuS1"><p>Watch the recorded demo and conversation about this week's topics.</p><p><a href="https://aka.ms/cnny/week3-demo" target="_blank" rel="noopener noreferrer">We were live on YouTube walking through today's (and the rest of this week's) demos</a>.  Join us Friday, February 10th and bring your questions!</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Gather requirements</li>
<li>Implement environment variables using ConfigMaps</li>
<li>Implement persistent volumes using Azure Files</li>
<li>Implement secrets using Azure Key Vault</li>
<li>Re-package deployments</li>
<li>Conclusion</li>
<li>Resources</li>
</ul>
<div class="theme-admonition theme-admonition-caution admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>caution</div><div class="admonitionContent_BuS1"><p>Before you begin, make sure you've gone through yesterday's <a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-1">post</a> to set up your AKS cluster.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="gather-requirements">Gather requirements<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#gather-requirements" class="hash-link" aria-label="Direct link to Gather requirements" title="Direct link to Gather requirements">​</a></h2>
<p>The eShopOnWeb application is written in .NET 7 and has two major pieces of functionality. The web UI is where customers can browse and shop. The web UI also includes an admin portal for managing the product catalog. This admin portal, is packaged as a WebAssembly application and relies on a separate REST API service. Both the web UI and the REST API connect to the same SQL Server container.</p>
<p>Looking through the source code which can be found <a href="https://github.com/Azure-Samples/eShopOnAKS/tree/main/src" target="_blank" rel="noopener noreferrer">here</a> we can identify requirements for configs, persistent storage, and secrets.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="database-server">Database server<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#database-server" class="hash-link" aria-label="Direct link to Database server" title="Direct link to Database server">​</a></h3>
<ul>
<li>Need to store the password for the <code>sa</code> account as a secure secret</li>
<li>Need persistent storage volume for data directory</li>
<li>Need to inject environment variables for SQL Server license type and EULA acceptance</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="web-ui-and-rest-api-service">Web UI and REST API service<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#web-ui-and-rest-api-service" class="hash-link" aria-label="Direct link to Web UI and REST API service" title="Direct link to Web UI and REST API service">​</a></h3>
<ul>
<li>Need to store database connection string as a secure secret</li>
<li>Need to inject ASP.NET environment variables to override app settings</li>
<li>Need persistent storage volume for ASP.NET key storage</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="implement-environment-variables-using-configmaps">Implement environment variables using ConfigMaps<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#implement-environment-variables-using-configmaps" class="hash-link" aria-label="Direct link to Implement environment variables using ConfigMaps" title="Direct link to Implement environment variables using ConfigMaps">​</a></h2>
<p>ConfigMaps are relatively straight-forward to create. If you were following along with the examples last week, this should be review 😉</p>
<p>Create a ConfigMap to store database environment variables.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: ConfigMap</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: mssql-settings</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">data:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  MSSQL_PID: Developer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ACCEPT_EULA: "Y"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Create another ConfigMap to store ASP.NET environment variables.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: ConfigMap</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: aspnet-settings</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">data:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ASPNETCORE_ENVIRONMENT: Development</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="implement-persistent-volumes-using-azure-files">Implement persistent volumes using Azure Files<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#implement-persistent-volumes-using-azure-files" class="hash-link" aria-label="Direct link to Implement persistent volumes using Azure Files" title="Direct link to Implement persistent volumes using Azure Files">​</a></h2>
<p>Similar to last week, we'll take advantage of storage classes built into AKS. For our SQL Server data, we'll use the <code>azurefile-csi-premium</code> storage class and leverage an <a href="https://learn.microsoft.com/azure/storage/files/storage-files-introduction?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure Files</a> resource as our PersistentVolume.</p>
<p>Create a PersistentVolumeClaim (PVC) for persisting SQL Server data.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: PersistentVolumeClaim</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: mssql-data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  accessModes:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - ReadWriteMany</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  storageClassName: azurefile-csi-premium</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  resources:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    requests:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      storage: 5Gi</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Create another PVC for persisting ASP.NET data.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: PersistentVolumeClaim</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: aspnet-data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  accessModes:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - ReadWriteMany</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  storageClassName: azurefile-csi-premium</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  resources:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    requests:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      storage: 5Gi</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="implement-secrets-using-azure-key-vault">Implement secrets using Azure Key Vault<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#implement-secrets-using-azure-key-vault" class="hash-link" aria-label="Direct link to Implement secrets using Azure Key Vault" title="Direct link to Implement secrets using Azure Key Vault">​</a></h2>
<p>It's a well known fact that Kubernetes secretes are not really secrets. They're just base64-encoded values and not secure, especially if malicious users have access to your Kubernetes cluster.</p>
<p>In a production scenario, you will want to leverage an external vault like <a href="https://azure.microsoft.com/products/key-vault?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure Key Vault</a> or <a href="https://www.vaultproject.io/" target="_blank" rel="noopener noreferrer">HashiCorp Vault</a> to encrypt and store secrets.</p>
<p>With AKS, we can enable the <a href="https://secrets-store-csi-driver.sigs.k8s.io/" target="_blank" rel="noopener noreferrer">Secrets Store CSI driver</a> add-on which will allow us to leverage Azure Key Vault.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Set some variables</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">RG_NAME=&lt;YOUR_RESOURCE_GROUP_NAME&gt;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AKS_NAME=&lt;YOUR_AKS_CLUSTER_NAME&gt;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ACR_NAME=&lt;YOUR_ACR_NAME&gt;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az aks enable-addons \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --addons azure-keyvault-secrets-provider \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AKS_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RG_NAME</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>With the add-on enabled, you should see <code>aks-secrets-store-csi-driver</code> and <code>aks-secrets-store-provider-azure</code> resources installed on each node in your Kubernetes cluster.</p>
<p>Run the command below to verify.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get pods \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --namespace kube-system \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --selector 'app in (secrets-store-csi-driver, secrets-store-provider-azure)'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The Secrets Store CSI driver allows us to use secret stores via Container Storage Interface (CSI) volumes. This provider offers capabilities such as mounting and syncing between the secure vault and Kubernetes Secrets. On AKS, the <a href="https://azure.github.io/secrets-store-csi-driver-provider-azure/docs/" target="_blank" rel="noopener noreferrer">Azure Key Vault Provider for Secrets Store CSI Driver</a> enables integration with <a href="https://learn.microsoft.com/azure/key-vault/general/overview?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure Key Vault</a>.</p>
<p>You may not have an Azure Key Vault created yet, so let's create one and add some secrets to it.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">AKV_NAME=$(az keyvault create \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name akv-eshop$RANDOM \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RG_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query name -o tsv)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Database server password</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az keyvault secret set \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --vault-name $AKV_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name mssql-password \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --value "@someThingComplicated1234"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Catalog database connection string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az keyvault secret set \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --vault-name $AKV_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name mssql-connection-catalog \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --value "Server=db;Database=Microsoft.eShopOnWeb.CatalogDb;User Id=sa;Password=@someThingComplicated1234;TrustServerCertificate=True;"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Identity database connection string</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az keyvault secret set \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --vault-name $AKV_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name mssql-connection-identity \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --value "Server=db;Database=Microsoft.eShopOnWeb.Identity;User Id=sa;Password=@someThingComplicated1234;TrustServerCertificate=True;"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="pods-authentication-using-azure-workload-identity">Pods authentication using Azure Workload Identity<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#pods-authentication-using-azure-workload-identity" class="hash-link" aria-label="Direct link to Pods authentication using Azure Workload Identity" title="Direct link to Pods authentication using Azure Workload Identity">​</a></h3>
<p>In order for our Pods to retrieve secrets from Azure Key Vault, we'll need to set up a way for the Pod to authenticate against Azure AD. This can be achieved by implementing the new <a href="https://learn.microsoft.com/azure/aks/workload-identity-overview?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure Workload Identity</a> feature of AKS.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>At the time of this writing, the workload identity feature of AKS is in Preview.</p></div></div>
<p>The workload identity feature within AKS allows us to leverage native Kubernetes resources and link a <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/" target="_blank" rel="noopener noreferrer">Kubernetes ServiceAccount</a> to an <a href="https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure Managed Identity</a> to authenticate against <a href="https://learn.microsoft.com/azure/active-directory/fundamentals/active-directory-whatis?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Azure AD</a>.</p>
<p>For the authentication flow, our Kubernetes cluster will act as an Open ID Connect (OIDC) issuer and will be able issue identity tokens to ServiceAccounts which will be assigned to our Pods.</p>
<p>The Azure Managed Identity will be granted permission to access secrets in our Azure Key Vault and with the ServiceAccount being assigned to our Pods, they will be able to retrieve our secrets.</p>
<p>For more information on how the authentication mechanism all works, check out this <a href="https://azure.github.io/azure-workload-identity/docs/introduction.html#how-it-works" target="_blank" rel="noopener noreferrer">doc</a>.</p>
<p>To implement all this, start by enabling the new preview feature for AKS.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az feature register \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --namespace "Microsoft.ContainerService" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name "EnableWorkloadIdentityPreview"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-caution admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>caution</div><div class="admonitionContent_BuS1"><p>This can take several minutes to complete.</p></div></div>
<p>Check the status and ensure the <code>state</code> shows <code>Regestered</code> before moving forward.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az feature show \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --namespace "Microsoft.ContainerService" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name "EnableWorkloadIdentityPreview"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Update your AKS cluster to enable the workload identity feature and enable the OIDC issuer endpoint.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks update \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AKS_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RG_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --enable-workload-identity \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --enable-oidc-issuer </span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Create an Azure Managed Identity and retrieve its client ID.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">MANAGED_IDENTITY_CLIENT_ID=$(az identity create \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name aks-workload-identity \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RG_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --subscription $(az account show --query id -o tsv) \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query 'clientId' -o tsv)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Create the Kubernetes ServiceAccount.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Set namespace (this must align with the namespace that your app is deployed into)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">SERVICE_ACCOUNT_NAMESPACE=default</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Set the service account name</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">SERVICE_ACCOUNT_NAME=eshop-serviceaccount</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Create the service account</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: ServiceAccount</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  annotations:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    azure.workload.identity/client-id: ${MANAGED_IDENTITY_CLIENT_ID}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  labels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    azure.workload.identity/use: "true"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: ${SERVICE_ACCOUNT_NAME}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  namespace: ${SERVICE_ACCOUNT_NAMESPACE}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>Note to enable this <code>ServiceAccount</code> to work with Azure Workload Identity, you must annotate the resource with <code>azure.workload.identity/client-id</code>, and add a label of <code>azure.workload.identity/use: "true"</code></p></div></div>
<p>That was a lot... Let's review what we just did.</p>
<p>We have an Azure Managed Identity (object in Azure AD), an OIDC issuer URL (endpoint in our Kubernetes cluster), and a Kubernetes ServiceAccount.</p>
<p>The next step is to "tie" these components together and establish a <a href="https://learn.microsoft.com/graph/api/resources/federatedidentitycredentials-overview?WT.mc_id=containers-84290-pauyu&amp;view=graph-rest-1.0" target="_blank" rel="noopener noreferrer">Federated Identity Credential</a> so that Azure AD can trust authentication requests from your Kubernetes cluster.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>This identity federation can be established between Azure AD any Kubernetes cluster; not just AKS 🤗</p></div></div>
<p>To establish the federated credential, we'll need the OIDC issuer URL, and a subject which points to your Kubernetes ServiceAccount.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Get the OIDC issuer URL</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">OIDC_ISSUER_URL=$(az aks show \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AKS_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RG_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query "oidcIssuerProfile.issuerUrl" -o tsv)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Set the subject name using this format: `system:serviceaccount:&lt;YOUR_SERVICE_ACCOUNT_NAMESPACE&gt;:&lt;YOUR_SERVICE_ACCOUNT_NAME&gt;`</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">SUBJECT=system:serviceaccount:$SERVICE_ACCOUNT_NAMESPACE:$SERVICE_ACCOUNT_NAME</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az identity federated-credential create \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name aks-federated-credential \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --identity-name aks-workload-identity \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RG_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --issuer $OIDC_ISSUER_URL \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --subject $SUBJECT</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>With the authentication components set, we can now create a <a href="https://secrets-store-csi-driver.sigs.k8s.io/getting-started/usage.html" target="_blank" rel="noopener noreferrer">SecretProviderClass</a> which includes details about the Azure Key Vault, the secrets to pull out from the vault, and identity used to access the vault.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Get the tenant id for the key vault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">TENANT_ID=$(az keyvault show \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AKV_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RG_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query properties.tenantId -o tsv)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Create the secret provider for azure key vault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: secrets-store.csi.x-k8s.io/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: SecretProviderClass</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: eshop-azure-keyvault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  provider: azure</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  parameters:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    usePodIdentity: "false"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    useVMManagedIdentity: "false"   </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    clientID: "${MANAGED_IDENTITY_CLIENT_ID}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    keyvaultName: "${AKV_NAME}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    cloudName: ""</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    objects:  |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      array:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          objectName: mssql-password</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          objectType: secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          objectVersion: ""</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          objectName: mssql-connection-catalog</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          objectType: secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          objectVersion: ""</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - |</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          objectName: mssql-connection-identity</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          objectType: secret</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          objectVersion: ""</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    tenantId: "${TENANT_ID}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  secretObjects:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - secretName: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    type: Opaque</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    data:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      - objectName: mssql-password</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        key: mssql-password</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      - objectName: mssql-connection-catalog</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        key: mssql-connection-catalog</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      - objectName: mssql-connection-identity</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        key: mssql-connection-identity</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Finally, lets grant the Azure Managed Identity permissions to retrieve secrets from the Azure Key Vault.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az keyvault set-policy \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AKV_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --secret-permissions get \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --spn $MANAGED_IDENTITY_CLIENT_ID</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="re-package-deployments">Re-package deployments<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#re-package-deployments" class="hash-link" aria-label="Direct link to Re-package deployments" title="Direct link to Re-package deployments">​</a></h2>
<p>Update your database deployment to load environment variables from our ConfigMap, attach the PVC and SecretProviderClass as volumes, mount the volumes into the Pod, and use the ServiceAccount to retrieve secrets.</p>
<p>Additionally, you may notice the database Pod is set to use <code>fsGroup:10001</code> as part of the <code>securityContext</code>. This is required as the MSSQL container runs using a non-root account called <code>mssql</code> and this account has the proper permissions to read/write data at the <code>/var/opt/mssql</code> mount path.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: apps/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: Deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  labels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    app: db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  replicas: 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  selector:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    matchLabels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      app: db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  template:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      labels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        app: db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      securityContext:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        fsGroup: 10001</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      serviceAccountName: ${SERVICE_ACCOUNT_NAME}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      containers:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: db</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          image: mcr.microsoft.com/mssql/server:2019-latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          ports:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - containerPort: 1433</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          envFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - configMapRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                name: mssql-settings</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          env:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: MSSQL_SA_PASSWORD</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              valueFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                secretKeyRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  key: mssql-password</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          resources: {}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          volumeMounts:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: mssqldb</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              mountPath: /var/opt/mssql</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              mountPath: "/mnt/secrets-store"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              readOnly: true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      volumes:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: mssqldb</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          persistentVolumeClaim:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            claimName: mssql-data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          csi:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            driver: secrets-store.csi.k8s.io</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            readOnly: true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            volumeAttributes:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              secretProviderClass: eshop-azure-keyvault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>We'll update the API and Web deployments in a similar way.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Set the image tag</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">IMAGE_TAG=&lt;YOUR_IMAGE_TAG&gt;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># API deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: apps/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: Deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: api</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  labels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    app: api</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  replicas: 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  selector:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    matchLabels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      app: api</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  template:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      labels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        app: api</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      serviceAccount: ${SERVICE_ACCOUNT_NAME}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      containers:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: api</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          image: ${ACR_NAME}.azurecr.io/api:${IMAGE_TAG}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          ports:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - containerPort: 80</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          envFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - configMapRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                name: aspnet-settings</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          env:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: ConnectionStrings__CatalogConnection</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              valueFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                secretKeyRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  key: mssql-connection-catalog</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: ConnectionStrings__IdentityConnection</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              valueFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                secretKeyRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  key: mssql-connection-identity</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          resources: {}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          volumeMounts:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: aspnet</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              mountPath: ~/.aspnet/https:/root/.aspnet/https:ro</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              mountPath: "/mnt/secrets-store"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              readOnly: true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      volumes:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: aspnet</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          persistentVolumeClaim:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            claimName: aspnet-data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          csi:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            driver: secrets-store.csi.k8s.io</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            readOnly: true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            volumeAttributes:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                secretProviderClass: eshop-azure-keyvault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">## Web deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: apps/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: Deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: web</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  labels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    app: web</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  replicas: 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  selector:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    matchLabels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      app: web</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  template:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      labels:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        app: web</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      serviceAccount: ${SERVICE_ACCOUNT_NAME}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      containers:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: web</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          image: ${ACR_NAME}.azurecr.io/web:${IMAGE_TAG}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          ports:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - containerPort: 80</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          envFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - configMapRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                name: aspnet-settings</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          env:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: ConnectionStrings__CatalogConnection</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              valueFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                secretKeyRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  key: mssql-connection-catalog</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: ConnectionStrings__IdentityConnection</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              valueFrom:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                secretKeyRef:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                  key: mssql-connection-identity</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          resources: {}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          volumeMounts:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: aspnet</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              mountPath: ~/.aspnet/https:/root/.aspnet/https:ro</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            - name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              mountPath: "/mnt/secrets-store"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              readOnly: true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      volumes:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: aspnet</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          persistentVolumeClaim:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            claimName: aspnet-data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        - name: eshop-secrets</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          csi:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            driver: secrets-store.csi.k8s.io</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            readOnly: true</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            volumeAttributes:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                secretProviderClass: eshop-azure-keyvault</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If all went well with your deployment updates, you should be able to browse to your website and buy some merchandise again 🥳</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">echo "http://$(kubectl get service web -o jsonpath='{.status.loadBalancer.ingress[0].ip}')"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>Although there is no visible changes on with our website, we've made a ton of changes on the Kubernetes backend to make this application much more secure and resilient.</p>
<p>We used a combination of Kubernetes resources and AKS-specific features to achieve our goal of securing our secrets and ensuring data is not lost on container crashes and restarts.</p>
<p>To learn more about the components we leveraged here today, checkout the resources and additional tutorials listed below.</p>
<p>You can also find manifests with all the changes made in today's post in the <a href="https://github.com/Azure-Samples/eShopOnAKS/tree/week3/day2" target="_blank" rel="noopener noreferrer">Azure-Samples/eShopOnAKS</a> repository.</p>
<p>See you in the next post!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Take the Cloud Skills Challenge!</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356" target="_blank" rel="noopener noreferrer">Enroll</a> in the Cloud Skills Challenge!</p><p>Don't miss out on this opportunity to level up your skills and stay ahead of the curve in the world of cloud native.</p></div></div>
<ul>
<li><a href="https://learn.microsoft.com/sql/linux/quickstart-sql-server-containers-kubernetes?WT.mc_id=containers-84290-pauyu&amp;view=sql-server-ver16" target="_blank" rel="noopener noreferrer">Quickstart: Deploy a SQL Server container with Azure Kubernetes Services (AKS)</a></li>
<li><a href="https://secrets-store-csi-driver.sigs.k8s.io/" target="_blank" rel="noopener noreferrer">Secrets Store CSI Driver</a></li>
<li><a href="https://azure.github.io/secrets-store-csi-driver-provider-azure/docs/" target="_blank" rel="noopener noreferrer">Azure Key Vault Provider for Secrets Store CSI Driver</a></li>
<li><a href="https://github.com/Azure/azure-workload-identity" target="_blank" rel="noopener noreferrer">Azure/azure-workload-identity</a></li>
<li><a href="https://azure.github.io/azure-workload-identity/docs/introduction.html" target="_blank" rel="noopener noreferrer">Azure AD Workload Identity</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/learn/tutorial-kubernetes-workload-identity?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">Tutorial: Use a workload identity with an application on Azure Kubernetes Service (AKS)</a></li>
</ul>]]></content:encoded>
            <category>cloud-native-new-year</category>
            <category>azure-kubernetes-service</category>
            <category>aks</category>
            <category>kubernetes</category>
            <category>configmaps</category>
            <category>persistent-storage</category>
            <category>secrets-management</category>
            <category>workload-identity</category>
        </item>
        <item>
            <title><![CDATA[3-3. Bringing Your Application to Kubernetes - Opening your Application with Ingress]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3</guid>
            <pubDate>Wed, 08 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Expose your web application on Azure Kubernetes Service with ease using the Web Application Routing add-on. Benefit from automatic installation of a NGINX Ingress Controller, integration with Azure DNS for custom domains, and secure TLS with Azure Key Vault. Follow our step-by-step guide to enhance the accessibility and security of your web application.]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 3 of Week 3</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is Bringing Your Application to Kubernetes. Yesterday we added configuration, secrets, and storage to our app. Today we'll explore how to expose the eShopOnWeb app so that customers can reach it over the internet using a custom domain name and TLS.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Ask the Experts Thursday, February 9th at 9 AM PST</div><div class="admonitionContent_BuS1"><p><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Watch our Q&amp;A with Experts from the Azure Kubernetes Service product team!</a></p></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Friday, February 10th at 11 AM PST</div><div class="admonitionContent_BuS1"><p>Watch the recorded demo and conversation about this week's topics.</p><p><a href="https://aka.ms/cnny/week3-demo" target="_blank" rel="noopener noreferrer">We were live on YouTube walking through today's (and the rest of this week's) demos</a>.  Join us Friday, February 10th and bring your questions!</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Gather requirements</li>
<li>Generate TLS certificate and store in Azure Key Vault</li>
<li>Implement custom DNS using Azure DNS</li>
<li>Enable Web Application Routing add-on for AKS</li>
<li>Implement Ingress for the web application</li>
<li>Conclusion</li>
<li>Resources</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="gather-requirements">Gather requirements<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3#gather-requirements" class="hash-link" aria-label="Direct link to Gather requirements" title="Direct link to Gather requirements">​</a></h2>
<p>Currently, our eShopOnWeb app has three Kubernetes services deployed:</p>
<ol>
<li><code>db</code> exposed internally via <code>ClusterIP</code></li>
<li><code>api</code> exposed externally via <code>LoadBalancer</code></li>
<li><code>web</code> exposed externally via <code>LoadBalancer</code></li>
</ol>
<p>As mentioned in <a href="https://azure.github.io/Cloud-Native/cnny-2023/fundamentals-day-2">my post last week</a>, Services allow applications to communicate with each other using DNS names. Kubernetes has service discovery capabilities built-in that allows Pods to resolve Services simply by using their names.</p>
<p>In the case of our <code>api</code> and <code>web</code> deployments, they can simply reach the database by calling its name. The service type of <code>ClusterIP</code> for the <code>db</code> can remain as-is since it only needs to be accessed by the <code>api</code> and <code>web</code> apps.</p>
<p>On the other hand, <code>api</code> and <code>web</code> both need to be accessed over the public internet. Currently, these services are using service type <code>LoadBalancer</code> which tells AKS to provision an Azure Load Balancer with a public IP address. No one is going to remember the IP addresses, so we need to make the app more accessible by adding a custom domain name and securing it with a TLS certificate.</p>
<p>Here's what we're going to need:</p>
<ul>
<li>Custom domain name for our app</li>
<li>TLS certificate for the custom domain name</li>
<li>Routing rule to ensure requests with <code>/api/</code> in the URL is routed to the backend REST API</li>
<li>Routing rule to ensure requests without <code>/api/</code> in the URL is routing to the web UI</li>
</ul>
<p>Just like last week, we will use the <a href="https://learn.microsoft.com/azure/aks/web-app-routing?WT.mc_id=containers-84290-pauyu&amp;tabs=without-osm" target="_blank" rel="noopener noreferrer">Web Application Routing</a> add-on for AKS. But this time, we'll integrate it with Azure DNS and Azure Key Vault to satisfy all of our requirements above.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>At the time of this writing the add-on is still in Public Preview</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="generate-tls-certificate-and-store-in-azure-key-vault">Generate TLS certificate and store in Azure Key Vault<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3#generate-tls-certificate-and-store-in-azure-key-vault" class="hash-link" aria-label="Direct link to Generate TLS certificate and store in Azure Key Vault" title="Direct link to Generate TLS certificate and store in Azure Key Vault">​</a></h2>
<p>We deployed an Azure Key Vault <a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-2">yesterday</a> to store secrets. We'll use it again to store a TLS certificate too.</p>
<p>Let's create and export a self-signed certificate for the custom domain.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">DNS_NAME=eshoponweb$RANDOM.com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">openssl req -new -x509 -nodes -out web-tls.crt -keyout web-tls.key -subj "/CN=${DNS_NAME}" -addext "subjectAltName=DNS:${DNS_NAME}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">openssl pkcs12 -export -in web-tls.crt -inkey web-tls.key -out web-tls.pfx -password pass:</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>For learning purposes we'll use a self-signed certificate and a fake custom domain name.</p><p>To browse to the site using the fake domain, we'll mimic a DNS lookup by adding an entry to your host file which maps the public IP address assigned to the ingress controller to the custom domain.</p><p>In a production scenario, you will need to have a real domain delegated to Azure DNS and a valid TLS certificate for the domain.</p></div></div>
<p>Grab your Azure Key Vault name and set the value in a variable for later use.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">RESOURCE_GROUP=cnny-week3</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">AKV_NAME=$(az resource list \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RESOURCE_GROUP \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-type Microsoft.KeyVault/vaults \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query "[0].name" -o tsv)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Grant yourself permissions to <code>get</code>, <code>list</code>, and <code>import</code> certificates.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">MY_USER_NAME=$(az account show --query user.name -o tsv)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">MY_USER_OBJECT_ID=$(az ad user show --id $MY_USER_NAME --query id -o tsv)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az keyvault set-policy \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AKV_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --object-id $MY_USER_OBJECT_ID \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --certificate-permissions get list import</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Upload the TLS certificate to Azure Key Vault and grab its certificate URI.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">WEB_TLS_CERT_ID=$(az keyvault certificate import \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --vault-name $AKV_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name web-tls \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --file web-tls.pfx \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query id \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --output tsv)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="implement-custom-dns-with-azure-dns">Implement custom DNS with Azure DNS<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3#implement-custom-dns-with-azure-dns" class="hash-link" aria-label="Direct link to Implement custom DNS with Azure DNS" title="Direct link to Implement custom DNS with Azure DNS">​</a></h2>
<p>Create a custom domain for our application and grab its Azure resource id.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">DNS_ZONE_ID=$(az network dns zone create \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $DNS_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RESOURCE_GROUP \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query id \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --output tsv)</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="enable-web-application-routing-add-on-for-aks">Enable Web Application Routing add-on for AKS<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3#enable-web-application-routing-add-on-for-aks" class="hash-link" aria-label="Direct link to Enable Web Application Routing add-on for AKS" title="Direct link to Enable Web Application Routing add-on for AKS">​</a></h2>
<p>As we enable the Web Application Routing add-on, we'll also pass in the Azure DNS Zone resource id which triggers the installation of the <a href="https://learn.microsoft.com/azure/aks/web-app-routing?WT.mc_id=containers-84290-pauyu&amp;tabs=without-osm#web-application-routing-add-on-overview:~:text=external%2Ddns%20controller%3A%20Watches%20for%20Kubernetes%20Ingress%20resources%20and%20creates%20DNS%20A%20records%20in%20the%20cluster%2Dspecific%20DNS%20zone.%20Note%20that%20this%20is%20only%20deployed%20when%20you%20pass%20in%20the%20%2D%2Ddns%2Dzone%2Dresource%2Did%20argument." target="_blank" rel="noopener noreferrer"><code>external-dns</code> controller</a> in your Kubernetes cluster. This controller will be able to write Azure DNS zone entries on your behalf as you deploy Ingress manifests.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">AKS_NAME=$(az resource list \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RESOURCE_GROUP \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-type Microsoft.ContainerService/managedClusters \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query "[0].name" -o tsv)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az aks enable-addons \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AKS_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RESOURCE_GROUP \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --addons web_application_routing \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --dns-zone-resource-id=$DNS_ZONE_ID \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --enable-secret-rotation</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The add-on will also deploy a new Azure Managed Identity which is used by the <code>external-dns</code> controller when writing Azure DNS zone entries. Currently, it does not have permission to do that, so let's grant it permission.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># This is where resources are automatically deployed by AKS</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">NODE_RESOURCE_GROUP=$(az aks show \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AKS_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RESOURCE_GROUP \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query nodeResourceGroup -o tsv)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># This is the managed identity created by the Web Application Routing add-on</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">MANAGED_IDENTTIY_OBJECT_ID=$(az resource show \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name webapprouting-${AKS_NAME} \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $NODE_RESOURCE_GROUP \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-type Microsoft.ManagedIdentity/userAssignedIdentities \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query properties.principalId \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --output tsv)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Grant the managed identity permissions to write DNS entries</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az role assignment create \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --role "DNS Zone Contributor" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --assignee $MANAGED_IDENTTIY_OBJECT_ID \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --scope $DNS_ZONE_ID</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The Azure Managed Identity will also be used to retrieve and rotate TLS certificates from Azure Key Vault. So we'll need to grant it permission for that too.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az keyvault set-policy \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $AKV_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --object-id $MANAGED_IDENTTIY_OBJECT_ID \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --secret-permissions get \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --certificate-permissions get</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="implement-ingress-for-the-web-application">Implement Ingress for the web application<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3#implement-ingress-for-the-web-application" class="hash-link" aria-label="Direct link to Implement Ingress for the web application" title="Direct link to Implement Ingress for the web application">​</a></h2>
<p>Before we create a new Ingress manifest, let's update the existing services to use <code>ClusterIP</code> instead of <code>LoadBalancer</code>. With an Ingress in place, there is no reason why we need the Service resources to be accessible from outside the cluster. The new Ingress will be the only entrypoint for external users.</p>
<p>We can use the <code>kubectl patch</code> command to update the services</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl patch service api -p '{"spec": {"type": "ClusterIP"}}'</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl patch service web -p '{"spec": {"type": "ClusterIP"}}'</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Deploy a new Ingress to place in front of the <code>web</code> Service. Notice there is a special <code>annotations</code> entry for <code>kubernetes.azure.com/tls-cert-keyvault-uri</code> which points back to our self-signed certificate that was uploaded to Azure Key Vault.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f - &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">apiVersion: networking.k8s.io/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kind: Ingress</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">metadata:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  annotations:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    kubernetes.azure.com/tls-cert-keyvault-uri: ${WEB_TLS_CERT_ID}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  name: web</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">spec:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  ingressClassName: webapprouting.kubernetes.azure.com</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  rules:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - host: ${DNS_NAME}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    http:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      paths:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      - backend:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          service:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            name: web</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            port:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              number: 80</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        path: /</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        pathType: Prefix</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      - backend:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          service:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            name: api</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            port:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">              number: 80</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        path: /api</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        pathType: Prefix</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  tls:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  - hosts:</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    - ${DNS_NAME}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    secretName: web-tls</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>In our manifest above, we've also configured the Ingress route the traffic to either the <code>web</code> or <code>api</code> services based on the URL path requested. If the request URL includes <code>/api</code>/ then it will send traffic to the <code>api</code> backend service. Otherwise, it will send traffic to the <code>web</code> service.</p>
<p>Within a few minutes, the <code>external-dns</code> controller will add an <code>A</code> record to Azure DNS which points to the Ingress resource's public IP. With the custom domain in place, we can simply browse using this domain name.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><div class="admonitionContent_BuS1"><p>As mentioned above, since this is not a real domain name, we need to modify our host file to make it seem like our custom domain is resolving to the Ingress' public IP address.</p><p>To get the ingress public IP, run the following:</p><div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Get the IP</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get ingress web -o jsonpath="{.status.loadBalancer.ingress[0].ip}"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Get the hostname</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get ingress web -o jsonpath="{.spec.tls[0].hosts[0]}"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>Next, open your host file and add an entry using the format <code>&lt;YOUR_PUBLIC_IP&gt; &lt;YOUR_CUSTOM_DOMAIN&gt;</code>. Below is an example of what it should look like.</p><div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">20.237.116.224 eshoponweb11265.com</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>See this <a href="https://linuxize.com/post/how-to-edit-your-hosts-file/" target="_blank" rel="noopener noreferrer">doc</a> for more info on how to do this.</p></div></div>
<p>When browsing to the website, you may be presented with a warning about the connection not being private. This is due to the fact that we are using a self-signed certificate. This is expected, so go ahead and proceed anyway to load up the page.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="why-is-the-admin-page-broken">Why is the Admin page broken?<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3#why-is-the-admin-page-broken" class="hash-link" aria-label="Direct link to Why is the Admin page broken?" title="Direct link to Why is the Admin page broken?">​</a></h3>
<p>If you log in using the <code>admin@microsoft.com</code> account and browse to the <strong>Admin</strong> page, you'll notice no products are loaded on the page.</p>
<p>This is because the admin page is built using Blazor and compiled as a WebAssembly application that runs in your browser. When the application was compiled, it packed the <code>appsettings.Development.json</code> file as an embedded resource. This file contains the base URL for the public API and it currently points to <code>https://localhost:5099</code>. Now that we have a domain name, we can update the base URL and point it to our custom domain.</p>
<p>From the root of the <code>eShopOnWeb</code> repo, update the configuration file using a <a href="https://www.geeksforgeeks.org/sed-command-in-linux-unix-with-examples/" target="_blank" rel="noopener noreferrer"><code>sed</code> command</a>.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">sed -i -e "s/localhost:5099/${DNS_NAME}/g" ./src/BlazorAdmin/wwwroot/appsettings.Development.json</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Rebuild and push the container to Azure Container Registry.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"># Grab the name of your Azure Container Registry</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">ACR_NAME=$(az resource list \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group $RESOURCE_GROUP \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-type Microsoft.ContainerRegistry/registries \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query "[0].name" -o tsv)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Invoke a build and publish job</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az acr build \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --registry $ACR_NAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --image $ACR_NAME.azurecr.io/web:v0.1.0 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --file ./src/Web/Dockerfile .</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Once the container build has completed, we can issue a <code>kubectl patch</code> command to quickly update the <code>web</code> deployment to test our change.</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl patch deployment web -p "$(cat &lt;&lt;EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  "spec": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "template": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      "spec": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        "containers": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            "name": "web",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            "image": "${ACR_NAME}.azurecr.io/web:v0.1.0"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ]</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">)"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If all went well, you will be able to browse the admin page again and confirm product data is being loaded 🥳</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>The Web Application Routing add-on for AKS aims to streamline the process of exposing it to the public using the open-source <a href="https://kubernetes.github.io/ingress-nginx/" target="_blank" rel="noopener noreferrer">NGINX Ingress Controller</a>. With the add-on being managed by Azure, it natively integrates with other Azure services like Azure DNS and eliminates the need to manually create DNS entries. It can also integrate with Azure Key Vault to automatically pull in TLS certificates and rotate them as needed to further reduce operational overhead.</p>
<p>We are one step closer to production and in the upcoming posts we'll further operationalize and secure our deployment, so stay tuned!</p>
<p>In the meantime, check out the resources listed below for further reading.</p>
<p>You can also find manifests with all the changes made in today's post in the <a href="https://github.com/Azure-Samples/eShopOnAKS/tree/week3/day3" target="_blank" rel="noopener noreferrer">Azure-Samples/eShopOnAKS</a> repository.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-3#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Take the Cloud Skills Challenge!</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356" target="_blank" rel="noopener noreferrer">Enroll</a> in the Cloud Skills Challenge!</p><p>Don't miss out on this opportunity to level up your skills and stay ahead of the curve in the world of cloud native.</p></div></div>
<ul>
<li><a href="https://learn.microsoft.com/azure/aks/web-app-routing?WT.mc_id=containers-84290-pauyu&amp;tabs=without-osm" target="_blank" rel="noopener noreferrer">Web Application Routing (Preview)</a></li>
<li><a href="https://dev.to/azure/web-application-routing-on-aks-58ap" target="_blank" rel="noopener noreferrer">Web Application Routing on AKS</a></li>
<li><a href="https://aka.ms/aks-webapp-routing-lab" target="_blank" rel="noopener noreferrer">Lab: Web Application Routing with AKS</a></li>
<li><a href="https://kubernetes.github.io/ingress-nginx/" target="_blank" rel="noopener noreferrer">NGINX Ingress Controller</a></li>
<li><a href="https://learn.microsoft.com/azure/dns/dns-overview?WT.mc_id=containers-84290-pauyu" target="_blank" rel="noopener noreferrer">What is Azure DNS?</a></li>
</ul>]]></content:encoded>
            <category>cloud-native-new-year</category>
            <category>azure-kubernetes-service</category>
            <category>aks</category>
            <category>kubernetes</category>
            <category>ingress</category>
            <category>nginx-ingress-controller</category>
            <category>azure-dns</category>
            <category>azure-key-vault</category>
        </item>
        <item>
            <title><![CDATA[3-4. Bringing Your Application to Kubernetes - Debugging and Instrumentation]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4</guid>
            <pubDate>Thu, 09 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Using Bridge to Kubernetes to debug your application.]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 4 of Week 3</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is Bringing Your Application to Kubernetes. Yesterday we exposed the eShopOnWeb app so that customers can reach it over the internet using a custom domain name and TLS. Today we'll explore the topic of debugging and instrumentation.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Ask the Experts Thursday, February 9th at 9 AM PST</div><div class="admonitionContent_BuS1"><p><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Watch our Q&amp;A with Experts from the Azure Kubernetes Service product team!</a></p></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Friday, February 10th at 11 AM PST</div><div class="admonitionContent_BuS1"><p>Watch the recorded demo and conversation about this week's topics.</p><p><a href="https://aka.ms/cnny/week3-demo" target="_blank" rel="noopener noreferrer">We were live on YouTube walking through today's (and the rest of this week's) demos</a>.  Join us Friday, February 10th and bring your questions!</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Debugging</li>
<li>Bridge To Kubernetes</li>
<li>Instrumentation</li>
<li>Resources: For self-study!</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="debugging">Debugging<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#debugging" class="hash-link" aria-label="Direct link to Debugging" title="Direct link to Debugging">​</a></h2>
<p>Debugging applications in a Kubernetes cluster can be challenging for several reasons:</p>
<ul>
<li><strong>Complexity:</strong> Kubernetes is a complex system with many moving parts, including pods, nodes, services, and config maps, all of which can interact in unexpected ways and cause issues.</li>
<li><strong>Distributed Environment:</strong> Applications running in a Kubernetes cluster are often distributed across multiple nodes, which makes it harder to determine the root cause of an issue.</li>
<li><strong>Logging and Monitoring:</strong> Debugging an application in a Kubernetes cluster requires access to logs and performance metrics, which can be difficult to obtain in a large and dynamic environment.</li>
<li><strong>Resource Management:</strong> Kubernetes manages resources such as CPU and memory, which can impact the performance and behavior of applications. Debugging resource-related issues requires a deep understanding of the Kubernetes resource model and the underlying infrastructure.</li>
<li><strong>Dynamic Nature:</strong> Kubernetes is designed to be dynamic, with the ability to add and remove resources as needed. This dynamic nature can make it difficult to reproduce issues and debug problems.</li>
</ul>
<p>However, there are many tools and practices that can help make debugging applications in a Kubernetes cluster easier, such as using centralized logging, monitoring, and tracing solutions, and following best practices for managing resources and deployment configurations.</p>
<p>There's also another great tool in our toolbox - <a href="https://learn.microsoft.com/visualstudio/bridge/overview-bridge-to-kubernetes?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Bridge to Kubernetes</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="bridge-to-kubernetes">Bridge to Kubernetes<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#bridge-to-kubernetes" class="hash-link" aria-label="Direct link to Bridge to Kubernetes" title="Direct link to Bridge to Kubernetes">​</a></h2>
<p>Bridge to Kubernetes is a great tool for microservice development and debugging applications without having to locally replicate all the required microservices.</p>
<p>Bridge to Kubernetes works with <a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.mindaro&amp;WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Visual Studio</a> or <a href="https://marketplace.visualstudio.com/items?itemName=mindaro.mindaro&amp;WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Visual Studio Code</a>.</p>
<p>We'll walk through using it with Visual Studio Code.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="connecting-bridge-to-kubernetes-to-our-cluster">Connecting Bridge to Kubernetes to Our Cluster<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#connecting-bridge-to-kubernetes-to-our-cluster" class="hash-link" aria-label="Direct link to Connecting Bridge to Kubernetes to Our Cluster" title="Direct link to Connecting Bridge to Kubernetes to Our Cluster">​</a></h3>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="ensure-your-aks-cluster-is-the-default-for-kubectl">Ensure your AKS cluster is the default for <code>kubectl</code><a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#ensure-your-aks-cluster-is-the-default-for-kubectl" class="hash-link" aria-label="Direct link to ensure-your-aks-cluster-is-the-default-for-kubectl" title="Direct link to ensure-your-aks-cluster-is-the-default-for-kubectl">​</a></h4>
<p>If you've recently spun up a new AKS cluster or you have been working with a different cluster, you may need to change what cluster credentials you have configured.</p>
<p>If it's a new cluster, we can use:</p>
<div class="language-shell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-shell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">RESOURCE_GROUP=&lt;YOUR RESOURCE GROUP NAME&gt;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">CLUSTER_NAME=&lt;YOUR AKS CLUSTER NAME&gt;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az aks get-credentials az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="open-the-command-palette">Open the command palette<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#open-the-command-palette" class="hash-link" aria-label="Direct link to Open the command palette" title="Direct link to Open the command palette">​</a></h4>
<p>Open the command palette and find <code>Bridge to Kubernetes: Configure</code>.  You may need to start typing the name to get it to show up.</p>
<p><img loading="lazy" alt="The command palette for Visual Studio Code is open and the first item is Bridge to Kubernetes: Configure" src="https://azure.github.io/Cloud-Native/assets/images/1-configure-bridge-to-kubernetes-33b483ced5b91fe095bbaaced8355f85.png" width="3852" height="2098" class="img_ev3q"></p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="pick-the-service-you-want-to-debug">Pick the service you want to debug<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#pick-the-service-you-want-to-debug" class="hash-link" aria-label="Direct link to Pick the service you want to debug" title="Direct link to Pick the service you want to debug">​</a></h4>
<p>Bridge to Kubernetes will redirect a service for you.  Pick the service you want to redirect, in this case we'll pick <code>web</code>.</p>
<p><img loading="lazy" alt="Selecting the web service to redirect in Visual Studio Code" src="https://azure.github.io/Cloud-Native/assets/images/2-configure-bridge-to-kubernetes-dfaff25b950fbb72bad2326144d3dee1.png" width="3852" height="2098" class="img_ev3q"></p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="identify-the-port-your-application-runs-on">Identify the port your application runs on<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#identify-the-port-your-application-runs-on" class="hash-link" aria-label="Direct link to Identify the port your application runs on" title="Direct link to Identify the port your application runs on">​</a></h4>
<p>Next, we'll be prompted to identify what port our application will run on locally.  For this application it'll be 5001, but that's just specific to this application (and the default for ASP.NET 7, I believe).</p>
<p><img loading="lazy" alt="Setting port 5001 as the port to redirect to the web Kubernetes service in Visual Studio Code" src="https://azure.github.io/Cloud-Native/assets/images/3-configure-bridge-to-kubernetes-d934e270f2317020abe65bb496826a24.png" width="3852" height="2098" class="img_ev3q"></p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="pick-a-debug-configuration-to-extend">Pick a debug configuration to extend<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#pick-a-debug-configuration-to-extend" class="hash-link" aria-label="Direct link to Pick a debug configuration to extend" title="Direct link to Pick a debug configuration to extend">​</a></h4>
<p>Bridge to Kubernetes has a couple of ways to run - it can inject it's setup and teardown to your existing debug configurations.  We'll pick <code>.NET Core Launch (web)</code>.</p>
<p><img loading="lazy" alt="Telling Bridge to Kubernetes to use the .NET Core Launch (web) debug configuration in Visual Studio Code" src="https://azure.github.io/Cloud-Native/assets/images/4-configure-bridge-to-kubernetes-ad871a07bf4fc2c9afbfa36da35ace2f.png" width="3852" height="2098" class="img_ev3q"></p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="forward-traffic-for-all-requests">Forward Traffic for All Requests<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#forward-traffic-for-all-requests" class="hash-link" aria-label="Direct link to Forward Traffic for All Requests" title="Direct link to Forward Traffic for All Requests">​</a></h4>
<p>The last prompt you'll get in the configuration is about how you want Bridge to Kubernetes to handle re-routing traffic.  The default is that all requests into the service will get your local version.</p>
<p>You can also redirect specific traffic.  Bridge to Kubernetes will set up a subdomain and route specific traffic to your local service, while allowing other traffic to the deployed service.</p>
<p><img loading="lazy" alt="Allowing the launch of Endpoint Manager on Windows" src="https://azure.github.io/Cloud-Native/assets/images/5-configure-bridge-to-kubernetes-ab4047f6e94988975e019ea3c2ecf698.png" width="3852" height="2098" class="img_ev3q"></p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="using-bridge-to-kubernetes-to-debug-our-service">Using Bridge to Kubernetes to Debug Our Service<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#using-bridge-to-kubernetes-to-debug-our-service" class="hash-link" aria-label="Direct link to Using Bridge to Kubernetes to Debug Our Service" title="Direct link to Using Bridge to Kubernetes to Debug Our Service">​</a></h3>
<p>Now that we've configured Bridge to Kubernetes, we see that tasks and a new launch configuration have been added.</p>
<p>Added to <code>.vscode/tasks.json</code>:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"label"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"bridge-to-kubernetes.resource"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"type"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"bridge-to-kubernetes.resource"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"resource"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"web"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"resourceType"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"service"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"ports"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token number" style="color:#36acaa">5001</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"targetCluster"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"aks1"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"targetNamespace"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"default"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"useKubernetesServiceEnvironmentVariables"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">false</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"label"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"bridge-to-kubernetes.compound"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"dependsOn"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"bridge-to-kubernetes.resource"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"build"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"dependsOrder"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"sequence"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>And added to <code>.vscode/launch.json</code>:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"name"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">".NET Core Launch (web) with Kubernetes"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"type"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"coreclr"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"request"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"launch"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"preLaunchTask"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"bridge-to-kubernetes.compound"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"program"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"${workspaceFolder}/src/Web/bin/Debug/net7.0/Web.dll"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"args"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"cwd"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"${workspaceFolder}/src/Web"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"stopAtEntry"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token boolean important" style="color:#36acaa">false</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"env"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"ASPNETCORE_ENVIRONMENT"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"Development"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"ASPNETCORE_URLS"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http://+:5001"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"sourceFileMap"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">"/Views"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"${workspaceFolder}/Views"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="launch-the-debug-configuration">Launch the debug configuration<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#launch-the-debug-configuration" class="hash-link" aria-label="Direct link to Launch the debug configuration" title="Direct link to Launch the debug configuration">​</a></h4>
<p>We can start the process with the <code>.NET Core Launch (web) with Kubernetes</code> launch configuration in the <code>Debug</code> pane in Visual Studio Code.</p>
<p><img loading="lazy" alt="Launch the .NET Core Launch (web) with Kubernetes from the Debug pane in Visual Studio Code" src="https://azure.github.io/Cloud-Native/assets/images/1-debug-with-bridge-to-kubernetes-a433698c3463d1d21268ce8f2ef9c4ac.png" width="3852" height="2098" class="img_ev3q"></p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="enable-the-endpoint-manager">Enable the Endpoint Manager<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#enable-the-endpoint-manager" class="hash-link" aria-label="Direct link to Enable the Endpoint Manager" title="Direct link to Enable the Endpoint Manager">​</a></h4>
<p>Part of this process includes a local service to help manage the traffic routing and your hosts file.  This will require admin or <code>sudo</code> privileges.  On Windows, you'll get a prompt like:</p>
<p><img loading="lazy" alt="Prompt to launch the endpoint manager." src="https://azure.github.io/Cloud-Native/assets/images/2-debug-with-bridge-to-kubernetes-347152aa59bf42c8e8c1d7c7849ea1de.png" width="838" height="274" class="img_ev3q"></p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="access-your-kubernetes-cluster-locally">Access your Kubernetes cluster "locally"<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#access-your-kubernetes-cluster-locally" class="hash-link" aria-label="Direct link to Access your Kubernetes cluster &quot;locally&quot;" title="Direct link to Access your Kubernetes cluster &quot;locally&quot;">​</a></h4>
<p>Bridge to Kubernetes will set up a tunnel (thanks to port forwarding) to your local workstation and create local endpoints for the other Kubernetes hosted services in your cluster, as well as pretending to be a pod in that cluster (for the application you are debugging).</p>
<p><img loading="lazy" alt="Output from Bridge To Kubernetes setup task." src="https://azure.github.io/Cloud-Native/assets/images/3-debug-with-bridge-to-kubernetes-3a9758005c10170e82891c63e603fe94.png" width="3852" height="2098" class="img_ev3q"></p>
<p>After making the connection to your Kubernetes cluster, the launch configuration will continue. In this case, we'll make a debug build of the application and attach the debugger.  (This process may cause the terminal in VS Code to scroll with build output. You can find the Bridge to Kubernetes output with the local IP addresses and ports in the Output pane for Bridge to Kubernetes.)</p>
<p>You can set breakpoints, use your debug console, set watches, run tests against your local version of the service.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="exploring-the-running-application-environment">Exploring the Running Application Environment<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#exploring-the-running-application-environment" class="hash-link" aria-label="Direct link to Exploring the Running Application Environment" title="Direct link to Exploring the Running Application Environment">​</a></h4>
<p>One of the cool things that Bridge to Kubernetes does for our debugging experience is bring the environment configuration that our deployed pod would inherit.  When we launch our app, it'll see configuration and secrets that we'd expect our pod to be running with.</p>
<p>To test this, we'll set a breakpoint in our application's start up to see what SQL Server is being used.  We'll set a breakpoint at <code>src/Infrastructure/Dependencies.cs</code> on line 32.</p>
<p>Then, we will start debugging the application with Bridge to Kubernetes.  When it hits the breakpoint, we'll open the Debug pane and type <code>configuration.GetConnectionString("CatalogConnection")</code>.</p>
<p>When we run locally (not with Bridge to Kubernetes), we'd see:</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">configuration.GetConnectionString("CatalogConnection")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "Server=(localdb)\\mssqllocaldb;Integrated Security=true;Initial Catalog=Microsoft.eShopOnWeb.CatalogDb;"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>But, with Bridge to Kubernetes we see something more like (yours will vary based on the password ):</p>
<div class="codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">configuration.GetConnectionString("CatalogConnection")</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"> "Server=db;Database=Microsoft.eShopOnWeb.CatalogDb;User Id=sa;Password=*****************;TrustServerCertificate=True;"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p><img loading="lazy" alt="Debugging our local application connected to Kubernetes." src="https://azure.github.io/Cloud-Native/assets/images/5-debug-with-bridge-to-kubernetes-2d8749df96c0961a972202cd3ac2a282.png" width="3852" height="2098" class="img_ev3q"></p>
<p>We can see that the database server configured is based on our <code>db</code> service and the password is pulled from our secret in Azure KeyVault (via AKS).</p>
<p>This helps us run our local application just like it was actually in our cluster.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="going-further">Going Further<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#going-further" class="hash-link" aria-label="Direct link to Going Further" title="Direct link to Going Further">​</a></h3>
<p>Bridge to Kubernetes also supports more advanced scenarios and, as you need to start routing traffic around inside your cluster, may require you to modify your application to pass along a <code>kubernetes-route-as</code> header to help ensure that traffic for your debugging workloads is properly handled.  The docs go into much greater detail about that.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="instrumentation">Instrumentation<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#instrumentation" class="hash-link" aria-label="Direct link to Instrumentation" title="Direct link to Instrumentation">​</a></h2>
<p>Now that we've figured out our debugging story, we'll need to ensure that we have the right context clues to find where we need to debug or to give us a better idea of how well our microservices are running.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="logging-and-tracing">Logging and Tracing<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#logging-and-tracing" class="hash-link" aria-label="Direct link to Logging and Tracing" title="Direct link to Logging and Tracing">​</a></h3>
<p>Logging and tracing become even more critical in Kubernetes, where your application could be running in a number of pods across different nodes. When you have an issue, in addition to the normal application data, you'll want to know what pod and what node had the issue, what the state of those resources were (were you resource constrained or were shared resources unavailable?), and if autoscaling is enabled, you'll want to know if a scale event has been triggered. There are a multitude of other concerns based on your application and the environment you maintain.</p>
<p>Given these informational needs, it's crucial to revisit your existing logging and instrumentation. Most frameworks and languages have extensible logging, tracing, and instrumentation libraries that you can iteratively add information to, such as pod and node states, and ensuring that requests can be traced across your microservices. This will pay you back time and time again when you have to troubleshoot issues in your existing environment.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="centralized-logging">Centralized Logging<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#centralized-logging" class="hash-link" aria-label="Direct link to Centralized Logging" title="Direct link to Centralized Logging">​</a></h3>
<p>To enhance the troubleshooting process further, it's important to implement centralized logging to consolidate logs from all your microservices into a single location. This makes it easier to search and analyze logs when you're troubleshooting an issue.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="automated-alerting">Automated Alerting<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#automated-alerting" class="hash-link" aria-label="Direct link to Automated Alerting" title="Direct link to Automated Alerting">​</a></h3>
<p>Additionally, implementing automated alerting, such as sending notifications when specific conditions occur in the logs, can help you detect issues before they escalate.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="end-to-end-visibility">End to end Visibility<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#end-to-end-visibility" class="hash-link" aria-label="Direct link to End to end Visibility" title="Direct link to End to end Visibility">​</a></h3>
<p>End-to-end visibility is also essential in understanding the flow of requests and responses between microservices in a distributed system. With end-to-end visibility, you can quickly identify bottlenecks and slowdowns in the system, helping you to resolve issues more efficiently.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-4#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Take the Cloud Skills Challenge!</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356" target="_blank" rel="noopener noreferrer">Enroll</a> in the Cloud Skills Challenge!</p><p>Don't miss out on this opportunity to level up your skills and stay ahead of the curve in the world of cloud native.</p></div></div>
<ul>
<li>
<p><a href="https://learn.microsoft.com/visualstudio/bridge/bridge-to-kubernetes-vs-code?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Use Bridge to Kubernetes in VS Code</a></p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.mindaro&amp;WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Bridge to Kubernetes Visual Studio Extension</a></p>
</li>
<li>
<p><a href="https://marketplace.visualstudio.com/items?itemName=mindaro.mindaro&amp;WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Bridge to Kubernetes Visual Studio Code Extension</a>.</p>
</li>
<li>
<p><a href="https://learn.microsoft.com/azure/architecture/aws-professional/eks-to-aks/monitoring?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Kubernetes monitoring and logging</a></p>
</li>
<li>
<p><a href="https://learn.microsoft.com/azure/architecture/microservices/logging-monitoring?WT.mc_id=containers-84290-stmuraws" target="_blank" rel="noopener noreferrer">Monitor a microservices architecture in Azure Kubernetes Service (AKS)</a></p>
</li>
</ul>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[3-5. Bringing Your Application to Kubernetes - CI/CD Secure Supply Chain]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5</guid>
            <pubDate>Fri, 10 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[In this article, you'll learn how to use Notary, an open-source project hosted by the Cloud Native Computing Foundation (CNCF) to digitally sign container images stored on Azure Container Registry.]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 5 of Week 3</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is Bringing Your Application to Kubernetes. Yesterday we talked about debugging and instrumenting our application. Today we'll explore the topic of container image signing and secure supply chain.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Ask the Experts Thursday, February 9th at 9 AM PST</div><div class="admonitionContent_BuS1"><p><a href="https://aka.ms/cnny/watch-ate" target="_blank" rel="noopener noreferrer">Watch our Q&amp;A with Experts from the Azure Kubernetes Service product team!</a></p></div></div>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Friday, February 10th at 11 AM PST</div><div class="admonitionContent_BuS1"><p>Watch the recorded demo and conversation about this week's topics.</p><p><a href="https://aka.ms/cnny/week3-demo" target="_blank" rel="noopener noreferrer">We were live on YouTube walking through today's (and the rest of this week's) demos</a>.  Join us Friday, February 10th and bring your questions!</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Introduction</li>
<li>Prerequisites</li>
<li>Create a digital signing certificate</li>
<li>Generate an Azure Container Registry Token</li>
<li>Set up Notation</li>
<li>Install the Notation Azure Key Vault Plugin</li>
<li>Add the signing Certificate to Notation</li>
<li>Sign Container Images</li>
<li>Conclusion</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction">​</a></h2>
<p>The secure supply chain is a crucial aspect of software development, delivery, and deployment, and digital signing plays a critical role in this process.</p>
<p>By using digital signatures to verify the authenticity and integrity of container images, organizations can improve the security of your software supply chain and reduce the risk of security breaches and data compromise.</p>
<p>In this article, you'll learn how to use Notary, an open-source project hosted by the Cloud Native Computing Foundation (CNCF) to digitally sign container images stored on Azure Container Registry.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="prerequisites">Prerequisites<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5#prerequisites" class="hash-link" aria-label="Direct link to Prerequisites" title="Direct link to Prerequisites">​</a></h2>
<p>To follow along, you'll need an instance of:</p>
<ul>
<li><a href="https://learn.microsoft.com/azure/container-registry/" target="_blank" rel="noopener noreferrer">Azure Container Registry</a></li>
<li><a href="https://learn.microsoft.com/azure/key-vault/" target="_blank" rel="noopener noreferrer">Azure Key Vault</a></li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="create-a-digital-signing-certificate">Create a digital signing certificate<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5#create-a-digital-signing-certificate" class="hash-link" aria-label="Direct link to Create a digital signing certificate" title="Direct link to Create a digital signing certificate">​</a></h2>
<p>A digital signing certificate is a certificate that is used to digitally sign and verify the authenticity and integrity of digital artifacts. Such documents, software, and of course container images.</p>
<p>Before you can implement digital signatures, you must first create a digital signing certificate.</p>
<p>Run the following command to generate the certificate:</p>
<ol>
<li>
<p>Create the policy file</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">cat &lt;&lt;EOF &gt; ./my_policy.json</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">{</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "issuerParameters": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        "certificateTransparency": null,</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        "name": "Self"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    },</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    "x509CertificateProperties": {</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        "ekus": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            "1.3.6.1.5.5.7.3.3"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        "key_usage": [</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            "digitalSignature"</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        ],</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        "subject": "CN=${keySubjectName}",</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        "validityInMonths": 12</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    }</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">}</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">EOF</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The <em>ekus</em> and <em>key usage</em> of this certificate policy dictate that the certificate can only be used for digital signatures.</p>
</li>
<li>
<p>Create the certificate in Azure Key Vault</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az keyvault certificate create --name $keyName --vault-name $keyVaultName --policy @my_policy.json</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Replace <code>$keyName</code> and <code>$keyVaultName</code> with your desired certificate name and Azure Key Vault instance name.</p>
</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="generate-a-azure-container-registry-token">Generate a Azure Container Registry token<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5#generate-a-azure-container-registry-token" class="hash-link" aria-label="Direct link to Generate a Azure Container Registry token" title="Direct link to Generate a Azure Container Registry token">​</a></h2>
<p>Azure Container Registry tokens are used to grant access to the contents of the registry. Tokens can be used for a variety of things such as pulling images, pushing images, or managing the registry.</p>
<p>As part of the container image signing workflow, you'll need a token to authenticate the Notation CLI with your Azure Container Registry.</p>
<p>Run the following command to generate an ACR token:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az acr token create \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $tokenName \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --registry $registry \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --scope-map _repositories_admin \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query 'credentials.passwords[0].value' \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --only-show-errors \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --output tsv</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Replace <code>$tokenName</code> with your name for the ACR token and <code>$registry</code> with the name of your ACR instance.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="setup-notation">Setup Notation<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5#setup-notation" class="hash-link" aria-label="Direct link to Setup Notation" title="Direct link to Setup Notation">​</a></h2>
<p>Notation is the command-line interface for the CNCF Notary project. You'll use it to digitally sign the <em>api</em> and <em>web</em> container images for the eShopOnWeb application.</p>
<p>Run the following commands to download and install the NotationCli:</p>
<ol>
<li>
<p>Open a terminal or command prompt window</p>
</li>
<li>
<p>Download the Notary notation release</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.0.0-rc.1/notation_1.0.0-rc.1_linux_amd64.tar.gz &gt; /dev/null 2&gt;&amp;1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>If you're not using Linux, you can find the releases <a href="https://github.com/notaryproject/notation/releases" target="_blank" rel="noopener noreferrer">here</a>.</p>
</li>
<li>
<p>Extract the contents of the <code>notation.tar.gz</code></p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">tar xvzf notation.tar.gz &gt; /dev/null 2&gt;&amp;1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Copy the notation binary to the $HOME/bin directory</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">cp ./notation $HOME/bin</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Add the $HOME/bin directory to the PATH environment variable</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">export PATH="$HOME/bin:$PATH"</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Remove the downloaded files</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">rm notation.tar.gz LICENSE</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Check the notation version</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">notation --version</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="install-the-notation-azure-key-vault-plugin">Install the Notation Azure Key Vault plugin<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5#install-the-notation-azure-key-vault-plugin" class="hash-link" aria-label="Direct link to Install the Notation Azure Key Vault plugin" title="Direct link to Install the Notation Azure Key Vault plugin">​</a></h2>
<p>By design the NotationCli supports plugins that extend its digital signing capabilities to remote registries. And in order to sign your container images stored in Azure Container Registry, you'll need to install the Azure Key Vault plugin for Notation.</p>
<p>Run the following commands to install the <code>azure-kv</code> plugin:</p>
<ol>
<li>
<p>Download the plugin</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">curl -Lo notation-azure-kv.tar.gz \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    https://github.com/Azure/notation-azure-kv/releases/download/v0.5.0-rc.1/notation-azure-kv_0.5.0-rc.1_linux_amd64.tar.gz &gt; /dev/null 2&gt;&amp;1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Non-Linux releases can be found <a href="https://github.com/Azure/notation-azure-kv/releases/" target="_blank" rel="noopener noreferrer">here</a>.</p>
</li>
<li>
<p>Extract to the plugin directory &amp; delete download files</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">tar xvzf notation-azure-kv.tar.gz -C ~/.config/notation/plugins/azure-kv notation-azure-kv &gt; /dev/null 2&gt;&amp;</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">rm -rf notation-azure-kv.tar.gz</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Verify the plugin was installed</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">notation plugin ls</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="add-the-signing-certificate-to-notation">Add the signing certificate to Notation<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5#add-the-signing-certificate-to-notation" class="hash-link" aria-label="Direct link to Add the signing certificate to Notation" title="Direct link to Add the signing certificate to Notation">​</a></h2>
<p>Now that you have Notation and the Azure Key Vault plugin installed, add the certificate's keyId created above to Notation.</p>
<ol>
<li>
<p>Get the Certificate Key ID from Azure Key Vault</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az keyvault certificate show \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --vault-name $keyVaultName \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name $keyName \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --query "kid" --only-show-errors --output tsv</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Replace <code>$keyVaultName</code> and <code>$keyName</code> with the appropriate information.</p>
</li>
<li>
<p>Add the Key ID to KMS using Notation</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">notation key add --plugin azure-kv --id $keyID $keyName</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
<li>
<p>Check the key list</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">notation key ls</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="sign-container-images">Sign Container Images<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5#sign-container-images" class="hash-link" aria-label="Direct link to Sign Container Images" title="Direct link to Sign Container Images">​</a></h2>
<p>At this point, all that's left is to sign the container images.</p>
<p>Run the <code>notation sign</code> command to sign the api and web container images:</p>
<div class="language-bash codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-bash codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">notation sign $registry.azurecr.io/web:$tag \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --username $tokenName \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --password $tokenPassword</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">notation sign $registry.azurecr.io/api:$tag \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --username $tokenName \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --password $tokenPassword</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Replace <code>$registry</code>, <code>$tag</code>, <code>$tokenName</code>, and <code>$tokenPassword</code> with the appropriate values. To improve security, use a SHA hash for the tag.</p>
<blockquote>
<p><em>NOTE</em>: If you didn't take note of the token password, you can rerun the <code>az acr token create</code> command to generate a new password.</p>
</blockquote>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="conclusion">Conclusion<a href="https://azure.github.io/Cloud-Native/cnny-2023/bring-your-app-day-5#conclusion" class="hash-link" aria-label="Direct link to Conclusion" title="Direct link to Conclusion">​</a></h2>
<p>Digital signing plays a critical role in ensuring the security of software supply chains.</p>
<p>By signing software components, organizations can verify the authenticity and integrity of software, helping to prevent unauthorized modifications, tampering, and malware.</p>
<p>And if you want to take digital signing to a whole new level by using them to prevent the deployment of unsigned container images, check out the <a href="https://github.com/deislabs/ratify" target="_blank" rel="noopener noreferrer">Ratify</a> project on GitHub!</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Take the Cloud Skills Challenge!</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356" target="_blank" rel="noopener noreferrer">Enroll</a> in the Cloud Skills Challenge!</p><p>Don't miss out on this opportunity to level up your skills and stay ahead of the curve in the world of cloud native.</p></div></div>]]></content:encoded>
            <category>cloud-native-new-year</category>
            <category>azure-kubernetes-service</category>
            <category>aks</category>
            <category>kubernetes</category>
            <category>secure-supply-chain</category>
            <category>notary</category>
            <category>notation</category>
            <category>azure-key-vault</category>
        </item>
        <item>
            <title><![CDATA[4-1. Serverless Container Options]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/serverless-containers</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/serverless-containers</guid>
            <pubDate>Mon, 13 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Explore serverless container options for development - including managed options like AKS and ACA]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Week 4</code> of #CloudNativeNewYear!</p>
<p>This week we'll <em>go further with Cloud-native</em> by exploring advanced topics and best practices for the Cloud-native practitioner. We'll start with an exploration of <em>Serverless Container Options</em>  - ranging from managed services to Azure Kubernetes Service (AKS) and Azure Container Apps (ACA), to options that allow more granular control!</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/serverless-containers#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>The Azure Compute Landscape</li>
<li>Serverless Compute on Azure</li>
<li>Comparing Container Options On Azure</li>
<li>Other Considerations</li>
<li>Exercise: Try this yourself!</li>
<li>Resources: For self-study!</li>
</ul>
<p><img loading="lazy" alt="Going further with cloud-native: Serverless container options by Nitya Narasimhan." src="https://azure.github.io/Cloud-Native/assets/images/30-16-a5828b89fd19d381a38742d0d80ea2d1.png" width="1001" height="420" class="img_ev3q"></p>
<hr>
<p>We started this series with an introduction to core concepts:</p>
<ul>
<li>In <a href="https://azure.github.io/Cloud-Native/cnny-2023/containers-101">Containers 101</a>, we learned <strong>why containerization matters</strong>. Think portability, isolation, scalability, resource-efficiency and cost-effectiveness. <em>But not all apps can be containerized.</em></li>
<li>In <a href="https://azure.github.io/Cloud-Native/cnny-2023/Kubernetes-101">Kubernetes 101</a>, we learned <strong>how orchestration works</strong>. Think systems to automate container deployment, scaling, and management. <em>But using Kubernetes directly can be complex</em>.</li>
<li>In <a href="https://azure.github.io/Cloud-Native/cnny-2023/explore-options">Exploring Cloud Native Options</a> we asked the real questions: <strong>can we containerize - and should we?</strong>. The first depends on app characteristics, the second on your requirements.</li>
</ul>
<p>For example:</p>
<ul>
<li><em>Can we containerize?</em> The answer might be no if your app has system or OS dependencies, requires access to low-level hardware, or maintains complex state across sessions.</li>
<li><em>Should we containerize?</em> The answer might be yes if your app is microservices-based, is stateless by default, requires portability, or is a legaacy app that can benefit from container isolation.</li>
</ul>
<p>As with every technology adoption decision process, there are no clear yes/no answers - just <em>tradeoffs</em> that you need to evaluate based on your <strong>architecture</strong> and <strong>application requirements</strong>. In today's post, we try to look at this from two main perspectives:</p>
<ol>
<li><em>Should you go serverless?</em> Think: managed services that let you focus on app, not infra.</li>
<li><em>What Azure Compute should I use?</em> Think: best fit for my architecture &amp; technology choices.</li>
</ol>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="azure-compute-landscape">Azure Compute Landscape<a href="https://azure.github.io/Cloud-Native/cnny-2023/serverless-containers#azure-compute-landscape" class="hash-link" aria-label="Direct link to Azure Compute Landscape" title="Direct link to Azure Compute Landscape">​</a></h2>
<p>Let's answer the second question first by exploring all <a href="https://learn.microsoft.com/azure/architecture/guide/technology-choices/compute-decision-tree?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer"><strong>available compute options on Azure</strong></a>. The illustrated decision-flow below is my favorite ways to navigate the choices, with questions like:</p>
<ul>
<li>Are you migrating an existing app or building a new one?</li>
<li>Can you app be containerized?</li>
<li>Does it use a specific technology (Spring Boot, Red Hat Openshift)?</li>
<li>Do you need access to the Kubernetes API?</li>
<li>What characterizes the workload? (event-driven, web app, microservices etc.)</li>
</ul>
<p>Read the docs to understand how your choices can be influenced by the <em>hosting model</em> (IaaS, PaaS, FaaS), supported <em>features</em> (Networking, DevOps, Scalability, Availability, Security), <em>architectural styles</em> (Microservices, Event-driven, High-Performance Compute, Task Automation,Web-Queue Worker) etc.</p>
<p><img loading="lazy" src="https://learn.microsoft.com/azure/architecture/guide/technology-choices/images/compute-choices.png" alt="Compute Choices" class="img_ev3q"></p>
<p>Now that we know <em>all</em> available compute options, let's address the second question: <em>why go serverless?</em> and what are my serverless compute options on Azure?</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="azure-serverless-compute">Azure Serverless Compute<a href="https://azure.github.io/Cloud-Native/cnny-2023/serverless-containers#azure-serverless-compute" class="hash-link" aria-label="Direct link to Azure Serverless Compute" title="Direct link to Azure Serverless Compute">​</a></h2>
<p>Serverless gets defined many ways, but from a compute perspective, we can focus on a few key characteristics that are key to influencing this decision:</p>
<ul>
<li><strong>managed services</strong> - focus on application, let cloud provider handle infrastructure.</li>
<li><strong>pay for what you use</strong> - get cost-effective resource utilization, flexible pricing options.</li>
<li><strong>autoscaling on demand</strong> - take advantage of built-in features like KEDA-compliant triggers.</li>
<li><strong>use preferred languages</strong> - write code in Java, JS, C#, Python etc. (specifics based on service)</li>
<li><strong>cloud-native architectures</strong> - can support event-driven solutions, APIs, Microservices, DevOps!</li>
</ul>
<p>So what are some of the key options for <a href="https://azure.microsoft.com/solutions/serverless/#solutions?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer"><strong>Serverless Compute on Azure</strong></a>? The article dives into serverless support for <em>fully-managed end-to-end serverless solutions</em> with comprehensive support for DevOps, DevTools, AI/ML, Database, Storage, Monitoring and Analytics integrations. But we'll just focus on the <strong>4 categories of applications</strong> when we look at Compute!</p>
<ol>
<li><strong>Serverless Containerized Microservices</strong> <em>using <a href="https://azure.microsoft.com/en-us/services/container-apps/?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure Container Apps</a></em>. Code in your preferred language, exploit full Dapr support, scale easily with any KEDA-compliant trigger.</li>
<li><strong>Serverless Application Environments</strong> <em>using <a href="https://azure.microsoft.com/products/app-service/?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure App Service</a></em>. Suitable for hosting monolithic apps (vs. microservices) in a managed service, with built-in support for on-demand scaling.</li>
<li><strong>Serverless Kubernetes</strong> <em>using <a href="https://azure.microsoft.com/products/kubernetes-service/?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service (AKS)</a></em>. Spin up pods inside container instances and deploy Kubernetes-based applications with built-in KEDA-compliant autoscaling.</li>
<li><strong>Serverless Functions</strong> <em>using <a href="https://azure.microsoft.com/products/functions/?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure Functions</a></em>. Execute "code at the granularity of functions" in your preferred language, and scale on demand with event-driven compute.</li>
</ol>
<p>We'll talk about these, and other compute comparisons, at the end of the article. But let's start with the core option you might choose if you want a managed serverless compute solution with built-in features for delivering containerized microservices at scale. Hello, <strong>Azure Container Apps!</strong>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="azure-container-apps">Azure Container Apps<a href="https://azure.github.io/Cloud-Native/cnny-2023/serverless-containers#azure-container-apps" class="hash-link" aria-label="Direct link to Azure Container Apps" title="Direct link to Azure Container Apps">​</a></h2>
<p><a href="https://learn.microsoft.com/azure/container-apps/?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure Container Apps (ACA)</a> became generally available in May 2022 - providing customers with the ability to run <strong>microservices and containerized applications on a serverless, consumption-based platform</strong>. The figure below showcases the different types of applications that can be built with ACA. Note that it comes with built-in KEDA-compliant autoscaling triggers, and other auto-scale criteria that may be better-suited to the type of application you are building.</p>
<p><img loading="lazy" src="https://techcommunity.microsoft.com/t5/image/serverpage/image-id/401522iACA9C8FFC49FE161/image-size/large?v=v2&amp;px=999" alt="About ACA" class="img_ev3q"></p>
<p>So far in the series, we've put the spotlight on Azure Kubernetes Service (AKS) - so you're probably asking yourself: <em>How does ACA compare to AKS?</em>. We're glad you asked. Check out our <em><a href="https://azure.github.io/Cloud-Native/blog/zero2hero-aca-01" target="_blank" rel="noopener noreferrer">Go Cloud-native with Azure Container Apps</a></em> post from the #ServerlessSeptember series last year for a deeper-dive, or review the figure below for the main comparison points.</p>
<p>The key takeaway is this. Azure Container Apps (ACA) <strong>also runs on Kubernetes</strong> but abstracts away its complexity in a <em>managed service offering</em> that lets you get productive quickly without requiring detailed knowledge of Kubernetes workings or APIs. However, if you <strong>want full access and control over the Kubernetes API</strong> then go with Azure Kubernetes Service (AKS) instead.</p>
<p><img loading="lazy" src="https://techcommunity.microsoft.com/t5/image/serverpage/image-id/401287i073CFBD50CB3A0B9/image-size/large?v=v2&amp;px=999&amp;WT.mc_id=javascript-99907-cxa" alt="Comparison" class="img_ev3q"></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="other-container-options">Other Container Options<a href="https://azure.github.io/Cloud-Native/cnny-2023/serverless-containers#other-container-options" class="hash-link" aria-label="Direct link to Other Container Options" title="Direct link to Other Container Options">​</a></h2>
<p>Azure Container Apps is the preferred <strong>Platform As a Service (PaaS)</strong> option for a fully-managed serverless solution on Azure that is purpose-built for cloud-native microservices-based application workloads. But - there are other options that may be suitable for your specific needs, from a requirements and tradeoffs perspective. Let's review them quickly:</p>
<ol>
<li><strong><a href="https://learn.microsoft.com/azure/azure-functions/functions-overview?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure Functions</a></strong> is the serverless <em>Functions-as-a-Service</em> (FaaS) option, as opposed to ACA which supports a PaaS approach. It's optimized for running event-driven applications built at the granularity of <em>ephemeral functions</em> that can be deployed as code or containers.</li>
<li><strong><a href="https://learn.microsoft.com/azure/app-service/?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure App Service</a></strong> provides fully managed hosting for web applications that may be deployed using code or containers. It can be integrated with other services including Azure Container Apps and Azure Functions. It's optimized for deploying traditional web apps.</li>
<li><strong><a href="https://learn.microsoft.com/azure/aks/intro-kubernetes?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure Kubernetes Service</a></strong> provides a fully managed Kubernetes option capable of running any Kubernetes workload, with  direct access to the Kubernetes API.</li>
<li><strong><a href="https://learn.microsoft.com/azure/container-instances/?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure Container Instances</a></strong> provides a <em>single pod</em> of Hyper-V isolated containers on demand, making them more of a low-level "building block" option compared to ACA.</li>
</ol>
<p>Based on the <strong>technology choices you made for application development</strong> you may also have more specialized options you want to consider. For instance:</p>
<ol>
<li><strong><a href="https://learn.microsoft.com/azure/spring-apps/overview?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure Spring Apps</a></strong> is ideal if you're running Spring Boot or Spring Cloud workloads on Azure,</li>
<li><strong><a href="https://learn.microsoft.com/azure/openshift/intro-openshift?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Azure Red Hat OpenShift</a></strong> is ideal for integrated Kubernetes-powered OpenShift on Azure.</li>
<li><strong><a href="https://learn.microsoft.com/azure/confidential-computing/choose-confidential-containers-offerings" target="_blank" rel="noopener noreferrer">Azure Confidential Computing</a></strong> is ideal if you have data/code integrity and confidentiality needs.</li>
<li><strong><a href="https://learn.microsoft.com/azure/architecture/operator-guides/aks/choose-kubernetes-edge-compute-option" target="_blank" rel="noopener noreferrer">Kubernetes At The Edge</a></strong> is ideal for bare-metal options that extend compute to edge devices.</li>
</ol>
<p>This is just the tip of the iceberg in your decision-making journey - but hopefully, it gave you a good sense of the options and criteria that influences your final choices. Let's wrap this up with a look at self-study resources for skilling up further.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="exercise">Exercise<a href="https://azure.github.io/Cloud-Native/cnny-2023/serverless-containers#exercise" class="hash-link" aria-label="Direct link to Exercise" title="Direct link to Exercise">​</a></h2>
<p>Want to get hands on learning related to these technologies?</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>TAKE THE CLOUD SKILLS CHALLENGE</div><div class="admonitionContent_BuS1"><p><a href="https://learn.microsoft.com/training/challenges?id=a0e385b9-f970-4182-b2e2-3b4619b6c356&amp;WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Register today</a> and level up your skills by completing free learning modules, while competing with your peers for a place on the leaderboards!</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/serverless-containers#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<ul>
<li><a href="https://learn.microsoft.com/azure/architecture/guide/technology-choices/compute-decision-tree?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Choose an Azure compute service</a></li>
<li><a href="https://azure.microsoft.com/solutions/serverless/#solutions?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Serverless On Azure</a></li>
<li><a href="https://azure.github.io/Cloud-Native/blog/zero2hero-aca-01?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Go Cloud-native with Azure Container Apps</a></li>
<li><a href="https://learn.microsoft.com/azure/container-apps/compare-options?WT.mc_id=javascript-84290-ninarasi" target="_blank" rel="noopener noreferrer">Comparing Container Apps with other Azure container options</a></li>
</ul>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[4-2. Jumpstart your applications with Draft]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/building-with-draft</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/building-with-draft</guid>
            <pubDate>Tue, 14 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Jump start your Kubernetes experience with Draft]]></description>
            <content:encoded><![CDATA[
<p>It's the final week of #CloudNativeNewYear! This week we'll go further with Cloud-native by exploring advanced topics and best practices for the Cloud-native practitioner. In today's post, we will introduce you to the basics of the open-source project Draft and how it can be used to easily create and deploy applications to Kubernetes.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>It's not too late to sign up for and complete the <a href="https://aka.ms/CNNY/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a>!</div></div>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/building-with-draft#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>What is Draft?</li>
<li>Draft basics</li>
<li>Demo: Developing to AKS with Draft</li>
<li>Resources</li>
</ul>
<p><img loading="lazy" alt="Promotional banner for Cloud Native New Year featuring colorful 3D icons representing security, containers, and cloud technology." src="https://azure.github.io/Cloud-Native/assets/images/hero-banner-991129dffd470b38678db8972274c09a.png" width="3840" height="654" class="img_ev3q"></p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-is-draft">What is Draft?<a href="https://azure.github.io/Cloud-Native/cnny-2023/building-with-draft#what-is-draft" class="hash-link" aria-label="Direct link to What is Draft?" title="Direct link to What is Draft?">​</a></h2>
<p><a href="https://github.com/azure/draft" target="_blank" rel="noopener noreferrer">Draft</a> is an open-source tool that can be used to streamline the development and deployment of applications on Kubernetes clusters. It provides a simple and easy-to-use workflow for creating and deploying applications, making it easier for developers to focus on writing code and building features, rather than worrying about the underlying infrastructure. This is great for users who are just getting started with Kubernetes, or those who are just looking to simplify their experience.</p>
<div class="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 14 16"><path fill-rule="evenodd" d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>New to Kubernetes?</div><div class="admonitionContent_BuS1"><p>Catch <a href="https://info.microsoft.com/ww-ondemand-a-quickstart-guide-to-kubernetes-concepts.html?lcid=en-us" target="_blank" rel="noopener noreferrer">A Quickstart Guide to Kubernetes Concepts</a> on demand, now!</p></div></div>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="draft-basics">Draft basics<a href="https://azure.github.io/Cloud-Native/cnny-2023/building-with-draft#draft-basics" class="hash-link" aria-label="Direct link to Draft basics" title="Direct link to Draft basics">​</a></h2>
<p>Draft streamlines Kubernetes development by taking a non-containerized application and generating the Dockerfiles, K8s manifests, Helm charts, and other artifacts associated with a containerized application. Draft can also create a GitHub Action workflow file to quickly build and deploy your application onto any Kubernetes cluster.</p>
<ol>
<li><strong>'draft create'':</strong> Create a new Draft project by simply running the 'draft create' command - this command will walk you through a series of questions on your application specification (such as the application language) and create a Dockerfile, Helm char, and Kubernetes</li>
<li><strong>'draft generate-workflow'':</strong> Automatically build out a GitHub Action using the 'draft generate-workflow' command</li>
<li><strong>'draft setup-gh'':</strong> If you are using Azure, use this command to automate the GitHub OIDC set up process to ensure that you will be able to deploy your application using your GitHub Action.</li>
</ol>
<p>At this point, you will have all the files needed to deploy your app onto a Kubernetes cluster (we told you it was easy!).</p>
<p>You can also use the <strong>'draft info'</strong> command if you are looking for information on supported languages and deployment types. Let's see it in action, shall we?</p>
<hr>
<h1>Developing to AKS with Draft</h1>
<p>In this Microsoft Reactor session below, we'll briefly introduce Kubernetes and the Azure Kubernetes Service (AKS) and then demo how enable your applications for Kubernetes using the open-source tool Draft. We'll show how Draft can help you create the boilerplate code to containerize your applications and add routing and scaling behaviours.</p>
<iframe width="560" height="315" src="https://www.youtube.com/watch?v=XDm2dqxGcvo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"></iframe>
<hr>
<p>##Conclusion</p>
<p>Overall, Draft simplifies the process of building, deploying, and managing applications on Kubernetes, and can make the overall journey from <a href="https://techcommunity.microsoft.com/t5/apps-on-azure-blog/code-to-cloud-with-azure-kubernetes-service-aks/ba-p/3669916_" target="_blank" rel="noopener noreferrer">code to Kubernetes</a> significantly easier.</p>
<hr>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/building-with-draft#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<ul>
<li><strong>LAST WEEK</strong> for the <a href="https://aka.ms/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a></li>
<li><strong>Learning Resources</strong>: <a href="https://aka.ms/CNNY/collection" target="_blank" rel="noopener noreferrer">#30DaysOfCloudNative Collection</a></li>
<li><strong>Podcast:</strong> <a href="https://www.youtube.com/watch?v=3RIulCcDet0" target="_blank" rel="noopener noreferrer">Containerize apps to AKS with Draft</a></li>
<li><strong>Project:</strong> <a href="https://github.com/azure/draft" target="_blank" rel="noopener noreferrer">Get started with Draft</a></li>
</ul>
<hr>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
        </item>
        <item>
            <title><![CDATA[4-3. Windows Containers]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/windows-containers</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/windows-containers</guid>
            <pubDate>Wed, 15 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[Let's learn about Windows containers!]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 3 of Week 4</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is going further with Cloud Native. Yesterday we talked about using Draft to accelerate your Kubernetes adoption. Today we'll explore the topic of Windows containers.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/windows-containers#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Introduction</li>
<li>Windows containers overview</li>
<li>Windows base container images</li>
<li>Isolation</li>
<li>Exercise: Try this yourself!</li>
<li>Resources: For self-study!</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a href="https://azure.github.io/Cloud-Native/cnny-2023/windows-containers#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction">​</a></h2>
<p>Windows containers were launched along with Windows Server 2016, and have evolved since. In its latest release, Windows Server 2022, Windows containers have reached a great level of maturity and allow for customers to run production grade workloads.</p>
<p>While suitable for new developments, Windows containers also provide developers and operations with a different approach than Linux containers. It allows for existing Windows applications to be containerized with little or no code changes. It also allows for professionals that are more comfortable with the Windows platform and OS, to leverage their skill set, while taking advantage of the containers platform.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="windows-container-overview">Windows container overview<a href="https://azure.github.io/Cloud-Native/cnny-2023/windows-containers#windows-container-overview" class="hash-link" aria-label="Direct link to Windows container overview" title="Direct link to Windows container overview">​</a></h2>
<p>In essence, Windows containers are very similar to Linux. Since Windows containers use the same foundation of Docker containers, you can expect that the same architecture applies - with the specific notes of the Windows OS. For example, when running a Windows container via Docker, you use the same commands, such as docker run. To pull a container image, you can use docker pull, just like on Linux. However, to run a Windows container, you also need a Windows container host. This requirement is there because, as you might remember, a container shares the OS kernel with its container host.</p>
<p>On Kubernetes, Windows containers are supported since Windows Server 2019. Just like with Docker, you can manage Windows containers like any other resource on the Kubernetes ecosystem. A Windows node can be part of a Kubernetes cluster, allowing you to run Windows container based applications on services like Azure Kubernetes Service. To deploy an Windows application to a Windows pod in Kubernetes, you can author a YAML specification much like you would for Linux. The main difference is that you would point to an image that runs on Windows, and you need to specify a node selection tag to indicate said pod needs to run on a Windows node.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="windows-base-container-images">Windows base container images<a href="https://azure.github.io/Cloud-Native/cnny-2023/windows-containers#windows-base-container-images" class="hash-link" aria-label="Direct link to Windows base container images" title="Direct link to Windows base container images">​</a></h2>
<p>On Windows containers, you will always use a base container image provided by Microsoft. This base container image contains the OS binaries for the container to run. This image can be as large as 3GB+, or small as ~300MB. The difference in the size is a consequence of the APIs and components available in each Windows container base container image. There are primarily, three images: Nano Server, Server Core, and Server.</p>
<p>Nano Server is the smallest image, ranging around 300MB. It's a base container image for new developments and cloud-native scenarios. Applications need to target Nano Server as the Windows OS, so not all frameworks will work. For example, .Net works on Nano Server, but .Net Framework doesn't. Other third-party frameworks also work on Nano Server, such as Apache, NodeJS, Phyton, Tomcat, Java runtime, JBoss, Redis, among others.</p>
<p>Server Core is a much larger base container image, ranging around 1.25GB. It's larger size is compensated by it's application compatibility. Simply put, any application that meets the requirements to be run on a Windows container, can be containerized with this image.</p>
<p>The Server image builds on the Server Core one. It ranges around 3.1GB and has even greater application compatibility than the Server Core image. In addition to the traditional Windows APIs and components, this image allows for scenarios such as Machine Learning via DirectX with GPU access.</p>
<p>The best image for your scenario is dependent on the requirements your application has on the Windows OS inside a container. However, there are some scenarios that are not supported at all on Windows containers - such as GUI or RDP dependent applications, some Windows Server infrastructure roles, such as Active Directory, among others.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="isolation">Isolation<a href="https://azure.github.io/Cloud-Native/cnny-2023/windows-containers#isolation" class="hash-link" aria-label="Direct link to Isolation" title="Direct link to Isolation">​</a></h2>
<p>When running containers, the kernel of the container host is shared with the containers running on it. While extremely convenient, this poses a potential risk for multi-tenant scenarios. If one container is compromised and has access to the host, it could potentially compromise other containers in the same system.</p>
<p>For enterprise customers running on-premises (or even in the cloud), this can be mitigated by using a VM as a container host and considering the VM itself a security boundary. However, if multiple workloads from different tenants need to share the same host, Windows containers offer another option: Hyper-V isolation. While the name Hyper-V is associated with VMs, its virtualization capabilities extend to other services, including containers. Hyper-V isolated containers run on a purpose built, extremely small, highly performant VM. However, you manage a container running with Hyper-V isolation the same way you do with a process isolated one. In fact, the only notable difference is that you need to append the <code>--isolation=hyperv</code> tag to the <code>docker run</code> command.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="exercise">Exercise<a href="https://azure.github.io/Cloud-Native/cnny-2023/windows-containers#exercise" class="hash-link" aria-label="Direct link to Exercise" title="Direct link to Exercise">​</a></h2>
<p>Here are a few examples of how to use Windows containers:</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="run-windows-containers-via-docker-on-your-machine">Run Windows containers via Docker on your machine<a href="https://azure.github.io/Cloud-Native/cnny-2023/windows-containers#run-windows-containers-via-docker-on-your-machine" class="hash-link" aria-label="Direct link to Run Windows containers via Docker on your machine" title="Direct link to Run Windows containers via Docker on your machine">​</a></h3>
<p>To pull a Windows base container image:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">docker pull mcr.microsoft.com/windows/servercore:ltsc2022</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To run a basic IIS container:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">#This command will pull and start a IIS container. You can access it from http://&lt;your local IP&gt;:8080</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">docker run -d -p 8080:80 mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Run the same IIS container with Hyper-V isolation</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">#This command will pull and start a IIS container. You can access it from http://&lt;your local IP&gt;:8080</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">docker run -d -p 8080:80 --isolation=hyperv mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To run a Windows container interactively:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">docker run -it mcr.microsoft.com/windows/servercore:ltsc2022 powershell</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="run-windows-containers-on-kubernetes">Run Windows containers on Kubernetes<a href="https://azure.github.io/Cloud-Native/cnny-2023/windows-containers#run-windows-containers-on-kubernetes" class="hash-link" aria-label="Direct link to Run Windows containers on Kubernetes" title="Direct link to Run Windows containers on Kubernetes">​</a></h3>
<p>To prepare an AKS cluster for Windows containers:
Note: Replace the values on the example below with the ones from your environment.</p>
<div class="language-azurecli codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-azurecli codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">echo "Please enter the username to use as administrator credentials for Windows Server nodes on your cluster: " &amp;&amp; read WINDOWS_USERNAME</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">az aks create \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --resource-group myResourceGroup \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --name myAKSCluster \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --node-count 2 \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --generate-ssh-keys \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --windows-admin-username $WINDOWS_USERNAME \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --vm-set-type VirtualMachineScaleSets \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --network-plugin azure</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>To add a Windows node pool for Windows containers:</p>
<div class="language-azurecli codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-azurecli codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks nodepool add \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --resource-group myResourceGroup \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --cluster-name myAKSCluster \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --os-type Windows \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --name npwin \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    --node-count 1</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Deploy a sample ASP.Net application to the AKS cluster above using the YAML file below:</p>
<div class="language-yml codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-yml codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> apps/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Deployment</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">replicas</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">template</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">labels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">nodeSelector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">"kubernetes.io/os"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> windows</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">containers</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> mcr.microsoft.com/dotnet/framework/samples</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">aspnetapp</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">resources</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token key atrule" style="color:#00a4db">limits</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">cpu</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token key atrule" style="color:#00a4db">memory</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 800M</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">          </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">containerPort</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">matchLabels</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">---</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">apiVersion</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">kind</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Service</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">metadata</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token key atrule" style="color:#00a4db">spec</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">type</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> LoadBalancer</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">protocol</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> TCP</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">port</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">80</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">selector</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">app</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> sample</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Save the file above and run the command below on your Kubernetes cluster:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl apply -f &lt;filename&gt; .</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>Once deployed, you can access the application by getting the IP address of your service:</p>
<div class="language-powershell codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-powershell codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">kubectl get service</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/windows-containers#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>It's not too late to sign up for and complete the <a href="https://aka.ms/CNNY/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a>!</div></div>
<ul>
<li><a href="https://learn.microsoft.com/virtualization/windowscontainers/?WT.mc_id=containers-84290-viniap" target="_blank" rel="noopener noreferrer">Windows containers documentation</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/learn/quick-windows-container-deploy-cli?WT.mc_id=containers-84290-viniap" target="_blank" rel="noopener noreferrer">Run Windows containers on AKS</a></li>
</ul>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
            <category>containers</category>
            <category>windows</category>
        </item>
        <item>
            <title><![CDATA[4-4. Azure Kubernetes Services Add-ons and Extensions]]></title>
            <link>https://azure.github.io/Cloud-Native/cnny-2023/aks-extensions-addons</link>
            <guid>https://azure.github.io/Cloud-Native/cnny-2023/aks-extensions-addons</guid>
            <pubDate>Thu, 16 Feb 2023 00:00:00 GMT</pubDate>
            <description><![CDATA[In this article we are going to learn about the extensions and add-ons available to AKS - Azure Kubernetes Services]]></description>
            <content:encoded><![CDATA[
<p>Welcome to <code>Day 4 of Week 4</code> of #CloudNativeNewYear!</p>
<p>The theme for this week is going further with Cloud Native. Yesterday we talked about Windows Containers. Today we'll explore addons and extensions available to Azure Kubernetes Services (AKS).</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="what-well-cover">What We'll Cover<a href="https://azure.github.io/Cloud-Native/cnny-2023/aks-extensions-addons#what-well-cover" class="hash-link" aria-label="Direct link to What We'll Cover" title="Direct link to What We'll Cover">​</a></h2>
<ul>
<li>Introduction</li>
<li>Add-ons</li>
<li>Extensions</li>
<li>Add-ons vs Extensions</li>
<li>Resources</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="introduction">Introduction<a href="https://azure.github.io/Cloud-Native/cnny-2023/aks-extensions-addons#introduction" class="hash-link" aria-label="Direct link to Introduction" title="Direct link to Introduction">​</a></h2>
<p>Azure Kubernetes Service (AKS) is a fully managed container orchestration service that makes it easy to deploy and manage containerized applications on Azure. AKS offers a number of features and capabilities, including the ability to extend its supported functionality through the use of add-ons and extensions.</p>
<p>There are also integrations available from <a href="https://learn.microsoft.com/azure/aks/integrations?WT.mc_id=containers-84290-joarteir#open-source-and-third-party-integrations" target="_blank" rel="noopener noreferrer">open-source projects and third parties</a>, but they are not covered by the <a href="https://learn.microsoft.com/azure/aks/support-policies?WT.mc_id=containers-84290-joarteir" target="_blank" rel="noopener noreferrer">AKS support policy</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="add-ons">Add-ons<a href="https://azure.github.io/Cloud-Native/cnny-2023/aks-extensions-addons#add-ons" class="hash-link" aria-label="Direct link to Add-ons" title="Direct link to Add-ons">​</a></h2>
<p>Add-ons provide a supported way to extend AKS. Installation, configuration and lifecycle are managed by AKS following <a href="https://learn.microsoft.com/azure/aks/integrations?WT.mc_id=containers-84290-joarteir#add-ons" target="_blank" rel="noopener noreferrer">pre-determine updates rules</a>.</p>
<p>As an example, let's enable Container Insights with the monitoring addon. on an existing AKS cluster using <code>az aks enable-addons --addons</code> CLI command</p>
<div class="language-azurecli codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-azurecli codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks enable-addons \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name MyManagedCluster \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group MyResourceGroup \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --addons monitoring</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>or you can use <code>az aks create --enable-addons</code> when creating new clusters</p>
<div class="language-azurecli codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-azurecli codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az aks create \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name MyManagedCluster \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group MyResourceGroup \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --enable-addons monitoring</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>The current available add-ons are:</p>
<ol>
<li><strong>http_application_routing</strong> - Configure ingress with automatic public DNS name creation. Only recommended for development.</li>
<li><strong>monitoring</strong> - Container Insights monitoring.</li>
<li><strong>virtual-node</strong> - CNCF virtual nodes open source project.</li>
<li><strong>azure-policy</strong> - Azure Policy for AKS.</li>
<li><strong>ingress-appgw</strong> - Application Gateway Ingress Controller (AGIC).</li>
<li><strong>open-service-mesh</strong> - CNCF Open Service Mesh project.</li>
<li><strong>azure-keyvault-secrets-provider</strong> - Azure Key Vault Secrets Provider for Secret Store CSI Driver.</li>
<li><strong>web_application_routing</strong> - Managed NGINX ingress Controller.</li>
<li><strong>keda</strong> - CNCF Event-driven autoscaling project.</li>
</ol>
<p>For more details, get the updated <a href="https://learn.microsoft.com/azure/aks/integrations?WT.mc_id=containers-84290-joarteir#available-add-ons" target="_blank" rel="noopener noreferrer">list of AKS Add-ons here</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="extensions">Extensions<a href="https://azure.github.io/Cloud-Native/cnny-2023/aks-extensions-addons#extensions" class="hash-link" aria-label="Direct link to Extensions" title="Direct link to Extensions">​</a></h2>
<p>Cluster Extensions uses Helm charts and integrates with Azure Resource Manager (ARM) to provide installation and lifecycle management of capabilities on top of AKS.</p>
<p>Extensions can be auto upgraded using minor versions, but it requires extra management and configuration. Using Scope parameter, it can be installed on the whole cluster or per namespace.</p>
<p>AKS Extensions requires an Azure CLI extension to be installed. To add or update this CLI extension use the following commands:</p>
<div class="language-azurecli codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-azurecli codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az extension add --name k8s-extension</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>and to update an existing extension</p>
<div class="language-azurecli codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-azurecli codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az extension update --name k8s-extension</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>There are only 3 available extensions:</p>
<ol>
<li><strong>Dapr</strong> - CNCF Dapr project.</li>
<li><strong>Azure ML</strong> - Integrate Azure Machine Learning with AKS to train, inference and manage ML models.</li>
<li><strong>Flux (GitOps)</strong> - CNCF Flux project integrated with AKS to enable cluster configuration and application deployment using GitOps.</li>
</ol>
<p>As an example, you can install Azure ML using the following command:</p>
<div class="language-azurecli codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_biex"><pre tabindex="0" class="prism-code language-azurecli codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain">az k8s-extension create \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --name aml-compute --extension-type Microsoft.AzureML.Kubernetes \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --scope cluster --cluster-name &lt;clusterName&gt; \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --resource-group &lt;resourceGroupName&gt; \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --cluster-type managedClusters \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  --configuration-settings enableInference=True allowInsecureConnections=True</span><br></span></code></pre><div class="buttonGroup__atx"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_eSgA" aria-hidden="true"><svg viewBox="0 0 24 24" class="copyButtonIcon_y97N"><path fill="currentColor" d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svg viewBox="0 0 24 24" class="copyButtonSuccessIcon_LjdS"><path fill="currentColor" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div>
<p>For more details, get the updated <a href="https://learn.microsoft.com/azure/aks/cluster-extensions?tabs=azure-cli&amp;WT.mc_id=containers-84290-joarteir#currently-available-extensions" target="_blank" rel="noopener noreferrer">list of AKS Extensions here</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="add-ons-vs-extensions">Add-ons vs Extensions<a href="https://azure.github.io/Cloud-Native/cnny-2023/aks-extensions-addons#add-ons-vs-extensions" class="hash-link" aria-label="Direct link to Add-ons vs Extensions" title="Direct link to Add-ons vs Extensions">​</a></h2>
<p>AKS Add-ons brings an advantage of been fully managed by AKS itself, and AKS Extensions are more flexible and configurable but requires extra level of management.</p>
<p>Add-ons are part of the AKS resource provider in the Azure API, and AKS Extensions are a separate resource provider on the Azure API.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="resources">Resources<a href="https://azure.github.io/Cloud-Native/cnny-2023/aks-extensions-addons#resources" class="hash-link" aria-label="Direct link to Resources" title="Direct link to Resources">​</a></h2>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>It's not too late to sign up for and complete the <a href="https://aka.ms/CNNY/Challenge" target="_blank" rel="noopener noreferrer">Cloud Skills Challenge</a>!</div></div>
<ul>
<li><a href="https://learn.microsoft.com/azure/aks/integrations?WT.mc_id=containers-84290-joarteir" target="_blank" rel="noopener noreferrer">Add-ons, Extensions, and other integrations with AKS</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/integrations#available-add-ons?WT.mc_id=containers-84290-joarteir" target="_blank" rel="noopener noreferrer">Available Add-ons on AKS</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/cluster-extensions?tabs=azure-cli&amp;WT.mc_id=containers-84290-joarteir#currently-available-extensions" target="_blank" rel="noopener noreferrer">Available Extensions on AKS</a></li>
<li><a href="https://learn.microsoft.com/azure/aks/integrations?WT.mc_id=containers-84290-joarteir#open-source-and-third-party-integrations" target="_blank" rel="noopener noreferrer">Open source and third-party integrations</a></li>
<li><a href="https://dapr.io/" target="_blank" rel="noopener noreferrer">CNCF Dapr project</a></li>
<li><a href="https://fluxcd.io/" target="_blank" rel="noopener noreferrer">CNCF Flux project</a></li>
<li><a href="https://keda.sh/" target="_blank" rel="noopener noreferrer">CNCF KEDA project</a></li>
</ul>]]></content:encoded>
            <category>cloud-native</category>
            <category>30daysofcloudnative</category>
            <category>zero-to-hero</category>
            <category>ask-the-expert</category>
            <category>azure-kubernetes-service</category>
            <category>containers</category>
            <category>addons</category>
            <category>extensions</category>
        </item>
    </channel>
</rss>