<img height="1" width="1" style="display:none;" alt="" src="https://px.ads.linkedin.com/collect/?pid=1232938&amp;fmt=gif">
Contact a Redapt Expert:

DevOps Adoption

Outpace your competitors by adopting DevOps culture to accelerate software delivery while increasing application resilience and stability.

Increase performance

High performing DevOps culture efficiently delivers new products and features faster while attracting and retaining top talent.


Reduce lead time

Dramatically cut down the time it takes for your teams to go from code committed to code successfully running in production.

Resiliency and stability

Strong DevOps processes increase application resiliency and stability by removing human error and enabling rapid recovery from outages.


Shift left on security

Weave strong security measures into your software development process without hindering delivery velocity.


Increase performance

High performing DevOps culture efficiently delivers new products and features faster while attracting and retaining top talent.


Reduce lead time

Dramatically cut down the time it takes for your teams to go from code committed to code successfully running in production.

Resiliency and stability

Strong DevOps processes increase application resiliency and stability by removing human error and enabling rapid recovery from outages.


Shift left on security

Weave strong security measures into your software development process without hindering delivery velocity.

Curious how DevOps can help cut the tension while increasing innovation?

Maybe your developers are trying to get new features to market. But your IT operations team is concerned about downtime. Eliminate the strain between the teams—and tasks—with DevOps. With stronger collaboration and automated application development, any barriers will dissolve.

Keep reading to find out how you can implement a DevOps solution that satisfies everyone on your team.

Redapt Mockup Guide - DevOps

Insights to help you get ahead

Articles, analysis, and adoption strategies from our team of experts.

Recipe for Deploying Managed Kubernetes On Prem_Twitter

The Recipe for Deploying Managed Kubernetes On-Premises

Learn how to accelerate the way you develop new products and services for your customers.


Taking the Leap with On-Premises or Co-Location Datacenters

How and why companies are successfully building and deploying their own infrastructure.

Top Reasons to Choose Dell EMC Powerscale for AI_LinkedIn

A Guide to Managing and Scaling Your Unstructured Data in a Hybrid Cloud

Learn how to manage your unstructured data while ensuring you meet your governance and security requirements.

Sarah: 00:00:07

Welcome everyone to Reach the Market at Light Speed with Azure Kubernetes Service. Today, we're going to be hearing from Jerry Meisner, who is our practice area lead for DevOps. Quickly, we'll share a bit about Redapt. 

At Redapt we're an end-to-end technology solutions provider that brings clarity to dynamic technical environments. We have more than 20 years of technology experience, helping organizations navigate through challenges and obstacles to accelerate business growth. We have deep cloud expertise, and we are excited to present to you all today about Azure Kubernetes Service. Go ahead, Jerry.

Jerry Meisner: 00:01:10

Perfect. Thanks for the introduction, Sarah. I will leave this slide up for a moment. We're talking about, as Sarah mentioned, Kubernetes Service. We'll talk a bit about containers and the benefits of containers, but I'm Jerry Meisner. I'm the DevOps Practice Lead. I've been working with Kubernetes since version 1.4 and I've helped many customers make the leap from two containers, and then eventually Kubernetes orchestration. Today we're going to cover the benefits of containers, we're going to talk a little bit about utilizing the Kubernetes Service, and then I'm actually going to do a technology demo and show you a sample application being deployed, and what the portal options give you. And, we'll talk through some of that.

The first thing we'll talk about is some of the benefits of containerization. There are really three main benefits of containerization. One of them is the fact that containers are going to be lightweight. There is also a standard developed, and then they are relatively secure when compared to running multiple processes on the same virtual machine. A container image is a lightweight standalone executable package of a piece of software that includes everything needed to run it. This includes code, run time, system tools, system library, settings, et cetera, and they're available for both Linux and Windows-based applications. Your container will generally run the same, regardless of the environment, and that's going to be one of the key benefits the standardization brings to the table.

So, what makes them lightweight? The fact that the containers are all running on a similar host and can share a common kernel, means there's less overhead. You're not running a kernel in an operating system for every single application, or every single application that you need to have isolated on a particular virtual machine. All the applications that are running as containers on a single hardware or virtual machine are leveraging the same kernel, the same operating system. From the secure aspect - these are going to be isolated processes. If you're running three or four containers in the same virtual machine, and, for example, one of your VMs, one of your containers on that virtual machine gets compromised, if something does go wrong with that particular container or it is compromised, the issues will be limited to that particular container.

You don't have the ability to go from container to container within the virtual machine, simply through HTTP requests. You'd have to have secrets, keys, identities, and things like that in order to get fully in. When we're talking about Docker, or containers in general, you heard Docker come up a lot. Docker is basically one of the early runtimes. There are also some command line tools, and some things they make easier from the development of containers. There are additional runtimes such as run C or containerd that is going to be the runtime environment for your container. It's going to be Docker-compliant — it's just going to be a little more lightweight than the traditional Docker daemon.

Now, there are three main components to Docker. You have the software, which is going to be the Docker daemon running on the host, that you would tell to run your container. And, there are going to be the objects, such as the container, the image themselves. Then you're going to have a concept of a registry, and the registry basically acts as an artifactory, if you're familiar with that concept. Essentially, you're pushing these images, or these artifacts, up to that registry. Then, when we tell Kubernetes, or we tell Docker to run them, we're going to basically tell it where to look. "Hey, go grab this image from this registry at this location." So, this is a general overview of containers.

The analyst firm Gartner predicts that by 2023, 70% of organizations will be running three or more containerized applications in production. We're seeing a very quick adoption of containers. When you think about the overhead of managing virtual machines, especially for stateless services, for example, there are a lot of benefits that can be had just by containerizing and moving over to a container. Another benefit would be for cost utilization, so you can have three processes running on the same virtual machine that are isolated from each other and make better use of the CPU, or memory, that that virtual machine is hosting, rather than having one of the processes sit idle and not be leveraging the CPU and memory of the node. There are a lot of benefits, and organizations are realizing those.

