{"id":33235,"date":"2017-06-09T08:41:03","date_gmt":"2017-06-09T08:41:03","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/visualstudioalm\/?p=33235"},"modified":"2019-02-14T15:51:34","modified_gmt":"2019-02-14T23:51:34","slug":"deploying-applications-to-azure-container-service","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/devops\/deploying-applications-to-azure-container-service\/","title":{"rendered":"Deploying Applications to Azure Container Service"},"content":{"rendered":"<p>In this blog post I will show you how to setup continuous delivery of a dockerized app by using Visual Studio Team Services (VSTS) to a Kubernetes cluster running in ACS.<\/p>\n<p><span><a href=\"https:\/\/azure.microsoft.com\/en-us\/services\/container-service\/\">Azure Container Service<\/a><\/span><span>\u00a0<\/span>(ACS) allows to deploy and manage containers using Kubernetes, Docker Swarm, Mesosphere DC\/OS orchestrators. You can now deploy these three orchestrators on Azure, by either using the portal, Azure Resource Manager template or Azure-CLI.<\/p>\n<p>The<span>\u00a0<\/span><span><a href=\"https:\/\/azure.microsoft.com\/en-us\/services\/container-registry\/\">Azure Container Registry<\/a><\/span><span>\u00a0 (ACR) is an <\/span>implementation of the open source Docker Registry. ACR is now available as an Azure Service and it is fully compatible with all the three orchestrators. ACR is used as a private registry to store Docker images for enterprise applications instead of having to use the public Docker Hub.<\/p>\n<p>The end to end setup will include building a .NET Core application followed by building a container image and pushing the image to Azure Container Registry. In release, we will deploy the container image to the Kubernetes Cluster.<\/p>\n<h3>Prerequisites<\/h3>\n<ol>\n<li>ACS Kubernetes cluster<\/li>\n<li>Azure Container Registry in the same Azure subscription<\/li>\n<\/ol>\n<h3>Code<\/h3>\n<p><span><a href=\"https:\/\/github.com\/azooinmyluggage\/k8s-docker-core\">Download\/fork our .NET Core sample app<\/a><\/span><span>.<\/span> Upload your code to Team Services or you\u2019re on-premises Team Foundation Server: either push your code to Git or check in your code to TFVC.<\/p>\n<h3>Build<\/h3>\n<ul>\n<li><span><a href=\"https:\/\/www.visualstudio.com\/en-in\/docs\/build\/apps\/node\/nodejs-to-azure#expando-begin-create-build-definition-open-team-project\">Open your team project in your web browser <\/a><\/span><\/li>\n<li><span><a href=\"https:\/\/www.visualstudio.com\/en-in\/docs\/build\/apps\/node\/nodejs-to-azure#expando-begin-create-build-definition-create\">Create a build definition (Build &amp; Release tab &gt; Builds)<\/a><\/span><\/li>\n<li>Click Empty to start with an empty definition.<\/li>\n<li>In the repository tab of build definition make sure the repository selected is the one where you pushed (Git) or checked in (TFVC) your code<\/li>\n<\/ul>\n<p>On the<span>\u00a0<\/span><strong>Tasks<\/strong><span>\u00a0<\/span>or<span>\u00a0<\/span><strong>Build<\/strong><span>\u00a0<\/span>tab, add these steps.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/32.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2017\/06\/32-1024x366.png\" alt=\"\" width=\"879\" height=\"314\" class=\"aligncenter size-large wp-image-33325\" \/><\/a>\n<a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/31.jpg\"><\/a><\/p>\n<table>\n<tbody>\n<tr>\n<td><strong>dotnet restore<\/strong><\/td>\n<td>Restores the dependencies and tools of your project. Dotnet restore command uses NuGet to restore dependencies.<\/p>\n<ul>\n<li>Command:<span>\u00a0<\/span> restore<\/li>\n<li>Projects: **\/*.csproj<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<tr>\n<td><strong>dotnet build<\/strong><\/td>\n<td>Build the project and all its dependencies<\/p>\n<ul>\n<li>Command:<span>\u00a0<\/span> restore<\/li>\n<li>Projects: **\/*.csproj<\/li>\n<li>Arguments: -c Release<\/li>\n<\/ul>\n<p>The project will be built in release configuration.<\/td>\n<\/tr>\n<tr>\n<td><strong>dotnet publish<\/strong><\/td>\n<td>Pack the application and its dependencies into a folder for deployment to a hosting system.<\/p>\n<ul>\n<li>Command:<span>\u00a0<\/span> publish<\/li>\n<li>Projects: **\/*.csproj<\/li>\n<li>Arguments: -o publish<\/li>\n<\/ul>\n<p>The name of the output directory will be publish.<\/td>\n<\/tr>\n<tr>\n<td><strong>Docker: Build an image<\/strong><\/td>\n<td>This step will build the container image from the Dockerfile. Team Services has support for Docker compose as well.<\/p>\n<ul>\n<li>Container Registry Type: Choose Azure Container Registry<\/li>\n<li><span>Select the Azure Subscription and the Azure Container Registry where the container image will be pushed<\/span><\/li>\n<li><span>Action: <\/span>Build an image<\/li>\n<li>Image name: docker-dotnetcore<\/li>\n<li>Qualify Image Name: Enable this option<\/li>\n<li>Additional Image Tags: $(Build.BuildId)<\/li>\n<\/ul>\n<p>You can also choose to add the \u2018Latest\u2019 tag as well to your image.<\/td>\n<\/tr>\n<tr>\n<td><strong>Docker: Push an image<\/strong><\/td>\n<td>This step will push the container image to a container registry.<\/p>\n<ul>\n<li>Container Registry Type: Choose Azure Container Registry<span>\u00a0<\/span><\/li>\n<li><span>Select the Azure Subscription and the Azure Container Registry where the container image will be pushed<\/span><\/li>\n<li><span>Action: <\/span>Push an image<\/li>\n<li>Image name: docker-dotnetcore<\/li>\n<li>Qualify Image Name: Enable this option<\/li>\n<li>Additional Image Tags: $(Build.BuildId)<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<tr>\n<td><strong>Build: Publish Kubernetes config files as Artifacts<\/strong><\/td>\n<td>Publish the Kubernetes configuration files used for creating <span><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/workloads\/controllers\/deployment\/\">deployment<\/a><\/span> and <span><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/service\/\">service<\/a><\/span> in the cluster. They are added to the <span><a href=\"https:\/\/github.com\/azooinmyluggage\/k8s-docker-core\/tree\/master\/k8config\">repository<\/a><\/span>.<\/p>\n<ul>\n<li>Path to Publish:<span>\u00a0<\/span>k8config<\/li>\n<li>Artifact name:<span>\u00a0<\/span>yaml<\/li>\n<li>Artifact Type:<span>\u00a0<\/span>Server<\/li>\n<\/ul>\n<p>We will use these files later to deploy to Kubernetes.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>You can add <span><a href=\"https:\/\/docs.microsoft.com\/en-us\/dotnet\/core\/tools\/dotnet-test\">dotnet test<\/a><\/span> command to run your unit tests as a part of your build. Similarly, Team Services has support for Docker compose as well and instead of using Dockerfile, compose can be used.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/42.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2017\/06\/42.png\" alt=\"\" width=\"929\" height=\"185\" class=\"aligncenter size-full wp-image-33285\" \/><\/a><\/p>\n<p>When you are working with a private registry (like ACR) and not with the Docker hub, you need to prefix the name of your image with the URL of your registry. In the Team Service Docker Tasks, you can just enable the \u201cQualify Image Name\u201d option to enforce this.<\/p>\n<p>Using $(Build.BuildId) tag on the image generated gives you traceability when the image gets deployed to an ACS cluster.<\/p>\n<h4>Enable continuous integration (CI)<\/h4>\n<p>On the<span>\u00a0<\/span><strong>Triggers<\/strong><span>\u00a0<\/span>tab, enable<span>\u00a0<\/span><strong>Continuous integration<\/strong><span>\u00a0<\/span>(CI). This tells the system to queue a build whenever someone on your team commits or checks in new code.<\/p>\n<h4>Save, queue, and test the build<\/h4>\n<p>Save and queue the build. Once the build is done, click the link to the completed build (for example,<span>\u00a0<\/span><em>Build 1634<\/em>), click<span>\u00a0<\/span><strong>Artifacts<\/strong>, and then click<span>\u00a0<\/span><strong>Explore<\/strong><span>\u00a0<\/span>to see the files produced by the build.<\/p>\n<h3>Release<\/h3>\n<ol>\n<li>Open the<span><\/span><strong>Releases<\/strong><span>\u00a0<\/span>tab of the<span>\u00a0<\/span><strong>Build &amp; Release<\/strong><span>\u00a0<\/span>hub, open the<span>\u00a0<\/span><strong>+<\/strong><span>\u00a0<\/span>drop-down in the list of release definitions, and choose<span>\u00a0<\/span><strong>Create release definition by using the Deploy to Kubernetes Cluster template.<\/strong><\/li>\n<li>Select the build definition you created earlier as the source of artifact to be deployed.<\/li>\n<\/ol>\n<ol start=\"3\">\n<li>Make sure you add three instances of <strong>Deploy to Kubernetes<\/strong> task. Configure the\u00a0<strong>Deploy to Kubernetes<\/strong> The task uses <span><a href=\"https:\/\/kubernetes.io\/docs\/user-guide\/kubectl-overview\/\">kubectl<\/a><\/span> for running commands against a Kubernetes cluster.<\/li>\n<li>For running kubectl commands by using the task, first you need to create a service connection to Kubernetes cluster by providing the following details:\n<ul>\n<li>A name of the connection<\/li>\n<li>Server url: you can get this detail from the Azure portal overview page of the ACS cluster. For example <span>https:\/\/&lt;cluster<\/span>_ name&gt;southcentralus.cloudapp.azure.com<\/li>\n<li>Kubeconfig: Copy paste the content of the <span><a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/container-service\/container-service-kubernetes-walkthrough\">master Kubernetes cluster configuration<\/a><\/span><\/li>\n<\/ul>\n<\/li>\n<li>As a part of release we will be executing the following steps:\n<ul>\n<li>Create a secret that cluster can use to connect to container registry<\/li>\n<li>Create a <span><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/workloads\/controllers\/deployment\/\">Kubernetes deployment<\/a><\/span> and <span><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/service\/\">service<\/a><\/span><\/li>\n<li>Use the new images we built and pushed to container registry earlier to update the Kubernetes cluster<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>Here is how the release definition will look like:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/26.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2017\/06\/26-1024x254.png\" alt=\"\" width=\"879\" height=\"218\" class=\"aligncenter size-large wp-image-33316\" \/><\/a><\/p>\n<table>\n<tbody>\n<tr>\n<td width=\"103\"><strong>Kubernetes: Create Deployment <\/strong><\/td>\n<td width=\"519\">In the first step we will create a <span><a href=\"https:\/\/kubernetes.io\/docs\/user-guide\/kubectl\/v1.6\/#-em-secret-docker-registry-em-\">new secret for use with Docker registries<\/a><\/span>. The task takes the container registry connection details and creates a secret.<\/p>\n<ul>\n<li>Container Registry type:<span>\u00a0<\/span>Azure Container registry<\/li>\n<li>Azure Subscription: Select the same Azure subscription which has your container registry.<\/li>\n<li>Azure Container registry: Select<\/strong> the azure container registry to which you pushed your container images<\/li>\n<li>Secret name: Name of the docker-registry secret. You can use this secret name in the Kubernetes YAML configuration file. In this case it is azurecontainerreg . Refer to <span><a href=\"https:\/\/github.com\/azooinmyluggage\/k8s-docker-core\/blob\/master\/k8config\/deployment.yaml\">imagepullsecretes in deployment.yaml<\/a><\/span><\/li>\n<li>Azure Container registry: Select<\/strong> the azure container registry to which you pushed your container images<\/li>\n<p>Now in the command section of the task let us create a <span><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/workloads\/controllers\/deployment\/\">deployment<\/a><\/span> by using the <span><a href=\"https:\/\/github.com\/azooinmyluggage\/k8s-docker-core\/blob\/master\/k8config\/deployment.yaml\">deployment.yaml<\/a><\/span> file<\/p>\n<li>Command: apply (you can run any kubectl command)<\/li>\n<li>Use Configuration file: Checked<\/li>\n<li>Configuration file: Use the file picker to select the deployment.yaml file which was published as an artifact from the build. E.g. $(System.DefaultWorkingDirectory)\/Kubernetes-ACS-CI\/yaml\/deployment.yaml<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"103\"><strong>Kubernetes: Create Service<\/strong><\/td>\n<td width=\"519\">In the command section of the task let us create a <span><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/service\/\">service<\/a><\/span> by using the <span><a href=\"https:\/\/github.com\/azooinmyluggage\/k8s-docker-core\/blob\/master\/k8config\/service.yaml\">service.yaml<\/a><\/span> file<\/p>\n<ul>\n<li>Command: <\/strong>apply (you can run any kubectl command)<\/li>\n<li>Use Configuration file: Checked<\/li>\n<li>Configuration file: Use the file picker to select the service.yaml file which was published as an artifact from the build. E.g. $(System.DefaultWorkingDirectory)\/Kubernetes-ACS-CI\/yaml\/service.yaml<\/li>\n<\/ul>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"103\"><strong>Kubernetes: Update<\/strong><\/td>\n<td width=\"519\">Now update with the latest image<\/p>\n<ul>\n<li>Command: set(you can run any kubectl command)<\/li>\n<li>Arguments: image deployment\/coreserverdeployment core-server=image:tag<\/li>\n<p>For example, in this case since we are using a private registry so the image name must be prefixed with the container registry name. And we used Build Id to tag our images too. So the image:tag value will be <em>Your-acr-name.azurecr.io\/docker-dotnetcore:$(Build.BuildId)<\/em>\n<em>docker-dotnetcore<\/em> is the image name we used in build.\n<\/ul>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<ol start=\"6\">\n<li>Type a name for the new release definition and, optionally, change the name of the environment from <span><\/span><strong>Default Environment<\/strong><span>\u00a0<\/span>to<span>\u00a0<\/span><strong>Dev<\/strong>. Also, set the deployment condition on the environment to \u201cAutomatically start after release creation\u201d.<\/li>\n<\/ol>\n<ol start=\"7\">\n<li>Save the new release definition. Create a new release and verify that the application has been deployed correctly.<\/li>\n<\/ol>\n<h3>Next steps<\/h3>\n<p>In this example, we used the kubectl set image command along with Build Id as tag. Using Build Id as tag has an added advantage of trace-ability. Avoid using latest tag with the container image. An alternate approach is to modify the yaml file with the Build Id used to tag the image.<\/p>\n<p>Kubernetes <span><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/overview\/working-with-objects\/namespaces\/\">namespace<\/a><\/span> allows complete separation of resources and management within the same cluster. So <span><a href=\"https:\/\/kubernetes.io\/docs\/concepts\/overview\/working-with-objects\/namespaces\/\">namespace<\/a><\/span> can be used to create multiple environments like Dev, QA, Production in the same ACS Kubernetes cluster.<\/p>\n<p>The Docker and Kubernetes task in Team services can help you setup an end to end CI \u2013 CD workflow. Do let us know your feedback\/suggestions. Use the \u201csend a smile\u201d feature, comment on this post.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog post I will show you how to setup continuous delivery of a dockerized app by using Visual Studio Team Services (VSTS) to a Kubernetes cluster running in ACS. Azure Container Service\u00a0(ACS) allows to deploy and manage containers using Kubernetes, Docker Swarm, Mesosphere DC\/OS orchestrators. You can now deploy these three orchestrators on [&hellip;]<\/p>\n","protected":false},"author":230,"featured_media":45953,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[224,253,226,1],"tags":[],"class_list":["post-33235","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-azure-devops-server","category-ci","category-devops"],"acf":[],"blog_post_summary":"<p>In this blog post I will show you how to setup continuous delivery of a dockerized app by using Visual Studio Team Services (VSTS) to a Kubernetes cluster running in ACS. Azure Container Service\u00a0(ACS) allows to deploy and manage containers using Kubernetes, Docker Swarm, Mesosphere DC\/OS orchestrators. You can now deploy these three orchestrators on [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/33235","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/users\/230"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/comments?post=33235"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/33235\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media\/45953"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media?parent=33235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/categories?post=33235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/tags?post=33235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}