Kubernetes Config
Quarkus includes the kubernetes-config
extension which allows developers to use Kubernetes ConfigMaps and Secrets as a configuration source, without having to mount them into the Pod running the Quarkus application or make any other modifications to their Kubernetes Deployment
(or OpenShift DeploymentConfig
).
Configuração
Once you have your Quarkus project configured you can add the kubernetes-config
extension
by running the following command in your project base directory.
quarkus extension add kubernetes-config
./mvnw quarkus:add-extension -Dextensions='kubernetes-config'
./gradlew addExtension --extensions='kubernetes-config'
Isto irá adicionar o seguinte trecho no seu arquivo de build:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-kubernetes-config</artifactId>
</dependency>
implementation("io.quarkus:quarkus-kubernetes-config")
Usage
The extension works by reading ConfigMaps and Secrets directly from the Kubernetes API server using the Kubernetes Client.
The extension understands the following types of ConfigMaps and Secrets as input sources:
The extension is disabled by default in order to prevent the application for making API calls when it is not running in a Kubernetes environment. To enable it, set quarkus.kubernetes-config.enabled=true
(for example using a specific profile).
The values of quarkus.kubernetes-config.config-maps
and quarkus.kubernetes-config.secrets
determine which ConfigMaps and/or Secrets will be used as configuration sources. Keep in mind that these ConfigMaps and Secrets must be in the same Kubernetes Namespace
as the running application. If they are to be found in a different namespace, then quarkus.kubernetes-config.namespace
must be set to the proper value.
Priority of obtained properties
The properties obtained from the ConfigMaps and Secrets have a higher priority than (i.e. they override) any properties of the same name that are found in application.properties
(or the YAML equivalents), but they have lower priority than properties set via Environment Variables or Java System Properties.
Furthermore, when multiple ConfigMaps (or Secrets) are used, ConfigMaps (or Secrets) defined later in the list have a higher priority that ConfigMaps defined earlier in the list.
Finally, when both ConfigMaps and Secrets are used, the latter always a higher priority than the former.
Kubernetes Permissions
Since reading ConfigMaps involves interacting with the Kubernetes API Server, when RBAC is enabled on the cluster, the ServiceAccount that is used to run the application needs to have the proper permissions for such access.
Thankfully, when using the kubernetes-config
extension along with the Kubernetes extension, all the necessary Kubernetes resources to make that happen are automatically generated.
Secrets
By default, the Kubernetes extension doesn’t generate the necessary resources to allow accessing secrets.
Set quarkus.kubernetes-config.secrets.enabled=true
to generate the necessary role and corresponding role binding.
Example configuration
A very common use case is to deploy a Quarkus application that needs to access a relational database which has itself already been deployed on Kubernetes. Using the quarkus-kubernetes-config
extension makes this use case very simple to handle.
Let’s assume that our Quarkus application needs to talk to PostgreSQL and that when PostgreSQL was deployed on our Kubernetes cluster, a Secret
named postgresql
was created as part of that deployment and contains the following entries:
-
database-name
-
database-user
-
database-password
One possible way to make Quarkus use these entries to connect the database is to use the following configuration:
%prod.quarkus.kubernetes-config.secrets.enabled=true (1)
quarkus.kubernetes-config.secrets=postgresql (2)
%prod.quarkus.datasource.jdbc.url=postgresql://somehost:5432/${database-name} (3)
%prod.quarkus.datasource.username=${database-user} (4)
%prod.quarkus.datasource.password=${database-password} (5)
1 | Enable reading of secrets. Note the use of %prod profile as we only want this setting applied when the application is running in production. |
2 | Configure the name of the secret that will be used. This doesn’t need to be prefixed with the %prod profile as it won’t have any effect if secret reading is disabled. |
3 | Quarkus will substitute ${database-name} with the value obtained from the entry with name database-name of the postgres Secret. somehost is the name of the Kubernetes Service that was created when PostgreSQL was deployed to Kubernetes. |
4 | Quarkus will substitute ${database-user} with the value obtained from the entry with name database-user of the postgres Secret. |
5 | Quarkus will substitute ${database-password} with the value obtained from the entry with name database-password of the postgres Secret. |
The values above allow the application to be completely agnostic of the actual database configuration used in production while also not inhibiting the usability of the application at development time.
Alternatives
The use of the quarkus-kubernetes-config
extensions is completely optional as there are other ways an application can be configured to use ConfigMaps or Secrets.
One common alternative is to map each entry of the ConfigMap and / Secret to an environment variable on the Kubernetes Deployment
- see this for more details.
To achieve that in Quarkus, we could use the quarkus-kubernetes
extension (which is responsible for creating Kubernetes manifests and include the following configuration) and configure it as so:
quarkus.kubernetes.env.secrets=postgresql
quarkus.kubernetes.env.mapping.database-name.from-secret=postgresql
quarkus.kubernetes.env.mapping.database-name.with-key=database-name
quarkus.kubernetes.env.mapping.database-user.from-secret=postgresql
quarkus.kubernetes.env.mapping.database-user.with-key=database-user
quarkus.kubernetes.env.mapping.database-password.from-secret=postgresql
quarkus.kubernetes.env.mapping.database-password.with-key=database-password
%prod.quarkus.datasource.jdbc.url=postgresql://somehost:5432/${database-name}
%prod.quarkus.datasource.username=${database-user}
%prod.quarkus.datasource.password=${database-password}
The end result of the above configuration would be the following env
part being applied the generated Deployment
:
env:
- name: DATABASE_NAME
valueFrom:
secretKeyRef:
key: database-name
name: postgresql
- name: DATABASE_USER
valueFrom:
secretKeyRef:
key: database-user
name: postgresql
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
key: database-password
name: postgresql
See this for more details.
Referência de configuração
Propriedade de Configuração Fixa no Momento da Compilação - Todas as outras propriedades de configuração podem ser sobrepostas em tempo de execução.
Configuration property |
Tipo |
Padrão |
---|---|---|
Whether configuration can be read from secrets. If set to Environment variable: Show more |
boolean |
|
The name of the role. Environment variable: Show more |
string |
|
The namespace of the role. Environment variable: Show more |
string |
|
Whether the role is cluster wide or not. By default, it’s not a cluster wide role. Environment variable: Show more |
boolean |
|
If the current role is meant to be generated or not. If not, it will only be used to generate the role binding resource. Environment variable: Show more |
boolean |
|
If set to true, the application will attempt to look up the configuration from the API server Environment variable: Show more |
boolean |
|
If set to true, the application will not start if any of the configured config sources cannot be located Environment variable: Show more |
boolean |
|
ConfigMaps to look for in the namespace that the Kubernetes Client has been configured for. ConfigMaps defined later in this list have a higher priority that ConfigMaps defined earlier in this list. Furthermore, any Secrets defined in Environment variable: Show more |
list of string |
|
Secrets to look for in the namespace that the Kubernetes Client has been configured for. If you use this, you probably want to enable Environment variable: Show more |
list of string |
|
Namespace to look for config maps and secrets. If this is not specified, then the namespace configured in the kubectl config context is used. If the value is specified and the namespace doesn’t exist, the application will fail to start. Environment variable: Show more |
string |