From the developer and engineering standpoint, moving applications to a more agile development environment leads to a few things. One of them would be an application portfolio assessment - having the ability to go to a single place and check logs, for example, or to check a GitHub repository and see what dependencies are built into the application. As well as tracking history and support control, that type of thing. All those things are going to be possible. The next benefit we have here is selection and implementation of "proof of concept" modernization work. When you have the ability to quickly bring up a new Flask application, you don't have to worry about bringing up the virtual machine, making sure that the virtual machine is patched, and making sure that the correct Python is installed in the virtual machine. Those types of things are removed from this process.

Once you have a good base candidate for a Flask container, for example, you can simply swap out the Python code and, for the most part, the Flask application that you prototyped will work relatively quickly. This allows you to, again, proof of concept, try some things out and rapidly iterate that type of thing. Developers really like that aspect of it. The third aspect is  full assistance during application migration and day two operations. When you think about managing virtual machines, there are several cloud providers. There are several on-premise solutions for containers, because it's a standard. It's going to work the same way whether it's in the cloud or whether it's on-prem. The benefit of this is that you have the community, which has gone ahead of us and developed some software that runs in containers we can easily deploy on our virtual machines.

There are also some tools and things like that that have been developed by third parties to make life a lot easier for folks that have adopted containers. Another benefit is, if you're going to potentially leverage a consulting firm such as Redapt, having a standard on containers is really easy for us to ramp up on and help you advance operations, and things like that. Because we don't necessarily have to get involved with how you set up virtual machines. We have the instructions for the container, we have the artifacts that need to be deployed, and then we have the instructions for configuration, ideally. The environment variables, configuration files, that type of thing, which is really easy to hand off, compared to trying to learn how to install software onto a virtual machine, or a bootstrap script that has to be modified as things advance.

Technology and business decision makers are also seeing some benefits, so investing in platforms that are more agile for application development. They're finding it to be more cost effective. Again, the overhead for deploying an application to a containerized environment is relatively low, compared to that of a virtual machine. Especially when you think about secure environments, where maybe you have teams that are provisioning the virtual machines, you have a team that installs the software, you have a team that does the security hardening aspects, etc. When you can boil those things down into a container image, and then you have the processes removed so you don't have to waste the time provisioning the virtual machine, the virtual machine should be there. Or a pool, a VM should be there. It's going to run our container on it.

Again, eliminating overhead is a big benefit for business leaders. Easier to scale as needed. Going back to that virtual machine process, if you needed three, four, or five instances of your application, you'd have to bring up those virtual machines individually. You could leverage something like Auto Scaling groups, but then you'd have to ensure that everything is immutable within the Auto Scaling group, and then the Auto Scaling group logic might be different between AWS and Azure and Google, for example. Certainly on-prem there are some challenges for Auto Scaling workloads, unless you're running something like OpenStack, or an on-premise cloud platform. The benefit of being able to scale up the container level is that we don't necessarily have to scale the hardware.

We can scale the processes running across the pool of hardware, so we can achieve replicas, high availability, and that type of thing without the additional need for tons of overhead with the operating system, additional Linux kernels, etc. The third big bullet that business decision makers see is, it creates a culture of increased innovation. When we talk about the developers being able to rapidly prototype something, for example, this will maybe give a developer within your organization who has a really good idea for a new feature, or something along those lines. Rather than having to go through all the traditional pipelines, they can immediately start working on a container and follow through the container pipeline process.

Which, maybe deploy the workload up, maybe there is a request for an opening up of firewall rule, or exposing a public IP, but at the end of the day there's a lot less overhead when you're working with a container deployment than there is with a traditional VM deployment which usually spans multiple teams. With containerized applications, you can avoid the slow pace of waterfall development. If you're familiar with the waterfall development process, it starts with a heavy design phase in the beginning, where you have to have all the requirements, all the functionality really well defined. Then the waterfall approach basically starts at the beginning, constantly working until all the design considerations have been met and then you have an application software at the end of the product, or rather at the end of the development cycle.

Traditionally, this has been the way it's worked in the past. However, we are moving more towards an agile world, where, instead of designing everything up front, you may have some initial designs up front, but you're going to start with generally a proof of concept, a minimum viable product, and then you're going to do an iterative process. The waterfall approach lends itself really well to binaries that you had to deliver to clients for example, on a regular interval, with the migration to SaaS solutions. Those things become less important. What becomes more important is being able to roll out new features relatively quickly, and so that's where reducing the lengthy times between development and deployment is going to come in handy. The other thing that I mentioned is the risk of downtime is reduced quite a bit.

Certainly, when you think about running virtual machines, you're going to have those three VMS — they'll have their software installed. If something happens on one of those virtual machines, there may not be any operating procedures to restart the processes, and things like that. Certainly, if there isn't, you'd want to have to go through that process of developing them. In the Kubernetes world, it's a desired state configuration. Essentially, when you're running a set of three containers across your node pool, if for any reason one of your three containers dies, maybe the node crashes itself, the entire host crashes, or some other effect happens, maybe the process within the container crashes, because it ran into a stack trace error or something along those lines.

But, the idea is that with Kubernetes you have the ability to restart workloads, so, if the nodes are healthy, we can start those workloads. If the node stops reporting, then we can move that workload to another node. You never really face a scenario where you have less than two or three instances at a time running. That increases your up time. This is a bit of a recap. Again, we talked about how they accelerate your development. Scale your applications in a cost effective way. Rapidly make improvements to your software or your products. Then minimizing downtime for your applications, as well. Now, we'll talk a little bit about the benefits of Kubernetes for container orchestration.

