ConfigMap File Mount on a Windows Kubernetes Pod
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.
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:
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:
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
Then we can check on the container logs with kubectl like so:
.\kubectl --kubeconfig .\_output\win-cluster\kubeconfig\kubeconfig.westus2.json logs configmapfilemount
You're done! Now you've deployed a Windows Kubernetes pod which reads a configMap as a file.
Wow! You read this far? Feel free to get in touch on my secret contact page !