Using Kubernetes Secrets with Payara Micro

Photo of Rudy De Busscher by Rudy De Busscher

In this blog, I'll discuss the basics around Kubernetes ConfigMaps and Secrets and give two examples of how you can use them in combination with Payara Micro.

Just as with your application, we want to keep the configuration values for the (Docker) Containers we are running within our Kubernetes Cluster separate from the image itself.


When our application needs to connect to a database or make use of values that could change over time, like a reference date, it is best to define them outside of the Docker Image. That way, we do not need to recreate the image, but instead, only need adjust those configuration values.


About Kubernetes Configmaps and Secrets

Kubernetes has two concepts for passing configuration values to the Containers: ConfigMaps, and Secrets. Configmaps and Secrets are identical other than the applied security.


You define key-value pairs holding your configuration values with them, and you can pass them to the container in two ways: as files or as environment values.


The concept of key-value pairs is probably known by everyone. The key defines what the value is about, like databasename=test. So whenever we want to know the value which is defined for the database name, we can request the configuration key databasename.


Within a Container, we can use some well-known concepts to retrieve those values, files, and environment variables and thus we do not need to integrate with some specially designed and implemented service within Kubernetes to retrieve those values. This makes retrieving those configuration values very easy. Keep reading to see examples of both ways of accessing the configuration values.


In the rest of this blog we will concentrate on using Kubernetes Secrets, but keep in mind using ConfigMaps is very similar.


Creating your First Secret

Let's execute some commands to generate some Kubernetes Secrets. For this blog, I assume you have access to a Kubernetes Cluster using the kubectl CLI command.


You can create a secret based on key-value pairs on the command line or defined within a file (use the --from-file option for that)


kubectl create secret generic test --from-literal=key=value


Get the list of all secrets known by Kubernetes (within the current namespace by default):


kubectl get secrets


Which gives as a result:


default-token-9cf56 3 38d
test Opaque 1 30s



Get the content of the Secret:


kubectl get secret test -o yaml


which gives as output:

apiVersion: v1
key: dmFsdWU=
kind: Secret
creationTimestamp: 2019-08-08T14:34:01Z
name: test
namespace: demo
resourceVersion: "1461989"
selfLink: /api/v1/namespaces/demo/secrets/test
uid: 90d5e1bc-b9e9-11e9-84c8-025000000001
type: Opaque

How Secure is a Secret?

At first glance, your configuration values are nicely secured when you see the output of the kubectl get secret command. Until you realise that `dmFsdWU=` is just the base64 encoding of `value`. So how secure are Secrets?


If you look at this subject within the documentation, you will learn that those Secrets can be encrypted at rest. So when stored within Kubernetes, it is encrypted. But once you request the value, it is decrypted. And this makes sense because the Secret must be readable as an environment variable, for example, so that it can be used by your scripts and applications.


To obscure it a bit, it is just base64 encoded when you request the value through the kubectl command. So make sure that you assign the appropriate roles (See Kubernetes RBAC system for more information on this) so that the secret can only be read by authorized people.


Secrets are kept "secret" in the best possible way, but eventually, the configuration value needs to be accessed readable by your Container.


Mounted File Example

There are various scenarios where you need a sensitive value as contents of a file in the running Container. Those sensitive values should not be defined with the Docker build script, as the values are then exposed to unauthorized people.


One of the scenarios which are a valid use case for this is the definition of the private key for some encryption done by your application. The application can read this file and use it.


Let's have a look at the yaml definition of the pod (which is also possible with a deployment which is preferred for production scenarios) how the mapping from a Kubernetes secret to a file can be done.



apiVersion: v1
kind: Pod
name: payara-secret
name: payara
- name: payara-secret
image: secret
imagePullPolicy: IfNotPresent
- name: secret-volume
mountPath: "/opt/payara/mounted"
readOnly: true
- name: secret-volume
secretName: aeskey
- key: key
path: secret


First, we define the mounted volume. We specify the path where it will be mounted, /opt/payara/mounted in the example, and the name of the volume that needs to be mounted at that location.


The volume, however, is not a real volume on a disk of your Kubernetes provider for example but is based on a Secret. The secretName defines the name of the secret and the path is the name of the file which needs to be created.


So the above example takes the value of key in the Secret called aeskey and places it in the /opt/payara/mounted/secret file.


The command to create the Secret is described earlier and could be like


kubectl create secret generic aeskey --from-literal=key=Dx5DfWnBDuCYPdFQX02HTg


The value, in this case, is a base64 encoded byte array which will be used for an AES symmetric encryption.


Environment Variable Example

Defining database values is a typical example where you can use environment values. With Payara Micro you can define the data sources through post-boot scripts.


These scripts contain the asadmin commands which needs to be executed when the Payara Micro instance is started and before the application is deployed. References to environment variables are possible within those commands. For more information on those scripts, you can have a look at the Payara Micro Documentation.


Creating a JDBC connection pool can be done through the following asadmin commands:


create-jdbc-connection-pool --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlDataSource --restype javax.sql.DataSource rubus-pool



The environment variables can be defined by the Kubernetes yaml file to create your deployment or pod like this



apiVersion: v1
kind: Pod
name: payara-env-secret
name: payara
- name: payara-env-secret
image: env-secret
imagePullPolicy: IfNotPresent
- name: database-server
name: database-config
key: database-server
- name: database-name
name: database-config
key: database-name
- name: user
name: database-config
key: user
- name: password
name: database-config
key: password


This config refers to the database-config secret which we can create with the following command


kubectl create secret generic database-config --from-literal=database-server= --from-literal=database-name=test --from-literal=user=app-user --from-literal=password=secret


When starting your Container, you can see in the log that those asadmin commands are executed with the Environment references replaced by the values defined in the Kubernetes Secret.


Using Kubernetes Secrets

You should not place configuration values within your Image so that you can easily change them without the need to rebuild your Container image. Kubernetes Configmaps and Secrets are designed for this purpose and allow you to 'map' these configuration values to Environment variables and files.

Kubernetes Secrets should be preferred when those configuration values contain sensitive information. They are encrypted within the Kubernetes system and when requested by a user, they are still base64 encoded so that the real content is not that easy to spot.


Payara Micro can easily be used in combination with Kubernetes Secrets and Environment variables as it has support for Environment Variables within the post-boot script file. Defining some database connection properties becomes quite easily in that case as I showed you in the example.

And of course, files are easy to use by any application and application server so there are many scenarios where the combination of Kubernetes Secrets and Volume mounting can be handy.


Download Payara Micro and Give it a Try:


Payara Micro Download


Learn More:

Payara Platform and Kubernetes