Microservicios con Spring Cloud Kubernetes

spring-cloud-kubernetes

spring-cloud-kubernetes


Cuando decidimos construir una arquitectura basadas en microservicios hacer uso de Spring Cloud y Kubernetes como plataforma para desplegarlos, son unas buenas soluciones. Por lo que en este artículo Microservicios con Spring Cloud Kubernetes, vamos a explorar el proyecto, bastante reciente todavía de Pivotal Spring Cloud Kubernetes. Si necesitas una introducción a Kubernetes quizás estos artículos te vengan bien. Aunque haremos uso de otras piezas como MongoDb, circuit breaker o comunicación a través de WebClient, en este artículo nos centraremos en el despliegue y configuración en Kubernetes, y haremos mención al resto de funcionalidades creadas.

¿Qué necesitamos para empezar?

  • Una instalación de Kubernetes, en nuestro caso usamos Minikube, configurada y arrancada.
  • Dos aplicaciones Spring Boot que se podrán comunicar a través de REST.

De todos modos todo lo necesario lo puedes encontrar en nuestro github

¿Qué vamos a construir y a usar?

El ejemplo que hemos creado consiste en la comunicación de dos microservicios, una tienda la cual hace pedidos, un ejemplo muy simple y sencillo pero que trae los conceptos necesarios para sacar provecho de Kubernetes. Este hará uso de un Service Discovery y un Load Balancer proporcionados por Kubernetes y además usaremos Hystrix como circuit breaker habilitado un fallback por si hubiera algún error al realizar la llamada a otro microservicio usando WebClient..

En nuestro ejemplo vamos a usar

  • Secretos (secrets): Los secretos de kubernetes nos permite almacenar información sensible como passwords, OAuth tokens, ssh keys etc…, en nuestro caso guardaremos la password y el usuario de la base de datos MongoDb.
  • ConfigMaps: Es un objeto utilizado para almacenar datos no confidenciales ni sensibles, se almacenan en formato clave valor, en nuestro caso almacenará un texto para mostrar los servicios.
  • Balanceador de Carga (Load balancer): En este caso se usará Ribbon para balancear la carga entre dos instancias.
  • Servicio de descubrimiento (service discovery): La dependencia de Kubernetes de Spring Cloud nos ayudará a descubrir las instancias o servicios desplegados.

Ejemplo Kubernetes y Spring Cloud

Dependencias Maven

A continuación mostramos las dependencias de kubernetes necesarias para las aplicaciones:

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-kubernetes</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-kubernetes- ribbon</artifactId>
		</dependency>

A parte, se han añadido alguna dependencia más del stack de netflix así como la dependencia de mongo, y spring cloud versión Hoxton.SR8

Configuración del Service Discovery y Load Balancer

Para poder hacer uso del service discovery y del balanceador con Ribbon vamos a activarlo en la clase principal de la aplicación:

@RibbonClient(name = "order-service", configuration = RibbonConfiguration.class)
@EnableDiscoveryClient

Con las anotaciones anteriores en la clase main del proyecto de Spring, hemos activado el balanceador de carga con Ribbon, para que pueda balancear las peticiones que haremos entre las instancias.

Configuración de ConfigMap y Secrets

En Spring Cloud podemos hacer uso del Config Server para guardar información no sensible y de Vault para guardar secretos o información sensible como Passwords. Pero con Spring Cloud Kubernetes podemos utilizar los objetos Secrets y ConfigMap de la propia plataforma de Kubernetes para este tipo de información.

ConfigMap

Para poder hacer uso del configmap de kubernetes primero habrá que desplegar un yaml de este tipo:

apiVersion: v1
kind: ConfigMap
metadata:
  name: shop-service
data:
  application.properties: |-
    configmap.message=Services : %s

Y a continuación para poder leer de este fichero la información ( de data), habrá que mapearlo con la aplicación:

@Configuration
@ConfigurationProperties(prefix = "configmap")
public class ShopConfig {

