44

Can one store a binary file in a Kubernetes ConfigMap and then later read the same content from a volume that mounts this ConfigMap? For example, if directory /etc/mycompany/myapp/config contains binary file keystore.jks, will

kubectl create configmap myapp-config --from-file=/etc/mycompany/myapp/config

include file keystore.jks in ConfigMap myapp-config that can later be mapped to a volume, mounted into a container, and read as a binary file?

For example, given the following pod spec, should keystore.jks be available to myapp at /etc/mycompany/myapp/config/keystore.jks?

apiVersion: v1
kind: Pod
metadata:
  name: myapp
spec:
  containers:
  - name: myapp
    image: mycompany/myapp
    volumeMounts:
    - name: myapp-config
      mountPath: /etc/mycompany/myapp/config

  volumes:
  - name: myapp-config
    configMap:
      name: myapp-config

Kubernetes version details:

derek@derek-HP-EliteOne-800-G1-AiO:~/Documents/platinum/fix/brvm$ kubectl version
Client Version: version.Info{Major:"1", Minor:"3", GitVersion:"v1.3.6", GitCommit:"ae4550cc9c89a593bcda6678df201db1b208133b", GitTreeState:"clean", BuildDate:"2016-08-26T18:13:23Z", GoVersion:"go1.6.2", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"3", GitVersion:"v1.3.6+coreos.0", GitCommit:"f6f0055b8e503cbe5fb7b6f1a2ee37d0f160c1cd", GitTreeState:"clean", BuildDate:"2016-08-29T17:01:01Z", GoVersion:"go1.6.2", Compiler:"gc", Platform:"linux/amd64"}
Derek Mahar
  • 27,608
  • 43
  • 124
  • 174
  • I observed that Kubernetes stores the binary `keystore.jks` in the configmap, but the file size is larger than the original file, as is the size of the file in the volume to which the configmap was subsequently mapped. – Derek Mahar Sep 10 '16 at 04:58
  • I reported issue https://github.com/kubernetes/kubernetes/issues/32432. – Derek Mahar Sep 10 '16 at 04:59
  • I changed the issue from a bug report to a feature request. – Derek Mahar Sep 12 '16 at 16:24

8 Answers8

41

Binary ConfigMaps are now supported since Kubernetes version 1.10.0. From the readme notes:

ConfigMap objects now support binary data via a new binaryData field. When using kubectl create configmap --from-file, files containing non-UTF8 data will be placed in this new field in order to preserve the non-UTF8 data. Note that kubectl's --append-hash feature doesn't take binaryData into account. Use of this feature requires 1.10+ apiserver and kubelets. (#57938, @dims)

See the changelog for more details: https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.10.md#apps

Thamaraiselvam
  • 6,961
  • 8
  • 45
  • 71
olly___
  • 534
  • 5
  • 2
  • 3
    Link is broken. Whats the status of this feature in 2020? – Akito Mar 16 '20 at 09:40
  • @Thamaraiselvam How can I add binary data in `kubectl secret`? – RNK Mar 30 '20 at 23:34
  • @RonakPatel `kubectl create configmap - - from-file ` – Thamaraiselvam Mar 31 '20 at 04:07
  • @Akito https://kubernetes.io/docs/concepts/configuration/configmap/#configmap-object Also an example from openshift site: https://docs.openshift.com/container-platform/4.4/builds/builds-configmaps.html#builds-configmap-overview_builds-configmaps – B.Z. Dec 19 '20 at 18:29
5

What I would do is encode this file in base64 and then the container that uses decoded to be able to use it

Luis Tobon
  • 101
  • 4
  • Good idea! I might do this until Kubernetes implements https://github.com/kubernetes/kubernetes/issues/32432. – Derek Mahar Sep 16 '16 at 19:56
  • Does it work ? I encoded my keystore in base64, added this base64 value in my Secret, mounted my Secret as a Volume as explained here: https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod, and finally deployed to my cluster. All my pods including this volume now fail to launch :/ – Jules Ivanic Oct 13 '17 at 16:03
  • Actually it works but you have to "base64 encode" the binary file twice. If you do it only once, the value saved in the store is in its binary form (as a string). This string contains a lot of strange characters that the Go code is not able to understand. Finally, to create the .jks file in the server you could use a `initContainer`: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-initialization/#creating-a-pod-that-has-an-init-container which will "base64 decode" the value in the Secret and put it in a file. – Jules Ivanic Oct 17 '17 at 08:20
5

Based on other answers, Base64 works for me (just once)

Steps:

on my workstation

base64 -w 0 cacerts   > cacerts.base64
sha256sum.exe cacerts.base64
keytool.exe  -list -v -keystore cacerts

OpenShift

I connect to openshift and create the config map

oc create configmap cacerts.base64 --from-file=cacerts.base64

deployment configuration

  ...
  template:
    metadata:
      name: mydeployment...
    spec:
      volumes:
        - name: cacerts-volume
          configMap:
            name: cacerts.base64
      containers:
        - name: crg-driver
          command:
            - base64
      args:
            - '--decode'
            - '-w 0'
            - '/opt/axatech/openpaas/certificates/cacerts.base64 >   /opt/axatech/openpaas/certificates/cacerts' #this does not work yet
          env:
            - name: SWARM_JVM_ARGS
              value: >-
                -Djavax.net.ssl.trustStore=/opt/certificates/cacerts.base64
                -Djavax.net.ssl.trustStorePassword=changeit

         volumeMounts:
           - name: cacerts-volume
             mountPath: /opt/certificates

The easiest way to edit/update an existing cacerts is to encode the new cacerts to base64 (with option -w 0) , open it with file editor (ie Notepad), copy the content and paste it via the OpenShift Console UI

https://osconsole.mycloud.something.example/console/project/project-dev/browse/config-maps/cacerts.base64

or in command line

oc edit configmap cacerts.base64

Andreas Panagiotidis
  • 2,763
  • 35
  • 32
3

According to Jorgan Liggitt in Kubernetes issue "Enable ConfigMaps to store binary files as well as character files.", Kubernetes 1.3.6 cannot store a binary file in a ConfigMap.

GitHub comment 1:

config maps store data as string, not []byte... not sure I'd expect to be able to put arbitrary binary content in them"

GitHub comment 2:

@liggitt Do ConfigMaps not encode binary content as strings?

they do not, they store strings. base64-encoding could be layered on top with application logic if desired

I subsequently demonstrated that ConfigMaps do not support binary files.

Derek Mahar
  • 27,608
  • 43
  • 124
  • 174
2

I use the secrets for binary files. You can use --from-file

kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
de1m
  • 71
  • 1
  • 4
2

In case you are using Secret to store value, you can leverage the property of stringData field. Encode the value once and put it in stringData field instead of data field. Kubernetes encodes the value present stringData. This way we reduce manual base64 encoding from two to one.

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
stringData:
  some_key: YWJjZA==

For more information on why double encoding is needed for binary data, you can refer to this link

Vikas Verma
  • 201
  • 2
  • 6
0

If you don't want to do it manually I would recommend looking into https://kustomize.io/

They have a configMap generator that generates configMaps from files: https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/configmapgenerator/#configmap-from-file

Binaries are also supported. Example:

configMapGenerator:
- name: text-config
  files:
  - configs/some.properties
- name: binary-cacerts
  files:
  - configs/keystore.jks
Markus
  • 1,887
  • 18
  • 23
0

Since version 1.10 config maps support binaryData field.

Ilya
  • 1,349
  • 11
  • 16