In the first part of the lab, you deployed a Windows container app to Google Compute Engine (GCE). This second part of the lab builds on the first part and you deploy the same app to Google Kubernetes Engine (GKE) for added resiliency and scalability.

What you'll learn

What you'll need

How will you use this tutorial?

Read it through only Read it and complete the exercises

How would rate your experience with Google Cloud Platform?

Novice Intermediate Proficient

For this codelab, you need a Google Cloud Platform project to interact with PowerShell. If you have an existing project, you can either use that or you can create a new project using the following steps.

Codelab-at-a-conference setup

The instructor will be sharing with you temporary accounts with existing projects that are already setup so you don't need to worry about enabling billing or any cost associated with running this codelab. All these accounts will be disabled shortly after the codelab is over.

After you have received a temporary username / password to login from the instructor, log into Google Cloud Platform Console: https://console.cloud.google.com/.

Here's what you should see once logged in:

Note the project ID you were assigned ( "codelab-test003" in the screenshot above). It will be referred to later in this codelab as PROJECT_ID.

Log into the Windows VM that you already created in the first part of the lab. You can simply click on the RDP button of the VM (or use your own RDP client if you like):

Once inside the VM, open a command prompt in admin mode. In the command prompt, you can see the Windows container image: iis-site-windows

C:\>docker images
REPOSITORY                                 TAG                          
gcr.io/dotnet-atamel/iis-site-windows      latest
mcr.microsoft.com/windows/servercore/iis   windowsservercore-ltsc2019
mcr.microsoft.com/windows/servercore       ltsc2019

In the next step, we will push this image to Google Container Registry (GCR).

We need to host the Windows container image in a public image repository before we can use it in other part of Google Cloud. Google Container Registry (GCR) is a good place for container images.

To push a container image from a Windows VM to GCR, we need to:

  1. Make sure that the Container Registry API is enabled in your project.
  2. Configure Docker to point to GCR.

Make sure the Container Registry API is enabled:

C:>gcloud services enable containerregistry.googleapis.com

Configure Docker to point to GCR:

C:>gcloud auth configure-docker
..
Do you want to continue (Y/n)?  Y

Docker configuration file updated.

Now, you can push the image to GCR (replace dotnet-atamel with your project id):

C:>docker push gcr.io/dotnet-atamel/iis-site-windows
The push refers to repository [gcr.io/dotnet-atamel/iis-site-windows]
4d8626c6a788: Pushed
8bd5cd9c33e0: Pushed
df246b0408a9: Pushed
fda45f6f282a: Pushed
f3f872f1087c: Pushed
7626b1fc1993: Pushed
fac2806747d6: Skipped foreign layer
c4d02418787d: Skipped foreign layer
latest: digest: sha256:2153656a3c4affefbe9973b79fe45cc35742c7495d6f4b1a689b5d9927dc92cb size: 2201

If you go to GCR section in Cloud Console, you can see the image:

This step is necessary to access the EAP feature. Make sure you create the service account in your whitelisted project.

Inside Cloud Shell, run the following commands to create a service account and link to your gcloud command.

Create a service account. Make sure to replace [SA-NAME] and [SA-DISPLAY-NAME]:

gcloud iam service-accounts create [SA-NAME] --display-name "[SA-DISPLAY-NAME]"

Download the service account key and store it in a json file. [SA-EMAIL] is [SA-NAME]@[PROJECT-ID].iam.gserviceaccount.com:

gcloud iam service-accounts list
gcloud iam service-accounts keys create [PATH-TO-KEY.json] --iam-account [SA-EMAIL]

Add IAM policy to bind the service account to the editor role:

gcloud projects add-iam-policy-binding [PROJECT-ID] --member "serviceAccount:[SA-EMAIL]" --role "roles/editor"

Active the service account for gcloud:

gcloud auth activate-service-account --key-file=[PATH-TO-KEY.json]

Now, you're ready to create a Kubernetes cluster with Windows nodes using gcloud.

Creating a Kubernetes cluster in GKE with Windows nodes happens in 2 steps:

  1. Create a GKE cluster with version 1.14 or higher, IP alias and 1 Linux node.
  2. Add a Windows node pool to the GKE cluster.