Containers being a standard open platform that can run in all clouds and on-prem, Kubernetes is going to be an orchestration platform for those containers that runs in all the major clouds, and on-prem as well. There are certainly some supported versions of Kubernetes, AKS is a managed Kubernetes solution, and we're going to talk a little bit about that one today, but the idea is that, if you can deploy into Kubernetes in one cloud, you should be able to deploy into Kubernetes on another cloud. Assuming you're not leveraging dependencies on that particular cloud, for example, the custom database solution that doesn't exist anywhere else. If you're using that in one cloud, you won't be able to leverage that in another cloud. You're still going to have to do some application modernization in that regard.

But, you do have multi-cloud capability, in that, if your application isn't leveraging cloud native, cloud-specific technologies, then you can deploy this exact same container to multiple environments and just configure it to have different connection streams, and that type of thing. Then, with Kubernetes, we're going to get increased developer productivity. Having the ability to build and run containers locally in the development environment is great, but Kubernetes allows you to create potentially dev name spaces, or dev clusters that will allow developers to deploy directly to those environments. You may have some gates, or some checks for the QA, or the production environment, but, for the dev environment, you don't necessarily need to have those types of checks. You can allow the developers to push code directly to, for example, their own namespace, or maybe their teams' namespace.

They can run some integration tasks before they approve the code for the next level in the life cycle. I'll talk a little bit about utilizing the Kubernetes Service. So, the Kubernetes Service, AKS in this particular case, the Azure Kubernetes Service, is looking to provide you with four main things. One is a full, enterprise-ready Kubernetes engine. I'm going to talk a little bit about the architecture of Kubernetes and why this is such a good benefit. A full, enterprise-ready elastic provisioning of capacity without managing an infrastructure, so this comes out-of-the-box with Kubernetes. Certainly, if you have a cloud provider connected, we can run additional virtual machines and things like that.

You don't have to worry about managing the infrastructure - you set your minimums and maximums, and then allow the workloads to scale accordingly. Third bullet we have here is an accelerated end-to-end development experience. I've mentioned this a bit, but there are some integrations with various tools. For example, Azure Monitor will actually show up in the portal. We can actually dive into individual containers running across our cluster, and take a look at their resource consumption and various things like that. At Azure DevOps, I have an example I'm going to show as part of the tech demo, but Azure DevOps is a pipeline tool that basically can deploy workloads to Kubernetes. You can have Azure DevOps built into the container and deploy it to a specific cluster within a specific namespace.

The first one here is Visual Studio Code Kubernetes tools. Certainly, if you're using VS code as an IDE, there are some Kubernetes integrations there as well - maybe help you crafting your YAML objects, or help you deploy your HELM charts to, or remote cluster. Those types of things are all available as part of this Visual Studio Code plugin. The fourth bit is identity and access management with Azure Active Directory and Azure Policy. Typically in a Kubernetes environment, you'll have some static users. In fact, if you want to have a user management system at all, you have to really roll your own and then essentially have those identities mapped to users within the cluster. Then you assign roles and permissions to those individual identities.

With AKS, they have native integration with Azure Active Directory, so you don't have to set this up. This will already be set up automatically, and we can set up Azure Active Directory, and then configure some Azure policies that prevent users from taking certain actions on the clusters based on their role, or based on their identity. With AKS, we can easily define, deploy, debug, and upgrade our applications. Basically, when you talk about redeploying an application, traditionally your containers are immutable. If we need to make an update, we can make an update in the code, build our container, and then redeploy our container with a similar configuration. Maybe some slight configuration changes as part of an upgrade, or part of a feature enhancement with our software.

So, automatically containerized applications. This is probably a bit of a loaded statement, but what we mean here by “automatically containerize your applications” is that, with Azure DevOps, and with tools that integrate, you can actually build your containers using Azure AKS. Certainly, you still have to build the dockerfile - you still have to understand the basic concepts. They're not going to be able to create a container from nothing, at least not right now. The third bullet is: Apply automated routine tasks to your AKS cluster for CI/CD pipelines. Again, this could be building the container, it could be deploying to a dev environment first and then later deploying to a test, and then running some integration tests against that environment, and having a manual approval step to deploy things to production once all those tests have been passed.

You can also ensure visibility into your environment with Kubernetes resource view, so I'll show this in the portal, as well taking a look at some of the available resources, and then utilize the fully-integrated Azure Cost Management tools to control costs. We talk about managing virtual machine costs and, essentially, your containers are going to be running on virtual machines. The Azure Cost Management tool will give you the ability to understand, “what is this cluster costing?” You can also take a look at node utilization, see if you're over provisioned, so, if you need to lower the hardware size, that type of thing, all those things will be exposed to you through the Kubernetes portal. There are also some security recommendations. If you're familiar with the Azure Security Center there are some integrations there that will pop out some helpful information. I'll show you an example of that as well.

That being said, we are going to pop out of this demonstration and we are going to take a look at our demonstration. The first thing I want to talk about is: What is Kubernetes and why is AKS such a good solution? Or: Why do I need to run AKS? Why couldn't I just run Kubernetes myself? What are the benefits that the managed offering provides? So what you're looking at here is an architecture overview. On the left-hand side, in the blue box, we have the control plane, which includes a lot of the system components of Kubernetes. I'll talk a bit about those. Then, on the right-hand side, we have some green boxes that include the nodes. If you want to consider, for example, these two nodes as being part of a node pool, maybe they have the similar VM size, they have a similar operating system, and that type of thing. This might be our single node pool.

Now, within Kubernetes we can have multiple node pools of various VM sizes, of various hardware capabilities, such as GPUs, and things like that, but there are some common components. If we start at the bottom and we can look at the kubelet, the kubelet is the agent of this system. In every node in the cluster, you're going to be running the kubelet, and the kubelet is essentially what is the go-between the API and the Docker daemon, or the container runtime on the individual virtual machine. Going up, we see the container runtime. Again, the container runtime is going to be that Docker daemon, or the run C or containerd runtime that's installed with Kubernetes. Over time, this is going to become containerd again - it's not something that you need to focus on too much.

