ConfigMap File Mount on a Windows Kubernetes Pod

  • Post category:Kubernetes

In this article we will mount a configMap as a file into a Windows Kubernetes pod.

ConfigMaps let you specify configuration values of an application as part of the deployment yaml. This decouples your application deployment from the config values, which is best practice.

Source code

Create a Windows Kubernetes cluster

We will use AKS Engine to create a Windows Kubernetes cluster.

make-aks-engine-cluster.ps1 along with win-cluster.json will create a Windows Kubernetes cluster for you in Azure. All you need to provide is a $SUBSCRIPTION_ID .

$SUBSCRIPTION_ID=''
$CLUSTER_NAME='win-cluster'
$LOCATION='westus2'
$API_MODEL='win-cluster.json'

# Creates the resource group which will house your cluster
az group create --subscription $SUBSCRIPTION_ID --location $LOCATION --name $CLUSTER_NAME

# Creates an Azure Service Principal to let AKS-Engine deploy resources (your cluster) to your resource group
$AZSP=az ad sp create-for-rbac --name win-cluster-service-principal --role="Owner" --scopes="/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$CLUSTER_NAME" -o json | ConvertFrom-Json
$CLIENT_ID=$AZSP.appId
$CLIENT_SECRET=$AZSP.password

# Let azure permissions propogate before creating cluster
Start-Sleep -Seconds 180

# Create a hostprocess capable kubernetes cluster using AKS-Engine
.\aks-engine deploy `
    --subscription-id $SUBSCRIPTION_ID  `
    --client-id $CLIENT_ID `
    --client-secret $CLIENT_SECRET `
    --resource-group $CLUSTER_NAME `
    --dns-prefix $CLUSTER_NAME `
    --location $LOCATION `
    --api-model $API_MODEL `
    --force-overwrite
{
   "apiVersion": "vlabs",
   "properties": {
      "orchestratorProfile": {
         "orchestratorType": "Kubernetes",
         "orchestratorRelease": "1.23",
         "kubernetesConfig": {
            "networkPlugin": "azure",
            "containerRuntime": "containerd",
            "windowsContainerdURL": "https://github.com/kubernetes-sigs/sig-windows-tools/releases/download/windows-containerd-nightly/windows-containerd.tar.gz",
            "loadBalancerSku": "basic"
         }
      },
      "masterProfile": {
         "count": 1,
         "vmSize": "Standard_D2_v2",
         "availabilityProfile": "AvailabilitySet",
         "platformUpdateDomainCount": 1
      },
      "agentPoolProfiles": [
         {
            "name": "windowspool",
            "count": 1,
            "vmSize": "Standard_D8s_v3",
            "availabilityProfile": "VirtualMachineScaleSets",
            "osType": "Windows",
            "enableVMSSNodePublicIP": true
         }
      ],
      "windowsProfile": {
         "adminUsername": "azureuser",
         "adminPassword": "password1234$",
         "sshEnabled": true,
         "enableAutomaticUpdates": true,
         "WindowsPublisher": "microsoft-aks",
         "WindowsOffer": "aks-windows",
         "WindowsSku": "2019-datacenter-core-ctrd-2108",
         "imageVersion": "17763.2061.210830"
      },
      "linuxProfile": {
         "adminUsername": "azureuser",
         "ssh": {
            "publicKeys": [
               {
                  "keyData": ""
               }
            ]
         }
      }
   }
}

Upon execution of the script, you should hopefully see:

Deploying a Windows Kubernetes using AKS Engine

Build a containerized app

The app we create will simply print the contents of a given file.

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"time"
)

func main() {
	configMapFilePath := os.Args[1]

	fmt.Printf("configMap file path: %s\n", configMapFilePath)

	// Read the configMap as a file from inside the container!
	content, err := ioutil.ReadFile(configMapFilePath)
	if err != nil {
		fmt.Printf("Error from reading: %v\n", err)
	}
	text := string(content)
	fmt.Println(text)

	// Sleep
	time.Sleep(1 * time.Hour)
}

We containerize it with a Dockerfile, which packages the executable into container format:

# Use golang image to build binary
FROM golang:1.17 AS builder

# Make a working directory
WORKDIR /usr/local/app

# Copy the source code into the container
COPY src/ .

# Build the app
RUN go build app.go

# Copy the app binary into the final container image
FROM mcr.microsoft.com/windows/nanoserver:1809
COPY --from=builder /usr/local/app/app.exe \
    /usr/local/bin/app.exe

ENTRYPOINT ["/usr/local/bin/app.exe"]

And bulid it using the docker command like program like so:

docker build -t configmapfilemount:v1.0.0 -f Dockerfile .
Building the containerized app

Launching a Pod which reads the configMap as a file

Next we define a pod and configMap in yaml format,

apiVersion: v1
kind: Pod
metadata:
  name: configmapfilemount
spec:
  nodeSelector:
    kubernetes.io/os: windows
  containers:
  - name: configmapfilemount
    image: coolstercodes.azurecr.io/configmapfilemount:v1.0.0
    imagePullPolicy: Always
    args: ["C:\\configmapdirectory\\configfile.json"]
    volumeMounts:
      - name: configmapmount
        mountPath: /configmapdirectory
  volumes:
    - name: configmapmount
      configMap:
        name: myconfigmap
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: myconfigmap
data:
  configfile.json: |
    {
      "ConfigKey": "Value"
    }

You’ll see above that we specify a volume at the pod layer, and give it the name of our configMap.

Next in the container layer, we specify a volumeMount, which mounts the volume previously specified.

As part of the volumeMount we give a new file path where this configMap will live, according to the container.

And finally, we pass C:\\configmapdirectory\\configfile.json to the container as the file we wish to print the contents of.

To deploy this pod, we use kubectl like so:

.\kubectl --kubeconfig .\_output\win-cluster\kubeconfig\kubeconfig.westus2.json apply -f configmapfilemount.yaml
Deploying the pod and configMap

Then we can check on the container logs with kubectl like so:

.\kubectl --kubeconfig .\_output\win-cluster\kubeconfig\kubeconfig.westus2.json logs configmapfilemount
App logs which print the contents of the “file”, aka the configMap!

You’re done! Now you’ve deployed a Windows Kubernetes pod which reads a configMap as a file.

This Post Has 2 Comments

  1. Adith

    I have json file under path “C:\app”, I need to overwrite that json file, with the content in configmap, but i am not able to mount the configmap into that container. What can i do to resolve this?

    1. Coolster

      What is the error you’re getting?
      Can you paste a link to the yaml file you’re using?
      In the article, “configmapfilemount.yaml” is the most basic way to mount the configmap into the container, maybe try that, and then slowly build up to your application

Leave a Reply