Windows nodes are only available in the Rapid release channel with IP alias enabled and at least 1 Linux node is needed in the GKE cluster before Windows nodes can be added.

Inside Cloud Shell, Create a GKE cluster (replace europe-west1-b with a zone of your choice):

gcloud container clusters create windows-cluster --cluster-version=1.14 --enable-ip-alias --num-nodes=1 --zone europe-west1-b

Once we have the basic GKE cluster, we can go ahead and add a Windows pool for Windows nodes to it:

gcloud container node-pools create windows-pool --cluster=windows-cluster --image-type=WINDOWS_SAC --no-enable-autoupgrade --machine-type=n1-standard-2 --num-nodes=1 --zone europe-west1-b

Notice that we're disabling automatic node upgrades. Windows container versions need to be compatible with the node OS version. To avoid unexpected workload disruption, it is recommended that users disable node autoupgrade for Windows node pools.

For Windows Server containers in GKE, you're already licensed for underlying Windows host VMs -- containers need no additional licensing.

In the end, the GKE cluster is ready with 1 Linux node and 1 Windows node:

Before running our Windows container as a pod on GKE, authenticate kubectl with the GKE cluster by copying/pasting the gcloud command in the Connect button:

kubectl is now setup to manage our cluster.

Let's create an iis-site-windows.yaml file to describe our Kubernetes deploymen (replace dotnet-atamel with your project id):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: iis-site-windows
  labels:
    app: iis-site-windows
spec:
  replicas: 2
  selector:
    matchLabels:
      app: iis-site-windows
  template:
    metadata:
      labels:
        app: iis-site-windows
    spec:
      nodeSelector:
        kubernetes.io/os: windows
      containers:
      - name: iis-site-windows
        image: gcr.io/dotnet-atamel/iis-site-windows
        ports:
        - containerPort: 80

Note that we're creating 2 pods with the image we pushed earlier to GCR. We're also making sure that the pods are scheduled onto Windows nodes with the nodeSelector tag.

Create the deployment:

kubectl apply -f iis-site-windows.yaml
deployment.apps/iis-site-windows created

After a few minutes, you should see the deployment created and pods running:

kubectl get deployment,pods

NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/iis-site-windows   2/2     2            2           3m4s

NAME                                    READY   STATUS    RESTARTS   AGE
pod/iis-site-windows-5b6dfdf64b-k5b6r   1/1     Running   0          3m4s
pod/iis-site-windows-5b6dfdf64b-msr9s   1/1     Running   0          3m4s

To make pods accessible to the outside world, we need to create a Kubernetes service with LoadBalancer type:

kubectl expose deployment iis-site-windows --type="LoadBalancer"

service/iis-site-windows exposed

In a few minutes, you should see a new service with an external IP:

kubectl get service

NAME               TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)
iis-site-windows   LoadBalancer   10.107.11.34   104.155.45.254  80:30035/TCP

And if we go to that external IP, we will see our app:

This is very similar to the previous lab where we deployed to GCE but the big difference is that Kubernetes is managing the pods. If something goes wrong with the pod or the node that the pod is running, Kubernetes will recreate and reschedule the pod for us. Great for resiliency.

Similarly, scaling pods is a single command in Kubernetes:

kubectl scale deployment iis-site-windows --replicas=4

deployment.extensions/iis-site-windows scaled
kubectl get pods

NAME                                READY   STATUS
iis-site-windows-5b6dfdf64b-2kn65   1/1     Running
iis-site-windows-5b6dfdf64b-8rvbm   1/1     Running
iis-site-windows-5b6dfdf64b-bq8dg   1/1     Running
iis-site-windows-5b6dfdf64b-zjr6c   1/1     Running

Once you're done testing, it's a good idea to delete the cluster.

First, delete the service and the deployment, which also deletes your external load balancer:

kubectl delete service,deployment iis-site-windows

service "iis-site-windows" deleted
deployment.extensions "iis-site-windows" deleted

Next, delete your cluster:

gcloud container clusters delete windows-cluster --zone=europe-west1-b

What we've covered

Next Steps