Going one layer up, we see the kube proxies. The kube proxies are going to be doing a lot of the service discovery work. There's internal DNS - there's potential for container network interfaces that do various things, Calico and flannel. Essentially, the kube proxy acts as the router service between the individual nodes, so if we have pod one here that gets to talk to this pod, it would essentially send a request out, the kube proxy would catch that request, board it to the appropriate proxy, which are then forwarded to the appropriate pod on the destination node. There are a couple of ways of handling which pods are related to which service, and hopefully we'll talk about that in this session, as well. On the left we'll go through some of the control plan components.

Again, everything in this blue box is managed by Azure, so you don't have to worry about maintaining etcd, or maintaining the API, or maintaining the cloud provider. Those things are all handled by AKS. The cool thing about this is that etcd is not an easy service to maintain. It is a raft storage methodology, so it does have to maintain a quorum. For example, if you had three instances of etcd, if you lost any two of them, you'd have data corruption or data loss. Similarly, if you had five and lost three, you'd have data loss. If you had six and lost three, you'd have data loss. You need to have more than 50% of the nodes at any given time available of etcd in order to keep it alive. Azure is going to be handling that for you in the backend.

On top of maintaining etcd, they are going to be doing automatic backups for you. For example, taking a backup of your clusters, so that, if anything needs to be restored within the control plane, they'll be able to automatically restore with that for you. You also have the API. The API is directly storing and reading data from the etcd service. Then you have the individual controller manager. So, as you interact with the API, you will just say, “schedule my pod.” That will get created in etcd - the controller manager that's looking for pods will see that entry in etcd through the API server call. Then it will tell the API to tell this kubelet, for example, to run my single pod. Now, looking at these services over here on the left. The cloud controller manager, this is going to be the one that's basically the Azure service principal will be integrated with.

Essentially, whenever you create a service of type load balancer where you create a service that requires disk, for example, the cloud controller manager essentially makes those Azure API calls on their behalf. It attaches the disc to the appropriate nodes, or attaches the load balancer to the appropriate nodes, and that type of thing. You can think about this cloud provider network edge - the load balancer gets created attached to all the nodes. There's some Kubernetes magic happening here with regards to how this load balancer knows which node it can go to and which it lands on. I'm not going to go into that as part of this session. There are some additional components - the controller managers, there are several controllers within the ecosystem of Kubernetes, and they're related to the objects that you can push to the API.

We'll talk a little bit about deployment, staple sets, and jobs here shortly, but, essentially, each of those is a controller manager that's looking for a desired state. If you put something into the etcd, the controller manager is going to look in etcd, it's going to look at the real example of what's running, and, if there are any discrepancies, it's going to try and make those changes. If it needs to delete something, or if it needs to add something, it will know by looking at etcd and comparing that to the current state. The scheduler is the next piece here. The scheduler is basically going to be looking at your pod definitions, your pod templates, and it's going to be deciding which node to run the workload. Typically it's going to be looking at CPU and memory, and then looking at this node to see if it has CPU memory, but there are other things they could check for.

Such as, we could have node pools again that have GPUs, and, if our workload requires GPUs, we would have to define that as part of our pod template. Then, when the scheduler sees that in the definition, it will know that the node pool one doesn't work. We need to put it on node pool two, which has GPUs. This is done through a taints and tolerations mechanism - I'm not going to go into that as part of this webinar - but some understand it's possible to have multiple node pools with different configurations and have the workload scheduled in the way you prefer them to. Additionally, there are things like pod affinity, where we can have workloads that prefer to schedule away from each other. So, if we had three instances of a web server, and we had three infrastructure nodes, we could find an affinity rule that says, “Hey, you guys prefer to be away from each other.”

That way Kubernetes will automatically schedule one here, one here, and one here. If we have a hardware failure, we still have two instances of our application running for high availability purposes. Having that overview of the Kubernetes cluster is beneficial. What we're going to talk about now is: How do you create a Kubernetes cluster and what are the options that AKS exposes to you through the portal? Certainly the options that are available to you here in this portal wizard are less than what's going to be available to you through the Azure API. I traditionally recommend that you create clusters through something like Terraform or arm templates, which will give you the more fine-grained control of creating these resources. Now, on the basics tab we have a typical Azure resource form here.

We've got a subscription that we're going to be targeting, we could potentially target a particular resource group, and we also want to have a name for our cluster. In my case, my cluster is jmeisner-test-aks. You can see that over there on the left, but I can do this. You'll notice that it'll allow me to create that. I can do it here, if I wanted to. You also have the ability to select a region. Some of the regions have availability zones — for example, if I switch to the U.S. East, you can see I'm putting in zone one, two, and three. In the West region, Western U.S., we do not have any availability zones supported yet, so you don't have the ability to choose there. Now, the main reason for choosing across the availability zones is certainly for high availability, fault tolerance, that type of thing. And Kubernetes does some really cool things around that.

You also have the ability to select which Kubernetes version you want to run. Understanding that Kubernetes itself is a software system developed by an open source community, and, as new features are developed, they're going to be upgrading Kubernetes itself. And Azure, while they contribute to the CNCF, they are not the Kubernetes developers. They are just the developers of the AKS, which is their managed solution. As new features become available in Kubernetes, they'll be appearing in later versions of Kubernetes, and you'll be able to upgrade later, but, when you create your cluster, you'll have to pick a version. If I wanted to say 1.19.7, I could start there. Certainly for production we would recommend that you avoid preview builds if at all possible. Typically, in dev, you might test a preview build before it needs to be promoted in production.

