In this page, you learn how to deploy a stateless Windows Server application. You can also learn how to deploy a stateful Windows application.
Deploying a Windows Server application to a standard cluster
The following tasks guide you through deploying your Windows Server application:
- Create a cluster.
- Create a Deployment manifest file.
- Create and expose the Deployment.
- Verify the Pod is running.
Create a cluster
For instructions, see Create a cluster using Windows Server node pools.
Create a Deployment manifest file
Windows Server nodes are tainted
with the following key-value pair: node.kubernetes.io/os=windows:NoSchedule
.
This taint ensures that the GKE scheduler does not attempt to run Linux containers on Windows Server nodes. To schedule Windows Server containers on Windows Server nodes, your manifest file must include this node selector:
nodeSelector:
kubernetes.io/os: windows
An admission webhook running in the cluster checks new workloads for the presence of this Windows node selector and when found, applies the following toleration to the workload which lets it run on the tainted Windows Server nodes:
tolerations:
- effect: NoSchedule
key: node.kubernetes.io/os
operator: Equal
value: windows
In some cases you may need to include this toleration explicitly in your manifest file. For example, if you are deploying a DaemonSet with a multi-arch container image to run on all Linux and Windows Server nodes in the cluster, then your manifest file will not include the Windows node selector. You must explicitly include the toleration for the Windows taint.
Example manifest file
The following example Deployment file (iis.yaml
) deploys Microsoft's IIS image
to a single Pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: iis
labels:
app: iis
spec:
replicas: 1
selector:
matchLabels:
app: iis
template:
metadata:
labels:
app: iis
spec:
nodeSelector:
kubernetes.io/os: windows
containers:
- name: iis-server
image: mcr.microsoft.com/windows/servercore/iis
ports:
- containerPort: 80
This file is for a cluster where all workloads use the same Windows Server node image type and version. For details on how to work with mixed node images, see the Using mixed node images section.
Create and expose the Deployment
Create and expose the Deployment file you created in the preceding step as a Kubernetes Service with an external load balancer Deployment.
To create the Deployment, run the following command:
kubectl apply -f iis.yaml
To expose the Deployment, run the following command:
kubectl expose deployment iis \ --type=LoadBalancer \ --name=iis
Verify the Pod is running
Make sure the Pod is functioning by validating it.
Check the status of the Pod using
kubectl
.kubectl get pods
Wait until the returned output shows that the Pod has
Running
as its status.NAME READY STATUS RESTARTS AGE iis-5c997657fb-w95dl 1/1 Running 0 28s
Get the status of the service, and wait until the external IP field is populated.
kubectl get service iis
You should see the following output:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE iis LoadBalancer 10.44.2.112 external-ip 80:32233/TCP 17s
Now you can use your browser to open http://external-ip to see the IIS web page.
Deploying a Windows Server application to a private cluster
This section shows you how to deploy a Windows Server container application to a private cluster.
Windows Server container images have several layers and the base layers are provided by Microsoft. The base layers are stored as a foreign layer instead of being embedded with the image as Linux Docker image layers are. When a Windows Server container image is pulled for the first time, the base layers must typically be downloaded from Microsoft servers. Because private cluster nodes don't have connectivity to the internet, the Windows Server base container layers cannot be pulled from Microsoft servers directly.
To use private clusters, you can configure the Docker daemon to allow pushing non-distributable layers to private registries. To learn more, see Considerations for air-gapped registries on Docker's GitHub page.
To deploy your Windows Server application to a private cluster:
- Create a private cluster with Windows Server nodes.
- Build the Windows Server application Docker image.
- Deploy the application to a private cluster.
- Verify that the Pod is running.
Create a private cluster
Follow the instructions in Creating a cluster with Windows Server nodes and Creating a private cluster to create and add a Windows node pool to a private cluster.
Create a Windows Server application image for use with private clusters.
To build the Docker image, start a Compute Engine instance with the Windows Server version you want to run your application containers on, such as Windows Server 2019 or Windows Server version 1909. Also, ensure you have internet connectivity.
In the Compute instance, navigate to the Docker daemon config:
PS C:\> cat C:\ProgramData\docker\config\daemon.json
Configure the Docker
daemon.json
file to allow foreign layers to be pushed to your private registry by adding these lines:{ "allow-nondistributable-artifacts": ["gcr.io"] }
gcr.io
refers to Container Registry, where the image will be hosted.Restart the Docker daemon:
PS C:\> Restart-Service docker
Build and tag the Docker image for your application:
PS C:\> cd C:\my-app
PS C:\my-app> docker build -t gcr.io/my-project/my-app:v2 .
This command instructs Docker to build the image using the Dockerfile in the current directory and tag it with a name, such as
gcr.io/my-project/my-app:v2
.Push the application's Docker image to the
gcr.io
registry inmy-project
. Theallow-nondistributable-artifacts
configuration set causes the Windows base layers to be pushed to your private registry.PS C:\my-app> docker push gcr.io/my-project/my-app:v2
Create a Deployment manifest file
A sample deployment manifest file called my-app.yaml
is given below. The image
in this example is the one you pushed in the previous step (gcr.io/my-
project/my-app:v2
).
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
labels:
app: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
nodeSelector:
kubernetes.io/os: windows
containers:
- name: my-server
image: gcr.io/my-project/my-app:v2
To deploy this application to your private cluster:
gcloud container clusters get-credentials var>private-cluster-name
kubectl apply -f my-app.yaml
Where private-cluster-name is the name of the cluster you created.
Verify the Pod is running
List all Pods to ensure it is running correctly.
kubectl get pods
The expected result should show the Pod with a status of Running
.
NAME READY STATUS RESTARTS AGE
my-app-c95fc5596-c9zcb 1/1 Running 0 5m
Using mixed node images
Your clusters can contain node pools with multiple Windows Server types and Windows Server versions. They can also combine Windows Server and Linux workloads. The following sections provide details on how to configure your workloads to use these types of clusters.
Using workloads with different Windows Server node image types
You can add node pools using different Windows Server image types (LTSC or SAC) to your cluster. In a cluster with mixed Windows Server types, you need to ensure that your Windows Server containers are not scheduled onto an incompatible Windows Server node.
If you have one Windows Server LTSC node pool and one Windows Server SAC node
pool, add the gke-os-distribution
node label to both of your workloads.
Include the following nodeSelector in the manifest file for your Windows Server LTSC workloads:
nodeSelector:
kubernetes.io/os: windows
cloud.google.com/gke-os-distribution: windows_ltsc
Include the following nodeSelector in the manifest file for your Windows Server SAC workloads:
nodeSelector:
kubernetes.io/os: windows
cloud.google.com/gke-os-distribution: windows_sac
Adding this label ensures that your LTSC container images do not get scheduled onto incompatible SAC nodes and vice-versa.
Using workloads with different Windows Server versions
If you need to run Windows Server node pools with multiple different LTSC or
SAC versions, we recommend building your container images as
multi-arch images
that can run on all of the Windows Server versions in use in your cluster.
The gke-os-distribution
node label is not sufficient to prevent your workloads
from potentially being scheduled onto incompatible nodes.
Using Linux and Windows Server workloads in a cluster
Add the following node selector to your Linux workloads to ensure they are always scheduled to Linux nodes:
nodeSelector:
kubernetes.io/os: linux
This provides additional protection to avoid Linux workloads being scheduled
onto Windows Server nodes in case the
NoSchedule
taint is accidentally removed
from the Windows Server nodes.