This tutorial is the third part of a series that helps you deploy a highly available Windows architecture with Microsoft Active Directory, SQL Server, and Internet Information Services (IIS). In this tutorial, you set up two IIS web servers that run in different zones within the same region. You then connect the web servers to your SQL Server availability group and domain controllers. By setting up the web servers behind a load balancer, you reduce the load to the individual servers. You are also able to keep the app running if one of the servers goes offline.
The series consists of these tutorials:
- Deploying a fault-tolerant Microsoft Active Directory environment
- Deploying a multi-subnet SQL Server
- Deploying load-balanced IIS web servers (this document)
You set up a domain controller and SQL Server instance on a Google Cloud project. Each component in this deployment is also designed to integrate securely with Windows authentication that's provided by the domain controllers.
The architecture described in this tutorial is designed to run on Google Cloud. However, some components, like Active Directory and SQL Server, could be run on-premises. This tutorial addresses only the scenario of running all components on Google Cloud.
Objectives
- Create two network subnets that span two zones.
- Deploy a Microsoft SQL Server virtual machine (VM) in each zone.
- Configure each SQL Server instance to join your Active Directory domain.
- Create a Windows Server failover cluster.
- Create and configure a SQL Server bookshelf sample database.
- Set up the SQL Server Always On availability group.
Costs
In this tutorial, you continue using Google Cloud resources that you configured in earlier tutorials. You use the following billable components:
The Pricing Calculator estimates the cost of this environment at around $4 per day.
Before you begin
The configuration that you use in this tutorial requires you to have access to a Windows domain controller and a working Active Directory domain. If you don't already have this environment, complete the steps in the following tutorials:
- Deploying a fault-tolerant Microsoft Active Directory environment
- Deploying a multi-subnet SQL Server
For parts of this tutorial, you perform tasks on a Windows workstation. This can be your local computer; it doesn't have to be inside the VPC network that you use for the IIS web servers. Make sure that the workstation has the following installed on it:
- Visual Studio 2013 or later
- Git
- Tools for Visual Studio. You can download these tools from the linked page.
Initializing common variables
In the first part of this series, you defined variables that control where elements of the infrastructure are deployed in Google Cloud. Verify that the variables are still set correctly and that they match the values that you set earlier.
Open Cloud Shell.
In Cloud Shell, create the following environment variables to set values that you need later in the tutorial.
The commands set the region to
us-east1
. If you used a different region in the previous tutorials, change the region in this script to match what you used before.region=us-east1 zone_1=${region}-b zone_2=${region}-c vpc_name=webappnet project_id=your-project-id
Replace your-project-id with the ID of the Cloud project that you're using.
Creating the network infrastructure
In this section, you add subnetworks to the existing virtual private cloud (VPC) network. (You created the VPC network in an earlier tutorial.) These subnets offer unique IP address ranges that are allocated for the web server instances, and that can later offer optional firewall policies based on the subnets.
In Cloud Shell, add a subnet to the existing VPC network:
gcloud compute networks subnets create public-webapp-zone \ --network $vpc_name \ --region $region \ --range 10.5.0.0/24 \ --project $project_id
Create an internal firewall rule to allow traffic between internal IP addresses:
gcloud compute firewall-rules create allow-internal-ports-public-webapp \ --network $vpc_name \ --allow tcp:1-65535,udp:1-65535,icmp \ --source-ranges 10.5.0.0/24 \ --project $project_id
Launching the web servers
You use an image from Google Cloud Marketplace to provision your web servers. After you provision the web servers, you can use them as targets to deploy web apps.
Create the first server
Go to Google Cloud Marketplace.
In the Google Cloud Console, select the Cloud project where you want the web server to run. Because this tutorial builds off of the previous set, use the same project for this tutorial that you used in the previous tutorials.
Set the following values in the page:
- Deployment Name:
webserver1
- Zone: zone_1
- Windows Server OS Version: 2016
- Boot type: SSD persistent disk
- Disk size: 200 GB
- Network name: vpc_name
- Subnetwork name:
public-webapp-zone
- Firewall: Allow WebDeploy traffic, Allow HTTP traffic
Replace zone_1 and vpc_name with values that you used when you initialized variables earlier.
- Deployment Name:
Click Deploy and wait for the Cloud Console to indicate that the deployment is complete.
Connect to the server instance
In Cloud Shell, create a password for the
webserver1
instance:gcloud compute reset-windows-password webserver1 \ --zone $zone_1 \ --project $project_id \ --quiet
Connect to the new Windows instance using Remote Desktop Protocol (RDP). Use the credentials that you created in the previous step.
Configure the server instance
On the
webserver1
instance, open the PowerShell terminal as Administrator.Set variables for the DNS IP addresses and for the domain name:
$DNS1 = "10.1.0.100" $DNS2 = "10.2.0.100" $DomainName = "example-gcp.com"
Create a local service account called
webapp.service
, which you will use later to publish the web app:net user webapp.service * /add
When you're prompted, enter a password. Use a strong password and store it in a safe location for future use.
Enable the account and add it to the Administrators local group:
net user webapp.service /active:yes net localgroup administrators webapp.service /add
Configure the DNS servers:
netsh interface ip set dns Ethernet static $DNS1 netsh interface ip add dns Ethernet $DNS2 index=2
Join the web server to the
example-gcp.com
domain:Add-Computer -DomainName $DomainName -Credential (Get-Credential "example\Administrator")
When you're prompted, enter a password for the Administrator account. This is the domain account that you used when you created an Active Directory forest in the first tutorial in this series. Use a strong password and store it in a safe location for future use.
You can ignore the following error message:
WARNING: The changes will take effect after you restart the computer webserver1.
Reboot the VM:
Restart-Computer
This closes the RDP session that you have open.
Create the second server instance and configure it
You now repeat the previous procedures in order to create a second server instance.
Repeat the procedure for creating the server, using the following values:
- Deployment name:
webserver2
- Zone: zone_2
- Machine type: 2 vCPU
- Windows Server OS Version: 2016
- Boot type: SSD persistent disk
- Disk size: 200 GB
- Network name: vpc_name
- Subnetwork name:
public-webapp-zone
- Firewall: Allow WebDeploy traffic, Allow HTTP traffic
Replace zone_2 and vpc_name with values that you used when you initialized variables earlier.
- Deployment name:
Create a password for the
webserver2
Windows instance:gcloud compute reset-windows-password webserver2 \ --zone $zone_2\ --project $project_id \ --quiet
This step sets the password for your user account for connecting with RDP. The username is your Google account name (that is, the username that's returned by the
gcloud config get-value core/account
command). Make a note of the username and password for use later in this tutorial.Connect to the instance using RDP. Use the credentials that you created in the previous step.
Connect to the
webserver2
instance. Follow the steps that you used for the first instance, but use the password that you created for the second server instance.Configure the
webserver2
instance. Follow the steps that you used for configuring the first instance. Create the same service account using the same password.
Cloning the web app
The next task is to configure each IIS server and deploy a sample ASP.NET app to it. The web app has credentials to automatically connect to the SQL Server instance that you configured in the previous tutorial.
Make sure you're signed in to the Windows workstation where Visual Studio and Git are installed.
In a command window on the Windows workstation, clone the sample source code repository to the workstation:
cd c:\ git clone https://github.com/GoogleCloudPlatform/getting-started-dotnet.git cd getting-started-dotnet git checkout ad49d787eec88fb30a4b45b4146f5cb63c0519e
Go to the following folder:
C:\getting-started-dotnet\aspnet\2-structured-data
To open the sample app solution in Visual Studio, double-click the
2-structured-data.sln
file.In the Solution Explorer pane, double-click the
Web.config
file to open it.Set the
GoogleCloudSamples:ProjectId
key to the project ID.For the project ID
webapp-sql-ad
, the line is similar to the following:<add key="GoogleCloudSamples:ProjectId" value="webapp-sql-ad" />
Set the
GoogleCloudSamples:BookStore
value tosqlserver
:<add key="GoogleCloudSamples:BookStore" value="sqlserver" />
Near the end of the file, under
<connectionStrings>
, find theconnectionStrings
XML subelement that has the attributename="LocalSqlServer"
. Then do the following:- Update the
connectionString
value with the name of the SQL Server availability group listener, which issql-listener
. (You set up this listener in Deploying a multi-subnet SQL Server in this tutorial series.) - Change
Initial Catalog
tobookshelf
. - Set
Integrated Security
toTrue
. - Use the username and sign-in password that you created for the database service account when you set up the database.
- Update the
Save and close the
Web.config
file.To build the solution, in the Visual Studio menu, click Build > Build Solution.
Deploying the ASP.NET app
In this section, you deploy the web app to both web servers.
On the workstation, if you closed the
2-structured-data.sln
file, reopen it. Find the file in the following folder and then double-click it:C:\getting-started-dotnet\aspnet\2-structured-data
In Visual Studio, click Tools > Google Cloud Tools > Google Cloud Explorer.
Select the project you're working on, and then expand Google Compute Engine.
Right-click the
webserver1
instance.Select Manage Windows credentials.
Click Add credentials.
Enter the username
webapp.service
.Select I have password for this user, and then enter the password that you created earlier when you launched the web servers.
Verify that Create a password for me is not selected, and then click Save.
To close the Windows Credentials window, click Close.
Close Google Cloud Explorer.
In Visual Studio, click Tools > Google Cloud Tools > Publish 2-structured-data to Google Cloud.
In the Publish dialog box, select Compute Engine.
Select the
webserver1
VM, and then set Credentials towebapp.service
.To build and deploy the sample app, click Publish.
After the sample app is published, Visual Studio opens the app in your default web browser.
Repeat this procedure for
webserver2
.
Setting up load balancing
You can now set up network load balancing for the web servers. As part of this procedure, you add health checking to the load balancer. The global load balancer spreads requests between the IIS servers automatically. In addition, if one of the IIS servers fails health checks and is offline, the load balancer automatically directs traffic to the other server.
In Cloud Shell, create a static external IP address for the load balancer:
gcloud compute addresses create webapp-lb-ip \ --region $region \ --project $project_id
The VM instances receive packets that are destined for this IP address.
Add an HTTP health check object:
gcloud compute http-health-checks create bookshelf-check \ --project $project_id \ --request-path /Books
This example uses the default settings for the health check mechanism. You can customize these settings. You specify the
/Books
request path because that's the path that the sample web app uses.Add a target pool that's in the same region as your VM instances. Target pools require a health check service to function; use the health check object that you created in step 2 for this target pool.
gcloud compute target-pools create books-lb \ --region $region \ --http-health-check bookshelf-check \ --project $project_id
Add the IIS server instances to the target pool:
gcloud compute target-pools add-instances books-lb \ --instances webserver1 \ --instances-zone $zone_1 \ --project $project_id gcloud compute target-pools add-instances books-lb \ --instances webserver2 \ --instances-zone $zone_2 \ --project $project_id
Instances within a target pool must be in the same region. However, the instances can be in different zones in the same region.
Add a forwarding rule on behalf of an external IP address and port range that points to your target pool:
gcloud compute forwarding-rules create www-rule \ --region $region \ --ports 80 \ --address webapp-lb-ip \ --target-pool books-lb \ --project $project_id
Sending traffic to the instances
After the load balancing service is configured, you can start sending traffic to the load balancer.
- Wait at least one minute after you've set up load balancing to allow the configuration to be fully loaded.
In Cloud Shell, check the health of the instances within the load balancer:
gcloud compute target-pools get-health books-lb \ --region $region \ --project $project_id
The output is similar to the following:
--- healthStatus: - healthState: HEALTHY instance: https://www.googleapis.com/compute/v1/projects/sales-enablement-support/zones/us-east1-c/instances/webserver1 ipAddress: 35.190.170.76 kind: compute#targetPoolInstanceHealth --- healthStatus: - healthState: HEALTHY instance: https://www.googleapis.com/compute/v1/projects/sales-enablement-support/zones/us-east1-b/instances/webserver2 ipAddress: 35.190.170.76
Copy the
ipAddress
value, which is the IP address of the load balancer.In a browser window, enter the load balancer IP address.
If everything is working, you see the default page for the ASP.NET web app that you deployed:
Testing load balancing and redundancy
You can now verify how the cluster behaves when components are taken offline. You can test load balancing and redundancy at multiple levels by selectively shutting down an instance of Active Directory, SQL Server, and the IIS servers.
In the Cloud Console, go the VM instances page:
Select an instance for Active Directory, for SQL Server, or for IIS. You can choose any of these instances in order to simulate a component going offline.
Click Stop.
In a browser window, enter the load balancer IP address again.
You see the default Bookshelf app page. This indicates that the app is still running even though components of the infrastructure are no longer available.
Optionally, repeat steps 2 and 3 for other components. For example, if you shut down SQL Server instance earlier, shut down an IIS instance this time.
As long as one instance of each component is running, the app continues to work.
Cleaning up
After you've finished the tutorial, you can clean up the Google Cloud resources that you created to ensure you aren't billed for them in the future. You can delete the whole project, or you can delete the resources. The following sections describe how to delete these resources.
Deleting the project
Deleting the resources within the project
At the beginning of the tutorial, you defined variables that control where elements of the infrastructure are deployed. You use those variables in this section for cleanup. Make sure the following variables are set:
region=us-east1 zone_1=${region}-b zone_2=${region}-c vpc_name=webappnet project_id=your-project-id
Replace your-project-id with the ID of the Cloud project you're using.
Delete the VMs that you created in this tutorial:
gcloud compute instances delete ad-dc1 \ --zone $zone_1 \ --project $project_id \ --quiet gcloud compute instances delete ad-dc2 \ --zone $zone_2 \ --project $project_id \ --quiet gcloud compute instances delete cluster-sql1 \ --zone $zone_1 \ --project $project_id \ --quiet gcloud compute instances delete cluster-sql2 \ --zone $zone_2 \ --project $project_id \ --quiet gcloud compute instances delete webserver1 \ --zone $zone_1 \ --project $project_id \ --quiet gcloud compute instances delete webserver2 \ --zone $zone_2 \ --project $project_id \ --quiet
Delete the firewall rules and routes that you created in this tutorial:
gcloud compute firewall-rules delete \ allow-internal-ports-private-ad \ allow-internal-ports-private-sql \ allow-internal-ports-public-webapp \ allow-rdp \ --project $project_id \ --quiet gcloud compute firewall-rules delete \ webserver1-tcp-80 \ webserver1-tcp-8172 \ webserver2-tcp-80 \ webserver2-tcp-8172 \ --project $project_id \ --quiet gcloud compute routes delete \ cluster-sql1-route \ cluster-sql1-route-listener \ cluster-sql2-route \ cluster-sql2-route-listener \ --project $project_id \ --quiet
Delete the subnets in the VPC network:
gcloud compute networks subnets delete \ --region $region \ private-ad-zone-a \ private-ad-zone-b \ private-sql-zone-a \ private-sql-zone-b \ public-webapp-zone \ --project $project_id \ --quiet
Delete the VPC network:
gcloud compute networks delete $vpc_name \ --project $project_id \ --quiet
Delete the load balancer static IP address that you created:
gcloud compute addresses delete webapp-lb-ip \ --region $region \ --project $project_id \ --quiet
Delete the load balancer infrastructure:
gcloud compute forwarding-rules delete www-rule \ --region $region \ --project $project_id \ --quiet gcloud compute target-pools delete books-lb \ --region $region \ --project $project_id \ --quiet gcloud compute http-health-checks delete bookshelf-check \ --project $project_id \ --quiet
What's next
- Review best practices for enterprise organizations.
- Try out other Google Cloud features for yourself. Have a look at our tutorials.