This, again, down here at the bottom, is the primary node pool. If you think about it, in our diagram we just had two nodes, for example, but we could have three nodes. In fact, I recommend a minimum of three nodes, and they're going to recommend the same thing as well, especially for production. Then you have the ability to change the node size. Again, this is a two-to-eight CPU ratio. If I have a bunch of workloads I'm going to be putting on these nodes, and I know that maybe I want to have a two-to-eight, but I want to double the size and I can use DS3.v2, for example, just select that and have that work. That was the default node pool - we can add additional node pools, and here is where we have the ability to do that. Let's say I wanted to put a GPU node pool here, and then I could go into here and choose my size, and we could do... Gosh.

I can go in here and find the GPU disc - I'm not going to waste time doing that - but I could essentially go in here and find a virtual machine hardware type that matches up. Maybe I want high memory or high compute, for example, for this particular pool, and you can get that set up right away. Now, the taint and toleration isn't available through the UI. Some of those things I recommend creating through a Terraform process, or through an arm template. So that you can taint the nodes, for example - so that workloads don't get scheduled on them that don't require GPU. That's a more advanced topic than this webinar is going to discuss. The third tab here is the authentication tab. We've got a couple of authentication methods. You can do service principles. When we talked about this overview, and we have this cloud controller manager that's making calls to create load bouncers and assigned discs, essentially, this is the identity that's going to be taking care of that.

Now, we can just choose a system, assign a manage identity, and we'll automatically handle the role assignment, the credential rotation, and that type of thing. I typically recommend this for development environments. Service principle might come in handy if you really need to make sure that the cloud provider can't do specific things, then you might create the service beforehand and pass it in here. I do recommend, if your first-time installation, that you either use the system assigned identity, or allow it to create a new service principle by checking this box. Certainly, you can go through and modify the permissions of the service principle that gets created if you need to. Going down a bit further, we can see the role-based access control, or the authentication authorization. When we talk about our back, there are some roles within the Kubernetes API. 

For example, if you want specific users to not be able to look at secrets, then you need to turn on the role-based access control and define the role-based access control resources, such as clusters, roles, and bindings. The next radio option here is whether you want to use the managed Azure Active Directory. Typically, for most folks that are using Azure, they're probably already leveraging AD, so we typically do enable this. Then you have the ability to choose an administrator group for the particular cluster. If you assign admin to a particular AD group, then anybody in that group will have admin access to the cluster. They'll be able to create additional roles, additional cluster bindings, and that type of thing using their active directory credentials. I'll talk a little bit about how to connect to a cluster here, shortly. By default, you're going to get encryption at rest. They're going to be using a platform managed key, so you don't even have the ability to turn this off — you're going to be maintaining some compliance there.

Especially if you have some regulatory concerns, you're going to get encryption at rest. Now, the option they have available to you is to provide your own key. If you want to provide your own key, if you don't want Azure to have the key to your data, then certainly you could check this option. This is going to be more geared towards regulatory concerns - that you aren't sharing anything with Azure or Microsoft. From the networking standpoints, there are a couple of different CNI configurations. I typically recommend Qnet, if you're going to be doing many, many containers on an individual node, or across a few nodes, a small node pool. Azure CNI has some benefits, including an ability to have IP addresses available outside of the cluster. If you wanted to hit a pod directly from outside the cluster, essentially what the CNI does is starts using the address spaces of the subnet that your node pool is deployed into, and it assigns the node to that many IP addresses. 

For every node that comes up, there might be 30 IP addresses associated with that, if the max pods is set to 30. Every time a new container is scheduled on that node, that network interface is mapped to that container. If you ever hit that IP address, it'll go into that virtual machine, and then down into that container. The next options here are basically really more networking-related, so certainly you want to deploy the worker pool, your node pool, onto an existing network. Or, you could create a new one. Then there are some service address ranges - a DNS service address range, and then a couple of Docker bridge address ranges. Typically, we recommend that you leave the Docker bridge address the same - it's going to be the same one on every single host in the cluster. As long as this doesn't conflict with anything on-prem or internal, I typically recommend leaving that the same. 

These two here, I'm certainly going to recommend that you choose address ranges that aren't consumed outside of the cluster, if possible. Theoretically, these are going to be mostly internal IP addresses, but later on down the road you may want to mesh these clusters together. We have the cluster's ability to cross-communicate with each other, and, in those scenarios, you want to make sure that this stress range is unique across each cluster. So, that's the consideration here. You don't want to have this router able to anything on-prem, or to any other cluster, if you can help it. If you know that your cluster is going to be standalone, it's never going to mesh with any other clusters, then these things are relatively arbitrary, and will remain mostly internal. There are a couple of things down here with the application routing. This would allow the Azure ALB for ingress management. Certainly there are some different ways of doing ingress management - they're not going to recommend you use this for production. 

They'll have it right there, so it's just not recommended for production clusters. In a production environment, I wouldn't even check this. In the development environment, if you have Jenkins, or maybe some system tools that you want to expose to the application load bouncer, then certainly enabling that, and creating those things there would be perfectly fine. Now, we have a couple of additional things to make the environment more secure, so we can enable private clusters by doing this. Essentially, it creates a private IP address for our API, so you won't be able to talk to the API of Kubernetes unless you're actually on the network. It's going to require a VPN, or some peering connection between your network that you're running on and the network that the Kubernetes is installed on is from here. Additionally, if you want to leave it exposed to the internet so that it is publicly accessible, then we can set some authorized IP address ranges. 

Instead of having it exposed to the internet, I could come in here and give it my address, and, if my request were to come in with this IP address to the API, it would allow that. Otherwise it would deny that. So you’ve got a couple of different options for locking down the cluster. I recommend, at the very least, that you do this option. Maybe this is the corporate NAT address, or maybe it's individual developer addresses here. You can do a range here, so this could be a bottom and a top. Then we have the ability to take a look at the network resources, so when we talk about network policies these are the options. You can have a none network policy, or you can have a Calico, or an Azure network policy. I intend to recommend either none or Azure, at least for the current iteration. The Calico CNI does support network policies, meaning you can restrict traffic from pod to pod based on some labels in the Kubernetes cluster.

