{"id":10018,"date":"2023-07-27T21:41:32","date_gmt":"2023-07-27T21:41:32","guid":{"rendered":"https:\/\/putridparrot.com\/blog\/?p=10018"},"modified":"2023-07-30T18:22:38","modified_gmt":"2023-07-30T18:22:38","slug":"running-and-deploying-to-azure-kubernetes","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/running-and-deploying-to-azure-kubernetes\/","title":{"rendered":"Running and deploying to Azure Kubernetes"},"content":{"rendered":"<p>We&#8217;re going to be deploying our web services to k8s using Docker, so first off we need to create a registry (if you don&#8217;t already have one) on Azure.<\/p>\n<ul>\n<li>Go to the Azure Dashboard and select <em>Create a resource<\/em><\/li>\n<li>Locate and click on <em>Container Registry<\/em><\/li>\n<li>Click on <em>Create<\/em><\/li>\n<li>Supply the <em>Resource Group<\/em> you want to use, I&#8217;m using the one I created for my previous post <a href=\"https:\/\/putridparrot.com\/blog\/creating-and-using-the-azure-service-bus\/\" rel=\"noopener\" target=\"_blank\">Creating and using the Azure Service Bus<\/a><\/li>\n<li>Create a registry name, mines <em>apptestregistry<\/em><\/li>\n<li>Select your location and SKU, I&#8217;ve gone <em>Basic<\/em> on the SKU<\/li>\n<\/ul>\n<p>Now click <em>Review + create<\/em>. Review your options and if all looks correct then click <em>Create<\/em>. Now wait for the Deployment to complete and go to the resource&#8217;s dashboard where you&#8217;ll see (at least on the current Dashboard) options to <em>Push a Container image<\/em>, <em>Deployment a container image<\/em> etc.<\/p>\n<p><strong>Adding a Kubernetes service<\/strong><\/p>\n<p>We now need to return to the main dashboard to select <em>Containers | Kubernetes services<\/em> or just type <em>Kubernetes services<\/em> into the Dashboard search bar.<\/p>\n<ul>\n<li>In <em>Kubernetes services<\/em> click Create<\/li>\n<li>Click <em>Create a Kubernetes cluster<\/em><\/li>\n<li>Supply a <em>Resource Group<\/em><\/li>\n<li>For <em>Cluster preset configuration<\/em> choose Dev\/Test for now<\/li>\n<li>Enter a <em>Kubernetes cluster name<\/em>, mine&#8217;s testappcluster<\/li>\n<li>Fill in the rest of the options to suite your location etc.<\/li>\n<\/ul>\n<p>Now click <em>Review + create<\/em>. <\/p>\n<p><strong>Stop, don&#8217;t press create yet<\/strong>. Before we click create, go to the Integrations tab and set the Container Registry to the one we created &#8211; if you don&#8217;t do this then you&#8217;ll get 401&#8217;s when trying to deploy from your registry into K8s. <\/p>\n<p><em>Note: There is a way to create this integration between k8s and your registry later, but it is so much simpler letting the Dashboard do the work for us.<\/em><\/p>\n<p>Now, review your options and if happy all looks correct, click <em>Create<\/em>. <\/p>\n<p><em>Note: I kept getting an error around quota&#8217;s on the setup above, I found if you reduce the autoscaling slider\/values (as mine showed it would be maxed out) then this should pass the review phase.<\/em><\/p>\n<p>Once the deployment in complete (and it may take a little while) we&#8217;ll need something to push to it&#8230;<\/p>\n<p><strong>Creating a simple set of microservices<\/strong><\/p>\n<ul>\n<li>Using Visual Studio, create a new <em>ASP.NET Core Web API<\/em>, make sure to have Docker support checked<\/li>\n<li>Delete the Weatherforecast controller and domain object<\/li>\n<li>Right mouse click on Controllers and select Add | Controller<\/li>\n<li>Select an empty controller<\/li>\n<\/ul>\n<p><em>Note: We&#8217;re going to use the Azure CLI tools, so if you&#8217;ve not got the latest, go to https:\/\/learn.microsoft.com\/en-us\/cli\/azure\/install-azure-cli-windows?tabs=azure-cli#install-or-update and install from here<\/em><\/p>\n<p>Now let&#8217;s dockerize our WebApi&#8230; <\/p>\n<p><em>Note: Replace apptestregistry with your registry name and I&#8217;m not going to include th az login etc. and my service within the registry is called myname, so replace with something meaningful. Also ver01: is the version I&#8217;m assigning to the image.<\/em><\/p>\n<ul>\n<li>Copy your Docker file for your WebApi into the solution folder of your project<\/li>\n<li>Run <em>az acr build -t myname:ver01 -r apptestregistry .<\/em><\/li>\n<\/ul>\n<p>That&#8217;s all there is to it, repeat for each WebApi you want to deploy.<\/p>\n<p>To check all went well. We&#8217;re going to use the following az command to list the Azure registry (change the registry name to yours)<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\naz acr repository list --name apptestregistry\r\n<\/pre>\n<p>Or you can go to the Azure container registry dashboard and select <em>Repositories<\/em><\/p>\n<p><strong>Deploying to Kubernetes<\/strong><\/p>\n<p>At this point we&#8217;ve created our WebApi, dockerized it and deployed to the Azure registry of our choice, but to get it into k8s we need to create the k8s manifests.<\/p>\n<p>We create a YML file, for example kubernetes-manifest-myname.yaml (change myname to the name of your service as well is with the YML below, don&#8217;t forget to change apptestregistry to your registry name also)<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\napiVersion: apps\/v1 \r\nkind: Deployment \r\nmetadata: \r\n  name: myname\r\n  labels: \r\n    app: myname\r\nspec: \r\n  selector: \r\n    matchLabels: \r\n      app: myname \r\n  replicas: 1 \r\n  template: \r\n    metadata: \r\n      labels: \r\n        app: myname\r\n    spec: \r\n      containers: \r\n      - name: myname\r\n        image: apptestregistry.azurecr.io\/myname:ver01 \r\n        resources: \r\n          requests: \r\n            cpu: 100m \r\n            memory: 100Mi \r\n          limits: \r\n            cpu: 200m \r\n            memory: 200Mi \r\n        ports: \r\n        - containerPort: 80 \r\n--- \r\napiVersion: v1 \r\nkind: Service \r\nmetadata: \r\n  name: myname\r\nspec:\r\n  ports: \r\n  - port: 80 \r\n  selector: \r\n    app: myname\r\n---\r\n<\/pre>\n<p>We need to set up <em>kubectl<\/em> access from Terminal\/PowerShell using<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\naz aks get-credentials -n testappcluster -g test-app-cluster\r\nkubectl apply -f .\\kubernetes-your-manifest-file-yaml\r\n<\/pre>\n<p>We can check that the pods exist using<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nkubectl get pods\r\n<\/pre>\n<p><em>If you notice Status or ImagePullBackOff then it&#8217;s possible you&#8217;ve not set up the integration of k8s and your registry, to be sure type &#8220;kubectl describe pod&#8221; along with your pod name to get more informations.<\/em><\/p>\n<p>and finally, let&#8217;s check the status of our services using<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nkubectl get services\r\n<\/pre>\n<p>In the Azure Kubernetes services dashboard you can select <em>Services and ingresses<\/em> to view the newly added service(s).<\/p>\n<p>We can see <em>Cluster IP<\/em> address which is an internal IP address. So for example if our <em>myname<\/em> service has Cluster IP 10.0.40.100 then other services deployed to the cluster can interact with the <em>myname<\/em> service by this IP.<\/p>\n<p><strong>External facing service<\/strong><\/p>\n<p>We&#8217;ve created an service which is hosted in a pod within k8s but we have no external interface to it. A simple way to create an external IP from our service is by declaring a service as a load balancer which routes calls to the various services we&#8217;ve deployed. <\/p>\n<p>So let&#8217;s assume we created a new WebApi, with Docker support and we added the following controller which routes operations to a single endpoint in this case, but ofcourse it could route to any WebApi that we&#8217;ve deployed via it&#8217;s Cluster IP<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n&#x5B;ApiController]\r\n&#x5B;Route(&quot;&#x5B;controller]&quot;)]\r\npublic class MathController : Controller\r\n{\r\n    &#x5B;HttpGet(&quot;Get&quot;)]\r\n    public async Task&lt;string&gt; Get(string op)\r\n    {\r\n        var httpClient = new HttpClient();\r\n        using var response = await httpClient.GetAsync($&quot;http:\/\/10.0.40.100\/myname\/get?operation={op}&quot;);\r\n        return await response.Content.ReadAsStringAsync();\r\n    }\r\n}\r\n<\/pre>\n<p>Once we have an <em>External IP<\/em> associate with this load balance type of service, then we can access from the web i.e. http:\/\/{external-ip}\/myservice\/get?op=display<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We&#8217;re going to be deploying our web services to k8s using Docker, so first off we need to create a registry (if you don&#8217;t already have one) on Azure. Go to the Azure Dashboard and select Create a resource Locate and click on Container Registry Click on Create Supply the Resource Group you want to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[96,3],"tags":[],"class_list":["post-10018","post","type-post","status-publish","format-standard","hentry","category-azure-2","category-c"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/10018","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=10018"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/10018\/revisions"}],"predecessor-version":[{"id":10064,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/10018\/revisions\/10064"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=10018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=10018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=10018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}