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:
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 .
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.
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?
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