However, this breaks down when you have multiple subnets and multiple worker pools. Typically, not leveraging workload isolation, or so that you don't have to have firewall rules within the cluster, or going with the Azure CNI, which has a different mechanism that basically is going to be trying to create firewall rules for your applications. We can take a look at some integrations. We talked a bit about the registry component of Docker — basically Azure has their own Azure Container Registry service. You will select a container registry in the region that your cluster is running on, and you can connect this cluster directly to that. This just means that you won't have to do any authentication when you're pushing and pulling images from this particular registry on this particular cluster. If you have multiple registries, this isn't going to work too well. You would have to look at the Kubernetes way of adding additional private registries, but by default you're going to sign one registry which will bypass a lot of their provincial fetching. 

When we look at the Azure Monitor, this is basically: Do we want to see CPU memory metrics, that type of thing? In the Azure portal, certainly there are some costs associated with storing that data long term, but it does flow right into a log analytics workspace, if you're familiar with that. I should be able to show an example of that here, as well. The last piece on here is the Azure Policy. If you want to use Azure policies for creating and managing resources within the AKS environment, then we could enable this. I would recommend enabling this, even if you don't use it. There's a little bit of overhead associated with it, but ideally I'd recommend enabling and then trending toward applying some common sense safeguards for the environment. The last two tabs are going to be very simple tags. This is similar to tagging other resources, but then Azure you may have some things that you need to put in here, such as cost center. 

Then, from the review and create perspective, you can actually validate that all of your settings were good and that you can create the cluster. In my case, I didn't supply everything. I skipped over some stuff, so it's not going to validate for me, which is fine - I've already got a Kubernetes service available to me. Let's take a look at that. Here I've drilled into my jmeisner-test-aks service. It's not a private cluster, so it is exposed to the internet and there are a couple of things that I can do. From the overview page, you'll just see this here, but you'll see this connect option. When you click the connect option, we will have some commands that we can run over here. If I pull these into my command line, I can basically run those and get logged in, then I can run this command here. Essentially, this command will download and configure my kubeconfig file.

So the kubeconfig file is what you are going to be using to authenticate against the API, and the kubectl command line tool will be looking for the kubeconfig file at this location. There are other ways, such as setting the kubeconfig environment variable, but the kubectl tool, whenever you leverage it, it's going to be looking for this environment variable, or this file to exist. What this file has - there are a few things. It's got a cluster, it's got a user, and then it's going to have a context section. Really, the context just matches the cluster and the individual user. As you add additional clusters to your configuration, or as you run this command multiple times for different clusters, each of those clusters will essentially get added to a kubeconfig file. Then, if you were to rerun this command, it's really going to be changing your current context. If you have multiple clusters, they're all in the same kubeconfig file. When you rerun this command, it's essentially going to just set your context. 

There are ways of doing this through the kubectl tool directly, if you have a kubeconfig file, but this is the main command line tool we use to interact with clusters so we can do things like Gitpods. We can look at logs, we can explain resources, and various things like that. Just as an example - if I want to get all the pods in my cluster across all the namespaces, I can do, I get pods stash A, and you'll see all the pods in my cluster. I've got some services running in the default namespace, I've got some services running in the test name space, I've got some additional components, such as SDO and Prometheus, basically things that allow me to do service meshing and NTLS, a lot of additional integrations here deployed under this cluster. Now, what I wanted to show you in the session is an example application. In order to do that, I need to talk about the controller. We've talked a little bit about pods - pods are the smallest definition of a runtime unit within Kubernetes.

The pods contain one or more containers and are all going to be scheduled onto a single, same host, so you can define pods directly. We can define a pod as a YAML definition and then directly apply that to the cluster, or we can define a replica set. The replica set would have a set number, maybe it's three or four replicas of this pod that need to be running, and the deployment manages the replica sets. Basically, the way it works is things collapse up the chain. If we do a duplicate here and we go to deployments, we can take a look at example definition. In here you can see this template section, this is going to be your pod template. When you're looking at a replica, set the template and the template that's part of the pod, the template in the replica set, and the template on the deployment are basically all using the same… what's called the pod spec. 

Everything below this template line is a part of the pod spec and is very similar, whether you're working with replica sets, deployments, staple sets, daemon sets, prem jobs, or jobs. The template is just telling what the pod template is. What are the things that are needed to run my container? The benefit of using a deployment, for example, is you might push out a change, and then the code change can actually bring up a new replica set, which contains three pods with your new code, and it can bring down the old replica set to two, then bring down to one, and then bring it down to zero. It's effectively getting a rolling update strategy, just by leveraging the deployment instead of managing pods directly. The replica set again, it's going to be looking to say, “I've got three replicas here.” This will create a replica set and it will maintain that there are three pods. If one of these pods gets destroyed, the replica set controller will see that the desired state, versus the actual state, doesn't match and create a pod. 

That's the main premise I need you to understand going forward. Circling back to our pool example - I have a repo here called favorite-beer. This is a public repo. So if you're interested in taking a look through this, you can github.com/readapt/favoritebeer. In here, under the spas-react-netcore-redis folder under voting, we have a dockerfile. This is an example - a dockerfile that includes the recipe for building a core application. There are some complex build patterns in here, I'm not going to go into what those are, but essentially we're building our DLL, and then we're pushing our DLL into a final container. Then, at the very end, we are running our service using our 80 port - using this environment variable and calling .net on that voting DLL. When that happens, our application will start running, assuming all the configurations and things are there correctly. What we want to do is talk about how we take this dockerfile, we can build it, we can do Docker build, get the container created, and push it up to our container registry. 

