Servidor de métricas, apoyado en la librería Audit4Improve
El objetivo de este código es practicar con:
- La gestión de dependencias
- La integración continua
- El lanzamiento continuo
Este servidor utiliza la api Audit4Improve, en la que los alumnos han trabajado a lo largo de las prácticas de la asignatura.
Para el entorno local de desarrollo vamos a usar Kubernetes en la máquina local. Para ello, vamos a necesitar installar previamente Kind y kubectl. Una vez instalado comprueba que podemos ejecutar el binario:
kind --version
La aplicación se va a desplegar en Kubernetes usando una herramienta de gestión de la configuración muy liviana llamada helm, que además es capaz de automatizar el proceso de release y rollback.
Para ello descarga e instala helm. Una vez instalado, comprueba que podemos ejecutar el binario:
helm version
NOTA: Las dependencias deben ser instaladas utilizando chocolatey para Sistemas Opeartivos Windows usando PowerShell. Para ello, además es necesario instalar docker-desktop
Para finalizar, necesitaremos un Personal Access Token de Github para poder probar el funcionamiento de la aplicación.
Puede comenzar probando el servicio instalándolo directamente en el entorno local. Antes de empezar, necesitamos cargar nuestro Personal Access Token en la shell donde probemos nuestro código.
export GITHUB_TOKEN=<token>
export GITHUB_PACKAGES=<token>
export GITHUB_LOGIN=<login>
Crea el fichero application.properties a partir del application.properties.sample, y configura el github token.
Para ejecutar el servidor web de en la máquina local, ejecuta el siguiente comando:
./gradlew bootRun
Prueba que el servicio expone un endpoint de metricas en /metricsInfo:
curl http://localhost:8080/metricsInfo/issues
El endpoint debe devolver la siguiente respuesta:
StatusCode : 200
StatusDescription :
Content : {"name":"issues","unit":"issues","description":"Tareas sin finalizar en el repositorio","type":"java.lang.Integer"}
RawContent : HTTP/1.1 200
Transfer-Encoding: chunked
...
Compruebe también el valor devuelto si solicta el recurso readyz
Para ejecutar los tests unitarios, ejecuta el siguiente comando:
./gradlew test
Para levantar la infraestructura kubernetes localmente, ejecuta el siguiente comando:
./gradlew localenv-up
La tarea localenv
levanta un cluster de Kubernetes y configura de forma
automática el contexto de Kubernetes para que podamos acceder a la API
de Kubernetes de manera local usando kubectl
. Levantar el entorno local
debe tardar alrededor de 3 minutos.
Finalmente comprobamos que tenemos acceso al cluster de Kubernetes:
kubectl get po --all-namespaces
Deberemos obtener una salida similar a la siguiente:
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-558bd4d5db-l8q2g 1/1 Running 0 83s
kube-system coredns-558bd4d5db-rqcbm 1/1 Running 0 84s
kube-system etcd-audit-server-control-plane 1/1 Running 0 94s
kube-system kindnet-glbk7 1/1 Running 0 85s
kube-system kube-apiserver-audit-server-control-plane 1/1 Running 1 94s
kube-system kube-controller-manager-audit-server-control-plane 1/1 Running 0 94s
kube-system kube-proxy-db56r 1/1 Running 0 85s
kube-system kube-scheduler-audit-server-control-plane 1/1 Running 0 94s
local-path-storage local-path-provisioner-547f784dff-vz7c2 1/1 Running 0 83s
Cuando hayamos terminado, simplemente borramos el cluster:
./gradlew localenv-down
Para desplegar la aplicación, ejecuta el siguiente comando:
./gradlew localenv-deploy
Al finalizar, aplicación se encuentra en el default
namespace, y debe
de haber 1 pod en estado running:
➜ ~ kubectl get po
NAME READY STATUS RESTARTS AGE
audit-server-7b7f9cbb96-x6kfw 1/1 Running 0 98s
Podemos interactuar con la aplicación y simular que recibe peticiones HTTP haciendo port-forwarding del servicio a nuestra máquina local. De esta forma, no necesitamos un Load Balancer real en nuestra infraestructura, ni configuración DNS extra:
kubectl port-forward svc/audit-server 8000:80
Esto abre un tunel al cluster de Kubernetes y expone el puerto 80 del servicio, que mapea al puerto 8080 del container que se ejecuta en la pod, al puerto 8000 de nuestra máquina local. Y ahora podemos abrir otro terminal y lanzarle peticiones a nuestro servicio:
➜ ~ curl http://localhost:8000/livez
{"healthy":true}
➜ ~ curl http://localhost:8000/metricsInfo/forks
{"name":"forks","unit":"forks","description":"Número de forks, no son los forks de la web","type":"java.lang.Integer"}
Podemos comenzar probando la aplicación directamente en el entorno local. Antes de empezar, necesitamos cargar nuestro Personal Access Token en el terminal de powershell en modo administrador:
[System.Environment]::SetEnvironmentVariable('GITHUB_OAUTH','TOKEN')
[System.Environment]::SetEnvironmentVariable('GITHUB_LOGIN','LOGIN')
[System.Environment]::SetEnvironmentVariable('GITHUB_PACKAGES','TOKEN')
O bien
$env:GITHUB_OAUTH='TOKEN'
$env:GITHUB_LOGIN='LOGIN'
$env:GITHUB_PACKAGES='TOKEN'
Y habilitar la ejecucion de scripts:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine
Crea el fichero application.properties a partir del application.properties.sample, y configura el github token.
Para ejecutar el servidor web de en la máquina local, ejecuta el siguiente comando:
./gradlew.bat bootRun
Prueba que el servicio expone un endpoint que devuelve información sobre las métricas manejadas en /metricsInfo. Para ello accede a la URL a traves del navegador o utiliza una consola MINGW64:
curl -v http://localhost:8080/metricsInfo/issues
El endpoint debe devolver algo similar a la siguiente respuesta:
StatusCode : 200
StatusDescription :
Content : {"name":"issues","unit":"issues","description":"Tareas sin finalizar en el repositorio","type":"java.lang.Integer"}
RawContent : HTTP/1.1 200
Transfer-Encoding: chunked
...
Compruebe también el valor devuelto si solicita el recurso readyz, algo similar a
➜ ~ curl -v http://localhost:8080/readyz
StatusCode : 200
StatusDescription :
Content : {"totalAdditions":738,"metric":{"name":"totalAdditions","value":738,"date":"2022-05-28T18:41:26.880+00:00","description":"Suma el total de adiciones desde que el repositorio se creó","source":"GitHub, calculada","unit":"additions"},"healthy":true}
RawContent : HTTP/1.1 200
Transfer-Encoding: chunked
Para ejecutar los tests unitarios, ejecuta el siguiente comando:
./gradlew.bat test
Para desplegar la infraestructura en local ejecuta el siguiente comando:
./gradlew.bat localenv-win-up
La tarea localenv
levanta un cluster de Kubernetes y configura de forma
automática el contexto de Kubernetes para que podamos acceder a la API
de Kubernetes de manera local usando kubectl
. Levantar el entorno local
debe tardar alrededor de 3 minutos.
Finalmente comprobamos que tenemos acceso al cluster de Kubernetes:
kubectl get po --all-namespaces
Deberemos obtener una salida similar a la siguiente:
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-558bd4d5db-l8q2g 1/1 Running 0 83s
kube-system coredns-558bd4d5db-rqcbm 1/1 Running 0 84s
kube-system etcd-audit-server-control-plane 1/1 Running 0 94s
kube-system kindnet-glbk7 1/1 Running 0 85s
kube-system kube-apiserver-audit-server-control-plane 1/1 Running 1 94s
kube-system kube-controller-manager-audit-server-control-plane 1/1 Running 0 94s
kube-system kube-proxy-db56r 1/1 Running 0 85s
kube-system kube-scheduler-audit-server-control-plane 1/1 Running 0 94s
local-path-storage local-path-provisioner-547f784dff-vz7c2 1/1 Running 0 83s
Para desplegar la aplicación, ejecuta el siguiente comando:
./gradlew localenv-win-deploy
Esta tarea también despliega la infraestructura, por lo que no sería necesario hacerlo antes
Al finalizar, aplicación se encuentra en el default
namespace, y debe
de haber 1 pod en estado running:
➜ ~ kubectl get po
NAME READY STATUS RESTARTS AGE
audit-server-7b7f9cbb96-x6kfw 1/1 Running 0 98s
Podemos interactuar con la aplicación y simular que recibe peticiones HTTP haciendo port-forwarding del servicio a nuestra máquina local. De esta forma, no necesitamos un Load Balancer real en nuestra infraestructura, ni configuración DNS extra. Si observa el script de despliegue verá que este redireccionamiento se ha realizado ya
kubectl port-forward svc/audit-server 8080:80
Esto abre un tunel al cluster de Kubernetes y expone el puerto 80 del servicio, que mapea al puerto 8080 del container que se ejecuta en la pod, al puerto 8080 de nuestra máquina local. Y ahora podemos abrir otro terminal y lanzarle peticiones a nuestro servicio:
➜ ~ curl http://localhost:8080/readyz
{"totalAdditions":738,"metric":{"name":"totalAdditions","value":738,"date":"2022-05-28T18:36:02.053+00:00","description":"Suma el total de adiciones desde que el repositorio se creó","source":"GitHub, calculada","unit":"additions"},"healthy":true}
➜ ~ curl http://localhost:8080/metricsInfo/forks
{"name":"forks","unit":"forks","description":"Número de forks, no son los forks de la web","type":"java.lang.Integer"}
Cuando hayamos terminado podemos borramos el cluster:
./gradlew.bat localenv-win-down
Enlaces generados automáticamente al crear el esqueleto del servicio en start.spring.io
Considere las siguientes referencias para más información:
- Official Gradle documentation
- Spring Boot Gradle Plugin Reference Guide
- Create an OCI image
- Spring Web
The following guides illustrate how to use some features concretely:
- Building a RESTful Web Service
- Serving Web Content with Spring MVC
- Building REST services with Spring
These additional references should also help you: