Spring Cloud Kubernetes
Spring Cloud Kubernetes provides implementations of Spring Cloud interfaces to allow developers to build and run Spring Cloud applications within Kubernetes environments.
We will now explain a series of steps to be able to include and use Spring Cloud Kubernetes within our projects.
Add the dependency
The first step will be to include the following dependency in our project’s «pom.xml»:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-kubernetes-config</artifactId>
</dependency>
Project settings
Once the dependency has been added, we need to configure a couple of files in our project to be able to use the functionalities that Spring Cloud Kubernetes offers:
Creating the Kubernetes files
The config-map are Kubernetes files that allow us to define key-value pairs that we can then use to configure our deployments. An example of a config-map would be the following one:
apiVersion: v1 by d
kind: ConfigMap
metadata:
name: onesait-cloudkubernetes
data:
application.properties: |-
example.message= Testing reload! Message from backend is: %s <br/> Services : %s
Once our config-map is defined, we can import it into our deployment:
onesait-cloudkubernetes.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: onesait-cloudkubernetes
labels:
app: onesait-cloudkubernetes
group: architecture
spec:
replicas: 1
selector:
matchLabels:
app: onesait-cloudkubernetes
template:
metadata:
creationTimestamp: null
labels:
app: onesait-cloudkubernetes
spec:
containers:
- name: app-back
image: >-
solucionesregistry.azurecr.io/architecture/cloud-kubernetes-example:dev
ports:
- name: 8080tcp8080
containerPort: 8080
protocol: TCP
envFrom:
- configMapRef:
name: onesait-cloudkubernetes
resources:
limits:
cpu: 500m
memory: 800Mi
requests:
cpu: 250m
memory: 500Mi
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: Always
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
securityContext: {}
imagePullSecrets:
- name: solutionsregistry
schedulerName: default-scheduler
strategy:
type: Recreate
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
Java client configuration
In our project, we have several ways to collect these environment variables that we define in the config-map. The recommended way would be to define a configuration class that collects the variables and access them through said class:
ClientConfig.java
@Configuration
@ConfigurationProperties(prefix = "example")
public class ClientConfig {
private String message = "Message from backend is: %s <br/> Services : %s";
// getters and setters
}
In this example, we are specifying that we are going to have the variable «example.message», which has a default value, but, in case a new value is specified in our configuration files, that new value would be used.
Defining this configuration class, when the project starts, it will look whether than variable exists, then it will obtain the value that has been defined for it. In this case the value is the one that has been defined in the config-map.
Definiendo esta clase de configuración, el proyecto al arrancar buscará si existe dicha variable y obtendrá el valor que se le haya definido, en este caso el valor es el que ha sido definido en el config-map.
Problems with roles
There is a chance that, when starting the application, we are notified that our Service Account does not have permissions to access the config-maps or the pods. To fix this, we need to create a new role with access to the following resources:
role-example.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: example
rules:
- verbs:
- get
- watch
- list
apiGroups:
- ''
resources:
- configmaps
- pods
And then create a role-binding of our Service Account, with the new role that has been created:
role-binding-example.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: role-binding-example
subjects:
- kind: ServiceAccount
name: default
namespace: onesait-caregiver
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: example
Variable reloading at runtime
Spring Cloud Kubernetes offers us the possibility that our project reloads the environment variables imported from the configmap every time they are changed, so that the execution is not interrupted and the changes are applied automatically. To do this, we need to define the following lines in our «application.yml»:
application.yml
spring.cloud.kubernetes.reload.enabled: true
spring.cloud.kubernetes.reload.mode: event
spring.cloud.kubernetes.reload.strategy: refresh
With this setting, and collecting the variables in a configuration file like the one explained above, every time the config-map is changed, our application will reload and update the values of the program’s internal variables.