How do we get this deployed to Kubernetes? One of the things I didn't talk about was Docker Compose. I'm not going to talk about it, but this is a tool used for developing local Docker images. It has its own format, and, in this read, I talk about how to convert the compose over to the actual staple set that you're going to need to run something comparable. Now, certainly Redis is something I recommend running, maybe using the Azure Redis Cache service, instead of running Redis within the Kubernetes cluster. But, I wanted to show an example of a staple set, as well as a deployment as part of this demo. Coming down, there is a concept of persistent volumes and persistent volume claims, and those things are mapped potentially back to the individual workloads. This is the mini kube example - just below that I have an AKS example that is much simpler. Here you can see we have a volume claim template down here. Whenever a new pod is created, we're going to get a new volume created that has one gigabytes of storage, and it's going to attach that to whatever node my Redis container runs on. 

Then we're using the Flash data pass, so making sure my data first sits across maybe Redis when it starts for example. So this is basically what the staple set would look like. I could just create this YAML file knowing that my images are public repository, there's no credentials necessary here, and then I can just apply that to my cluster. What we're seeing down here is my favorite-beer Redis service running as a pod. If I do kubectl, I get stable sets, including the dash in tests, because we're working with the test namespace. You can see my favorite-beer Redis staple set exists, and it's actually managing the single pods. There's one of one - just a single pod. Now, what I want to do is actually expose this service to the internet. I don't want to expose it to the internet, per se, I want to actually expose it to my other web service, so my web API server uses Redis as  the backend, so this is actually going to be a private endpoint. 

There are a couple of different service options - in this case I'm using a cluster IP, essentially just defining a service YAML and applying that to the cluster, and this will get one of those service address ranges that will be internal for the cluster. And, it'll also establish a DNS name within the test name space called favorite-beer-redis. Applying those we get our service, and I can show you what that looks like if I do get service Azure - test. You can see that favorite-beer Redis service is created here with a cluster IP - we're exposing 6, 3 79, all the typical Redis jargon. Then, here we have our actual favorite-beer application deployment example. This is a very simple example that doesn't use any dynamic figuration - this basically just uses an alternate JSON file that I have defined within the container to show beer options. Now, if we take a quick look at the source code, we can see there are a couple service settings. There's a service settings, all in service settings .JSONfile. 

This is just setting this environment variable - telling it where to find its settings. Now, what I want to do is actually use another concept called a ConfigMap, so I can actually inject configs through volumes with Kubernetes. I can create a ConfigMap that has this service sentence JSON as one of my keys and my value. Then I can redefine my deployment with a volume and a volume map, essentially mounting this JSON file to etcd config, and then telling my application where to find that configuration file. Again, public repo, this is my DNS name within the test name space for my favorite-beer Redis service. Using this name here - the name of the service. When I deploy this application up, essentially it will be able to communicate to the backend using those settings and deployments. Now this is a little bit different exposure, so I want to expose this to the internet. This time, I'm creating a service and the type is going to be a type load bouncer. 

This is to tell the cloud provider that I want to reach out and create a load bouncer, and it's going to attach to a specific note port, in this case 31650. Anytime traffic comes from that load bouncer, or into 31650, we're going to hit port 80 on our container, which is the container we have been listening for on our workplace. After you create that service, after we apply that service definition, you'll see that service pops up in our list of available services here. You'll also see that, after a few minutes, we'll get an external IP address that we can actually hit and play with with our service. If I hit that IP address, you can see here's my favorite-beer service, pointing back to the configuration that we injected using our JSON file, or ConfigMap, and we now have our application run. That's pretty quick to get an application running. Obviously, I didn't shut the Docker build step. Building a container, pushing it up to that registry, and then applying these YAML files to the cluster is all you need to get a workload going. 

Now, I have taken these few steps further, so there are some things in here in the examples, such as a helm chart. The helm chart is mostly the same things. You have a deployment, you'll have a state set for Redis, for example, and basically this is a free form directory where I accrued all those resources that we just talked about. But, instead of populating the individual values, I'm using some interpolation functions. I can actually upgrade the image repo — upgrade the image tag, just by changing the values at the deploy time here. One of the cool use cases for something like this is… Let's say I wanted to run this application for different markets, maybe Atlanta and Denver. In Atlanta values, I have my service settings for my ConfigMap including just some of these beers, and then, in my Denver values, we're including different beers. Now, the key takeaway for the helm is that this is a free form values file, and the templates file basically references those. 

So when you say values.servicesettings, for example, that's where we're looking, that can be injected right in here to this ConfigMap through some interesting helm functionality. I want to pick up the pace a little bit. What I want to share next is an example of some logs of a particular workload running in Kubernetes. Let's just go through the overview really quickly. From here you can see the Kubernetes cluster — it's up — you can go down here in settings and take a look at some of the various settings. When you want to look at the workloads, for example, we can go into our workloads tab. The things that you just saw, we're using the key sincere tool to find, I can actually find right through the Azure portal. Here's my staple set for my beer, here are all my pods that are running, and I've got several replica sets for different things running on my cluster. There's some daemon sets and some jobs, and there are no crown jobs on this particular cluster. 

Having the ability to see what's in here through these dashboards is really convenient, especially if you have a lot of teams, or you have a lot of workloads deployed onto the cluster. This is that resource view we mentioned earlier. Again, we can come down here to cluster configuration - we can do an upgrade. To upgrade the control plane, for example, I brought this up to 1.9 and save.  Azure basically handled the upgrade for me, and then I would need to go in here to the node pools and tell my node pool to upgrade, as well. You would upgrade the control plane first to the desired version, and then you would upgrade the node pools. Certainly I recommend having multiple clusters, so you can have a non-prod and a production environment, so you can test these upgrades in that type of environment. If you want to take a look, we can set up our minimums and maximums for our node pools. We can turn this on to auto scale and set this to 10.