  private String message = "Services : %s";

de esta manera, seremos capaces de mostrar en el campo message el texto del configmap, hay que tener en cuenta el nombre del configmap debe coincidir con el del servicio para que sea accesible.

kubectl apply -f configmap.yaml

Secrets

Como hemos comentado los secrets en Kubernetes es un tipo de objeto en el que guardaremos información sensible como podríamos hacer en Vault con Spring.

Para poder crear objetos por ejemplo, en nuestro caso para la contraseña y el usuario de MongoDb, vamos a crear un objeto Secrets de la siguiente manera:

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
data:
  username: dXNlcg==
  password: cDQ1NXcwcmQ=

Una vez que hemos desplegado este objeto podremos utilizar esta información donde sea necesaria.

kubectl apply -f secret.yaml

Uso de Secrets de Kubernetes

Una vez que hemos desplegado los secretos vamos a ver su uso mediante una imagen de MongoDb en kubernetes:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mongo
spec:
  replicas: 1
  selector:
    matchLabels:
      service: mongo
  template:
    metadata:
      labels:
        service: mongo
      name: mongodb-service
    spec:
      containers:
        - args:
            - mongod
          image: mongo:latest
          name: mongo
          env:
            - name: MONGO_INITDB_ROOT_USERNAME
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: username
            - name: MONGO_INITDB_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: password
kubectl create -f mongo-deployment.yaml

En el anterior objeto vamos a utilizar la clave y el usuario creados en el secreto, lo único que habrá que tener en cuenta que habrá que habrá que utilizar el mismo nombre que como se llama el secreto desplegado en nuestro caso es db-secret.

Configuración del Servicio para usar secretos

Una vez se ha desplegado tanto el objecto secrets como el deployment, que usará los secrets, en nuestro caso MongoDb, habrá que hacer configurar el application de la aplicación para que puedan ser aplicados:

spring:
  application:
    name: order-service
  cloud:
    kubernetes:
      reload:
        enabled: true
    secrets:
      name: db-secret
  data:
    mongodb:
      host: mongodb-service
      port: 27017
      database: admin
      username: ${MONGO_USERNAME}
      password: ${MONGO_PASSWORD}

En este caso lo que le hemos dicho a nuestro servicio donde van a estar los secrets, y la clave y la contraseña no la escribimos.

Configuración de Acceso basado en Roles

Como último de paso de configuración, sin el cual, nuestras aplicaciones tal y como están no funcionarían, faltaría un acceso basado en roles dentro del clúster. De esta manera nos vamos a asegurar que un Pod que se ejecuta con spring-cloud-kubernets tenga acceso a la API de Kuberntes, y así por ejemplo en nuestro ejemplo pueda obtener todos los servicios.

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: namespace-reader
rules:
  - apiGroups: ["", "extensions", "apps"]
    resources: ["configmaps", "pods", "services", "endpoints", "secrets"]
    verbs: ["get", "list", "watch"]

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: namespace-reader-binding
  namespace: default
subjects:
  - kind: ServiceAccount
    name: default
    apiGroup: ""
roleRef:
  kind: Role
  name: namespace-reader
  apiGroup: ""

Desplegar aplicación Spring Cloud en Kubernetes

Una vez que hemos creado todos nuestro objetos de kubernetes , servicios, secrets, configmaps y deployment, llega el momento de crear los deployment de las aplicaciones que hemos creado en Spring.

Por un lado tendremos el servicio, para exponer una aplicación que se ejecuta en un conjunto de Pods.





apiVersion: v1
kind: Service
metadata:
  name: order-service
spec:
  selector:
    app: order-service
  ports:
    - protocol: TCP
      port: 8080
      nodePort: 30081
  type: NodePort
  externalIPs:
    - 1.2.4.120

Y por otro lado tendremos el deployment de la propia aplicación. Aunque previamente, se tendrá que crear la imagen docker de la aplicación. Este deployment hará referencia al servicio, el deployment que a continuación escribimos, tendrá como variables, el usuario y contraseña de mongodb, que escribimos en el application.yaml de la aplicación:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  selector:
    matchLabels:
      app: order-service
  replicas: 2
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service
          image: order-service:latest
          imagePullPolicy: Never
          ports:
            - containerPort: 8080
          env:
            - name: MONGO_USERNAME
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: username
            - name: MONGO_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: password

Este deployment hace referencia a la imagen order-service, que se habrá creado previamente mediante un Dockerfile que se encuentra en la aplicación.

kubectl create -f deployment.yaml

Verificar el correcto funcionamiento de todos los Pods

Verificamos que nuestros pods están running ejecutando el siguiente comando:

kubectl get pods  

o también

kubectl get po

Si el estado no es running podemos ejecutar

kubectl logs -f <nombre-pod> 

para ver los logs de la aplicación.

Si todo es correcto desde un terminal podemos hacer

minikube service shop-service

para arrancar el navegador y ver lo que muestra.

Conclusión

En esta entrada de Microservicios con Spring Cloud Kubernetes, hemos visto como podemos montar una arquitectura de una manera rápida y eficaz haciendo uso de las principales características que nos ofrece Kubernetes. En nuestro github podrás encontrar todo el proyecto.

Si tienes alguna duda o sugerencia no dudes en comentarlo.

Otros artículos que te pueden interesar

Objetos en Kubernetes

Introducción a Kubernetes

Arquitectura de Kubernetes: Master Node

Arquitectura de Kubernetes: Worker Node


1 pensamiento sobre “Microservicios con Spring Cloud Kubernetes

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *