In this tutorial, you learn how to use Visual Studio Team Services (VSTS), Kubernetes Engine, and Container Registry to create a continuous integration/continuous deployment (CI/CD) pipeline. The tutorial uses the ASP.NET MusicStore web application, which is based on ASP.NET Core.
The CI/CD pipeline uses two separate Kubernetes Engine clusters, one for testing and one for production. At the beginning of the pipeline, developers commit changes to the example codebase. This action triggers the pipeline to create a release and to deploy it to the development cluster. A release manager can then promote the release so that it's deployed into the production cluster. The following diagram illustrates this process.
The tutorial assumes that you have basic knowledge of .NET Core, VSTS, and Kubernetes Engine. The tutorial also requires you to have administrative access to a VSTS account and a Visual Studio 2017 installation that's already connected to your VSTS account.
Objectives
- Connect Container Registry to VSTS for publishing Docker images.
- Prepare a .NET Core sample application for deployment into Kubernetes Engine.
- Authenticate securely against Kubernetes Engine without having to use legacy authentication.
- Use VSTS release management to orchestrate Kubernetes Engine deployments.
Costs
This tutorial uses billable components of Google Cloud Platform, including:
- Kubernetes Engine
- Cloud Load Balancing
- Cloud Storage (for Container Registry)
Use the Pricing Calculator to generate a cost estimate based on your projected usage. Check the VSTS pricing page for any fees that might apply for using VSTS.
Before you begin
It's usually advisable to use separate projects for development and production workloads so that identity and access management (IAM) roles and permissions can be granted individually. For the sake of simplicity, this tutorial uses a single project for both Kubernetes Engine clusters, one for development and one for production.
-
Select or create a GCP project.
-
Make sure that billing is enabled for your project.
- Make sure you have a VSTS account and have administrator access to it. If you don't yet have a VSTS account, you can sign up on the VSTS home page.
- Make sure you have Visual Studio 2017 installed and that it's connected to your VSTS account.
Creating a VSTS project
You use VSTS to manage the source code, run builds and tests, and orchestrate the deployment to Kubernetes Engine. To begin, you create a new project in your VSTS account.
- Go to the VSTS home page
(
https://[YOUR_VSTS_ACCOUNT_NAME].visualstudio.com/_projects) - Click New Project (or Create Project if you're using the new navigation UI).
- Enter a project name such as
Music Store. - Choose Git for version control and then click Create.
-
After the project has been created, in the top menu, click Code.
You're prompted to clone, push, import, or initialize a repository.
-
Click Import to fork the MusicStore repository from GitHub. Set the following values:
- Source type:
Git - Clone URL:
https://github.com/aspnet/MusicStore.git - Leave the Requires authorization checkbox unselected.

- Source type:
-
Click Import.
-
Select Code > Files.
You now see the source code of the MusicStore application.
Building continuously
You can now use VSTS to set up continuous integration. For each commit that's pushed to the Git repository, VSTS builds the code and packages the build artifacts into a Docker container. The container is then published to Container Registry.
Creating a testing branch
To make sure that the instructions in this tutorial work, you'll create a branch of the code that's based on a specific version of the source code. (This will help make sure that future changes to the code on GitHub don't break this tutorial.)
- In VSTS, select Code > Tags.
- In the list of tags, expand rel and then right-click 2.0.0.
- Select New branch.
-
Enter
testingas the branch name and then click Create branch to confirm your selections.
Building the code
After you create the branch, you can begin to automate the build. Because MusicStore is an ASP.NET Core application, building includes four steps:
- Downloading and installing dependencies.
- Compiling the code.
- Running unit tests.
- Publishing the build results.
Later you'll add additional steps to deploy to Kubernetes Engine. Because Kubernetes Engine is a Linux-based environment, you'll set up the entire build process to run on Linux-based build agents.
- In VSTS, select Build and Release > Builds and then click New Definition.
- Select VSTS Git to set the default branch for manual.
- In the Default branch for manual and scheduled builds list, select testing and then click Continue.
- Select the ASP.NET Core template and then click Apply. Be careful to choose ASP.NET Core and not ASP.NET or ASP.NET Core (.NET Framework).
-
On the next page, apply the following settings:
- Name:
MusicStore-CI. You can use any name that doesn't contain whitespace characters. - Agent queue:
Hosted Linux Preview.This instructs VSTS to perform the build on Linux-based machines. - Project(s) to restore and build:
samples/**/*.csproj - Project(s) to test:
test/MusicStore.Test/*.csproj
- Name:
-
In the left navigation pane, click Restore and configure the following settings (you can leave the other settings as they are):
- Feeds and authentication: The Feeds in my NuGet.config option.
- Path to NuGet.config:
NuGet.config
-
Click Build and configure just the following settings:
- Arguments:
--configuration $(BuildConfiguration) --framework=$(TargetFramework)
- Arguments:
-
Click Test and configure the following settings:
- Arguments:
--configuration $(BuildConfiguration) --framework=$(TargetFramework)
- Arguments:
-
Click Publish and configure the following settings:
- Arguments:
--configuration $(BuildConfiguration) --framework=$(TargetFramework)
Be sure to remove the
--outputparameter that has been prepopulated for you.- Clear the Zip Published Projects checkbox, because later you'll add steps that require access to the unpackaged files.
- Clear the Add project name to publish path checkbox.
- Arguments:
-
Click the Variables tab and add the following variables:
- Name:
TargetFramework - Value:
netcoreapp2.0
- Name:
-
Click the Triggers tab and select the Enable continuous integration checkbox.
- At the top of the screen, click Save & queue.
- In the dialog, enter a comment if you want, and then confirm by clicking Save & queue.
- Follow the link at the top of the screen (Build nnn, where nnn is the build number) to track the progress of the build. If the build does not complete within about 2 minutes, check the build output in the Logs tab for any error messages.
Publishing Docker images
To deploy the MusicStore application to Kubernetes Engine, the application must be packaged as a Docker container and published to Container Registry. You will now extend the build definition to automate these steps.
Setting up a service account for publishing images
Connecting to Container Registry requires that VSTS can authenticate with GCP. To do this, you'll create a service account in GCP that's dedicated to this purpose.
-
Switch to your project in the GCP Console and open Cloud Shell.
-
To save time typing your project ID and Compute Engine zone options, set default configuration values by running the following commands:
gcloud config set project [PROJECT_NAME] gcloud config set compute/zone [ZONE]
Replace
[PROJECT_NAME]with the name of your GCP project and replace[ZONE]with the name of the zone that you're going to use for creating resources. If you're unsure about which zone to pick, useus-central1-a.Example:
gcloud config set project vsts-test-project-12345 gcloud config set compute/zone us-central1-a
-
Enable the Container Registry API for your project:
gcloud services enable containerregistry.googleapis.com
-
Create a service account for VSTS to publish Docker images:
gcloud iam service-accounts create vsts-publisher --display-name "VSTS Publisher"
-
Assign the Storage Admin IAM role to the service account:
PROJECT_NUMBER=$(gcloud projects describe \ $(gcloud config get-value core/project) \ --format=value(projectNumber))
VSTS_PUBLISHER=$(gcloud iam service-accounts list \ --filter="displayName:VSTS Publisher" \ --format='value(email)')
gcloud projects add-iam-policy-binding \ $(gcloud config get-value core/project) \ --member serviceAccount:$VSTS_PUBLISHER \ --role roles/storage.admin -
Generate a service account key:
gcloud iam service-accounts keys create \ vsts-publisher.json --iam-account $VSTS_PUBLISHER tr -d '\n' < vsts-publisher.json > vsts-publisher-oneline.json -
Launch Code Editor by clicking the button in the upper-right corner of Cloud Shell:

-
Open the file named
vsts-publisher-oneline.json. You'll need the content of this file in one of the following steps.
Connecting VSTS to Container Registry
With the service account created, you can now connect VSTS to Container Registry.
- In VSTS, in the menu at the top of the page, hold the mouse over the gear icon and click Services. If you're using the new navigation UI, click Project Settings at the bottom of the menu and then choose Service Endpoints.
- Click New Service Endpoint.
- From the list, select Docker Registry.
-
In the dialog, enter values for the following fields:
- Connection Name:
gcr-tutorial -
Docker Registry:
https://gcr.io/[PROJECT-NAME], where[PROJECT_NAME]is the name of your GCP project.Example:
https://gcr.io/vsts-test-project-12345 -
Docker ID:
_json_key - Password: The content of
vsts-publisher-oneline.json
- Connection Name:
-
Click OK to create the endpoint.
Checking out the project in Visual Studio
To create a Dockerfile that defines the contents of the Docker image, you must first check out the code.
- In Visual Studio, open Team Explorer.
- In the menu, click the Manage Connections icon.
-
Select Manage Connections > Connect to a Project.

-
In the next dialog, select the Music Store Git repository and then click Clone.

-
Open Team Explorer again.
- Click Branches and then expand the remotes/origin folder.
- Right-click the testing branch and click Checkout.
Creating a Dockerfile
With the code checked out, you can configure the Dockerfile.
- In Visual Studio, open Solution Explorer.
- In the root of the solution, create a new file named
Dockerfile. -
Copy the following code and paste into the file, and then save the file:
FROM microsoft/aspnetcore:2.0.0 WORKDIR /app COPY samples/MusicStore/bin/release/netcoreapp2.0/publish /app/ ENTRYPOINT ["dotnet", "MusicStore.dll"]
-
In the root of the solution, create a new file named
deployment.yaml. Leave the file empty for now. - Open Team Explorer and click the Home icon at upper left to switch to the Home view.
- Click Changes.
- Enter a commit message like
Add Dockerfile and placeholder for the Kubernetes manifest. - Click Commit All and Push.
Extending the build definition to build a Docker image
With all of the necessary files checked in, you can now go back to VSTS to extend the build definition.
- In VSTS, select Build and Release > Builds > MusicStore-CI.
- Click Edit.
- Select Phase 1 and then click the + icon to add another step to the process.
- Select the Command Line task and click Add.
- Select the newly added task and drag it so that it runs after the Publish task and before the Publish Artifact task.
-
Configure the following settings:
- Version:
1.* - Display name:
Lock image version in deployment.yaml - Tool:
/bin/bash - Arguments:
-c "awk '{gsub(\"MUSICSTORE_IMAGE\", \"gcr.io/$(musicstore.docker.imagename):$(Build.BuildId)\", $0); print}' deployment.yaml > $(build.artifactstagingdirectory)/deployment.yaml"
- Version:
-
On Phase 1, click the + icon to add another step to the process.
- Select the Docker task and then click Add.
- Select the new task and move it to the end of the list.
-
Configure the following settings for the Docker task:
- Display name:
Build image - Container Registry Type:
Container Registry - Docker Registry Connection:
gcr-tutorial - Action:
Build an image - Image name:
$(musicstore.docker.imagename):$(Build.BuildId)
- Display name:
-
On Phase 1, click the + icon to add another step to the process.
- Select the Docker task and then click Add.
- Select the newly added task and move it to the end of the list.
-
Configure the following settings for the Docker task:
- Display name:
Publish image - Container Registry Type:
Container Registry - Docker Registry Connection:
gcr-tutorial - Action:
Push an image - Image name:
$(musicstore.docker.imagename):$(Build.BuildId)
- Display name:
-
Verify that the order of steps is the same as in the following screenshot:

-
Switch to the Variables tab and add another variable:
- Name:
musicstore.docker.imagename - Value:
[PROJECT-NAME]/musicstore. Replace the[PROJECT-NAME]placeholder with the name of your GCP project.
- Name:
-
At the top of the screen, click Save & queue.
- In the dialog, enter a comment if you want, and then confirm by clicking Save & queue.
- Follow the link at the top of the screen to track the progress of the build. It might take around 2 minutes for the build to complete.
- To verify that the image has been published to Container Registry, switch to the GCP Console, select Container Registry > Images, and then click musicstore.
-
Observe that there is a single image, and that the tag of this image corresponds to the numeric ID of the build that was run in VSTS.

Deploying continuously
With VSTS automatically building your code and publishing Docker images for each commit, you can now turn your attention to deployment.
Unlike some other continuous integration systems, VSTS makes a distinction between building and deploying, and it provides a specialized set of tools labeled Release Management for all of the deployment-related tasks.
VSTS Release Management is built around these concepts:
- A release refers to set of artifacts that make up a specific version of your application and that are usually the result of a build process.
- Deployment refers to the process of taking a release and deploying it into a specific environment.
- A deployment performs a set of tasks, which can be grouped in phases.
- Environments allow you to distinguish between different sets of systems to deploy.
- A pipeline allows orchestrating deployments into multiple environments.
The primary artifact that the MusicStore build process produces is the Docker image. However, because the Docker image is published to Container Registry, the image is outside the scope of VSTS. The image therefore doesn't serve well as the definition of a release.
To deploy to Kubernetes, you also need a manifest, which resembles a bill of materials. The manifest not only defines the resources that Kubernetes is supposed to create and manage, but also specifies the exact version of the Docker image to use. The Kubernetes manifest is well suited to serve as the artifact that defines the release in VSTS Release Management.
Configuring the Kubernetes deployment
To run the MusicStore in Kubernetes, you need the following resources:
- A Deployment that defines a single pod that runs the Docker image produced by the build.
- A NodePort service that makes the pod accessible to a load balancer.
- An Ingress that exposes the application to the public internet by using a Cloud HTTP(S) load balancer.
With the MusicStore application, you can use either SQL Server or an embedded, locally stored database. For the sake of simplicity, use the default configuration that relies on the embedded database, although it comes with two restrictions:
- Only a single copy of the pod can run at a time. Otherwise users might see different data depending on which pod serves them.
- Any data changes are lost whenever the pod is restarted, unless you change the deployment to use persistent volumes. (We do not cover this scenario in the tutorial.)
To define these Kubernetes resources, you perform the following steps:
- In Visual Studio, open Solution Explorer.
-
Open
deployment.yamland paste in the following code, and then save the file:apiVersion: v1 kind: Service metadata: name: musicstore spec: ports: - port: 80 targetPort: 80 protocol: TCP name: http selector: app: musicstore type: NodePort
--- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: musicstore spec: backend: serviceName: musicstore servicePort: 80
--- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: musicstore spec: replicas: 1 template: metadata: labels: app: musicstore spec: containers: - name: musicstore image: MUSICSTORE_IMAGE ports: - containerPort: 80 livenessProbe: # Used by deployment controller httpGet: path: / port: 80 initialDelaySeconds: 5 periodSeconds: 5 readinessProbe: # Used by Ingress/GCLB httpGet: path: / port: 80 initialDelaySeconds: 3 periodSeconds: 5 resources: limits: memory: 1024Mi requests: memory: 768Mi -
Open Team Explorer and switch to the Home view.
- Click Changes.
- Enter a commit message like
Add Kubernetes manifest. - Click Commit All and Push.
Setting up the development and production environments
Before returning to VSTS Release Management, you need to create the Kubernetes Engine clusters.
Creating Kubernetes Engine clusters
- In GCP, open a Cloud Shell instance.
-
To save time typing your project ID and Compute Engine zone options, set the default configuration values by running the following commands:
gcloud config set project [PROJECT_NAME] gcloud config set compute/zone [ZONE]
Example:
gcloud config set project vsts-test-project-12345 gcloud config set compute/zone us-central1-a
-
Enable the Kubernetes Engine API for your project:
gcloud services enable container.googleapis.com
-
Create the development cluster by using the following command. Note that it might take a few minutes to complete:
gcloud container clusters create vsts-cicd-dev
-
Create the production cluster by using the following command. Note that it might take a few minutes to complete:
gcloud container clusters create vsts-cicd-prod
Setting up service accounts for deploying builds
Deploying to Kubernetes Engine requires that VSTS can authenticate to Kubernetes Engine. To facilitate this authentication, you'll create two more service accounts in GCP, each dedicated to deploying one environment.
-
Create a service account for VSTS to deploy Dev builds:
gcloud iam service-accounts create vsts-deployer-dev --display-name "VSTS Deployer for Dev"
-
Assign the Container Developer role to the service account:
PROJECT_NUMBER=$(gcloud projects describe \ $(gcloud config get-value core/project) --format=value(projectNumber))
VSTS_DEPLOYER_DEV=$(gcloud iam service-accounts list \ --filter="displayName:VSTS Deployer for Dev" --format='value(email)')
gcloud projects add-iam-policy-binding \ $(gcloud config get-value core/project) \ --member serviceAccount:$VSTS_DEPLOYER_DEV \ --role roles/container.developer -
Generate a service account key for the service account:
gcloud iam service-accounts keys create \ vsts-deployer-dev.json --iam-account $VSTS_DEPLOYER_DEV cat vsts-deployer-dev.json | base64 -w 0 > vsts-deployer-dev-oneline.json -
Create a service account for VSTS to deploy production builds:
gcloud iam service-accounts create vsts-deployer-prod --display-name "VSTS Deployer for Prod"
-
Assign the Container Developer role to the service account:
PROJECT_NUMBER=$(gcloud projects describe \ $(gcloud config get-value core/project) --format=value(projectNumber))
VSTS_DEPLOYER_PROD=$(gcloud iam service-accounts list \ --filter="displayName:VSTS Deployer for Prod" --format='value(email)')
gcloud projects add-iam-policy-binding \ $(gcloud config get-value core/project) \ --member serviceAccount:$VSTS_DEPLOYER_PROD \ --role roles/container.developer -
Generate a service account key:
gcloud iam service-accounts keys create \ vsts-deployer-prod.json --iam-account $VSTS_DEPLOYER_PROD cat vsts-deployer-prod.json | base64 -w 0 > vsts-deployer-prod-oneline.json -
Launch Code Editor by clicking the button in the upper-right corner of Cloud Shell. In one of the following steps, you'll need the contents of both
vsts-deployer-dev.jsonandvsts-deployer-prod.json, and Code Editor is the easiest way to copy those contents.
Configuring the release pipeline
After you set up the Kubernetes Engine infrastructure, you return to VSTS to automate the deployment, which includes the following:
- Deploying to the development environment.
- Requesting manual approval before initiating a deployment to the production environment.
- Deploying to the production environment.
Just as you can use VSTS to connect to an external Docker registry like Container Registry, VSTS supports integrating external Kubernetes clusters. To use this feature with Kubernetes Engine, however, you would have to enable legacy authentication, which isn't advisable. Rather than using this VSTS feature, you're going to create a task group that you can use to interact with Kubernetes Engine by using service account key-based authentication.
Creating a release definition
As a first step, create a new release definition.
- In VSTS, select Build and Release > Releases.
- Click New Definition.
- From the list of templates, select Empty Process.
- When you're prompted for an environment name, enter Dev.
- At the top of the screen, name the release MusicStore-KubernetesEngine.
- In the pipeline diagram, next to Artifacts, click Add.
-
Select Build and add the following settings:
- Source:
MusicStore-CI - Default version:
Latest - Source Alias:
manifest
- Source:
-
Click Add.
- On the Artifact box, click the lightning bolt icon to add a deployment trigger.
- Set the switch to Enabled.
- Click Save.
- Enter a comment if you want, and then confirm by clicking Save.
The pipeline now looks like this:

Creating a task group for Kubernetes Engine deployments
With the release definition created, you can now create a task group that encapsulates the steps that are necessary to authenticate and communicate securely with Kubernetes Engine. You can use this task group for deploying to both the development and production environments, so you won't need to configure these steps twice.
- In VSTS, switch to the Tasks tab.
- Click Agent phase.
- Change the agent queue to Hosted Linux Preview.
- Next to Agent phase, click the + icon to add a step to the phase.
- Select the Docker task and click Add.
-
Click the newly added task and configure the following settings:
- Display name:
Kubernetes Engine - Container Registry Type:
Container Registry - Docker Registry Connection:
gcr-tutorial - Action:
Run an image - Image Name:
gcr.io/cloud-builders/kubectl - Volumes:
$(System.ArtifactsDirectory):/workspace - Environment Variables:
SA_KEY=$(ServiceAccountKey) - Entrypoint Override:
/bin/bash - Command:
-c "echo $SA_KEY | base64 -d > _key.json && gcloud auth activate-service-account --key-file=_key.json && gcloud container clusters get-credentials $(KubernetesCluster.Name) --zone $(KubernetesCluster.Zone) --project $(KubernetesCluster.Project) && kubectl $(Command)"
This command uses the service account key, which is supplied as a parameter, and it uses
gcloudto authenticate to GCP. The command downloads the configuration that's necessary to communicate with the Kubernetes Engine cluster, and then runs akubectlcommand. Because neithergcloudnorkubectlare available on a VSTS agent by default, VSTS runs the steps in a Google-supplied Docker container that has these tools preinstalled. - Display name:
-
Clear Run In Background.
- Click Save.
- Enter a comment if you want, and then confirm by clicking OK.
- In the left pane, right-click the Kubernetes Engine step, and then click Create task group.
- Enter
Kubernetes Engineas the name and click Create. Note that this action causes some redThis setting is requiredwarnings to appear. You'll resolve these issues shortly.
Deploying to the development cluster
The next step is to configure the deployment to the Kubernetes Engine development cluster.
-
In VSTS, switch to the Variables tab and add the following variables:
Name Value ServiceAccountKey.DevCopy the content of the file vsts-deployer-dev-oneline.json
Note: Click the lock icon to ensure that the variable is treated as secret.KubernetesCluster.Dev.Namevsts-cicd-devKubernetesCluster.Dev.ZoneThe zone in which you created the cluster. KubernetesCluster.Dev.ProjectThe name of the GCP project in which you created the cluster (for example, vsts-test-project-12345). -
Switch to the Tasks tab.
-
Click Task group: Kubernetes Engine and configure the following settings. Note that the fields might show up in a different order than listed here.
- Display name:
Deploy to dev - Command:
apply -f '/workspace/manifest/drop/deployment.yaml' - KubernetesCluster.Name:
$(KubernetesCluster.Dev.Name) - KubernetesCluster.Zone:
$(KubernetesCluster.Dev.Zone) - KubernetesCluster.Project:
$(KubernetesCluster.Dev.Project) - ServiceAccountKey:
$(ServiceAccountKey.Dev)
- Display name:
-
Click Save.
- Enter a comment if you want, and then confirm by clicking OK.
Deploying to the production cluster
Finally, you configure the deployment to the Kubernetes Engine production cluster.
- In VSTS, switch to the Pipeline tab.
- In the Environments box, select Add > New environment.
- From the list of templates, select Empty Process.
- When you're prompted for an environment name, enter
Prod. - Click the lightning bolt icon of the newly created environment.
-
Configure the following settings:
- Select trigger:
After environment - Environment:
Dev - Pre-deployment approvals: (enabled)
- Approvers: Select your own user name or group.
The pipeline now looks like this:

- Select trigger:
-
On the Variables tab, add the following variables:
Name Value ServiceAccountKey.ProdCopy the content of the file vsts-deployer-prod-oneline.json
Note: Click the lock icon to ensure that the variable is treated as secretKubernetesCluster.Prod.Namevsts-cicd-prodKubernetesCluster.Prod.ZoneThe zone in which you created the cluster. KubernetesCluster.Prod.ProjectThe name of the GCP project in which you created the cluster. -
Switch to the Tasks tab.
- Hold the mouse over the Tasks tab and select Tasks > Prod.
- Click Agent phase.
- Change the agent queue to Hosted Linux Preview.
- Click the + icon to add a step to the phase.
- Select the Kubernetes Engine task and click Add.
-
Click the Kubernetes Engine task and configure the following settings. Note that the fields might show up in a different order r than listed here.
- Display name:
Deploy to prod - Command:
apply -f '/workspace/manifest/drop/deployment.yaml' - KubernetesCluster.Name:
$(KubernetesCluster.Prod.Name) - KubernetesCluster.Zone:
$(KubernetesCluster.Prod.Zone) - KubernetesCluster.Project:
$(KubernetesCluster.Prod.Project) - ServiceAccountKey:
$(ServiceAccountKey.Prod)
- Display name:
-
Click Save.
- Enter a comment if you want, and then confirm by clicking OK.
Running the pipeline
Now that you've configured the entire pipeline, it's time to test it by performing a source code change.
- In Visual Studio, open the file
samples\MusicStore\config.json. - In line 3, change the
SiteTitlesetting toMusic Store running on Google Kubernetes Engine. - Open Team Explorer and switch to the Home view.
- Click Changes.
- Enter a commit message like
Change site title. - Click Commit All and Push.
-
In VSTS, select Build and Release > Builds and observe that a build has been triggered automatically:

It might take around 2 minutes before the status switches to Succeeded.
-
When the build is finished, select Build and Release > Releases and observe that a release process has been initiated:

-
Click Release-2 to open the details page, and wait for the status of the Dev environment to switch to Succeeded. You might need to refresh the status by clicking the Refresh button in the menu or by reloading the browser page.
- In the GCP Console, select Kubernetes Engine > Services.
- Locate the Ingress service for the vsts-cicd-dev cluster, and wait for its status to switch to Ok. This might take several minutes.
- Copy the URL of the link that's labeled
*/*within the same row and remove the trailing asterisk. -
Open the URL in a new browser tab. You might see an error at first because the load balancer takes a few minutes to become available. When it's ready, observe that the Music Store has been deployed and is using the custom title:

-
In VSTS, at the top of the release page, click Approve or Reject:

If you don't see the yellow-shaded bar, you might need to first approve or reject a previous release.
-
Click Approve to trigger the deployment to the production environment.
- Wait for the status of the Prod environment to switch to Succeeded. You might need to manually refresh the page in your browser.
- In the GCP Console, refresh the Services page.
- Locate the Ingress service for the vsts-cicd-prod cluster and wait for its status to switch to Ok. This might take several minutes.
- Copy the URL of the link that's labeled
*/*within the same row and remove the trailing asterisk. - Open the URL in a new browser tab. Again, you might see an error at first because the load balancer take a few minutes to become available. When it's ready, you see the MusicStore app with the custom title again, this time running in the production cluster.
Cleaning up
To avoid incurring further costs after you have completed this tutorial, delete the entities that you've created.
Delete the VSTS project
Delete the project in VSTS. Note that this also causes all source code changes to be lost.
Delete the GCP project
- In the GCP Console, go to the Projects page.
-
In the project list, select the project you
want to delete and click Delete project.
- In the dialog, type the project ID, and then click Shut down to delete the project.
What's next
- Configure fine-grained access control for Container Registry.
- Learn how to deploy a highly available SQL Server group on Compute Engine.
- Read about .NET on Google Cloud Platform.
- Install Cloud Tools for Visual Studio.
- Try out other Google Cloud Platform features for yourself. Have a look at our tutorials.