Basically, as long as we tell Kubernetes how much CPU and memory our workload needs as part of the product template, Kubernetes can schedule things appropriately. I'm not going to go through every single tab here, but certainly there are some interesting things I'm going to show you - the options you have available. In my case, I didn't turn on the application routing, I don't have a private cluster, I don't have any authorized ranges, and I'm just using this as my demo example. Dev Space is not available in my region - this is something that's probably going to be retired, and they're actually calling that out here. There is a bridge to Kubernetes service that they're working on. I'm not going to go into that today, but certainly worth looking into in your free time. What I do want to go over really quickly is some of the insights and monitoring that are available to you. Out of the box, because there are some workloads deployed to the Kubernetes cluster by Azure that basically allows them to have some visibility into how much CPU you are utilizing.

Not only at the node level, but we can actually drill into the container level and see some of this. You can see 2% CB utilization and we could drill into specific things. There's an Auto Scaling service running here, for example, and there are some requests and some limits associated with this workload. Essentially, if I come in here, I can take a look at various things. I can also view container logs, which would open up a log stream of just that container. Alternatively, I can come down here at the logs tab, and take a look at the container log section, and then maybe run a query to pull all the logs in all my different namespaces. Here you can see - I've got a log entry here and it came directly from standard out of the container. It was picked up by the OMS agent forwarding device, and then forwarded directly here to the Azure logging system. You don't have to worry about building out that elastic search cluster, or building out that log collection, or log sync - it's built in automatically. 

All you have to do is start deploying workloads that are logging appropriately to a standard out. The last thing I wanted to share, before we wrap everything up, is the Azure DevOps integration pieces. The main understanding is that, if you come into your project, your Azure DevOps project, you'll have this project settings button down here at the bottom. When you click that project settings button, you can then go into service connections. Here I've defined some service connections to my cluster in different namespaces. I've got my test namespace, prod, dev, default, and if I click on this I can get a resource ID, essentially up here. I can grab this ID and say this is a connection to my Kubernetes cluster, and, in this case, the test namespace. The benefit of this is that I can now find my Azure pipelines, that YAML file, and I can actually put these connections in here. 

You'll see my Dev AKS service connection, my test AKS service connection, and I can basically define this. Instead of putting my credentials or anything in here, basically ADO will use the identity that I've provided in the YAML file when it's making those authentications. Later on, I can do a build step with Docker, we can get built, and, this is an interesting example, again, all part of the favorite-beer. Then I can deploy my application using helm code. I'm just overriding the image tag, and then a repository to select the image that I just built and deploy that one to my individual environment. There's quite a complex example of a pipeline here, certainly there are some areas for improvement, but this is a pretty solid example from a base pipeline standpoint. Then, once you have this all configured, you'll have the individual steps as part of the pipeline, and then you can see those individual steps get executed.

In this case, I did an action where I merged a pull request and I deployed that to test. Built a container first, then deployed that ultimately to my test environment - it gives me a happy status message from the backend. That being said, I'm going to pop back over to our slideshow and close out our session. To sum things up, we called out that containerization is key to accelerating your dev and deployment of applications, ensuring your applications are always updated, and reducing your infrastructure and hardware costs. Creating a culture of increased innovation. AKS is going to provide you with enterprise-grade Kubernetes and Azure, and the critical cost monitoring, visibility tools, and that type of thing. In general, you're also going to receive all the benefits of Kubernetes, such as the community available for Kubernetes, and deployments or helm charts that have been developed by the community. For example, if you want to install Prometheus there's a helm chart out there for that.

You don't necessarily have to figure out how to install all of those things manually yourself. There are other integrations such as Datadog, for example. They have their own daemons set that you could deploy to cluster and automatically integrate with their service. You get a lot of those integrations with a lot less overhead. And in a traditional landscape, you have to make sure that your VMs all have the Datadog agent installed, or that they were all boarding to an external Datadog agent. In the Kubernetes world, things like that become a little simpler. Now, I want to talk a little bit about working with Redapt. Some of the content that I showed today is part of our DevOps workshop. We have a full, eight hour workshop where I walk through containers all the way through to helm deployments and automation. Really, the main benefits are going to be our expertise in containerization and DevOps in general. The fact that we've been using Kubernetes for a really long time before Azure AKS was even a thing. 

We've been an Azure partner for quite a while, so we have a team of engineers familiar with all of the ins and outs of establishing an Azure cloud environment. As far as what we can do to help, we can certainly do the workshop, and we can also help implement, so we can actually help your team build containers in the right size environment. If you're noticing that your costs are getting a little out of control, we can help with some of that stuff, as well. If you have a full migration, for example, your team wants to leverage Kubernetes, but you need a third party to come in and help get you stood up, get AKS running, get all the work loads migrated over to AKS, we can handle that, as well. That being said, I hope the webinar brought some value to you as a watcher. And, whether you're just getting started down the road to cloud adoption, or have already got some resources in Azure, we can certainly help utilize AKS to accelerate development and deployment cycles. Please reach out to one of our experts at your leisure.

Sarah: 01:02:02

Thanks so much, Jerry. This has been great. We did have one question come in and the question is, can I have different VM sizes in a single cluster?

Jerry Meisner: 01:02:18

The answer to that question is absolutely yes. When we're talking about our node pool example by bringing up the cluster creation page, or by going back into my node pools. This is my existing cluster - I've created it. I can come back in here and add a node pool, and, from the node pool screen, I can choose a different size. If I created a secondary node pool that had a different CPU-to-memory ratio, for example, or maybe it has a GPU, I could create that as a separate node pool and then manage that through the node pools section here.

Sarah: 01:03:00

Awesome. Wonderful. Well, thanks so much Jerry for walking us through this today, and thanks everyone for joining us and for watching. Please reach out with any questions or concerns. Just go to redapt.com and contact us. We will happily field your questions and concerns. Thanks so much, Jerry.